Part of the Khronos Group
OpenGL.org

The Industry's Foundation for High Performance Graphics

from games to virtual reality, mobile phones to supercomputers

Results 1 to 4 of 4

Thread: Specular problem

  1. #1
    Junior Member Newbie
    Join Date
    Oct 2017
    Posts
    3

    Specular problem

    Greetings, fellow humans.

    I'm having a problem getting proper specular shading in my openGL 3.3 core application (using glfw, and GLAD, on win7 64, AMD Radeon HD 6570, v. 15.200.1062.1004). As you can see here (https://imgur.com/4QNuiiZ), no matter the viewing angle, the entire cube is uniformly covered in specular highlights. I've combed through the code over and over, and I simply cannot find where I'm going wrong. This is all from a tutorial found at https://learnopengl.com/#!Lighting/Lighting-maps.

    Here is the main class:

    Code :
     
     int main()
    {
     
    	glfwInit();
    	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
     
    	GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "Yabba-dabba-doooooo!", NULL, NULL);
    	if(window == NULL)
    	{
    		std::cout << "Failed to create window. Stopping program.";
     
    		glfwTerminate();
    		return -1;
    	}
     
    	glfwMakeContextCurrent(window);
    	glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);  
    	glfwSetCursorPosCallback(window, mouse_callback);
    	glfwSetScrollCallback(window, scroll_callback);
    	  //mine
    	 glfwSetMouseButtonCallback(window, mouse_button_callback);
     
    	 // tell GLFW to capture our mouse
        glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);//GLFW_CURSOR_DISABLED
     
    	if(!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
    	{
    		std::cout << "Failed to initialize GLAD";
    	}  
     
    	 glEnable(GL_DEPTH_TEST);
     
    	Shader lightingShader(vertDmapDirectory, fragDmapDirectory);
    	Shader lampShader(vertLightDirectory, fragLightDirectory);
     
     
    float vertices[] = {
        // positions          // normals           // texture coords
        -0.5f, -0.5f, -0.5f,  0.0f,  0.0f, -1.0f,  0.0f, 0.0f,
         0.5f, -0.5f, -0.5f,  0.0f,  0.0f, -1.0f,  1.0f, 0.0f,
         0.5f,  0.5f, -0.5f,  0.0f,  0.0f, -1.0f,  1.0f, 1.0f,
         0.5f,  0.5f, -0.5f,  0.0f,  0.0f, -1.0f,  1.0f, 1.0f,
        -0.5f,  0.5f, -0.5f,  0.0f,  0.0f, -1.0f,  0.0f, 1.0f,
        -0.5f, -0.5f, -0.5f,  0.0f,  0.0f, -1.0f,  0.0f, 0.0f,
     
        -0.5f, -0.5f,  0.5f,  0.0f,  0.0f, 1.0f,   0.0f, 0.0f,
         0.5f, -0.5f,  0.5f,  0.0f,  0.0f, 1.0f,   1.0f, 0.0f,
         0.5f,  0.5f,  0.5f,  0.0f,  0.0f, 1.0f,   1.0f, 1.0f,
         0.5f,  0.5f,  0.5f,  0.0f,  0.0f, 1.0f,   1.0f, 1.0f,
        -0.5f,  0.5f,  0.5f,  0.0f,  0.0f, 1.0f,   0.0f, 1.0f,
        -0.5f, -0.5f,  0.5f,  0.0f,  0.0f, 1.0f,   0.0f, 0.0f,
     
        -0.5f,  0.5f,  0.5f, -1.0f,  0.0f,  0.0f,  1.0f, 0.0f,
        -0.5f,  0.5f, -0.5f, -1.0f,  0.0f,  0.0f,  1.0f, 1.0f,
        -0.5f, -0.5f, -0.5f, -1.0f,  0.0f,  0.0f,  0.0f, 1.0f,
        -0.5f, -0.5f, -0.5f, -1.0f,  0.0f,  0.0f,  0.0f, 1.0f,
        -0.5f, -0.5f,  0.5f, -1.0f,  0.0f,  0.0f,  0.0f, 0.0f,
        -0.5f,  0.5f,  0.5f, -1.0f,  0.0f,  0.0f,  1.0f, 0.0f,
     
         0.5f,  0.5f,  0.5f,  1.0f,  0.0f,  0.0f,  1.0f, 0.0f,
         0.5f,  0.5f, -0.5f,  1.0f,  0.0f,  0.0f,  1.0f, 1.0f,
         0.5f, -0.5f, -0.5f,  1.0f,  0.0f,  0.0f,  0.0f, 1.0f,
         0.5f, -0.5f, -0.5f,  1.0f,  0.0f,  0.0f,  0.0f, 1.0f,
         0.5f, -0.5f,  0.5f,  1.0f,  0.0f,  0.0f,  0.0f, 0.0f,
         0.5f,  0.5f,  0.5f,  1.0f,  0.0f,  0.0f,  1.0f, 0.0f,
     
        -0.5f, -0.5f, -0.5f,  0.0f, -1.0f,  0.0f,  0.0f, 1.0f,
         0.5f, -0.5f, -0.5f,  0.0f, -1.0f,  0.0f,  1.0f, 1.0f,
         0.5f, -0.5f,  0.5f,  0.0f, -1.0f,  0.0f,  1.0f, 0.0f,
         0.5f, -0.5f,  0.5f,  0.0f, -1.0f,  0.0f,  1.0f, 0.0f,
        -0.5f, -0.5f,  0.5f,  0.0f, -1.0f,  0.0f,  0.0f, 0.0f,
        -0.5f, -0.5f, -0.5f,  0.0f, -1.0f,  0.0f,  0.0f, 1.0f,
     
        -0.5f,  0.5f, -0.5f,  0.0f,  1.0f,  0.0f,  0.0f, 1.0f,
         0.5f,  0.5f, -0.5f,  0.0f,  1.0f,  0.0f,  1.0f, 1.0f,
         0.5f,  0.5f,  0.5f,  0.0f,  1.0f,  0.0f,  1.0f, 0.0f,
         0.5f,  0.5f,  0.5f,  0.0f,  1.0f,  0.0f,  1.0f, 0.0f,
        -0.5f,  0.5f,  0.5f,  0.0f,  1.0f,  0.0f,  0.0f, 0.0f,
        -0.5f,  0.5f, -0.5f,  0.0f,  1.0f,  0.0f,  0.0f, 1.0f
    };
     
     // first, configure the cube's VAO (and VBO)
        unsigned int VBO, cubeVAO;
        glGenVertexArrays(1, &cubeVAO);
        glGenBuffers(1, &VBO);
     
        glBindBuffer(GL_ARRAY_BUFFER, VBO);
        glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
     
        glBindVertexArray(cubeVAO);
     
     
        // position attribute
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);
        glEnableVertexAttribArray(0);
        // normal attribute
        glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float)));
        glEnableVertexAttribArray(1);
    	//texture attribute
    	glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float)));
    	glEnableVertexAttribArray(2);
     
     
     
    	 // second, configure the light's VAO (VBO stays the same; the vertices are the same for the light object which is also a 3D cube)
        unsigned int lightVAO;
        glGenVertexArrays(1, &lightVAO);
        glBindVertexArray(lightVAO);
     
        glBindBuffer(GL_ARRAY_BUFFER, VBO);
        // note that we update the lamp's position attribute's stride to reflect the updated buffer data
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);
        glEnableVertexAttribArray(0);
     
     
    	//load texture 
    	unsigned int diffuseMap = loadTexture(containerImagePath);
     
    	// shader configuration
        // --------------------
        lightingShader.use(); 
        lightingShader.setInt("material.diffuse", 0);
     
     
     
    	while(!glfwWindowShouldClose(window)) //this is the render loop, which also handles user input
    	{
     
    		float currentFrame = glfwGetTime();
    		deltaTime = currentFrame - lastFrame;
    		lastFrame = currentFrame;  
     
    	  // input
            // -----
            processInput(window);
     
            // render
            // ------
            glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
            glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // also clear the depth buffer now!
     
     
    	 // be sure to activate shader when setting uniforms/drawing objects
            lightingShader.use();
            lightingShader.setVec3("light.position", lightPos);
            lightingShader.setVec3("viewPos", camera.Position);
     
     
            // light properties
    		lightingShader.setVec3("light.ambient", glm::vec3(0.2f, 0.2f, 0.2f)); 
    		lightingShader.setVec3("light.diffuse", glm::vec3(0.5f, 0.5f, 0.5f));
    		lightingShader.setVec3("light.specular", glm::vec3( 1.0f, 1.0f, 1.0f));
     
            // material properties
    		lightingShader.setVec3("material.specular", glm::vec3(0.5f, 0.5f, 0.5f));
            lightingShader.setFloat("material.shininess", 32.0f);
     
    		//attempts to fix the whiteness
    		lightingShader.setVec3("material.objectColor", glm::vec3(1.0f, 1.0f, 1.0f));
    		//failure, but interesting in that it allows for further color customization
     
            // view/projection transformations
            glm::mat4 projection = glm::perspective(glm::radians(camera.Zoom), (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f);
            glm::mat4 view = camera.GetViewMatrix();
            lightingShader.setMat4("projection", projection);
            lightingShader.setMat4("view", view);
     
            // world transformation
            glm::mat4 model;
            lightingShader.setMat4("model", model);
     
    		// bind diffuse map
            glActiveTexture(GL_TEXTURE0);
            glBindTexture(GL_TEXTURE_2D, diffuseMap);
     
            // render the cube
            glBindVertexArray(cubeVAO);
            glDrawArrays(GL_TRIANGLES, 0, 36);
     
    		 // also draw the lamp object
            lampShader.use();
            lampShader.setMat4("projection", projection);
            lampShader.setMat4("view", view);
     
            model = glm::mat4();
            model = glm::translate(model, lightPos);
            model = glm::scale(model, glm::vec3(0.2f)); // a smaller cube
            lampShader.setMat4("model", model);
     
            glBindVertexArray(lightVAO);
            glDrawArrays(GL_TRIANGLES, 0, 36);
     
     
            // glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.)
            // -------------------------------------------------------------------------------
            glfwSwapBuffers(window);
            glfwPollEvents();
    	}
     
    	glDeleteVertexArrays(1, &cubeVAO);
        glDeleteVertexArrays(1, &lightVAO);
        glDeleteBuffers(1, &VBO);
     
        // glfw: terminate, clearing all previously allocated GLFW resources.
        // ------------------------------------------------------------------
        glfwTerminate();
        return 0;
    }
     
     
     void mouse_callback(GLFWwindow* window, double xpos, double ypos)
    {
     
        if(firstMouse)
        {
            lastX = xpos;
            lastY = ypos;
            firstMouse = false;
        }
     
    	if(leftClick != true)
    	{
    		 lastX = xpos;
            lastY = ypos;
    		//return;
     
    	}
     
        float xoffset = xpos - lastX;
        float yoffset = lastY - ypos; 
        lastX = xpos;
        lastY = ypos;
     
       camera.ProcessMouseMovement(xoffset, yoffset);
    }
     void mouse_button_callback(GLFWwindow* window, int button, int action, int mods)
    {
    	//GLFW_RELEASE.
    	if (button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_PRESS)
    	{
    		leftClick = true;
    		camera.leftClick = true;
    	//	std::cout << "left clicked." << std::endl;
    	}
    	else if (button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_RELEASE)
    	{
    		leftClick = false;
    		camera.leftClick = false;
    	}
           // popup_menu();
    }


    Here is the vertex shader code in glsl:

    Code :
    #version 330 core
    layout (location = 0) in vec3 aPos;
    layout (location = 1) in vec3 aNormal;
    layout (location = 2) in vec2 aTexCoords;
     
    out vec3 FragPos;
    out vec3 Normal;
    out vec2 TexCoords;
     
    uniform mat4 model;
    uniform mat4 view;
    uniform mat4 projection;
     
    void main()
    {
        FragPos = vec3(model * vec4(aPos, 1.0));
        Normal = mat3(transpose(inverse(model))) * aNormal;  
        TexCoords = aTexCoords;
     
        gl_Position = projection * view * vec4(FragPos, 1.0);
    }

    And here is the fragment shader:

    Code :
    #version 330 core
    out vec4 FragColor;
     
    struct Material {
        sampler2D diffuse;
        vec3 specular;    
        float shininess;
        vec3 objectColor;//experimental
    }; 
     
    struct Light {
        vec3 position;
     
        vec3 ambient;
        vec3 diffuse;
        vec3 specular;
    };
     
    in vec3 FragPos;  
    in vec3 Normal;  
    in vec2 TexCoords;
     
    uniform vec3 viewPos;
    uniform Material material;
    uniform Light light;
     
    void main()
    {
        // ambient
        vec3 ambient = light.ambient * texture(material.diffuse, TexCoords).rgb;
     
        // diffuse 
        vec3 norm = normalize(Normal);
        vec3 lightDir = normalize(light.position - FragPos);
        float diff = max(dot(norm, lightDir), 0.0);
        vec3 diffuse = light.diffuse * diff * texture(material.diffuse, TexCoords).rgb;  
     
        // specular
        vec3 viewDir = normalize(viewPos - FragPos);
        vec3 reflectDir = reflect(-lightDir, norm);  
        float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
        vec3 specular = light.specular * (spec * material.specular);  //light.specular * (spec * material.specular);  
     
        vec3 result = (ambient + diffuse + specular) * material.objectColor; //vec3 result = ambient + diffuse + specular;
        FragColor = vec4(result, 1.0);
    }

    This compromises the bulk of the code I'm using, although as you can see, there is a camera and shader header as well. Thanks in advance for those willing to wade through.

  2. #2
    Member Regular Contributor
    Join Date
    Jul 2012
    Posts
    425
    Code :
    lightingShader.setVec3("viewPos", camera.Position);

    Is camera.Position in the same space than the calculations done in your fragment shader ?

  3. #3
    Junior Member Newbie
    Join Date
    Oct 2017
    Posts
    3
    Quote Originally Posted by Silence View Post
    Code :
    lightingShader.setVec3("viewPos", camera.Position);

    Is camera.Position in the same space than the calculations done in your fragment shader ?


    Yes, it is. In the fragment shader....

    Code :
    ...
    uniform vec3 viewPos;
    ...
     vec3 viewDir = normalize(viewPos - FragPos);
    ...

    ...is used to derive a bunch of other values.


    There's two functions that set the viewing angle and position of the camera.

    Code :
    void processInput(GLFWwindow *window)
    {
    	if(glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
    	{
    		 glfwSetWindowShouldClose(window, true);
    	}
     
    	if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS)
            camera.ProcessKeyboard(FORWARD, deltaTime);
        if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS)
            camera.ProcessKeyboard(BACKWARD, deltaTime);
        if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS)
            camera.ProcessKeyboard(LEFT, deltaTime);
        if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS)
            camera.ProcessKeyboard(RIGHT, deltaTime);
    }
     void mouse_callback(GLFWwindow* window, double xpos, double ypos)
    {
    	if(leftClick != true)
    	{
    		 lastX = xpos;
            lastY = ypos;
    	}
     
        float xoffset = xpos - lastX;
        float yoffset = lastY - ypos; 
        lastX = xpos;
        lastY = ypos;
     
       camera.ProcessMouseMovement(xoffset, yoffset);
    }

    Then, in the camera header...

    Code :
       void ProcessKeyboard(Camera_Movement direction, float deltaTime)
        {
            float velocity = MovementSpeed * deltaTime;
            if (direction == FORWARD)
                Position += Front * velocity;
            if (direction == BACKWARD)
                Position -= Front * velocity;
            if (direction == LEFT)
                Position -= Right * velocity;
            if (direction == RIGHT)
                Position += Right * velocity;
        }
     
        // Processes input received from a mouse input system. Expects the offset value in both the x and y direction.
        void ProcessMouseMovement(float xoffset, float yoffset, GLboolean constrainPitch = true)
        {
    		if(leftClick == true)
    		{
    			xoffset *= MouseSensitivity;
    			 yoffset *= MouseSensitivity;
     
    			Yaw   += xoffset;
    			Pitch += yoffset;
    		}
     
            // Make sure that when pitch is out of bounds, screen doesn't get flipped
            if (constrainPitch)
            {
                if (Pitch > 89.0f)
                    Pitch = 89.0f;
                if (Pitch < -89.0f)
                    Pitch = -89.0f;
            }
     
            // Update Front, Right and Up Vectors using the updated Eular angles
            updateCameraVectors();
        }



    In the main loop, we tell the camera to set it's view matrix.

    Code :
    ...
     glm::mat4 view = camera.GetViewMatrix();
    ...


    Then, the camera returns the view matrix.

    Code :
     // Returns the view matrix calculated using Eular Angles and the LookAt Matrix
        glm::mat4 GetViewMatrix()
        {
            return glm::lookAt(Position, Position + Front, Up);
        }

  4. #4
    Junior Member Newbie
    Join Date
    Oct 2017
    Posts
    3
    Alright, I got it working. What was the problem? I never actually found it. Instead, I simply created a new project and followed the tutorial to a 't.' My guess is that it had to do with the camera, but the world will never know.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •