OpenGL ES 2.0 Точечный световой шейдер

В настоящее время я пытаюсь написать шейдер, который должен включать в себя простой точечный свет в OpenGL ES 2.0, но он не совсем работает.

Я создал свой собственный небольшой SceneGraph, и каждый объект (в настоящее время только боксы) может иметь свой собственный перевод / поворот / масштаб, и рендеринг работает нормально. Каждому из ящиков назначается собственная модель ModelView и матрица нормалей, и все они используют одну и ту же матрицу проекции.

Для каждого объекта я передаю шейдеру матрицы и положение источника света как единое целое.

Если объект не вращается, свет работает нормально, но как только объект вращается, кажется, что свет вращается вместе с объектом, а не остается в том же положении.

Вот код. Сначала создание матриц:

GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f);
GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 0.0f);

Каждый из узлов вычисляет собственную матрицу преобразования, содержащую перемещение / поворот / масштаб, и умножает ее на модель ViewMatrix:

modelViewMatrix = GLKMatrix4Multiply(modelViewMatrix, transformation);

Эта матрица передается шейдеру, и после рендеринга объекта старая матрица восстанавливается.

Матрица нормалей рассчитывается следующим образом:

GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL);

Вершинный шейдер:

attribute vec4 Position;
attribute vec2 TexCoordIn;
attribute vec3 Normal;

uniform mat4 modelViewProjectionMatrix;
uniform mat4 modelViewMatrix;
uniform mat3 normalMatrix;

uniform vec3 lightPosition;

varying vec2 TexCoordOut;
varying vec3 n, PointToLight;

void main(void) {
    gl_Position =  modelViewProjectionMatrix * Position;
    n = normalMatrix * Normal;

    PointToLight = ((modelViewMatrix * vec4(lightPosition,1.0)) - (modelViewMatrix * Position)).xyz;

    // Pass texCoord
    TexCoordOut = TexCoordIn;
}

Фрагмент-шейдер:

varying lowp vec2 TexCoordOut;
varying highp vec3 n, PointToLight;

uniform sampler2D Texture;

void main(void) {
    gl_FragColor = texture2D(Texture, TexCoordOut);

    highp vec3 nn = normalize(n);
    highp vec3 L = normalize(PointToLight);

    lowp float NdotL = clamp(dot(n, L), -0.8, 1.0);
    gl_FragColor *= (NdotL+1.)/2.;
}

Я предполагаю, что PointToLight вычислен неправильно, но я не могу понять, что не так.


person creativ    schedule 31.10.2012    source источник


Ответы (1)


Я наконец понял, что пошло не так.

Вместо умножения lightPosition на modelViewMatrix мне просто нужно умножить его на viewMatrix, который содержит только преобразования камеры, а не преобразования для блока:

PointToLight = ((viewMatrix * vec4(lightPosition,1.0)) - (viewMatrix * modelMatrix * Position)).xyz;

Теперь работает нормально.

person creativ    schedule 31.10.2012