簡體   English   中英

Shadow Mapping OpenGL 陰影並不總是繪制,而是繪制在燈光位置的位置

[英]Shadow Mapping OpenGL shadow not always drawing, and drawing where the position of the light is

我一直在嘗試使用 LearnOpenGL 作為源在我的自定義引擎中進行基本的陰影映射。 可以找到確切教程的鏈接: here

我已經調試這個 bug 大約兩個星期了,研究了互聯網,甚至試圖把我的腦袋圍繞在這個問題上,但我只能說陰影幾乎從來沒有出現過,當它出現時,它就是燈所在的位置x 和 z 的項。 我嘗試按照教程中的所有內容進行大約 10 次,我也嘗試查看此網站是否有類似問題,但對於我發現的每一種方式,這都不是我的情況。

發現

在此Image(1) 中,您可以看到當燈光位於其頂部時陰影不可見,但是當 lightPos.x 變量在 -4.5 或 4.5 左右時,它在此Image (2)上可見,這是所以對於 lightPos.z 變量也是如此。 出現時的陰影是在lightPos所在的地方繪制的,在圖片中它被紅線圈住。

我使用多個着色器,一個用於光影計算 (ShadowMapping),一個用於基本深度映射 (ShadowMapGen) 這是我的 ShadowMapping 着色器:

陰影映射頂點

version 460
in vec3 vertexIn;
in vec3 normalIn;
in vec2 textureIn;

out vec3 FragPos;
out vec3 normalOut;
out vec2 textureOut;

out vec4 FragPosLightSpace;

uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
uniform mat4 lightSpaceMatrix;

void main()
{
    textureOut = textureIn;

    FragPos = vec3(model * vec4(vertexIn, 1.0));
    normalOut = mat3(transpose(inverse(model))) * normalIn;  
    FragPosLightSpace = lightSpaceMatrix * vec4(FragPos, 1.0);    

    gl_Position = projection * view * model * vec4(vertexIn, 1.0);
}

陰影映射片段

out vec4 FragColor;

in vec3 FragPos;
in vec3 normalOut;
in vec2 textureOut;

in vec4 FragPosLightSpace;

uniform sampler2D diffuseTexture;
uniform sampler2D shadowMap;

uniform vec3 lightPos;
uniform vec3 viewPos;

float ShadowCalculation(vec4 fragPosLightSpace, vec3 lightdir)
{
    // perform perspective divide
    vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w;
    // transform to [0,1] range
    projCoords = projCoords * 0.5 + 0.5;
    // get closest depth value from light's perspective (using [0,1] range fragPosLight as coords)
    float closestDepth = texture(shadowMap, projCoords.xy).r; 
    // get depth of current fragment from light's perspective
    float currentDepth = projCoords.z;
    // check whether current frag pos is in shadow
    float bias = max(0.05 * (1.0 - dot(normalOut, lightdir)), 0.005);

    // check whether current frag pos is in shadow
//    float shadow = currentDepth - bias > closestDepth  ? 1.0 : 0.0;
//    // PCF
    float shadow = 0.0;

    vec2 texelSize = 1.0 / textureSize(shadowMap, 0);
    for(int x = -1; x <= 1; ++x)
    {
        for(int y = -1; y <= 1; ++y)
        {
            float pcfDepth = texture(shadowMap, projCoords.xy + vec2(x, y) * texelSize).r; 
            shadow += currentDepth - bias > pcfDepth  ? 1.0 : 0.0;        
        }    
    }

    shadow /= 9.0;

    // keep the shadow at 0.0 when outside the far_plane region of the light's frustum.
        if(projCoords.z > 1.0)
        shadow = 0.0;

    return shadow;
}

void main()
{           
    vec3 color = texture(diffuseTexture, textureOut).rgb;
    vec3 normal = normalize(normalOut);
    vec3 lightColor = vec3(1.0f);
    // ambient
    vec3 ambient = 0.30 * color;
    // diffuse
    vec3 lightDir = normalize(lightPos - FragPos);
    float diff = max(dot(lightDir, normal), 0.0);
    vec3 diffuse = diff * lightColor;
    // specular
    vec3 viewDir = normalize(viewPos - FragPos);
    vec3 reflectDir = reflect(-lightDir, normal);
    float spec = 0.0;
    vec3 halfwayDir = normalize(lightDir + viewDir);  
    spec = pow(max(dot(normal, halfwayDir), 0.0), 64.0);
    vec3 specular = spec * lightColor;    
    // calculate shadow
    float shadow = ShadowCalculation(FragPosLightSpace, lightDir);                      
    vec3 lighting = (ambient + (1.0 - shadow) * (diffuse + specular)) * color;    

    FragColor = vec4(lighting, 1.0);
}

ShadowMapGen 頂點

此着色器的片段着色器為空

version 460

in vec3 vertexIn;
uniform mat4 model;
uniform mat4 lightSpaceMatrix;

void main()
{
    gl_Position =  model * lightSpaceMatrix * vec4(vertexIn, 1.0);
}

變量初始化

lightPos = glm::vec3(-2.0f, 4.0f, -1.0f);
near_plane = 1.0f;
far_plane = 7.5f;

//SAMPLE 2D Uniform binding
TheShader::Instance()->SendUniformData("ShadowMapping_diffuseTexture", 0);
TheShader::Instance()->SendUniformData("ShadowMapping_shadowMap", 1);

深度圖幀緩沖生成

這就是我在場景的構造函數中生成深度貼圖/陰影貼圖紋理的方式:

glGenFramebuffers(1, &depthMapFBO);
//Create depth texture
glGenTextures(1, &depthMap);
glBindTexture(GL_TEXTURE_2D, depthMap);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, SHADOW_WIDTH, SHADOW_HEIGHT, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL); // Height and Width = 1024
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_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);

float borderColor[] = { 1.0, 1.0, 1.0, 1.0 };
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor);

//Attach depth texture as FBO's depth buffer
glBindFramebuffer(GL_FRAMEBUFFER, depthMapFBO);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthMap, 0);
glDrawBuffer(GL_NONE);
glReadBuffer(GL_NONE);
glBindFramebuffer(GL_FRAMEBUFFER, 0);

然后在引擎的 While 循環中運行的 Update() 函數中,我首先執行:

從光的角度渲染對象

//Light Projection and view Matrix 
m_lightProjection = glm::ortho(-10.0f, 10.0f, -10.0f, 10.0f, near_plane, far_plane);
m_lightView = glm::lookAt(lightPos, glm::vec3(0.0f), glm::vec3(0.0f, 1.0f, 0.0f));
//Calculate light matrix and send it.
m_lightSpaceMatrix = m_lightProjection * m_lightView;
TheShader::Instance()->SendUniformData("ShadowMapGen_lightSpaceMatrix", 1, GL_FALSE, m_lightSpaceMatrix);

//Render to Framebuffer depth Map
glViewport(0, 0, SHADOW_WIDTH, SHADOW_HEIGHT);
glBindFramebuffer(GL_FRAMEBUFFER, depthMapFBO);
glClear(GL_DEPTH_BUFFER_BIT);

//Set current Shader to ShadowMapGen
m_floor.SetShader("ShadowMapGen");
m_moon.SetShader("ShadowMapGen");
//Send model Matrix to current Shader
m_floor.Draw();
m_moon.Draw();
//Set current Shader back to ShadowMapping
m_moon.SetShader("ShadowMapping");
m_floor.SetShader("ShadowMapping");

glBindFramebuffer(GL_FRAMEBUFFER, 0);

從相機的角度渲染對象

glViewport(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//Update Camera and Send the view and projection matrices to the ShadowMapping shader
m_freeCamera->Update();
m_freeCamera->Draw();

//Send Light Pos 
TheShader::Instance()->SendUniformData("ShadowMapping_lightPos", lightPos);
//Send LightSpaceMatrix
TheShader::Instance()->SendUniformData("ShadowMapping_lightSpaceMatrix", 1, GL_FALSE, m_lightSpaceMatrix);

//Activate Shadow Mapping texture
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, depthMap);

//Send model Matrix to ShadowMapping shaders
m_moon.Draw();  
m_floor.Draw();

我希望有人會看到這個,謝謝你的時間。

我嘗試像教程中那樣做所有事情大約 10 次

好吧,您似乎至少錯過了一件顯而易見的事情:

 m_lightSpaceMatrix = m_lightProjection * m_lightView;

到目前為止,一切都很好,但是在您的“ShadowMapGen”頂點着色器中,您寫道:

 gl_Position = model * lightSpaceMatrix * vec4(vertexIn, 1.0);

所以你最終得到了model * projection * view乘法順序,無論你遵守哪種約定,這都沒有意義。 由於本教程使用默認 GL 約定,因此您始終需要projection * view * model * vertex乘法順序,本教程也正確使用了該順序。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM