Я реализовал простой шейдер для освещения; это вид работ, но свет, кажется, движется, когда камера вращается (и только когда она вращается).opengl - точечный свет перемещается, когда камера вращается при использовании шейдера
Я экспериментировал с прожектором, это то, как она выглядит (это место в центре):
Если теперь повернуть камеру, пятно движется вокруг; например, здесь я посмотрел вниз (я вообще не двигался, просто посмотрел вниз), и это казалось у моих ног:
Я искал его, и я видел, что это распространенная ошибка, смешивание систем отсчета в шейдере и/или при настройке положения света перед перемещением камеры.
Дело в том, что я уверен, что не делаю эти две вещи, но, видимо, я ошибаюсь; просто я не могу найти ошибку.
Вот шейдер:
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 вызывает встроенные функции языка для рисования сцены; У меня здесь не так много власти.
Итак, либо я делаю что-то не так в шейдере, либо на языке есть что-то, что «за кулисами» ломает вещи.
Можете ли вы указать мне правильное направление?
Моя ошибка, положение света находится в пространстве зрения в шейдере. Я думаю, что вы правы в отношении других вещей, но все еще не может найти настоящую проблему. – Beriol
Если ваше светлое положение находится в пространстве просмотра, вам придется обновлять его всякий раз, когда камера меняется. Ваша последовательность 'SetupLights()' перед 'UpdateCamera()' представляется концептуально неправильной для этого. – derhass