Я только что реализовал шейдер "god-ray" с прекрасного сайта nVidia GPU Gems: http://http.developer.nvidia.com/GPUGems3/gpugems3_ch13.html
В любом случае, он почти идеален, за исключением одного недостатка.Каким-то образом положение света не меняется с остальной частью сцены.
Примеры изображений:
Это выглядит именно так, как и должно быть.
Это не так.Свет должен излучаться наружу от белой сферы, но похоже, что положение не изменилось с первого изображения.
Я делаю преобразования в вершинном шейдере:
uniform vec4 light_coords;
varying vec2 light_pos;
void main()
{
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
gl_TexCoord[0] = gl_MultiTexCoord0;
light_pos = vec2(gl_ModelViewProjectionMatrix * light_coords) * 0.5 + 0.5;
}
Это правильно?
Положение источника света в мировых координатах (0, 0, -2) Вполне возможно, что ошибка находится где-то еще в коде, но я хотел убедиться, что мои вычисления в вершинном шейдере были правильнымиперед погружением в остальную часть.
РЕДАКТИРОВАТЬ: Я сделал некоторые изменения, основанные на том, что Николь Болас предложил ниже, и это лучше, но все же не правильно.
Он по-прежнему выглядит хорошо, когда камера находится в исходном положении, но когда я поворачиваю сцену, это выглядит так, как будто рассчитанное положение света теперь слишком далеко влево.
Вот код GLSL, который я использую:
iform vec4 light_coords;униформа mat4 light_modelview;меняя vec2 light_pos;
void main()
{
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
gl_TexCoord[0] = gl_MultiTexCoord0;
light_pos = vec2(gl_ProjectionMatrix * light_modelview * light_coords) * 0.5 + 0.5;
}
light_modelview
получается здесь:
glPushMatrix()
glTranslatef(self.position[0], self.position[1], self.position[2])
glScalef(2, 2, 2)
self.modelview = glGetFloatv(GL_MODELVIEW_MATRIX)
glCallList(self.sphere)
glLightfv(self.light_id, GL_POSITION, self.position)
glPopMatrix()
position
равно [0, 0, -2]
.Он передается в шейдер как light_coords
В идеале, я бы хотел, чтобы light_pos
было где-нибудь в пределах (0, 0) - (1, 1), если оно на экране, и больше или меньшечто если это с экрана.
Есть подсказка, что я делаю не так?Я все еще новичок в OpenGL, поэтому я немного не уверен, что и что делает.