我首先制作了一个没有阴影的场景,并测试了它,结果很好,然后我试图为我的场景制作阴影,结果每个对象都是黑色的。不过,我剩下的功能正常。
我认为可能有一些统一的值没有正确分配,但我无法识别它们。
这是我的代码片段:
getSceneVertShader()
return "#version 330 coren"
"uniform vec3 view_position;"
""
"layout(location = 0) in vec3 position;"
"layout(location = 1) in vec3 normals;"
""
"uniform mat4 worldMatrix;"
"uniform mat4 viewMatrix;"
"uniform mat4 projectionMatrix;"
"uniform mat4 lightSpaceMatrix;"
""
"out vec3 fragment_normal;"
"out vec3 fragment_position;"
"out vec4 fragment_position_light_space;"
""
"void main()"
"{"
" fragment_normal = mat3(worldMatrix) * normals;"
" fragment_position = vec3(worldMatrix * vec4(position, 1.0));"
" fragment_position_light_space = lightSpaceMatrix * vec4(fragment_position, 1.0);"
" gl_Position = projectionMatrix * viewMatrix * worldMatrix * vec4(position, 1.0);"
"}";
getSceneFragShader()
return "#version 330 coren"
"const float PI = 3.1415926535897932384626433832795;"
""
"uniform vec3 light_color;"
"uniform vec3 light_position; "
"uniform vec3 light_direction; "
""
"uniform vec3 overrideColor; "
""
"const float shading_ambient_strength = 0.1;"
"const float shading_diffuse_strength = 0.6;"
"const float shading_specular_strength = 0.3;"
""
"uniform float light_cutoff_outer; "
"uniform float light_cutoff_inner; "
"uniform float light_near_plane; "
"uniform float light_far_plane; "
""
"uniform vec3 view_position; "
""
"uniform sampler2D shadow_map; "
""
"in vec3 fragment_position; "
"in vec4 fragment_position_light_space; "
"in vec3 fragment_normal; "
""
"in vec4 gl_FragCoord; "
""
"out vec4 result; "
""
"vec3 ambient_color(vec3 light_color_arg) {"
" return shading_ambient_strength * light_color_arg; "
"}"
""
"vec3 diffuse_color(vec3 light_color_arg, vec3 light_position_arg) {"
" vec3 light_direction = normalize(light_position_arg - fragment_position); "
" return shading_diffuse_strength * light_color_arg *" "max(dot(normalize(fragment_normal), light_direction), 0.0f); "
"}"
""
"vec3 specular_color(vec3 light_color_arg, vec3 light_position_arg) {"
" vec3 light_direction = normalize(light_position_arg - fragment_position); "
" vec3 view_direction = normalize(view_position - fragment_position); "
" vec3 reflect_light_direction = reflect(-light_direction, normalize(fragment_normal));"
""
" return shading_specular_strength * light_color_arg *" "pow(max(dot(reflect_light_direction, view_direction), 0.0f),32); "
"}"
""
"float shadow_scalar() {"
// this function returns 1.0 when the surface receives light, and 0.0 when it is in a shadow
// perform perspective divide
" vec3 normalized_device_coordinates = fragment_position_light_space.xyz / fragment_position_light_space.w; "
// transform to [0,1] range
" normalized_device_coordinates = normalized_device_coordinates * 0.5 + 0.5; "
// get closest depth value from light's perspective (using [0,1] range fragment_position_light_space as coords)
" float closest_depth = texture(shadow_map, normalized_device_coordinates.xy).r; "
// get depth of current fragment from light's perspective
" float current_depth = normalized_device_coordinates.z; "
// check whether current frag pos is in shadow
// bias applied in depth map: see shadow_vertex.glsl
" float bias = 0.006; "
" return ((current_depth - bias) < closest_depth) ? 1.0 : 0.0; "
"}"
""
"float spotlight_scalar() {"
" float theta = dot(normalize(fragment_position - light_position), light_direction); "
""
" if(theta > light_cutoff_inner) {"
" return 1.0; "
" } else if(theta > light_cutoff_outer) {"
" return (1.0 - cos(PI * (theta - light_cutoff_outer) / (light_cutoff_inner - light_cutoff_outer))) / 2.0; "
" } else {"
" return 0.0; "
" }"
"}"
""
"void main()"
"{"
" vec3 ambient = vec3(0.0f); "
" vec3 diffuse = vec3(0.0f); "
" vec3 specular = vec3(0.0f); "
""
" float scalar = shadow_scalar() * spotlight_scalar();"
" ambient = ambient_color(light_color); "
" diffuse = scalar * diffuse_color(light_color, light_position); "
" specular = scalar * specular_color(light_color, light_position); "
""
" vec3 color = (specular + diffuse + ambient) * overrideColor;"
""
" result = vec4(color, 1.0f); "
"}";
getShadowVertShader()
return
"#version 330 coren"
"layout(location = 0) in vec3 position;"
""
"uniform mat4 lightSpaceMatrix;"
"uniform mat4 worldMatrix;"
""
"void main()"
"{"
" gl_Position ="
""
" lightSpaceMatrix * worldMatrix * vec4(position, 1.0);"
"}";
getShadowFragShader()
return
"#version 330 coren"
""
"out vec4 FragColor;"
"in vec4 gl_FragCoord;"
"void main()"
"{"
" gl_FragDepth = gl_FragCoord.z;"
" FragColor = vec4(vec3(gl_FragCoord.z), 1.0f);"
"}";
createVertexArrayObject(const glm::vec3* vertexArray, int arraySize)
glGenVertexArrays(1, &vertexArrayObject);
glBindVertexArray(vertexArrayObject);
GLuint vertexBufferObject;
glGenBuffers(1, &vertexBufferObject);
glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject);
glBufferData(GL_ARRAY_BUFFER, arraySize, vertexArray, GL_STATIC_DRAW);
glVertexAttribPointer(0, // attribute 0 matches aPos in Vertex Shader
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
2*sizeof(glm::vec3), // stride - each vertex contain 2 vec3 (position, color)
(void*)0 // array buffer offset
);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, // attribute 1 matches aNormal in Vertex Shader
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
2 * sizeof(glm::vec3), // stride - each vertex contain 1 vec3 (position)
(void*)(sizeof(glm::vec3)) // array buffer offset
);
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
return vertexArrayObject;
main()
glfwInit();
GLFWwindow* window = glfwCreateWindow(1024, 768, "some programs", NULL, NULL);
glfwMakeContextCurrent(window);
glewExperimental = true; // Needed for core profile
if (glewInit() != GLEW_OK) {
std::cerr << "Failed to create GLEW" << std::endl;
glfwTerminate();
return -1;
}
glClearColor(0.2f, 0.298f, 0.298f, 1.0f);
float lastFrameTime = glfwGetTime();
// Compile and link shaders here ...
int shaderProgram = compileAndLinkSceneShaders();
int shadowShaderProgram = compileAndLinkShadowShaders();
/*bind vao */
const unsigned int DEPTH_MAP_TEXTURE_SIZE = 1024;
/*other variables initionalizations*/
glm::vec3 lightInvDir = glm::vec3(0.5f, 2, 2);
GLuint depth_map_texture;
glGenTextures(1, &depth_map_texture);
glBindTexture(GL_TEXTURE_2D, depth_map_texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, DEPTH_MAP_TEXTURE_SIZE, DEPTH_MAP_TEXTURE_SIZE, 0, GL_DEPTH_COMPONENT, GL_FLOAT,
NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
GLuint depth_map_fbo;
glGenFramebuffers(1, &depth_map_fbo);
glBindFramebuffer(GL_FRAMEBUFFER, depth_map_fbo);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depth_map_texture, 0);
glDrawBuffer(GL_NONE);
GLuint shadowMatrixLocation = glGetUniformLocation(shaderProgram, "lightSpaceMatrix");
GLuint projectionMatrixLocation = glGetUniformLocation(shaderProgram, "projectionMatrix");
GLuint viewMatrixLocation = glGetUniformLocation(shaderProgram, "viewMatrix");
GLuint colorLocation = glGetUniformLocation(shaderProgram, "overrideColor");
GLuint worldMatrixLocation = glGetUniformLocation(shaderProgram, "worldMatrix");
GLuint lightInnerLocation = glGetUniformLocation(shaderProgram, "light_cutoff_inner");
GLuint lightOuterLocation = glGetUniformLocation(shaderProgram, "light_cutoff_outer");
GLuint lightColorLocation = glGetUniformLocation(shaderProgram, "light_color");
GLuint lightPositionLocation = glGetUniformLocation(shaderProgram, "light_position");
GLuint lightDirectionLocation = glGetUniformLocation(shaderProgram, "light_direction");
GLuint viewPositionLocation = glGetUniformLocation(shaderProgram, "view_position");
GLuint lightNearLocation = glGetUniformLocation(shaderProgram, "light_near_plane");
GLuint lightFarLocation = glGetUniformLocation(shaderProgram, "light_far_plane");
GLuint shadowWorldMatrixLocation = glGetUniformLocation(shadowShaderProgram, "worldMatrix");
GLuint shadowShadowMatrixLocation = glGetUniformLocation(shadowShaderProgram, "lightSpaceMatrix");
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
float lightAngleOuter = 30.0;
float lightAngleInner = 20.0;
// Set light cutoff angles on scene shader
glUniform1f(lightInnerLocation, cos(glm::radians(lightAngleInner)));
glUniform1f(lightOuterLocation, cos(glm::radians(lightAngleOuter)));
// Set light color on scene shader
GLfloat lightColor[3] = { 1.0f, 1.0f, 1.0f };
glUniform3fv(lightColorLocation,1, &lightColor[0]);
while (!glfwWindowShouldClose(window))
{
float dt = glfwGetTime() - lastFrameTime;
lastFrameTime += dt;
//set the camera
glm::vec3 cameraPos = glm::vec3(cameraPan, 2.0f, cameraZoom + 6.0f);
glm::mat4 viewMatrix = glm::lookAt(cameraPos,
glm::vec3(cameraPan, cameraTilt + 2.0f, cameraZoom),
glm::vec3(0.0f, 1.0f, 0.0f));
glUniformMatrix4fv(viewMatrixLocation, 1, GL_FALSE, &viewMatrix[0][0]);
glUniform3fv(viewPositionLocation, 1, &cameraPos[0]);
glm::mat4 projectionMatrix = glm::perspective(glm::radians(45.0f), // field of view in degrees
1024.0f / 768.0f, // aspect ratio
0.01f, 100.0f); // near and far (near > 0)
glUniformMatrix4fv(projectionMatrixLocation, 1, GL_FALSE, &projectionMatrix[0][0]);
glm::vec3 lightPosition = glm::vec3(1.0f, 2.0f, 5.0f); // the location of the light in 3D space
glm::vec3 lightFocus(0.0, 0.0, -1.0); // the point in 3D space the light "looks" at
glm::vec3 lightDirection = normalize(lightFocus - lightPosition);
float lightNearPlane = 1.0f;
float lightFarPlane = 180.0f;
glm::mat4 lightProjectionMatrix = glm::frustum(-1.0f, 1.0f, -1.0f, 1.0f, lightNearPlane, lightFarPlane);
//perspective(20.0f, (float)DEPTH_MAP_TEXTURE_SIZE / (float)DEPTH_MAP_TEXTURE_SIZE, lightNearPlane, lightFarPlane);
glm::mat4 lightViewMatrix = glm::lookAt(lightPosition, lightFocus, glm::vec3(0.0f, 1.0f, 0.0f));
glm::mat4 lightSpaceMatrix = lightProjectionMatrix * lightViewMatrix;
glUniformMatrix4fv(shadowMatrixLocation, 1, GL_FALSE, &lightSpaceMatrix[0][0]);
glUniformMatrix4fv(shadowShadowMatrixLocation, 1, GL_FALSE, &lightSpaceMatrix[0][0]);
glUniform1f(lightNearLocation, lightNearPlane);
glUniform1f(lightFarLocation, lightFarPlane);
glUniform3fv(lightPositionLocation, 1, &lightPosition[0]);
glUniform3fv(lightDirectionLocation, 1, &lightDirection[0]);
glUseProgram(shadowShaderProgram);
glViewport(0, 0, DEPTH_MAP_TEXTURE_SIZE, DEPTH_MAP_TEXTURE_SIZE);
// Bind depth map texture as output framebuffer
glBindFramebuffer(GL_FRAMEBUFFER, depth_map_fbo);
// Clear depth data on the framebuffer
glClear(GL_DEPTH_BUFFER_BIT);
/*draw items*/
//assigned overrideColor and using shadowShaderProgram to draw
glBindVertexArray(0);
glUseProgram(shaderProgram);
int width, height;
glfwGetFramebufferSize(window, &width, &height);
glViewport(0, 0, width, height);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
// Each frame, reset color of each pixel to glClearColor
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
/*draw items*/
//assigned overrideColor and using shaderProgram to draw
glBindVertexArray(0);
glfwSwapBuffers(window);
glfwPollEvents();
已解决
除了main()
:中的这一部分之外,我的代码的所有内容似乎都是正确的
float lightAngleOuter = 30.0;
float lightAngleInner = 20.0;
// Set light cutoff angles on scene shader
glUniform1f(lightInnerLocation, cos(glm::radians(lightAngleInner)));
glUniform1f(lightOuterLocation, cos(glm::radians(lightAngleOuter)));
// Set light color on scene shader
GLfloat lightColor[3] = { 1.0f, 1.0f, 1.0f };
glUniform3fv(lightColorLocation,1, &lightColor[0]);
要解决此问题,只需将此部分移动到while
循环中并全部设置即可。