Нормали GLSL с нестандартной проекционной матрицей - PullRequest
2 голосов
/ 19 апреля 2011

После нескольких дней работы моего вершинного шейдера GLSL для правильного отображения вершин я перешел к освещению!Мое понимание освещения / нормалей openGL не слишком велико для любого воображения, так что терпите меня.Я не уверен, какие переводы мне нужно применить к моим нормальным, чтобы они отображались правильно.Вот код приложения, который устанавливает мои огни:

    final float diffuseIntensity = 0.9f;
    final float ambientIntensity = 0.5f;

    final float position[] = { 0f, 0f, 25000f, 0f};
    gl.glLightfv(GL.GL_LIGHT0, GL.GL_POSITION, position, 0);
    final float diffuse[] = { 0, diffuseIntensity, 0, 1f};
    gl.glLightfv(GL.GL_LIGHT0, GL.GL_DIFFUSE, diffuse, 0);
    final float ambient[] = { ambientIntensity, ambientIntensity, ambientIntensity, 1f};
    gl.glLightfv(GL.GL_LIGHT0, GL.GL_AMBIENT, ambient, 0);

Довольно стандартные вещи до сих пор.Теперь из-за требований приложения вот вершинный шейдер (несколько странный):

void main()
{   
// P is the camera matrix, model_X_matrices are the relative translation/rotation etc of the model currently being rendered.
vec4 pos = gl_ProjectionMatrix * P * modelTranslationMatrix * modelRotationMatrix * modelScaleMatrix * gl_Vertex;

gl_Position = pos;

gl_TexCoord[0] = gl_MultiTexCoord0;

gl_FrontColor = gl_Color;           
}

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

vec4 normal = modelTranslationMatrix * modelRotationMatrix * modelScaleMatrix * vec4(gl_Normal);

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

vec3 light_position = gl_LightSource[0].position.xyz;

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

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

РЕДАКТИРОВАТЬ: После прочтения, что нормальная матрица (gl_NormalMatrix) представляет собой всего лишь 3x3 обратную матрице gl_ModelView, яЯ предполагаю, что правильный способ вычислить нормаль в мировом пространстве - это умножить gl_Normal на обратное modelTranslationMatrix * modelRotationMatrix * modelScaleMatrix?Мне все еще нужно умножить это на матрицу P или это не имеет значения для обычных вычислений?

Ответы [ 2 ]

1 голос
/ 19 апреля 2011

Вы должны предварительно умножить modelTranslationMatrix * modelRotationMatrix * modelScaleMatrix и передать это только как одну униформу.

Нормалы умножаются на обратную транспонированность матрицы вида модели, подробности объясняются в отличной статье, найденной здесь http://www.lighthouse3d.com/tutorials/glsl-tutorial/the-normal-matrix/

0 голосов
/ 12 апреля 2012

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

Вектор в opengl представляется синонимично точке (то есть одна координата на ось). Это означает, что его направление определяется переводом от начала координат к этим координатам. Когда вы переводите концептуальный математический вектор, вы не меняете его направление. Когда вы переводите вектор opengl без перевода его источника , вы делаете.

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

Ergo, а не

vec4 normal = modelTransformMatrix * vec4(gl_Normal);

Вы действительно хотите

vec3 normal = mat3(modelTransformMatrix) * gl_Normal;

Следовательно, исключая термины перевода, но сохраняя любое вращение, масштаб и сдвиг.

Что касается использования матрицы камеры, это зависит от того, что вы хотите сделать. Важно то, что все значения в уравнении находятся в одном координатном пространстве. При этом, умножение на проекцию камеры, вероятно, вызовет проблемы, поскольку оно (вероятно) настроено для проецирования из трехмерных мировых координат относительно камеры в координаты экрана + глубину. Как правило, вы рассчитываете освещение в мировом пространстве - умножение на перевод модели, но не на проекцию камеры.

...