1

所以我设法为定向光(无限延伸)创建阴影贴图。现在我正在尝试创建点光阴影立方体贴图,因此阴影在光->片段的方向上传播。我像这样创建了一个新的 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);

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

接下来我创建我的 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);

投影矩阵好吗?在做立方体贴图而不是像我对定向光做的正交映射时,它应该是透视图吗?我不知道这些值是否正常:这就是我所拥有的,纹理的宽度和高度是 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. 第二部好吗?我是否只是绘制对象并将立方体贴图传递给着色器并让他计算哪个片段相对于光在哪里?如果是这样,我该如何计算?

这是我的第一遍着色器(因此从 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,如果我不这样做,那么它全部呈现黑色。

4

0 回答 0