Results 1 to 4 of 4

Thread: Diffuse shading fix not working

  1. #1
    Junior Member Newbie
    Join Date
    May 2015
    Posts
    16

    Diffuse shading fix not working

    I've got diffuse lighting working, but it seems to be stuck in world space. I've looked at a few guides and understand that the reason this is happening is because the model is being lit in world space and then once it's transformed to model space, it keeps the lighting it received from world space. Great demonstration of the problem here.

    To fix this, I'm doing the following (except it's not working):

    Vertex Shader
    Code :
    #version 440 compatibility
    layout(location = 0) in vec3 position;
    layout(location = 1) in vec3 normal;
    layout(location = 2) in float offset;
     
    out vec3 theNormal;
    out vec3 thePosition;
     
    uniform mat4 FullTransformMatrix;
    uniform mat4 ModelToWorldTransformMatrix;
     
    void main() {
     
    	vec4 v = vec4(position, 1.0);
    	gl_Position = FullTransformMatrix * v;
    	theNormal = normal;
    	thePosition = vec3(ModelToWorldTransformMatrix * v);
    }

    Fragment Shader
    Code :
    #version 440 compatibility
    layout(location = 0) out vec4 outColor;
    in vec3 theNormal;
    in vec3 thePosition;
     
    uniform vec3 LightPosition;
     
    void main()
    {
    	vec3 lightVector = normalize(LightPosition - thePosition);
    	float brightness = dot(lightVector, theNormal);
    	outColor = vec4(brightness, brightness, brightness, 1.0);
    }

    Part of the update loop

    Code :
    		glm::mat4 ProjectionMatrix = mainCamera->getProjectionMatrix ();
    		glm::mat4 ViewMatrix = mainCamera->getViewMatrix ();
     
    		// Plane
    		glBindVertexArray ( planeVertexArray );
    		translation = glm::translate ( glm::mat4 ( 1 ), glm::vec3 ( 0.0f, 0.0f, 0.0f ) );
    		ModelMatrix = glm::rotate ( translation, 0.0f, glm::vec3 ( 1.0f, 0.0f, 0.0f ) );
    		mvp = ProjectionMatrix * ViewMatrix * ModelMatrix;
    		glProgramUniformMatrix4fv ( program, modelToWorldMatrixLocation, 1, GL_FALSE, &ModelMatrix[0][0] );
    		glProgramUniformMatrix4fv ( program, fullTransformMatrixLocation, 1, GL_FALSE, &mvp[0][0] );
    		glDrawElements ( GL_TRIANGLES, planeIndices.size (), GL_UNSIGNED_INT, ( void* ) ( planeVertices.size () * sizeof ( GLfloat ) ) );
     
    		glBindVertexArray ( vertexArray );
    		// Object 1
    		translation = glm::translate ( glm::mat4 ( 1 ), glm::vec3 ( 2.0f, 2.0f, -2.0f ) );
    		ModelMatrix = glm::rotate (translation, 180.0f, glm::vec3 ( 0.0, 1.0f, 0.0f ) );
    		mvp = ProjectionMatrix * ViewMatrix * ModelMatrix;
    		glProgramUniformMatrix4fv ( program, fullTransformMatrixLocation, 1, GL_FALSE, &mvp[0][0] );
    		glProgramUniformMatrix4fv ( program, modelToWorldMatrixLocation, 1, GL_FALSE, &ModelMatrix[0][0] );
    		//glDrawElementsInstanced ( GL_TRIANGLES, suzIndices.size (), GL_UNSIGNED_INT, nullptr, 3 );
    		glDrawElements ( GL_TRIANGLES, suzIndices.size (), GL_UNSIGNED_INT, ( void* ) (suzVertices.size() * sizeof(GLfloat)) );
     
    		// Object 2
    		translation = glm::translate ( glm::mat4 ( 1 ), glm::vec3 ( 0.0f, 2.0f, 2.0f ) );
    		ModelMatrix = glm::rotate ( translation, 0.0f, glm::vec3 ( 0.0f, 1.0f, 0.0f ) );
    		mvp = ProjectionMatrix * ViewMatrix * ModelMatrix;
    		glProgramUniformMatrix4fv ( program, fullTransformMatrixLocation, 1, GL_FALSE, &mvp[0][0] );
    		glProgramUniformMatrix4fv ( program, modelToWorldMatrixLocation, 1, GL_FALSE, &ModelMatrix[0][0] );
    		glDrawElements ( GL_TRIANGLES, suzIndices.size (), GL_UNSIGNED_INT, ( void* ) ( suzVertices.size () * sizeof ( GLfloat ) ) );



    What gives?

  2. #2
    Senior Member Regular Contributor uwi2k2's Avatar
    Join Date
    Mar 2011
    Posts
    138
    hi,

    i just took a quik look, but i am very sure you forget to rotate the normals.
    as the normals are relevant for the dotproduct of light, you need to have a matrix that only includes rotation .
    multiply this one with the normals in the vertex shader and you should be fine ...

    cu
    uwi2k2
    uwi2k2 - OpenGL Trainer: www.opengl-trainer.com
    ---------------------------------------------------------
    The OpenGL and VULKAN Podcast ( OpenGL2GO ) : OpenGL & Vulkan Podcast
    ---------------------------------------------------------
    timbling.com - Indie TeamUp

  3. #3
    Junior Member Newbie
    Join Date
    May 2015
    Posts
    16
    Hm. Only rotation? I'm putting both translation and rotation (and in the future, scale) into the model matrix.

    Code :
    translation = glm::translate ( glm::mat4 ( 1 ), glm::vec3 ( 0.0f, 0.0f, 0.0f ) );
    ModelMatrix = glm::rotate ( translation, 0.0f, glm::vec3 ( 1.0f, 0.0f, 0.0f ) );

    In the vertex Shader, ModelMatrix is called ModelToWorldTransformMatrix. I multiple the position by it. I don't see any diffuse shading examples where the normals are multiplied by a rotation matrix. This is essential what my shaders are (just different variable names and out of order): https://www.opengl.org/sdk/docs/tuto...s/lighting.php

    EDIT: All is good... had to get farther in that tutorial series... derp. Rotation wasn't being factored in. So, you were right.

  4. #4
    Senior Member OpenGL Guru
    Join Date
    Jun 2013
    Posts
    3,100
    Quote Originally Posted by Stradigos View Post
    Hm. Only rotation? I'm putting both translation and rotation (and in the future, scale) into the model matrix.
    You need to ensure that any translation doesn't affect the normal.

    You can either extract the upper-left 3x3 submatrix and transform the normals by that, or convert the normal from vec3 to vec4 with zero as the w component (meaning that the values in the right-hand column of the matrix will always be multiplied by zero, resulting in them having no effect upon the transformed normal).

    One other caveat: if the matrix isn't orthogonal (e.g. if it includes non-uniform scaling), then the normals must be transformed by the inverse of the transpose of the matrix. If the matrix is orthogonal, then the inverse and the transpose are the same except for a uniform scaling factor, so you can just use the original matrix (so long as the normals are scaled correctly).

    To see why this is required, consider "squashing" a shape vertically. The slope of each face will become closer to horizontal, meaning that its normal will become closer to vertical.

Similar Threads

  1. Diffuse lighting working per-vertex but not per-pixel
    By WizardOfUs in forum OpenGL: Basic Coding
    Replies: 3
    Last Post: 11-04-2015, 09:28 PM
  2. Shading not working when texture used
    By JMENON in forum OpenGL: Basic Coding
    Replies: 2
    Last Post: 08-20-2010, 06:10 PM
  3. simple shading/diffuse/specular
    By true_atlantis in forum OpenGL: Basic Coding
    Replies: 1
    Last Post: 10-18-2005, 03:54 AM
  4. Diffuse shading / Bug
    By in forum OpenGL: Linux
    Replies: 2
    Last Post: 07-12-2003, 05:44 AM
  5. Smooth shading not working correctly
    By in forum OpenGL: Basic Coding
    Replies: 4
    Last Post: 11-02-2002, 05:41 PM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Proudly hosted by Digital Ocean