问题
I am trying to use lighting on a cube but I don't understand where am going wrong. I can be able to view the light source but the rest of the screen appears black so I don't understand why the cube is disappearing.
Here is the code:
/*Header Inclusions*/
#include <iostream>
#include <GL/Glew.h>
#include <GL/freeglut.h>
// GLM Math inclusions
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include<glm/gtc/type_ptr.hpp>
using namespace std; // Uses the standard namespace
#define WINDOW_TITLE "Modern OpenGL" // Macro for window title
//Vertex and fragment shader
#ifndef GLSL
#define GLSL(Version, source) "#version " #Version "\n" #source
#endif
// Variable declarations for shaders, and window size initialization, buffer and vertex array object
GLint cubeShaderProgram, lampShaderProgram, WindowWidth = 800, WindowHeight = 600;
GLuint VBO, CubeVAO, LightVAO;
// subject position and scale
glm::vec3 cubePosition(0.0f, 0.0f, 0.0f);
glm::vec3 cubeScale(2.0f);
//cube and light color
glm::vec3 objectColor(0.6f, 0.5f, 0.75f);
glm::vec3 lightColor(1.0f, 1.0f, 1.0f);
//light position and scale
glm::vec3 lightPosition(0.5f, 0.5f, -3.0f);
glm::vec3 lightScale(0.3f);
//camera position
glm::vec3 cameraPosition(0.0f, 0.0f, -6.0f);
//camera rotation
float cameraRotation = glm::radians(-25.0f);
/* User-defined Function prototypes to:*/
void UResizeWindow(int,int);
void URenderGraphics(void);
void UCreateShader(void);
void UCreateBuffers(void);
/*Cube Vertex shader source code*/
const GLchar * cubeVertexShaderSource = GLSL(330,
layout (location = 0) in vec3 position;
layout (location = 1) in vec3 normal;
out vec3 Normal; //declare a vec 3 variable
out vec3 FragmentPos;
//Global variables for the transform matrices
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main(){
gl_Position = projection * view * model * vec4(position, 1.0f);//transform vertices
FragmentPos = vec3(model * vec4(position, 1.0f));
Normal = mat3(transpose(inverse(model))) * normal;
}
);
/*Cube Fragment shader program source code*/
const GLchar * cubeFragmentShaderSource = GLSL(330,
in vec3 Normal;
in vec3 FragmentPos;
out vec4 cubeColor;
//uniform variables
uniform vec3 objectColor;
uniform vec3 lightColor;
uniform vec3 lightPos;
uniform vec3 viewPosition;
void main(){
//phong lighting model calculations to generate ambient, diffuse, and specular components
//calculate ambient lighting
float ambientStrength = 0.1f;
vec3 ambient = ambientStrength * lightColor;
//calculater diffuse lighting
vec3 norm = normalize(Normal);
vec3 lightDirection = normalize(lightPos - FragmentPos);
float impact = max(dot(norm, lightDirection), 0.0);
vec3 diffuse = impact * lightColor;
//calculate specular lighting
float specularIntensity = 1.8f;
float highlightSize = 16.0f;
vec3 viewDir = normalize(viewPosition - FragmentPos);
vec3 reflectDir = reflect(-lightDirection, norm);
//calculate specular component
float specularComponent = pow(max(dot(viewDir, reflectDir), 0.0), highlightSize);
vec3 specular = specularIntensity * specularComponent * lightColor;
//calculate phong result
vec3 phong = (ambient + diffue + specular) * objectColor;
cubeColor = vec4(phong, 1.0f);
}
);
/* lamp shader source code*/
const GLchar * lampVertexShaderSource = GLSL(330,
layout (location = 0) in vec3 position;
//Global variables for the transform matrices
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main()
{
gl_Position = projection * view * model * vec4(position, 1.0f);//transform vertices
}
);
/*Fragment Shader Source Code*/
const GLchar * lampFragmentShaderSource = GLSL(330,
out vec4 color;
void main()
{
color = vec4(1.0f);
}
);
//main program
int main(int argc, char* argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowSize(WindowWidth, WindowHeight);
glutCreateWindow(WINDOW_TITLE);
glutReshapeFunc(UResizeWindow);
glewExperimental = GL_TRUE;
if (glewInit()!= GLEW_OK)
{
std::cout << "Failed to initialize GLEW" << std::endl;
return -1;
}
UCreateShader();
UCreateBuffers();
glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Set background color
glutDisplayFunc(URenderGraphics);
glutMainLoop();
// Destroys Buffer objects once used
glDeleteVertexArrays(1, &CubeVAO);
glDeleteVertexArrays(1, &LightVAO);
glDeleteBuffers(1, &VBO);
return 0;
}
/* Resizes the window*/
void UResizeWindow(int w, int h)
{
WindowWidth = w;
WindowHeight = h;
glViewport(0, 0, WindowWidth, WindowHeight);
}
/* Renders graphics */
void URenderGraphics(void)
{
glEnable(GL_DEPTH_TEST); // Enable z-depth
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clears the screen
GLint modelLoc, viewLoc, projLoc, objectColorLoc, lightColorLoc, lightPositionLoc, viewPositionLoc;
glm::mat4 model;
glm::mat4 view;
glm::mat4 projection;
//use cube shader and activate cube VAO
glUseProgram(cubeShaderProgram);
glBindVertexArray(CubeVAO);
//transform the cube
model = glm::translate(model, cameraPosition);
model = glm::scale(model, cubeScale);
// Transforms the camera
view = glm::translate(view, cameraPosition);
view = glm::rotate(view, cameraRotation, glm::vec3(0.0f, 1.0f, 0.0f));
//set the camera projection to perspective
projection = glm::perspective(45.0f, (GLfloat)WindowWidth / (GLfloat)WindowHeight, 0.1f, 100.0f);
// reference matrix uniforms from the cube shader program
modelLoc = glGetUniformLocation(cubeShaderProgram, "model");
viewLoc = glGetUniformLocation(cubeShaderProgram, "view");
projLoc = glGetUniformLocation(cubeShaderProgram, "projection");
//pass matrix data to the cube shader program's matrix uniforms
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(projection));
// reference matrix uniforms from the cube shader program for the cube color, light color, light position, and camera position
objectColorLoc = glGetUniformLocation(cubeShaderProgram, "objectColor");
lightColorLoc = glGetUniformLocation(cubeShaderProgram, "lightColor");
lightPositionLoc = glGetUniformLocation(cubeShaderProgram, "lightPos");
viewPositionLoc = glGetUniformLocation(cubeShaderProgram, "viewPosition");
//pass color, light, and camera data to the cube shader program's corresponding uniforms
glUniform3f(objectColorLoc, objectColor.r, objectColor.g, objectColor.b);
glUniform3f(lightColorLoc, lightColor.r, lightColor.g, lightColor.b);
glUniform3f(lightPositionLoc, lightPosition.x, lightPosition.y, lightPosition.z);
glUniform3f(viewPositionLoc, cameraPosition.x, cameraPosition.y, cameraPosition.z);
glDrawArrays(GL_TRIANGLES, 0, 36);
// use the lamp shader and activate the LVAO
glUseProgram(lampShaderProgram);
glBindVertexArray(LightVAO);
// transform the smaller cube
model = glm::translate(model, lightPosition);
model = glm::scale(model, lightScale);
// reference matrix uniforms from the lamp shader program
modelLoc = glGetUniformLocation(lampShaderProgram, "model");
viewLoc = glGetUniformLocation(lampShaderProgram, "view");
projLoc = glGetUniformLocation(lampShaderProgram, "projection");
//pass matrix data to the lamp shader program's matrix uniforms
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(projection));
glDrawArrays(GL_TRIANGLES,0, 36);
glBindVertexArray(0); // Deactivate the Vertex Array Object
glutPostRedisplay();
glutSwapBuffers();
}
/*Creates the Shader program*/
void UCreateShader()
{
// cube Vertex shader
GLint cubeVertexShader = glCreateShader(GL_VERTEX_SHADER); // Creates the Vertex Shader
glShaderSource(cubeVertexShader, 1, &cubeVertexShaderSource, NULL); // Attaches the Vertex Shader to the source code
glCompileShader(cubeVertexShader); // Compiles the Vertex Shader
// cube Fragment Shader
GLint cubeFragmentShader = glCreateShader(GL_FRAGMENT_SHADER); // Creates the Fragment Shader
glShaderSource(cubeFragmentShader, 1, &cubeFragmentShaderSource, NULL);// Attaches the Fragment Shader to the source code
glCompileShader(cubeFragmentShader); // Compiles the Fragment Shader
// Cube Shader program
cubeShaderProgram = glCreateProgram(); // Creates the Shader program and returns an id
glAttachShader(cubeShaderProgram, cubeVertexShader); // Attach Vertex Shader to the Shader program
glAttachShader(cubeShaderProgram, cubeFragmentShader);; // Attach Fragment Shader to the Shader program
glLinkProgram(cubeShaderProgram); //Link Vertex and Fragment shader, to Shader program
// Delete the cube Vertex and Fragment shaders once linked
glDeleteShader(cubeVertexShader);
glDeleteShader(cubeFragmentShader);
// Lamp Vertex Shader
GLint lampVertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(lampVertexShader, 1, &lampVertexShaderSource, NULL);
glCompileShader(lampVertexShader);
// Lamp Fragment Shader
GLint lampFragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(lampFragmentShader, 1, &lampFragmentShaderSource, NULL);
glCompileShader(lampFragmentShader);
// Cube Shader program
lampShaderProgram = glCreateProgram(); // Creates the Shader program and returns an id
glAttachShader(lampShaderProgram, lampVertexShader); // Attach Vertex Shader to the Shader program
glAttachShader(lampShaderProgram, lampFragmentShader);; // Attach Fragment Shader to the Shader program
glLinkProgram(lampShaderProgram); //Link Vertex and Fragment shader, to Shader program
// Delete the lamp Vertex and Fragment shaders once linked
glDeleteShader(lampVertexShader);
glDeleteShader(lampFragmentShader);
}
/*creates the buffer and array object*/
void UCreateBuffers()
{
I have tried testing the vertices on their own and i can see the cube. I dont understand why its disapering after adding the lighting.
//position and color data
GLfloat vertices[] = {
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f,
0.5f, -0.5f, -0.5f, 0.0f,0.0f, -1.0f,
0.5f, 0.5f, -0.5f, 0.0f,0.0f, -1.0f,
0.5f, 0.5f, -0.5f, 0.0f, 0.0f,-1.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 0.0f,-1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f,-1.0f,
-0.5f, -0.5f, 0.5f, 0.0f,0.0f, 1.0f,
0.5f, -0.5f, 0.5f, 0.0f,0.0f, 1.0f,
0.5f, 0.5f, 0.5f, 0.0f,0.0f, 1.0f,
0.5f, 0.5f, 0.5f, 0.0f,0.0f, 1.0f,
-0.5f, 0.5f, 0.5f, 0.0f,0.0f, 1.0f,
-0.5f, -0.5f, 0.5f, 0.0f,0.0f, 1.0f,
-0.5f, 0.5f, 0.5f, -1.0f, 0.0f,0.0f,
-0.5f, 0.5f, -0.5f, -1.0f, 0.0f,0.0f,
-0.5f, -0.5f, -0.5f, -1.0f, 0.0f,0.0f,
-0.5f, -0.5f, -0.5f, -1.0f, 0.0f,0.0f,
-0.5f, -0.5f, 0.5f, -1.0f, 0.0f,0.0f,
-0.5f, 0.5f, 0.5f, -1.0f, 0.0f,0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,0.0f,
0.5f, 0.5f, -0.5f, 1.0f, 0.0f,0.0f,
0.5f, -0.5f, -0.5f, 1.0f, 0.0f,0.0f,
0.5f, -0.5f, -0.5f, 1.0f, 0.0f,0.0f,
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,0.0f,
-0.5f, -0.5f, -0.5f, 0.0f, -1.0f,0.0f,
0.5f, -0.5f, -0.5f, 0.0f, -1.0f,0.0f,
0.5f, -0.5f, 0.5f, 0.0f, -1.0f,0.0f,
0.5f, -0.5f, 0.5f, 0.0f, -1.0f,0.0f,
-0.5f, -0.5f, 0.5f, 0.0f, -1.0f,0.0f,
-0.5f, -0.5f, -0.5f, 0.0f, -1.0f,0.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f,0.0f,
0.5f, 0.5f, -0.5f, 0.0f, 1.0f,0.0f,
0.5f, 0.5f, 0.5f, 0.0f, 1.0f,0.0f,
0.5f, 0.5f, 0.5f, 0.0f, 1.0f,0.0f,
-0.5f, 0.5f, 0.5f, 0.0f, 1.0f,0.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f,0.0f
};
//Generate buffer id,
glGenVertexArrays(1, &CubeVAO);
glGenBuffers(1,&VBO);
// Activate the Vertex Array Object before binding and setting any VB0s and Vertex Attribute Pointers.
glBindVertexArray(CubeVAO);
// Activate the VBO
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); //Copy vertices to VBO
// Set attribute pointer 0 to hold Position data
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0); // Enables vertex attribute
// Set attribute pointer 1 to hold normal data
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
glEnableVertexAttribArray(1); // Enables vertex attribute
glBindVertexArray(0); // Deactivates the VAC, which is good practice
/*Generate buffer ids for lamp (smaller cube)*/
glGenVertexArrays(1, &LightVAO);
// activate the VAO
glBindVertexArray(LightVAO);
// referencing the same VBO
glBindBuffer(GL_ARRAY_BUFFER, VBO);
// set attribute pointer 0 to hold position data for the lamp
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0);
glBindVertexArray(0);
}
回答1:
The "cube" fragment shader fails to compile. The variable diffus
does not exist, it has to be diffuse
:
vec3 phong = (ambient + diffus + specular) * objectColor;
vec3 phong = (ambient + diffuse + specular) * objectColor;
I recommend to verify if compiling the shader succeeded by glGetShaderiv(..., GL_COMPILE_STATUS, ...) and linking succeeded by glGetProgramiv(..., GL_LINK_STATUS, ...).
Implement functions which validate a shader and a program and log the error messages:
#include <iostream>
#include <vector>
void CompileStatus( GLuint shader )
{
GLint status = GL_TRUE;
glGetShaderiv( shader, GL_COMPILE_STATUS, &status );
if (status == GL_FALSE)
{
GLint logLen;
glGetShaderiv( shader, GL_INFO_LOG_LENGTH, &logLen );
std::vector< char >log( logLen );
GLsizei written;
glGetShaderInfoLog( shader, logLen, &written, log.data() );
std::cout << "compile error:" << std::endl << log.data() << std::endl;
}
}
void LinkStatus( GLuint program )
{
GLint status = GL_TRUE;
glGetProgramiv( program, GL_LINK_STATUS, &status );
if (status == GL_FALSE)
{
GLint logLen;
glGetProgramiv( program, GL_INFO_LOG_LENGTH, &logLen );
std::vector< char >log( logLen );
GLsizei written;
glGetProgramInfoLog( program, logLen, &written, log.data() );
std::cout << "link error:" << std::endl << log.data() << std::endl;
}
}
Validate the shaders after glCompileShader
and the program after glLinkProgram
:
void UCreateShader()
{
// cube Vertex shader
GLint cubeVertexShader = glCreateShader(GL_VERTEX_SHADER); // Creates the Vertex Shader
glShaderSource(cubeVertexShader, 1, &cubeVertexShaderSource, NULL); // Attaches the Vertex Shader to the source code
glCompileShader(cubeVertexShader); // Compiles the Vertex Shader
CompileStatus( cubeVertexShader );
// cube Fragment Shader
GLint cubeFragmentShader = glCreateShader(GL_FRAGMENT_SHADER); // Creates the Fragment Shader
glShaderSource(cubeFragmentShader, 1, &cubeFragmentShaderSource, NULL);// Attaches the Fragment Shader to the source code
glCompileShader(cubeFragmentShader); // Compiles the Fragment Shader
CompileStatus( cubeFragmentShader );
// Cube Shader program
cubeShaderProgram = glCreateProgram(); // Creates the Shader program and returns an id
glAttachShader(cubeShaderProgram, cubeVertexShader); // Attach Vertex Shader to the Shader program
glAttachShader(cubeShaderProgram, cubeFragmentShader);; // Attach Fragment Shader to the Shader program
glLinkProgram(cubeShaderProgram); //Link Vertex and Fragment shader, to Shader program
LinkStatus( cubeShaderProgram );
// [...]
}
来源:https://stackoverflow.com/questions/59235204/light-shows-but-the-cube-does-not-appear