Зеркальное освещение появляется как на обращенной к глазам, так и на задней стороне объекта.

StackOverflow https://stackoverflow.com//questions/20008089

Вопрос

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

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

Насколько я понимаю, зеркальный компонент пропорционален углу между вектором глаза и вектором отраженного света.

Для простоты мой тестовый код пытается сделать это в мировом пространстве.Положение камеры и вектор света жестко закодированы (извините), как (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);

}

Я не могу найти здесь ошибку;Может ли кто-нибудь объяснить, почему зеркальный компонент появляется как сзади, так и на светлой стороне объекта?

Большое спасибо.

Это было полезно?

Решение

Ваш зеркальный вклад на самом деле будет одинаковым для передней и задней сторон, потому что GLSL reflect нечувствителен к знаку нормальности.От эта ссылка:

reflect(I, N) = I - 2.0 * dot(N, I) * N

поэтому изменение знака N приводит к появлению двух знаков минус, которые отменяются.На словах, что reflect заключается в изменении знака компонента I который находится вдоль той же оси, что и N.Это не зависит от того, в какую сторону N сталкивается.

Если вы хотите удалить зеркальный компонент с задних граней, я думаю, вам нужно будет явно проверить dot(vE,vN).

Другие советы

Попробуйте изменение

fragpos_world = vec3(modelMtx * vec4(inVPos, 0.0)); 
.

к

fragpos_world = vec3(modelMtx * vec4(inVPos, 1.0)); 
.

Потому что http://www.Opengl-tuterial.Орг / начинающие-учебники / Учебники-3-матрицы / # Homogeneous_Coordinates

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top