GLSL - вычисление координат экрана из мировых координат не работает должным образом - PullRequest
3 голосов
/ 15 декабря 2011

Я только что реализовал шейдер "god-ray" с прекрасного сайта nVidia GPU Gems: http://http.developer.nvidia.com/GPUGems3/gpugems3_ch13.html

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

Примеры изображений:

Это выглядит именно так, как и должно быть.

enter image description here

Это не так.Свет должен излучаться наружу от белой сферы, но похоже, что положение не изменилось с первого изображения.

enter image description here

Я делаю преобразования в вершинном шейдере:

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) Вполне возможно, что ошибка находится где-то еще в коде, но я хотел убедиться, что мои вычисления в вершинном шейдере были правильнымиперед погружением в остальную часть.

РЕДАКТИРОВАТЬ: Я сделал некоторые изменения, основанные на том, что Николь Болас предложил ниже, и это лучше, но все же не правильно.

Он по-прежнему выглядит хорошо, когда камера находится в исходном положении, но когда я поворачиваю сцену, это выглядит так, как будто рассчитанное положение света теперь слишком далеко влево.

enter image description here

Вот код 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, поэтому я немного не уверен, что и что делает.

1 Ответ

4 голосов
/ 15 декабря 2011

Если light_coords находится в мировом пространстве, то умножение его на gl_ModelViewProjectionMatrix имеет смысл, только если gl_Vertex равно также в мировом пространстве.Почему-то я сомневаюсь, что это так.

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

...