如何用延迟渲染做点光阴影?
How to do point light shadows with deferred rendering?
我想知道如何使用延迟渲染对点光源阴影进行编程?
我没有看到点光源阴影。我认为这与以下行有关: float shadow = calculate_shadows(FragPos);至于定向阴影,我将 fragpos 与 lightSpaceMatrix (lightView * lightProj) 相乘并且有效,但对于点阴影,我没有 lightSpaceMatrix 可以使用。
灯光片段着色器
#version 420 core
out vec4 FragColor;
in vec2 _texcoord;
uniform vec3 camera_pos;
uniform sampler2D gPosition;
uniform sampler2D gNormal;
uniform sampler2D gAlbedo;
uniform sampler2D gSpecular;
uniform sampler2D gMetalness;
uniform samplerCube gPointShadowmap;
uniform mat4 viewMatrix;
uniform vec3 lightPos;
vec3 FragPos;
vec3 Normal;
float calculate_shadows(vec3 light_space_pos)
{
// perform perspective divide
vec3 fragToLight = light_space_pos - vec3(0.0f, 0.0f, 0.0f);
// get closest depth value from light's perspective (using [0,1] range fragPosLight as coords)
float closestDepth = texture(gPointShadowmap, fragToLight).r;
// it is currently in linear range between [0,1], let's re-transform it back to original depth value
closestDepth *= 25.0f;
// now get current linear depth as the length between the fragment and light position
float currentDepth = length(fragToLight);
// test for shadows
float bias = 0.05; // we use a much larger bias since depth is now in [near_plane, far_plane] range
float shadow = currentDepth - bias > closestDepth ? 1.0 : 0.0;
//FragColor = vec4(vec3(closestDepth / 25.0f), 1.0);
return shadow;
}
void main(void)
{
FragPos = texture(gPosition, _texcoord).rgb;
Normal = texture(gNormal, _texcoord).rgb;
vec3 Diffuse = texture(gAlbedo, _texcoord).rgb;
float Emissive = texture(gAlbedo, _texcoord).a;
vec3 Specular = texture(gAlbedo, _texcoord).rgb;
vec3 Metalness = texture(gMetalness, _texcoord).rgb; // Reflection pass
float AmbientOcclusion = texture(gSsao, _texcoord).r;
vec3 lightColor = vec3(0.3);
// ambient
vec3 ambient = 0.3 * Diffuse;
// diffuse
vec3 lightDir = normalize(vec3(0.0, 0.0, 0.0) - FragPos);
float diff = max(dot(lightDir, Normal), 0.0);
vec3 diffuse = diff * lightColor;
// specular
vec3 viewDir = normalize(camera_pos - 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 = calculate_shadows(FragPos);
vec3 lighting = (ambient + (1.0 - shadow) * (diffuse + specular));
FragColor = vec4(lighting, 1.0);
}
pointshadows顶点着色器
#version 330 core
layout(location = 0) in vec3 position;
uniform mat4 model;
void main(void)
{
gl_Position = model * vec4(position, 1.0);
}
点阴影片段着色器
#version 330 core
in vec4 FragPos;
void main(void)
{
float lightDistance = length(FragPos.xyz - vec3(0.0, 3.0, 0.0));
// map to [0;1] range by dividing by far_plane
lightDistance = lightDistance / 25.0;
// write this as modified depth
gl_FragDepth = lightDistance;
}
点阴影几何着色器
#version 330 core
layout (triangles) in;
layout (triangle_strip, max_vertices = 18) out;
uniform mat4 shadowMatrices[6];
out vec4 FragPos;
void main(void)
{
for(int face = 0; face < 6; ++face)
{
gl_Layer = face; // built-in variable that specifies to which face we render.
for(int i = 0; i < 3; ++i) // for each triangle's vertices
{
FragPos = gl_in[i].gl_Position;
gl_Position = shadowMatrices[face] * FragPos;
EmitVertex();
}
EndPrimitive();
}
}
温度点阴影class
#ifndef __POINTSHADOWPASS
#define __POINTSHADOWPASS
#include "Content.h"
class PointShadowPass
{
private:
static unsigned int _shadow_fbo;
public:
static unsigned int _shadow_texture;
static glm::vec3 lightPos;
static std::vector<glm::mat4> shadowTransforms;
PointShadowPass() {}
~PointShadowPass() {}
inline static void Initialise()
{
lightPos = glm::vec3(0.0f, 0.0f, 0.0f);
glGenFramebuffers(1, &_shadow_fbo);
glGenTextures(1, &_shadow_texture);
glBindTexture(GL_TEXTURE_2D, _shadow_texture);
for (unsigned int i = 0; i < 6; i++)
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_DEPTH_COMPONENT, 1024, 1024, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
glBindFramebuffer(GL_FRAMEBUFFER, _shadow_fbo);
glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, _shadow_texture, 0);
glDrawBuffer(GL_NONE);
glReadBuffer(GL_NONE);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
inline static void Render(unsigned int pointshadow_program, Camera* camera, std::vector<Actor*> _actors)
{
glDisable(GL_BLEND); // Disable blending for opique materials
glEnable(GL_DEPTH_TEST); // Enable depth test
glm::mat4 model;
glm::mat4 shadowProj = glm::perspective(glm::radians(90.0f), (float)1024 / (float)1024, 1.0f, 25.0f);
shadowTransforms.push_back(shadowProj * glm::lookAt(lightPos, lightPos + glm::vec3(1.0f, 0.0f, 0.0f), glm::vec3(0.0f, -1.0f, 0.0f)));
shadowTransforms.push_back(shadowProj * glm::lookAt(lightPos, lightPos + glm::vec3(-1.0f, 0.0f, 0.0f), glm::vec3(0.0f, -1.0f, 0.0f)));
shadowTransforms.push_back(shadowProj * glm::lookAt(lightPos, lightPos + glm::vec3(0.0f, 1.0f, 0.0f), glm::vec3(0.0f, 0.0f, 1.0f)));
shadowTransforms.push_back(shadowProj * glm::lookAt(lightPos, lightPos + glm::vec3(0.0f, -1.0f, 0.0f), glm::vec3(0.0f, 0.0f, -1.0f)));
shadowTransforms.push_back(shadowProj * glm::lookAt(lightPos, lightPos + glm::vec3(0.0f, 0.0f, 1.0f), glm::vec3(0.0f, -1.0f, 0.0f)));
shadowTransforms.push_back(shadowProj * glm::lookAt(lightPos, lightPos + glm::vec3(0.0f, 0.0f, -1.0f), glm::vec3(0.0f, -1.0f, 0.0f)));
glViewport(0, 0, 1024, 1024);
glBindFramebuffer(GL_FRAMEBUFFER, _shadow_fbo);
glClear(GL_DEPTH_BUFFER_BIT);
glUseProgram(pointshadow_program);
for (unsigned int i = 0; i < 6; ++i)
glUniformMatrix4fv(glGetUniformLocation(pointshadow_program, ("shadowMatrices[" + std::to_string(i) + "]").c_str()), 1, GL_FALSE, glm::value_ptr(shadowTransforms[i]));
for (unsigned int i = 0; i < _actors.size(); i++)
{
model = _actors[i]->GetModelMatrix() * camera->GetViewMatrix();
glUniformMatrix4fv(glGetUniformLocation(pointshadow_program, "model"), 1, GL_FALSE, glm::value_ptr(model)); // set the model matrix uniform
_actors[i]->Render();
}
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
};
std::vector<glm::mat4> PointShadowPass::shadowTransforms;
unsigned int PointShadowPass::_shadow_fbo;
unsigned int PointShadowPass::_shadow_texture;
glm::vec3 PointShadowPass::lightPos;
#endif
我设法显示了一些东西(阴影随相机旋转而移动)
看了你的评论,你似乎对延迟渲染中可以拥有哪些信息有一些误解?
您说所有坐标都必须在屏幕上space,这是不正确的。对于延迟渲染,您有一个 G-Buffer,您可以在其中放置您想要的任何类型的信息。要获取世界位置信息,您有两种选择,要么拥有世界位置缓冲区,这样您就知道每个片段在世界中的位置。或者您可以从深度缓冲区和相机投影矩阵返回计算此信息。
如果你有一个在前向渲染中工作的点阴影计算,你可以在延迟渲染中做同样的事情,在做所有光计算的着色器中你需要阴影立方体贴图,光位置,你像你一样做计算习惯了。
编辑:
查看 calculate_shadows(vec3 light_space_pos)
的代码,在延迟渲染中,您不会向它发送您在光线 space 中的位置,而是在世界 space 中的位置。所以函数应该是:
calculate_shadows(vec3 frag_world_pos)
第一行 vec3 fragToLight = light_space_pos - vec3(0.0f, 0.0f, 0.0f);
应该是vec3 fragToLight = frag_world_pos- lightPos
.
或者您在使用该函数之前进行此计算。无论哪种方式,您都需要点光源的位置来计算片段和光源之间的方向和距离。
我想知道如何使用延迟渲染对点光源阴影进行编程?
我没有看到点光源阴影。我认为这与以下行有关: float shadow = calculate_shadows(FragPos);至于定向阴影,我将 fragpos 与 lightSpaceMatrix (lightView * lightProj) 相乘并且有效,但对于点阴影,我没有 lightSpaceMatrix 可以使用。
灯光片段着色器
#version 420 core
out vec4 FragColor;
in vec2 _texcoord;
uniform vec3 camera_pos;
uniform sampler2D gPosition;
uniform sampler2D gNormal;
uniform sampler2D gAlbedo;
uniform sampler2D gSpecular;
uniform sampler2D gMetalness;
uniform samplerCube gPointShadowmap;
uniform mat4 viewMatrix;
uniform vec3 lightPos;
vec3 FragPos;
vec3 Normal;
float calculate_shadows(vec3 light_space_pos)
{
// perform perspective divide
vec3 fragToLight = light_space_pos - vec3(0.0f, 0.0f, 0.0f);
// get closest depth value from light's perspective (using [0,1] range fragPosLight as coords)
float closestDepth = texture(gPointShadowmap, fragToLight).r;
// it is currently in linear range between [0,1], let's re-transform it back to original depth value
closestDepth *= 25.0f;
// now get current linear depth as the length between the fragment and light position
float currentDepth = length(fragToLight);
// test for shadows
float bias = 0.05; // we use a much larger bias since depth is now in [near_plane, far_plane] range
float shadow = currentDepth - bias > closestDepth ? 1.0 : 0.0;
//FragColor = vec4(vec3(closestDepth / 25.0f), 1.0);
return shadow;
}
void main(void)
{
FragPos = texture(gPosition, _texcoord).rgb;
Normal = texture(gNormal, _texcoord).rgb;
vec3 Diffuse = texture(gAlbedo, _texcoord).rgb;
float Emissive = texture(gAlbedo, _texcoord).a;
vec3 Specular = texture(gAlbedo, _texcoord).rgb;
vec3 Metalness = texture(gMetalness, _texcoord).rgb; // Reflection pass
float AmbientOcclusion = texture(gSsao, _texcoord).r;
vec3 lightColor = vec3(0.3);
// ambient
vec3 ambient = 0.3 * Diffuse;
// diffuse
vec3 lightDir = normalize(vec3(0.0, 0.0, 0.0) - FragPos);
float diff = max(dot(lightDir, Normal), 0.0);
vec3 diffuse = diff * lightColor;
// specular
vec3 viewDir = normalize(camera_pos - 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 = calculate_shadows(FragPos);
vec3 lighting = (ambient + (1.0 - shadow) * (diffuse + specular));
FragColor = vec4(lighting, 1.0);
}
pointshadows顶点着色器
#version 330 core
layout(location = 0) in vec3 position;
uniform mat4 model;
void main(void)
{
gl_Position = model * vec4(position, 1.0);
}
点阴影片段着色器
#version 330 core
in vec4 FragPos;
void main(void)
{
float lightDistance = length(FragPos.xyz - vec3(0.0, 3.0, 0.0));
// map to [0;1] range by dividing by far_plane
lightDistance = lightDistance / 25.0;
// write this as modified depth
gl_FragDepth = lightDistance;
}
点阴影几何着色器
#version 330 core
layout (triangles) in;
layout (triangle_strip, max_vertices = 18) out;
uniform mat4 shadowMatrices[6];
out vec4 FragPos;
void main(void)
{
for(int face = 0; face < 6; ++face)
{
gl_Layer = face; // built-in variable that specifies to which face we render.
for(int i = 0; i < 3; ++i) // for each triangle's vertices
{
FragPos = gl_in[i].gl_Position;
gl_Position = shadowMatrices[face] * FragPos;
EmitVertex();
}
EndPrimitive();
}
}
温度点阴影class
#ifndef __POINTSHADOWPASS
#define __POINTSHADOWPASS
#include "Content.h"
class PointShadowPass
{
private:
static unsigned int _shadow_fbo;
public:
static unsigned int _shadow_texture;
static glm::vec3 lightPos;
static std::vector<glm::mat4> shadowTransforms;
PointShadowPass() {}
~PointShadowPass() {}
inline static void Initialise()
{
lightPos = glm::vec3(0.0f, 0.0f, 0.0f);
glGenFramebuffers(1, &_shadow_fbo);
glGenTextures(1, &_shadow_texture);
glBindTexture(GL_TEXTURE_2D, _shadow_texture);
for (unsigned int i = 0; i < 6; i++)
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_DEPTH_COMPONENT, 1024, 1024, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
glBindFramebuffer(GL_FRAMEBUFFER, _shadow_fbo);
glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, _shadow_texture, 0);
glDrawBuffer(GL_NONE);
glReadBuffer(GL_NONE);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
inline static void Render(unsigned int pointshadow_program, Camera* camera, std::vector<Actor*> _actors)
{
glDisable(GL_BLEND); // Disable blending for opique materials
glEnable(GL_DEPTH_TEST); // Enable depth test
glm::mat4 model;
glm::mat4 shadowProj = glm::perspective(glm::radians(90.0f), (float)1024 / (float)1024, 1.0f, 25.0f);
shadowTransforms.push_back(shadowProj * glm::lookAt(lightPos, lightPos + glm::vec3(1.0f, 0.0f, 0.0f), glm::vec3(0.0f, -1.0f, 0.0f)));
shadowTransforms.push_back(shadowProj * glm::lookAt(lightPos, lightPos + glm::vec3(-1.0f, 0.0f, 0.0f), glm::vec3(0.0f, -1.0f, 0.0f)));
shadowTransforms.push_back(shadowProj * glm::lookAt(lightPos, lightPos + glm::vec3(0.0f, 1.0f, 0.0f), glm::vec3(0.0f, 0.0f, 1.0f)));
shadowTransforms.push_back(shadowProj * glm::lookAt(lightPos, lightPos + glm::vec3(0.0f, -1.0f, 0.0f), glm::vec3(0.0f, 0.0f, -1.0f)));
shadowTransforms.push_back(shadowProj * glm::lookAt(lightPos, lightPos + glm::vec3(0.0f, 0.0f, 1.0f), glm::vec3(0.0f, -1.0f, 0.0f)));
shadowTransforms.push_back(shadowProj * glm::lookAt(lightPos, lightPos + glm::vec3(0.0f, 0.0f, -1.0f), glm::vec3(0.0f, -1.0f, 0.0f)));
glViewport(0, 0, 1024, 1024);
glBindFramebuffer(GL_FRAMEBUFFER, _shadow_fbo);
glClear(GL_DEPTH_BUFFER_BIT);
glUseProgram(pointshadow_program);
for (unsigned int i = 0; i < 6; ++i)
glUniformMatrix4fv(glGetUniformLocation(pointshadow_program, ("shadowMatrices[" + std::to_string(i) + "]").c_str()), 1, GL_FALSE, glm::value_ptr(shadowTransforms[i]));
for (unsigned int i = 0; i < _actors.size(); i++)
{
model = _actors[i]->GetModelMatrix() * camera->GetViewMatrix();
glUniformMatrix4fv(glGetUniformLocation(pointshadow_program, "model"), 1, GL_FALSE, glm::value_ptr(model)); // set the model matrix uniform
_actors[i]->Render();
}
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
};
std::vector<glm::mat4> PointShadowPass::shadowTransforms;
unsigned int PointShadowPass::_shadow_fbo;
unsigned int PointShadowPass::_shadow_texture;
glm::vec3 PointShadowPass::lightPos;
#endif
我设法显示了一些东西(阴影随相机旋转而移动)
看了你的评论,你似乎对延迟渲染中可以拥有哪些信息有一些误解?
您说所有坐标都必须在屏幕上space,这是不正确的。对于延迟渲染,您有一个 G-Buffer,您可以在其中放置您想要的任何类型的信息。要获取世界位置信息,您有两种选择,要么拥有世界位置缓冲区,这样您就知道每个片段在世界中的位置。或者您可以从深度缓冲区和相机投影矩阵返回计算此信息。
如果你有一个在前向渲染中工作的点阴影计算,你可以在延迟渲染中做同样的事情,在做所有光计算的着色器中你需要阴影立方体贴图,光位置,你像你一样做计算习惯了。
编辑:
查看 calculate_shadows(vec3 light_space_pos)
的代码,在延迟渲染中,您不会向它发送您在光线 space 中的位置,而是在世界 space 中的位置。所以函数应该是:
calculate_shadows(vec3 frag_world_pos)
第一行 vec3 fragToLight = light_space_pos - vec3(0.0f, 0.0f, 0.0f);
应该是vec3 fragToLight = frag_world_pos- lightPos
.
或者您在使用该函数之前进行此计算。无论哪种方式,您都需要点光源的位置来计算片段和光源之间的方向和距离。