Jump to content
  • Advertisement
Sign in to follow this  
taby

Lighting Shaders

This topic is 1066 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi, I downloaded these shaders a few weeks ago, but I lost the URL where I got them from. Can anyone discern which shading model is used in the fragment shader, and what the following lines from the vertex shader do (switching from one space to another, I imagine):

 

transformed_frag_position = vec3(view_matrix * vec4(position, 1.0f));
transformed_normal = mat3(transpose(inverse(view_matrix))) * normal; 

 

 

Full vertex shader:

#version 410 core
layout (location = 0) in vec3 position;
layout (location = 1) in vec3 normal;
 
out vec3 transformed_frag_position;
out vec3 transformed_normal;
 
uniform mat4 model_matrix;
uniform mat4 view_matrix;
uniform mat4 projection_matrix;
 
void main()
{
gl_Position = projection_matrix * view_matrix * model_matrix * vec4(position, 1.0f);
transformed_frag_position = vec3(view_matrix * vec4(position, 1.0f));
transformed_normal = mat3(transpose(inverse(view_matrix))) * normal;  
} 

 

 

Full fragment shader:

#version 410 core
 
out vec4 color;
 
in vec3 transformed_frag_position;  
in vec3 transformed_normal;  
  
uniform vec3 light_position; 
uniform vec3 view_position;
uniform vec3 light_colour;
uniform vec3 object_colour;
 
void main()
{
    // Ambient
float ambient_strength = 0.1f;
    vec3 ambient = ambient_strength * light_colour;
   
    // Diffuse 
    vec3 norm = normalize(transformed_normal);
    vec3 light_direction = normalize(light_position - transformed_frag_position);
    float diff = max(dot(norm, light_direction), 0.0);
    vec3 diffuse = diff * light_colour;
    
    // Specular
    float specular_strength = 1.0f;
    vec3 view_direction = normalize(view_position - transformed_frag_position);
    vec3 reflect_direction = reflect(-light_direction, norm);  
    float spec = pow(max(dot(view_direction, reflect_direction), 0.0), 32);
    vec3 specular = specular_strength * spec * light_colour;  
        
    vec3 result = (ambient + diffuse + specular) * object_colour;
    color = vec4(result, 1.0f);
}  

 

Thanks in advance for any help that you can provide.

Share this post


Link to post
Share on other sites
Advertisement

I suggest you to learn how to write shaders,

These two are very basic shaders to calculate the final position of the vertex and the final color of the fragment. 

I could easily tell you what each line means, it would be better if you understand it as well. 

Share this post


Link to post
Share on other sites

I suggest you to learn how to write shaders,

These two are very basic shaders to calculate the final position of the vertex and the final color of the fragment. 

I could easily tell you what each line means, it would be better if you understand it as well. 

 

 

I understand the majority, just not the name of the algorithm. The two lines from the vertex shader are the confusing part for me, not the part where I multiply my matrices and the position to get the vertex's position. The reason they're confusing for me is that the majority of the shaders I've looked at use a normal matrix passed in as a uniform, which these shaders do not do. You'll have to forgive me; the last time I worked with lighting shaders, we used assembly LOL:

   vertex_shader_src = "vs.1.1\n";

    vertex_shader_src += "dcl_position v0\n";
    vertex_shader_src += "dcl_normal v1\n";
    vertex_shader_src += "dcl_color v2\n";

    vertex_shader_src += ";Do the final transformation and emit it in oPos. This\n";
    vertex_shader_src += ";is completely independent of the lighting operations\n";
    vertex_shader_src += "m4x4 oPos, v0, c0\n";

    vertex_shader_src += ";Dot product of light vector with normal vector\n";
    vertex_shader_src += ";and store it in r0.x for use with the lit instruction\n";
    vertex_shader_src += "dp3 r0.x, v1, -c4\n";

    vertex_shader_src += ";Compute the Vector from eye to vertex in object space\n";
    vertex_shader_src += ";and store the vector in r1\n";
    vertex_shader_src += "sub r1, c5, v0\n";

    vertex_shader_src += ";Normalize the eye vector\n";
    vertex_shader_src += "dp3 r1.w, r1, r1\n";
    vertex_shader_src += "rsq r1.w, r1.w\n";
    vertex_shader_src += "mul r1, r1, r1.w\n";

    vertex_shader_src += ";Compute half angle between the eye vector and the light\n";
    vertex_shader_src += ";vector. The result in stored in r2\n";
    vertex_shader_src += "add r2, r1, -c4\n";
    vertex_shader_src += "dp3 r2.w, r2, r2\n";
    vertex_shader_src += "rsq r2.w, r2.w\n";
    vertex_shader_src += "mul r2, r2, r2.w\n";

    vertex_shader_src += ";Find N dot H and store the result in r0.y\n";
    vertex_shader_src += "dp3 r0.y, r2, v1\n";

    vertex_shader_src += ";Place the power in r0.w\n";
    vertex_shader_src += "mov r0.w, c6.w\n";

    vertex_shader_src += ";Find the final diffuse and specular intensities\n";
    vertex_shader_src += "lit r4, r0\n";

    vertex_shader_src += ";Compute the specular light value\n";
    vertex_shader_src += "mul r5, r4.z, c6\n";

    vertex_shader_src += ";Compute the diffuse light value and add the ambient light\n";
    vertex_shader_src += "mul r6, r4.y, c7\n";
    vertex_shader_src += "mad r6, r6, v2, c8\n";

//    vertex_shader_src += ";Add the specular component and output the final color\n";
//    vertex_shader_src += "add oD0, r5, r6\n";

//    vertex_shader_src += ";Add the specular component and output the final color, with gamma adjustment\n";
    vertex_shader_src += "add r5, r5, r6\n";
    vertex_shader_src += "mad oD0, r5, c11.yyyy, c11.xxxx\n";

    // transparency
    vertex_shader_src += "mov oD0.w, c10.xxxx\n";    
Edited by taby

Share this post


Link to post
Share on other sites

This is an implementation of a really basic Phong (note: not Blinn-Phong!) lighting model.

 

These two lines are the important ones:

vec3 reflect_direction = reflect(-light_direction, norm);  
float spec = pow(max(dot(view_direction, reflect_direction), 0.0), 32);

This calculates the surface reflection vector and calculates the phong specular term by doing f_spec = pow(R.V, phong_exponent)

 

Those vertex shader lines calculate a view-space position and a view-space normal vector. If you're confused about the inverse transposed view matrix, there's plenty of explanations on the math behind it and why it's required available on google :)

Edited by Radikalizm

Share this post


Link to post
Share on other sites

This is an implementation of a really basic Phong (note: not Blinn-Phong!) lighting model.

 

These two lines are the important ones:

vec3 reflect_direction = reflect(-light_direction, norm);  
float spec = pow(max(dot(view_direction, reflect_direction), 0.0), 32);

This calculates the surface reflection vector and calculates the phong specular term by doing f_spec = pow(R.V, phong_exponent)

 

Those vertex shader lines calculate a view-space position and a view-space normal vector. If you're confused about the inverse transposed view matrix, there's plenty of explanations on the math behind it and why it's required available on google smile.png

 

Thank you, those space-based examples are what I was looking for!

 

It looks like the normal matrix is the inverse transpose of the 3x3 version of the model view matrix (view matrix in my code because the model matrix is the identity matrix). Thanks for the help.

 

Is there any way to tell if the compiler is optimizing those inverse transpose calls so that it is called once per draw call instead of once per vertex?

Edited by taby

Share this post


Link to post
Share on other sites

Is there any way to tell if the compiler is optimizing those inverse transpose calls so that it is called once per draw call instead of once per vertex?

Yes: do that optimization yourself - then you can be sure that it's been done smile.png
I would slap any graphics programmer that used the inverse or determinant functions (or any other expensive transformation of constant data) inside a shader. That's a terrible habit to get into!

Share this post


Link to post
Share on other sites

Done... (time to brush up on my linear algebra)

 
 
// http://www.gamedev.net/topic/648190-algorithm-for-4x4-matrix-inverse/?view=findpost&p=5096421
bool invert_4x4_matrix(const float (&in_a)[16], float (&out)[16])
{
    float inv[16], det;
    int i;
    
    inv[0] = in_a[5]  * in_a[10] * in_a[15] -
    in_a[5]  * in_a[11] * in_a[14] -
    in_a[9]  * in_a[6]  * in_a[15] +
    in_a[9]  * in_a[7]  * in_a[14] +
    in_a[13] * in_a[6]  * in_a[11] -
    in_a[13] * in_a[7]  * in_a[10];
    
    inv[4] = -in_a[4]  * in_a[10] * in_a[15] +
    in_a[4]  * in_a[11] * in_a[14] +
    in_a[8]  * in_a[6]  * in_a[15] -
    in_a[8]  * in_a[7]  * in_a[14] -
    in_a[12] * in_a[6]  * in_a[11] +
    in_a[12] * in_a[7]  * in_a[10];
    
    inv[8] = in_a[4]  * in_a[9] * in_a[15] -
    in_a[4]  * in_a[11] * in_a[13] -
    in_a[8]  * in_a[5] * in_a[15] +
    in_a[8]  * in_a[7] * in_a[13] +
    in_a[12] * in_a[5] * in_a[11] -
    in_a[12] * in_a[7] * in_a[9];
    
    inv[12] = -in_a[4]  * in_a[9] * in_a[14] +
    in_a[4]  * in_a[10] * in_a[13] +
    in_a[8]  * in_a[5] * in_a[14] -
    in_a[8]  * in_a[6] * in_a[13] -
    in_a[12] * in_a[5] * in_a[10] +
    in_a[12] * in_a[6] * in_a[9];
    
    inv[1] = -in_a[1]  * in_a[10] * in_a[15] +
    in_a[1]  * in_a[11] * in_a[14] +
    in_a[9]  * in_a[2] * in_a[15] -
    in_a[9]  * in_a[3] * in_a[14] -
    in_a[13] * in_a[2] * in_a[11] +
    in_a[13] * in_a[3] * in_a[10];
    
    inv[5] = in_a[0]  * in_a[10] * in_a[15] -
    in_a[0]  * in_a[11] * in_a[14] -
    in_a[8]  * in_a[2] * in_a[15] +
    in_a[8]  * in_a[3] * in_a[14] +
    in_a[12] * in_a[2] * in_a[11] -
    in_a[12] * in_a[3] * in_a[10];
    
    inv[9] = -in_a[0]  * in_a[9] * in_a[15] +
    in_a[0]  * in_a[11] * in_a[13] +
    in_a[8]  * in_a[1] * in_a[15] -
    in_a[8]  * in_a[3] * in_a[13] -
    in_a[12] * in_a[1] * in_a[11] +
    in_a[12] * in_a[3] * in_a[9];
    
    inv[13] = in_a[0]  * in_a[9] * in_a[14] -
    in_a[0]  * in_a[10] * in_a[13] -
    in_a[8]  * in_a[1] * in_a[14] +
    in_a[8]  * in_a[2] * in_a[13] +
    in_a[12] * in_a[1] * in_a[10] -
    in_a[12] * in_a[2] * in_a[9];
    
    inv[2] = in_a[1]  * in_a[6] * in_a[15] -
    in_a[1]  * in_a[7] * in_a[14] -
    in_a[5]  * in_a[2] * in_a[15] +
    in_a[5]  * in_a[3] * in_a[14] +
    in_a[13] * in_a[2] * in_a[7] -
    in_a[13] * in_a[3] * in_a[6];
    
    inv[6] = -in_a[0]  * in_a[6] * in_a[15] +
    in_a[0]  * in_a[7] * in_a[14] +
    in_a[4]  * in_a[2] * in_a[15] -
    in_a[4]  * in_a[3] * in_a[14] -
    in_a[12] * in_a[2] * in_a[7] +
    in_a[12] * in_a[3] * in_a[6];
    
    inv[10] = in_a[0]  * in_a[5] * in_a[15] -
    in_a[0]  * in_a[7] * in_a[13] -
    in_a[4]  * in_a[1] * in_a[15] +
    in_a[4]  * in_a[3] * in_a[13] +
    in_a[12] * in_a[1] * in_a[7] -
    in_a[12] * in_a[3] * in_a[5];
    
    inv[14] = -in_a[0]  * in_a[5] * in_a[14] +
    in_a[0]  * in_a[6] * in_a[13] +
    in_a[4]  * in_a[1] * in_a[14] -
    in_a[4]  * in_a[2] * in_a[13] -
    in_a[12] * in_a[1] * in_a[6] +
    in_a[12] * in_a[2] * in_a[5];
    
    inv[3] = -in_a[1] * in_a[6] * in_a[11] +
    in_a[1] * in_a[7] * in_a[10] +
    in_a[5] * in_a[2] * in_a[11] -
    in_a[5] * in_a[3] * in_a[10] -
    in_a[9] * in_a[2] * in_a[7] +
    in_a[9] * in_a[3] * in_a[6];
    
    inv[7] = in_a[0] * in_a[6] * in_a[11] -
    in_a[0] * in_a[7] * in_a[10] -
    in_a[4] * in_a[2] * in_a[11] +
    in_a[4] * in_a[3] * in_a[10] +
    in_a[8] * in_a[2] * in_a[7] -
    in_a[8] * in_a[3] * in_a[6];
    
    inv[11] = -in_a[0] * in_a[5] * in_a[11] +
    in_a[0] * in_a[7] * in_a[9] +
    in_a[4] * in_a[1] * in_a[11] -
    in_a[4] * in_a[3] * in_a[9] -
    in_a[8] * in_a[1] * in_a[7] +
    in_a[8] * in_a[3] * in_a[5];
    
    inv[15] = in_a[0] * in_a[5] * in_a[10] -
    in_a[0] * in_a[6] * in_a[9] -
    in_a[4] * in_a[1] * in_a[10] +
    in_a[4] * in_a[2] * in_a[9] +
    in_a[8] * in_a[1] * in_a[6] -
    in_a[8] * in_a[2] * in_a[5];
    
    det = in_a[0] * inv[0] + in_a[1] * inv[4] + in_a[2] * inv[8] + in_a[3] * inv[12];
    
    if (det == 0)
        return false;
    
    det = 1.0f / det;
    
    for (i = 0; i < 16; i++)
        out[i] = inv[i] * det;
    
    return true;
}
 
 // http://stackoverflow.com/questions/24816728/fastest-way-to-transpose-4x4-byte-matrix
bool transpose_4x4_matrix(const float (&in_a)[16], float (&out)[16])
{
    // A B C D    A E I M
    // E F G H    B F J N
    // I J K L    C G K O
    // M N O P    D H L P
 
    float temp[16];
    
    temp[0]  = in_a[0];  // A . . .
    temp[1]  = in_a[4];  // A E . .
    temp[2]  = in_a[8];  // A E I .
    temp[3]  = in_a[12]; // A E I M
    temp[4]  = in_a[1];  // B . . .
    temp[5]  = in_a[5];  // B F . .
    temp[6]  = in_a[9];  // B F J .
    temp[7]  = in_a[13]; // B F J N
    temp[8]  = in_a[2];  // C . . .
    temp[9]  = in_a[6];  // C G . .
    temp[10] = in_a[10]; // C G K .
    temp[11] = in_a[14]; // C G K O
    temp[12] = in_a[3];  // D . . .
    temp[13] = in_a[7];  // D H . .
    temp[14] = in_a[11]; // D H L .
    temp[15] = in_a[15]; // D H L P
    
    for(size_t i = 0; i < 16; i++)
        out[i] = temp[i];
}
Edited by taby

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!