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

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

введите описание изображения здесь

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

Вот как выглядит мой вершинный световой шейдер:
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;
}

Фрагмент:

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, поэтому зеркальное отображение больше не переходит на темную сторону. Спасибо за помощь.

введите описание изображения здесь

12

Решение

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

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

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

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

Матрица Normal должна иметь верхние 3×3 транспонирования инверсии матрицы Modelview, что эквивалентно верхним 3×3 матрицы Modelview, если ModelView содержит только повороты и переводы (без масштабирования).

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

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

19

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]