I am pretty newbie to GLSL and I have been struggling with trying to find a way to color the face of my rotating cube red. I have achieved drawing red on one of the faces getting the normal x but my objective is to make the cube draw a red face to whatever face is facing front to the camera.
Fragment Shader
#version 330
in vec3 normal;
out vec4 fragColor;
in vec4 color;
in vec4 vertexColor;
void main() {
vec3 nor = normalize(normal);
fragColor = vec4(nor.x, 0.0, 0.0, 1.0);
}
Vertex Shader
#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;
out vec4 fragColor;
out vec4 vertexColor;
out vec4 color;
void main()
{
normal = a_normal;
gl_Position = u_vp_matrix * u_m_matrix * vec4(a_position, 1.0);
}
I tried messing with the dot product with normals and the direction at which the camera is looking (0, 0, 1) but I have not achieved anything yet.
This would be the desired effect:
I do in fact think it involves some mathematics ( dot product ), maybe getting the cosTetha and seeing if the vector is completdly perpendicular or not and depending on that drawing the faces red or black?
I view space, the z axis points out of the view port. When a side of the cube faces the camera, then the normal vector in view space is (0, 0, 1). The red color can be get form the z component of the normal vector.
But the normal vector has to be transformed from modle space to view space (in the vertex shader). For that you have to know the view matrix:
mat3 normalMat = inverse(transpose(mat3(u_v_matrix * u_m_matrix)));
normal = normalMat * a_normal;
In the fragment shader, the red color channel can be get from the z component:
vec3 nor = normalize(normal);
fragColor = vec4(nor.z, 0.0, 0.0, 1.0);
You can approximate a normal vector in normalized device space, by transforming with mat3(u_vp_matrix * u_m_matrix)
. That's inaccurate, but it tints the faces dependent on its orientation, too. In normalized device space, the z axis points into the viewport. e.g:
Vertex shader:
#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);
}
Fragment shader:
#version 330
in vec3 normal;
out vec4 fragColor;
void main() {
vec3 nor = normalize(normal);
fragColor = vec4(-nor.z, 0.0, 0.0, 1.0);
}
If you just want to color the face which that faces the camera, then you have to compare the cosine of the angle between the normal vector of the face and the view space z axis by the cosine of 45°. step
compares a value to a edge and returns 0.0 or 1.0, dependent on the result:
Vertex shader:
mat3 normalMat = inverse(transpose(mat3(u_v_matrix * u_m_matrix)));
normal = normalMat * a_normal;
Fragment shader:
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);