Я пишу небольшой тест затенения Фонга и бьюсь головой о кирпичную стену, пытаясь заставить работать зеркальный компонент. Похоже, он работает правильно, за исключением того, что зеркальный свет применяется как к передней, так и к задней части объекта. (Сам объект прозрачен, лица отсортированы на стороне процессора вручную.)
Обратите внимание, что диффузный компонент работает отлично (появляется только на стороне, обращенной к источнику света), что, как мне кажется, исключает проблему с нормалями, поступающими во фрагментный шейдер.
Насколько я понимаю, зеркальный компонент пропорционален cos угла между вектором глаза и вектором отраженного света.
Чтобы все было максимально просто, мой тестовый код пытается сделать это в мировом пространстве. Положение камеры и вектор света жестко закодированы (извините) как (0,0,4)
и (-0.707, 0, -0.707)
соответственно. Таким образом, вектор глаза равен (0,0,4) - fragPosition
.
Поскольку матрица модели выполняет только вращение, вершинный шейдер просто преобразует нормаль вершины по матрице модели. (Примечание: это не очень хорошая практика, поскольку многие типы преобразования не сохраняют нормальную ортогональность. Как правило, для нормальной матрицы вы должны использовать обратное транспонирование верхнего левого 3x3 матрицы модели.) Чтобы сохранить Все просто: фрагментный шейдер работает с одним плавающим цветовым каналом и пропускает показатель степени отражения (/ использует показатель степени, равный 1).
Вершинный шейдер:
#version 140
uniform mat4 mvpMtx;
uniform mat4 modelMtx;
in vec3 inVPos;
in vec3 inVNormal;
out vec3 normal_world;
out vec3 fragpos_world;
void main(void) {
gl_Position = mvpMtx * vec4(inVPos, 1.0);
normal_world = vec3(modelMtx * vec4(inVNormal, 0.0));
fragpos_world = vec3(modelMtx * vec4(inVPos, 1.0));
}
Фрагментный шейдер:
#version 140
uniform float
uLightS,
uLightD,
uLightA;
uniform float uObjOpacity;
in vec3 normal_world, fragpos_world;
out vec4 fragOutColour;
void main(void) {
vec3 vN = normalize(normal_world);
vec3 vL = vec3(-0.707, 0, -0.707);
// Diffuse:
// refl in all directions is proportional to cos(angle between -light vector & normal)
// i.e. proportional to -l.n
float df = max(dot(-vL, vN), 0.0);
// Specular:
// refl toward eye is proportional to cos(angle between eye & reflected light vectors)
// i.e. proportional to r.e
vec3 vE = normalize(vec3(0, 0, 4) - fragpos_world);
vec3 vR = reflect(vL, vN);
float sf = max(dot(vR, vE), 0.0);
float col = uLightA + df*uLightD + sf*uLightS;
fragOutColour = vec4(col, col, col, uObjOpacity);
}
Я не могу найти здесь ошибку; Кто-нибудь может объяснить, почему зеркальный компонент появляется как на задней, так и на светлой стороне объекта?
Большое спасибо.
NormalMatrix = T (ModelView^-1)
. Это то, чем былgl_NormalMatrix
в старой школе GLSL, но вы можете так же легко вычислить это в своем вершинном шейдере или в другой юниформ-матрице. - person Andon M. Coleman   schedule 18.11.2013