2009-12-11 8 views
2

У меня есть следующий код GLSL для освещения:Как превратить направленный свет в пространство камеры в GLSL

uniform vec3 lightDir; // Parallel light 
uniform float ambient; 
uniform vec3 lightColour; 

void main() 
{ 
    gl_Position = ftransform(); 

    vec3 eyeNormal = normalize(gl_NormalMatrix * gl_Normal); 
    float intensity = max(ambient, dot(eyeNormal, normalize(-lightDir)); 

    gl_FrontColor = gl_Color * vec4(lightColour, 1.0) * intensity; 
} 

света вектор, указанный в мировом пространстве. Я установил ориентацию и положение камеры, используя gluLookAt. Поскольку OpenGL предполагает, что вектор света находится в пространстве камеры, свет перемещается вместе с камерой, а не остается неподвижной.

Я попытался активировать шейдер и установить вектор света до и после вызова gluLookAt, но я получаю тот же эффект. Что именно я должен сделать, чтобы правильно преобразовать вектор света?

ответ

-1

Проблема в вашем шейдере заключается в том, что у вас есть нормали пространства глаз и огни мирового пространства.
Я не уверен, но преобразование вашего вектора света вашей обычной матрицей должно устранить проблему.

Или, чтобы быть более эффективным, вы можете преобразовать свет vec в пространстве объекта (в программном коде), тогда преобразование для каждого нормального элемента не требуется.

+0

Я попытался умножая lightDir на gl_NormalMatrix в затенении и не было никакого эффекта. Я также попробовал умножить на gl_ModelViewMatrix, например: 'vec3 lightEyeDir = normalize (vec3 (gl_ModelViewMatrix * vec4 (-lightDir, 1.0)));' Выполнение этого полностью отбросило диффузный вклад. Для преобразования вектора света в программный код, какое преобразование я бы сделал точно? – Aaron

+0

Преобразуя световой сигнал в обратную модельную матрицу, вы должны получить свет пространства модели. – Tryum

+1

NormalMatrix - это просто часть вращения модели ModelView (без перевода и масштабирования). Умножение света на него означает также применение вращения модели (и вы этого не хотите). – MaR

-2

код в шейдере вычисляет направленный свет, который не изменяется с положением света, поэтому вы должны использовать функции spotLight или pointLight.

Попробуйте найти шейдеры для этих источников света. если вы не можете найти, скажите мне, поэтому я пришлю вам.

2

Вы должны решить, в каком пространстве вы будете делать освещение. Если вы хотите следовать «стандартным» OpenGL, то это view space. Затем ваш вектор света должен быть повернут частью вращения матрицы представлений перед тем, как перейти к шейдеру (самое простое решение imho).

Вы также можете применять огни в других местах (касание, объект, мир или даже пространство экрана - для дефорированного затенения), но это другая тема. Также обратите внимание на то, что для расширенного использования вам нужно будет забыть OpenGL и делать все с помощью собственных матриц и шейдеров (без по умолчанию освещения/преобразования).

3

У вас есть общая проблема, часто встречающаяся в учебниках GLSL в Интернете. Вы передаете свои значения освещенности в форме. Почему бы вам не использовать вызовы glLight, например, с фиксированной функцией рендеринга, и вывести значения из gl_LightSource[n]. Разница в том, что openGL автоматически преобразует все в пространстве взгляда.

void main() 
{ 
    // remember: directional lights are GL_POSITION with w = 0 
    vec3 lightDir = vec3(gl_LightSource[0].position); 
    float ambient = gl_LightSource[0].ambient; 
    vec3 lightColour = vec3(gl_LightSource[0].diffuse); 


    gl_Position = ftransform(); 

    vec3 eyeNormal = normalize(gl_NormalMatrix * gl_Normal); 
    float intensity = max(ambient, dot(eyeNormal, normalize(-lightDir)); 

    gl_FrontColor = gl_Color * vec4(lightColour, 1.0) * intensity; 
} 

А всегда большой ресурс по теме: http://www.lighthouse3d.com/opengl/glsl/index.php?lights

И всегда полезным является GLSL Чит Чит: http://www.cs.brown.edu/courses/cs123/resources/glslQuickRef.pdf

+0

Но в этом случае, я думаю, вам не нужно отрицать направление света, поскольку значение в поле 'position' должно быть уже вектором TO light (теоретически положение на бесконечности). –

+1

Обратите внимание, что использование вызовов glLight теперь устарело, в отличие от передаваемых значений освещения в виде униформы. –

-1

Я подозреваю, часть проблемы заключается в: float intensity = max(ambient, dot(eyeNormal, normalize(-lightDir));.

Окружающий термин в шейдерах, основанных на Ламбертии, масштабируется точечным продуктом. Здесь окружающий термин будет часто утверждать себя, потому что он, вероятно, будет больше, чем точечный продукт. Использование gl_NormalMatrix также является проблемой, поскольку, как отмечалось выше, это означает, что lightDir находится в пространстве объектов, тогда как нормальный вектор преобразуется из пространства объектов и в координаты глаз.

Try:

vec3 n=normalize(normal); 
float ndotl=max(0.0, dot(n, normalize(lightDir))); 

vec3 diffuse=ambient * ndotl; 
+0

Это неправильно. Теперь вы предполагаете, что 'lightDir' находится в пространстве модели. И окружающий термин - это чит-термин, который всегда дает свет, даже если отсутствует направленный свет, поэтому его определенно не следует умножать на точечный продукт, но он добавляется (или используется только тогда, когда света недостаточно, как и он) , То, что вы, вероятно, имеете в виду, это врожденная интенсивность света, которая в его случае представлена ​​«lightColour», которую он умножает на точечный продукт. –

 Смежные вопросы

  • Нет связанных вопросов^_^