Подтвердить что ты не робот

Зеркальное освещение GLSL

Когда я использую свои шейдеры, я получаю следующие результаты: enter image description here

enter image description here

Одна из проблем заключается в том, что зеркальный свет деформируется, и вы можете видеть сферические треугольники, а другое - видеть, что я вижу зеркало, где я не должен (второе изображение). Один свет справки выполняется в вершинном шейдере, другой - в фрагменте.

Вот как выглядит мой шейдер с вершинным светом: Vertex:

// Material data.
uniform vec3 uAmbient;
uniform vec3 uDiffuse;
uniform vec3 uSpecular;
uniform float uSpecIntensity;
uniform float uTransparency;

uniform mat4 uWVP;
uniform mat3 uN;
uniform vec3 uSunPos;
uniform vec3 uEyePos;
attribute vec4 attrPos;
attribute vec3 attrNorm;
varying vec4 varColor;

void main(void)
{
    vec3 N = uN * attrNorm;
    vec3 L = normalize(uSunPos);
    vec3 H = normalize(L + uEyePos);
    float df = max(0.0, dot(N, L));
    float sf = max(0.0, dot(N, H));
    sf = pow(sf, uSpecIntensity);

    vec3 col = uAmbient + uDiffuse * df + uSpecular * sf;
    varColor = vec4(col, uTransparency);
    gl_Position = uWVP * attrPos;
}

Fragment:

varying vec4 varColor;

void main(void)
{

    //vec4 col = texture2D(texture_0, varTexCoords);
    //col.r += uLightDir.x;
    //col.rgb = vec3(pow(gl_FragCoord.z, 64));
    gl_FragColor = varColor;

}

Возможно, что мои предоставленные данные из кода неверны. uN - это мировая матрица (не инвертированная и не транспонированная, хотя выполнение этого не показало ничего другого). UWVP - матрица прогнозов мирового уровня.

Любые идеи относительно того, где может быть проблема, будут оценены.

[EDIT] Вот мои легкие вычисления, сделанные в фрагменте: Файл шейдера вершин:

uniform mat4 uWVP;
uniform mat3 uN;
attribute vec4 attrPos;
attribute vec3 attrNorm;
varying vec3 varEyeNormal;

void main(void)
{
    varEyeNormal = uN * attrNorm;
    gl_Position = uWVP * attrPos;
}

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

// Material data.
uniform vec3 uAmbient;
uniform vec3 uDiffuse;
uniform vec3 uSpecular;
uniform float uSpecIntensity;
uniform float uTransparency;

uniform vec3 uSunPos;
uniform vec3 uEyePos;
varying vec3 varEyeNormal;

void main(void)
{
    vec3 N = varEyeNormal;
    vec3 L = normalize(uSunPos);
    vec3 H = normalize(L + uEyePos);

    float df = max(0.0, dot(N, L));
    float sf = max(0.0, dot(N, H));
    sf = pow(sf, uSpecIntensity);

    vec3 col = uAmbient + uDiffuse * df + uSpecular * sf;

    gl_FragColor = vec4(col, uTransparency);
}

[EDIT2] Как отметил Йоаким, я не нормализую varEyeNormal в шейдере фрагментов. После исправления этого результата результат намного лучше в шейдере фрагментов. Я также использовал функцию нормализации на uEyePos, поэтому зеркальный цвет больше не идет на темную сторону. Спасибо за помощь.

enter image description here

4b9b3361

Ответ 1

Краткий ответ: вам нужно нормализовать varEyeNormal в шейдере фрагмента, а не в вершинном шейдере.

Более длинный ответ: Чтобы получить плавное освещение, вам нужно будет вычислить нормали на пиксель вместо каждой вершины. Варьирование, вычисленное в вершинном шейдере, линейно интерполируется перед передачей в шейдер фрагмента, который отлично работает как ярлык в некоторых случаях, но хуже в других.

Причина, по которой вы видите края треугольника, связана с тем, что интерполяция между нормалями приводит к сокращению до 1,0 нормалей во всех пикселях между вершинами.

Чтобы исправить это, вам нужно будет нормализовать нормали в шейдере фрагмента, а не в вершинном шейдере.

Нормальная матрица должна быть верхним 3x3 транспонирования обратного к матрице Modelview, что эквивалентно верхнему 3x3 модели Modelview, если Modelview содержит только вращения и переводы (без масштабирования)

Подробнее о матрице Normal см. ниже: http://www.lighthouse3d.com/tutorials/glsl-tutorial/the-normal-matrix/

(Отредактировано для правильности в соответствии с комментарием ниже.)