Я смотрю пространство, ось z указывает на порт просмотра. Когда сторона куба обращена к камере, вектор нормали в пространстве вида равен (0, 0, 1). Красный цвет может быть получен из z-компонента вектора нормалей.
Но вектор нормалей должен быть преобразован из пространства модели в пространство просмотра (в вершинном шейдере). Для этого вам нужно знать матрицу вида:
mat3 normalMat = inverse(transpose(mat3(u_v_matrix * u_m_matrix)));
normal = normalMat * a_normal;
В фрагментном шейдере канал красного цвета можно получить из компонента z:
vec3 nor = normalize(normal);
fragColor = vec4(nor.z, 0.0, 0.0, 1.0);
Вы можете аппроксимируйте нормальный вектор в нормализованном пространстве устройства, преобразовав mat3(u_vp_matrix * u_m_matrix)
. Это неточно, но оно также окрашивает грани в зависимости от его ориентации. В нормализованном пространстве устройства ось z указывает на область просмотра. Например:
Вершинный шейдер:
#version 330
uniform mat4 u_m_matrix;
uniform mat4 u_vp_matrix;
layout (location=0) in vec3 a_position;
layout (location=1) in vec3 a_normal;
out vec3 normal;
void main()
{
normal = mat3(u_vp_matrix * u_m_matrix) * a_normal;
gl_Position = u_vp_matrix * u_m_matrix * vec4(a_position, 1.0);
}
Фрагментный шейдер:
#version 330
in vec3 normal;
out vec4 fragColor;
void main() {
vec3 nor = normalize(normal);
fragColor = vec4(-nor.z, 0.0, 0.0, 1.0);
}
Если вы просто хотите закрасить грань, которая обращена к камере, то вы должны сравнить косинус угла между вектором нормали к лицу и осью пространства z по косинусу 45 °. step
сравнивает значение с ребром и возвращает 0.0 или 1.0, в зависимости от результата:
Вершинный шейдер:
mat3 normalMat = inverse(transpose(mat3(u_v_matrix * u_m_matrix)));
normal = normalMat * a_normal;
Фрагментный шейдер:
vec3 nor = normalize(normal);
//float red = step(0.707, abs(dot(nor, vec3(0.0, 0.0, 1.0))));
float red = step(0.707, dot(nor, vec3(0.0, 0.0, 1.0)));
fragColor = vec4(red, 0.0, 0.0, 1.0);