Pointlight Shadow Cube Mapping

时间:2013-12-15 21:07:22

标签: c++ opengl glsl shadow-mapping

所以我设法为定向灯(在无限远处扩展)创建阴影贴图。现在我正在尝试创建点光影立方体贴图,因此阴影在light->片段的方向上展开。我创建了一个像这样的新FBO:

        //gen new fbo
        glGenFramebuffers(1, &framebuffer_object);
        glBindFramebuffer(GL_FRAMEBUFFER, framebuffer_object);

        //gen color texture
        glGenTextures(1, &texture_color);
        glBindTexture(GL_TEXTURE_2D, texture_color);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
        glTexImage2D(GL_TEXTURE_2D, 0,GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);

        //gen cubemap
        glGenTextures(1, &shadow_cubemap);
        glBindTexture(GL_TEXTURE_2D_ARRAY, shadow_cubemap);
        glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);
        glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
        glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_DEPTH_TEXTURE_MODE, GL_INTENSITY);

        glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_DEPTH_COMPONENT, width, height, 0, GL_DEPTH_COMPONENT, GL_FLOAT, 0);
        glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_DEPTH_COMPONENT, width, height, 0, GL_DEPTH_COMPONENT, GL_FLOAT, 0);
        glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_DEPTH_COMPONENT, width, height, 0, GL_DEPTH_COMPONENT, GL_FLOAT, 0);
        glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_DEPTH_COMPONENT, width, height, 0, GL_DEPTH_COMPONENT, GL_FLOAT, 0);
        glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_DEPTH_COMPONENT, width, height, 0, GL_DEPTH_COMPONENT, GL_FLOAT, 0);
        glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_DEPTH_COMPONENT, width, height, 0, GL_DEPTH_COMPONENT, GL_FLOAT, 0);     

        //bind color texture
        unsigned int attachment_index_color_texture = 0;
        glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0+attachment_index_color_texture, texture_color,0);

        //add attachments
        std::vector<GLenum> drawbuffers;
        drawbuffers.push_back(GL_COLOR_ATTACHMENT0+attachment_index_color_texture);
        glDrawBuffers(drawbuffers.size(),&drawbuffers[0]);

        //check the fbo state
        if(glCheckFramebufferStatus(GL_FRAMEBUFFER)!=GL_FRAMEBUFFER_COMPLETE){
            std::cout<<"Error.FBO not integral."<<std::endl;
            std::cin.get();
            std::terminate();
        }

        //Unbind
        glBindFramebuffer(GL_FRAMEBUFFER,0);

在重新整形时调用此函数(所以你可以说在初始化时)在程序启动时调用一次reshape。

接下来,我创建了我的light_view矩阵,每个视图用于不同的立方体面,以及我的投影矩阵,如下所示:

    //view matrix for +x
    lightView_matrix[0]=glm::lookAt(light_position,light_position+glm::vec3(1,0,0),glm::vec3(0,1,0));

    //view_matrix for -x
    lightView_matrix[1]=glm::lookAt(light_position,light_position+glm::vec3(-1,0,0),glm::vec3(0,1,0));

    //view_matrix for +z
    lightView_matrix[2]=glm::lookAt(light_position,light_position+glm::vec3(0,0,1),glm::vec3(0,1,0));

    //view_matrix for -z
    lightView_matrix[3]=glm::lookAt(light_position,light_position+glm::vec3(0,0,-1),glm::vec3(0,1,0));

    //view_matrix for +y
    lightView_matrix[4]=glm::lookAt(light_position,light_position+glm::vec3(0,1,0),glm::vec3(0,0,-1));

    //view_matrix for -y
    lightView_matrix[5]=glm::lookAt(light_position,light_position+glm::vec3(0,-1,0),glm::vec3(0,0,1));

    lightProjection_matrix = glm::perspective(90.0f, 1.0f, 0.5f, 140.0f);

投影矩阵是否正常?在进行立方体贴图而不是像我对定向光那样的ortographic时,它应该是透视吗?我不知道数值是否正常:这就是我所拥有的,纹理的宽度和高度是1366 x 768这是我的窗口大小,我的整个场景是从z轴的-70到70,所以总共140 ,我选择了pi / 4的fov。

继续前进到第一遍 - 希望生成立方体贴图的6个面:

    cube_fbo.bind();
    {

        for(int i=0;i<6;i++){

            glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, cube_fbo.shadow_cubemap, 0);
            //clear screen
            glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

            //use shader
            glUseProgram(program_shader);

            //send uniform values
            glUniformMatrix4fv(glGetUniformLocation(program_shader,"light_view_matrix"),1,false,glm::value_ptr(lightView_matrix[i]));
            glUniformMatrix4fv(glGetUniformLocation(program_shader,"light_projection_matrix"),1,false,glm::value_ptr(lightProjection_matrix));

            //draw my objects with textures,i also have an alpha texture hence the has_alpha in the shaders (will post below )

        }
    }
    //unbind fbo
    cube_fbo.unbind();

现在第二遍应该根据片段位置绘制阴影(我应该在绘图函数中还是在着色器中执行此操作?)

    {

        //clear screen
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        glUseProgram(program_shadow);

        //send uniform values
        glUniformMatrix4fv(glGetUniformLocation(program_shadow,"view_matrix"),1,false,glm::value_ptr(view_matrix));
        glUniformMatrix4fv(glGetUniformLocation(program_shadow,"projection_matrix"),1,false,glm::value_ptr(projection_matrix));


        glUniformMatrix4fv(glGetUniformLocation(program_shadow,"light_view_matrix"),1,false,glm::value_ptr(light_view_matrix));
        glUniformMatrix4fv(glGetUniformLocation(program_shadow,"light_projection_matrix"),1,false,glm::value_ptr(light_projection_matrix));
        glUniformMatrix4fv(glGetUniformLocation(program_shadow,"BiasMatrix"),1,false,glm::value_ptr(BiasMatrix));
        glUniform3f(glGetUniformLocation(program_shadow,"light_position"),light_position.x,light_position.y,light_position.z);

        //sphere at light position for reference------------------------
        glUniformMatrix4fv(glGetUniformLocation(program_shadow,"model_matrix"),1,false,glm::value_ptr(light_model_matrix));
        lab::drawSolidSphere(2,6,6);

        //glEnable(GL_CULL_FACE);
        //glCullFace(GL_BACK);
        //ground----------------------------
        glUniformMatrix4fv(glGetUniformLocation(program_shadow,"model_matrix"),1,false,glm::value_ptr(ground_model_matrix));
        glActiveTexture(GL_TEXTURE1);
        glBindTexture(GL_TEXTURE_2D, ground_texture);
        glUniform1i( glGetUniformLocation(program_shadow, "textura1"), 1 );
        glUniform1i( glGetUniformLocation(program_shadow, "has_alpha"), 0);
        //glDisable(GL_CULL_FACE);

        //send cubemap texture(GLuint bound in the first part (shadow_cubemap))
        glActiveTexture(GL_TEXTURE2);
        glBindTexture(GL_TEXTURE_CUBE_MAP, cube_fbo[0].getCubeMapTexture());

        glUniform1i(glGetUniformLocation(program_shadow, "textura_depth"), 2);

        glBindVertexArray(ground_vao);
        glDrawElements(GL_TRIANGLES, ground_num_indices, GL_UNSIGNED_INT, 0);

        //bamboo(s)----------------------------
        glActiveTexture(GL_TEXTURE0+1);
        glBindTexture(GL_TEXTURE_2D, bamboo_texture_color);
        glActiveTexture(GL_TEXTURE0+2);
        glBindTexture(GL_TEXTURE_2D, bamboo_texture_alpha);
        glUniform1i( glGetUniformLocation(program_shadow, "textura1"), 1 );
        glUniform1i( glGetUniformLocation(program_shadow, "textura2"), 2 );

        glUniform1i( glGetUniformLocation(program_shadow, "has_alpha"), 1); 

        //send cubemap texture
        glActiveTexture(GL_TEXTURE3);
        glBindTexture(GL_TEXTURE_2D, cube_fbo[0].getCubeMapTexture());

        glUniform1i(glGetUniformLocation(program_shadow, "textura_depth"), 3);

        glBindVertexArray(bamboo_vao);
        for(int i=0;i<10;i++) for(int j=0;j<10;j++) {
            if(j==5){
            glUniformMatrix4fv(glGetUniformLocation(program_shadow,"model_matrix"),1,false,glm::value_ptr(bamboo_model_matrix[i*10+j]));
            glDrawElements(GL_TRIANGLES, bamboo_num_indices, GL_UNSIGNED_INT, 0);
            }
        }
                }

正如您在最后一部分中所看到的,我从相机位置绘制并传递到着色器,立方体贴图从第一遍开始生成。我有一些误解,可能还有一些错误,直到这一点。

  1. 我从第一次传递(从着色器)返回什么,当我为定向光进行阴影贴图时,我返回了深度(glFragcoord.z),但现在我必须返回一个vec3方向?我如何计算。我还需要其他东西传递给着色器吗?

  2. 第二部分可以吗?我是否只是绘制对象并将立方体贴图传递给着色器并让他计算哪个片段与光相关?如果是这样,我该如何计算呢?

  3. 这是第一遍的着色器(因此从6个灯光视图生成立方体贴图):

    #version 330 /*VERTEX SHADER*\
    
    layout(location = 0) in vec3 in_position;       
    layout(location = 2) in vec2 in_texcoord;
    
    uniform mat4 model_matrix;
    uniform mat4 light_view_matrix,light_projection_matrix;
    
    out vec2 texcoord;
    out vec4 v_position;
    
    void main(){
    
    texcoord = in_texcoord;
    
    gl_Position = light_projection_matrix*light_view_matrix*model_matrix*vec4(in_position,1); 
    
    
    }
    #version 330 /*FRAGMENT SHADER*\
    
    
    layout(location = 0) out vec4 out_color;
    //layout(location = 1) out float depth;
    
    uniform sampler2D textura1;
    uniform sampler2D textura2;
    uniform int has_alpha;
    
    in vec2 texcoord;
    in vec4 v_position;
    
    void main(){
    
    
    vec3 tex1 = texture(textura1, texcoord).xyz;
    vec3 tex2 = texture(textura2, texcoord).xyz;
    
    if(has_alpha>0.5) if((tex2.r<0.1) && (tex2.g<0.1) && (tex2.b<0.1)) discard;
    
    out_color = vec4(tex1, 1);
    }
    

    第二遍的着色器(试图通过从世界空间中的像素位置获取vec3来计算阴影 - 世界空间中的光位置)

    #version 330 core /*VERTEX SHADER*\
    
    layout(location = 0) in vec3 in_position;
    layout(location = 1) in vec3 in_normal;     
    layout(location = 2) in vec2 in_texcoord;
    
    out vec3 lightPosw;
    out vec3 pixelPosw;
    out vec2 texcoord;
    
    uniform mat4 model_matrix,view_matrix,projection_matrix;
    uniform vec3 light_position;
    
    void main(){
    
    texcoord=in_texcoord;
    gl_Position = projection_matrix*view_matrix*model_matrix*vec4(in_position,1);
    lightPosw= (model_matrix * vec4(light_position,1)).xyz;
    pixelPosw = (model_matrix * vec4(in_position, 1)).xyz;
    }
    
    #version 330 core /*FRAGMENT SHADER*\
    
    in vec3 lightPosw;
    in vec3 pixelPosw;
    in vec2 texcoord;
    
    out vec4 out_color;
    
    uniform samplerCube textura_depth;
    uniform sampler2D textura1,textura2;
    
    uniform mat4 view_matrix,model_matrix;
    
    uniform int has_alpha;
    
    
    
    void main(){
    
    vec3 lightToPixel=pixelPosw-lightPosw;
    
    vec3 tex1 = texture(textura1, texcoord).xyz;
    vec3 tex2 = texture(textura2, texcoord).xyz;
    
    if(has_alpha>0.5) if((tex2.r<0.1) && (tex2.g<0.1) && (tex2.b<0.1)) discard;
    
    float shadowDepth = texture(textura_depth, normalize(lightToPixel));
    
    float shadowFactor=1.0;
    if(length(lightToPixel) < shadowDepth)
        shadowFactor=0.5;
    
    out_color = vec4(tex1*shadowFactor,1);
    
       }
    

    对不起代码墙,我想发布所有相关的东西,以便我可以得到更好的帮助。我的问题是,一切都呈现半黑色,因为我将片段着色器中的输出颜色设置为0.5,如果我不这样做,那么它都呈现黑色。

0 个答案:

没有答案