2016-08-06 7 views
0

Я реализовал простой шейдер для освещения; это вид работ, но свет, кажется, движется, когда камера вращается (и только когда она вращается).opengl - точечный свет перемещается, когда камера вращается при использовании шейдера

Я экспериментировал с прожектором, это то, как она выглядит (это место в центре): enter image description here

Если теперь повернуть камеру, пятно движется вокруг; например, здесь я посмотрел вниз (я вообще не двигался, просто посмотрел вниз), и это казалось у моих ног: enter image description here

Я искал его, и я видел, что это распространенная ошибка, смешивание систем отсчета в шейдере и/или при настройке положения света перед перемещением камеры.

Дело в том, что я уверен, что не делаю эти две вещи, но, видимо, я ошибаюсь; просто я не могу найти ошибку.

Вот шейдер:

Vertex Shader

varying vec3 vertexNormal; 
varying vec3 lightDirection; 

void main() 
{ 
    vertexNormal = gl_NormalMatrix * gl_Normal; 

    lightDirection = vec3(gl_LightSource[0].position.xyz - (gl_ModelViewMatrix * gl_Vertex).xyz); 

    gl_Position = ftransform(); 
} 

Фрагмент Shader

uniform vec3 ambient; 
uniform vec3 diffuse; 
uniform vec3 specular; 
uniform float shininess; 

varying vec3 vertexNormal; 
varying vec3 lightDirection; 

void main() 
{ 
    vec3 color = vec3(0.0, 0.0, 0.0); 

    vec3 lightDirNorm; 
    vec3 eyeVector; 
    vec3 half_vector; 
    float diffuseFactor; 
    float specularFactor; 
    float attenuation; 
    float lightDistance; 

    vec3 normalDirection = normalize(vertexNormal); 

    lightDirNorm = normalize(lightDirection); 

    eyeVector = vec3(0.0, 0.0, 1.0); 
    half_vector = normalize(lightDirNorm + eyeVector); 

    diffuseFactor = max(0.0, dot(normalDirection, lightDirNorm)); 

    specularFactor = max(0.0, dot(normalDirection, half_vector)); 
    specularFactor = pow(specularFactor, shininess); 

    color += ambient * gl_LightSource[0].ambient; 
    color += diffuseFactor * diffuse * gl_LightSource[0].diffuse; 
    color += specularFactor * specular * gl_LightSource[0].specular; 

    lightDistance = length(lightDirection[i]); 

    float constantAttenuation = 1.0; 
    float linearAttenuation = (0.02/SCALE_FACTOR) * lightDistance; 
    float quadraticAttenuation = (0.0/SCALE_FACTOR) * lightDistance * lightDistance; 

    attenuation = 1.0/(constantAttenuation + linearAttenuation + quadraticAttenuation); 

    // If it's a spotlight 
    if(gl_LightSource[i].spotCutoff <= 90.0) 
    { 
     float spotEffect = dot(normalize(gl_LightSource[0].spotDirection), normalize(-lightDirection)); 
     if (spotEffect > gl_LightSource[0].spotCosCutoff) 
     { 
      spotEffect = pow(spotEffect, gl_LightSource[0].spotExponent); 

      attenuation = spotEffect/(constantAttenuation + linearAttenuation + quadraticAttenuation); 
     } 
     else 
      attenuation = 0.0; 
    } 

    color = color * attenuation; 

    // Moltiplico il colore per il fattore di attenuazione 
    gl_FragColor = vec4(color, 1.0); 
} 

Теперь я не могу показать вам код, где я вынести вещи, потому что это настраиваемый язык, который объединяет opengl и предназначен для создания 3D-приложений (это не помогло бы вам показать); но то, что я делаю что-то вроде этого:

SetupLights(); 
UpdateCamera(); 
RenderStuff(); 

Где:

  • SetupLights содержит фактические вызовы OpenGL, что установки огней и их позиции;
  • UpdateCamera обновляет положение камеры, используя встроенные классы языка; У меня здесь не так много власти;
  • RenderStuff вызывает встроенные функции языка для рисования сцены; У меня здесь не так много власти.

Итак, либо я делаю что-то не так в шейдере, либо на языке есть что-то, что «за кулисами» ломает вещи.

Можете ли вы указать мне правильное направление?

ответ

2

Вы писали

положения света уже в мировых координатах, и именно там я делаю вычисление

однако, так как вы подаете gl_ModelViewMatrix к вашей вершине и gl_NormalMatrix к вашим нормальным значениям, эти значения, вероятно, находятся в поле зрения, что может вызвать движущийся свет.

как в сторону, ваш вектор глаз выглядит так, как будто он должен быть в виде координат, однако пространство просмотра - это правая система координат, поэтому «вперед» указывает вдоль отрицательной оси z.Кроме того, ваши зеркальные вычисления, скорее всего, будут отключены, так как вы используете один и тот же вектор глаз для всех фрагментов, но, вероятно, это должно указывать на положение этого фрагмента на ближних/дальних плоскостях.

+0

Моя ошибка, положение света находится в пространстве зрения в шейдере. Я думаю, что вы правы в отношении других вещей, но все еще не может найти настоящую проблему. – Beriol

+0

Если ваше светлое положение находится в пространстве просмотра, вам придется обновлять его всякий раз, когда камера меняется. Ваша последовательность 'SetupLights()' перед 'UpdateCamera()' представляется концептуально неправильной для этого. – derhass

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

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