gpt4 book ai didi

c++ - OpenGL 阴影平移

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:39:48 25 4
gpt4 key购买 nike

我通过两次绘制过程为 OpenGL 中的场景添加阴影,一次绘制到深度图,一次绘制到普通帧缓冲区。

在使用深度贴图的时候没有使用bias,有很多阴影粉刺。

shadow acne without bias

这是通过向深度图检查添加偏差来解决的。

shadow with bias

但是,当光线移动到不同的角度时,这会导致阴影与物体“分离”。

peter panning

我相信这种效果被称为彼得平移,是由于对不同角度使用了更大的偏差造成的。

通常的解决方法似乎是在绘制阴影贴图时剔除背面的三角形,但是由于地板平面是 2D 对象,我认为这不会正常工作。

我使用的实际地形是程序生成的,因此创建它的 3D 版本并不像这个简单示例中那么简单。

如何才能将彼得平移固定在这样的 2D 对象上?


顶点着色器

#version 400

layout(location = 0) in vec3 position;
layout(location = 1) in vec3 normal;
layout(location = 2) in vec2 texture_coords;

out VS_OUT {
vec4 position;
vec3 normal;
vec2 texture_coords;
vec4 shadow_position;
} vs_out;

uniform mat4 model;
uniform mat4 model_view;
uniform mat4 model_view_perspective;
uniform mat3 normal_matrix;
uniform mat4 depth_matrix;

void main() {
vec4 position_v4 = vec4(position, 1.0);

vs_out.position = model_view * position_v4;
vs_out.normal = normal_matrix * normal;
vs_out.texture_coords = texture_coords;
vs_out.shadow_position = depth_matrix * model * position_v4;

gl_Position = model_view_perspective * position_v4;
}

片段着色器

#version 400

in VS_OUT {
vec4 position;
vec3 normal;
vec2 texture_coords;
vec4 shadow_position;
} fs_in;

out vec4 colour;

uniform mat4 view;
uniform mat4 model_view_perspective;
uniform vec3 light_position;
uniform vec3 emissive_light;
uniform float shininess;
uniform int textured;
uniform sampler2D tex;
uniform sampler2DShadow shadow_texture;

void main() {
const vec3 specular_albedo = vec3(1.0, 0.8, 0.6);

colour = vec4(0.8, 0.8, 0.8, 0.8);
if(textured != 0) {
colour = texture(tex, fs_in.texture_coords);
}

vec3 light_direction = normalize(light_position);
vec3 normal = normalize(fs_in.normal);

float visibility = 1.0;
if(fs_in.shadow_position.z <= 1.0) {
float bias = max(0.05 * (1.0 - dot(normal, light_direction)), 0.005);
if(fs_in.shadow_position.z > texture(shadow_texture, fs_in.shadow_position.xyz, 0.0) + bias){
visibility = 0.0;
}
}

/* Ambient */
vec3 ambient = colour.xyz * 0.1;

/* Diffuse */
vec3 diffuse = visibility * (clamp(dot(normal, light_direction), 0, 1) * colour.xyz);

/* Specular */
vec3 specular = vec3(0.0);
if(dot(normal, light_direction) > 0) {
vec3 V = normalize(-fs_in.position.xyz);
vec3 half_dir = normalize(light_direction + V);
specular = visibility * (pow(max(dot(normal, half_dir), 0.0), shininess) * specular_albedo.xyz);
}

colour = vec4(((ambient + diffuse) * colour.xyz) + specular + emissive_light, 1.0);
}

最佳答案

https://msdn.microsoft.com/en-us/library/windows/desktop/ee416324(v=vs.85).aspx

Calculating tight near planes and far planes also helps avoid Peter Panning.

Slope-Scale Depth Bias

As previously mentioned, self-shadowing can lead to shadow acne. Adding too much bias can result in Peter Panning. Additionally, polygons with steep slopes (relative to the light) suffer more from projective aliasing than polygons with shallow slopes (relative to the light). Because of this, each depth map value may need a different offset depending on the polygon's slope relative to the light.

Direct3D 10+ hardware has the ability to bias a polygon based on its slope with respect to the view direction. This has the effect of applying a large bias to a polygon that is viewed edge-on to the light direction, but not applying any bias to a polygon facing the light directly. Figure 10 illustrates how two neighboring pixels can alternate between shadowed and unshadowed when testing against the same unbiased slope.

http://www.sunandblackcat.com/tipFullView.php?l=eng&topicid=35

The problem is to determine optimal offset for each depth in shadow map. If you apply not enough offset, z-fighting will be still present. If you apply very large offset then Peter Panning will become noticeable. Offset should depend on precision of the shadow map, and on slope of the surface relative to direction to light source.

OpenGL can automatically compute and add offset to values which are stored in Z-Buffer. You can setup offset with glPolygonOffset function. Two parameters are available: multiplier for offset that depends on slope of the surface, and value that determines amount of additional smallest possible offsets (depends on format of shadow map):

https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glPolygonOffset.xhtml

关于c++ - OpenGL 阴影平移,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40671823/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com