OpenGL阴影平移 [英] OpenGL shadow peter-panning

查看:85
本文介绍了OpenGL阴影平移的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我通过两次绘制过程将阴影添加到OpenGL中的场景中,一次绘制到深度图,另一次绘制到正常帧缓冲区.

I'm adding shadows to a scene in OpenGL by doing two draw passes, one to a depth map and one to the normal frame buffer.

在使用深度图时不使用任何偏见,会有很多暗疮痤疮.

Without using a bias when using the depth map, there is a lot of shadow acne.

通过在深度图检查中添加偏差来解决此问题.

This is fixed by adding a bias to the depth map check.

但是,当光线移动到另一个角度时,这会导致阴影从对象分离".

However, this causes the shadow to 'detach' from the object when the light is moved to a different angle.

我认为这种效果被称为平移",是由于在不同角度上使用了较大的偏差所致.

I believe this effect is called peter-panning and is caused by a larger bias being used for different angles.

通常的解决方法似乎是在绘制阴影贴图时剔除朝后的三角形,但是由于地板是2D对象,所以我认为这不能正常工作.

The usual fix for this seems to be to cull back facing triangles when drawing the shadow map, however as the floor plane is a 2D object, I don't believe this would work properly.

我正在使用的实际地形是通过过程生成的,因此创建3D版本并不像在这个简单示例中那样简单.

The actual terrain I am using is procedurally generated and so it is not as simple to create a 3D version of it as in this simple example.

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

How can the peter-panning be fixed on a 2D object such as this?

顶点着色器

#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

计算紧密的近平面和远平面也有助于避免Peter Panning.

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

坡度深度偏差

如前所述,自我遮盖可能会导致暗疮痤疮. 添加过多的偏见可能会导致Peter Panning.此外, 斜度较大(相对于光线)的多边形遭受的影响更大 射影别名比具有浅斜率的多边形(相对于 光).因此,每个深度图值可能需要不同的值 偏移量取决于多边形相对于光线的坡度.

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+硬件具有根据其偏向多边形的能力 相对于观察方向的倾斜度.具有以下效果 将大的偏斜应用于在光线上边缘观察的多边形 方向,但不对朝向灯光的多边形施加任何偏压 直接地.图10说明了两个相邻像素如何 在针对阴影进行测试时,在阴影和非阴影之间交替 相同的无偏斜度.

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

问题是要确定阴影中每个深度的最佳偏移量 地图.如果您没有应用足够的偏移,则z角战斗将仍然存在. 如果您应用非常大的偏移量,则Peter Panning将成为 显.偏移量应取决于阴影贴图的精度,并且 表面相对于光源方向的倾斜度.

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可以自动计算并向以下值添加偏移量 存储在Z缓冲区中.您可以使用glPolygonOffset设置偏移量 功能.有两个参数可用:偏移量的乘数 取决于表面的坡度,以及确定 其他可能的最小偏移量(取决于阴影的格式 地图):

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

这篇关于OpenGL阴影平移的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆