2016-11-18 16 views
5

Tôi đang thêm bóng vào một cảnh trong OpenGL bằng cách thực hiện hai đường vẽ, một đến bản đồ độ sâu và một đến bộ đệm khung bình thường.OpenGL shadow peter-panning

Không sử dụng sai lệch khi sử dụng bản đồ độ sâu, có rất nhiều mụn trứng cá.

shadow acne without bias

này được cố định bằng cách thêm một sự thiên vị để kiểm tra bản đồ độ sâu.

shadow with bias

Tuy nhiên, điều này gây ra bóng tối để 'Mở cửa sổ mới' từ đối tượng khi ánh sáng được chuyển đến một góc độ khác nhau.

peter panning

tôi tin rằng hiệu ứng này được gọi là peter-panning và được gây ra bởi một sự thiên vị lớn hơn được sử dụng cho các góc khác nhau.

Việc sửa lỗi thông thường cho việc này có vẻ là hủy các hình tam giác khi vẽ bản đồ bóng, tuy nhiên khi mặt phẳng sàn là đối tượng 2D, tôi không tin điều này sẽ hoạt động đúng.

Địa hình thực tế tôi đang sử dụng được tạo theo cách thủ công và do đó, việc tạo phiên bản 3D của nó giống như trong ví dụ đơn giản này không hề đơn giản.

Làm cách nào để xoay khung hình được cố định trên một đối tượng 2D như thế này?


Vertex Shader

#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; 
} 

Fragment Shader

#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); 
} 
+0

Bạn có thể vẽ địa hình của bạn hai lần trong bóng tối lật các tam giác bình thường và bù đắp chúng bởi sự thiên vị trong hướng nhìn trong bóng đổ một lần - nó sẽ tăng gấp đôi hình tam giác rút ra nhưng nó sẽ cho phép bạn kích hoạt mặt sau culling (vì vậy nó nên ngay cả ở mức tối thiểu). Và vâng, trong kỹ thuật peter-panning này đang leo lên, luôn luôn. – BeyelerStudios

+0

Độ lệch quy mô độ dốc thường được giới thiệu trong giai đoạn xây dựng shadowmap để khắc phục vấn đề này. Tra cứu 'glDepthOffset'. Biết rằng điều này sẽ phá vỡ một số loại tối ưu hóa bộ đệm độ sâu trong khi dựng hình, nhưng điều đó có thể không quan trọng vì bạn chỉ cần lấp đầy bộ đệm sâu và không chạy trình đổ bóng phân đoạn phức tạp. –

+0

Cảm ơn, tôi sẽ thử những điều này. – Caw

Trả lời

2

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

Tính toán chặt chẽ gần máy bay và máy bay xa cũng giúp tránh Peter Panning.

Slope-Scale Depth Bias

Như đã đề cập trước đây, tự shadowing có thể dẫn đến mụn trứng cá shadow. Thêm quá nhiều thiên vị có thể dẫn đến Peter Panning. Ngoài ra, đa giác có sườn dốc (so với ánh sáng) bị ảnh hưởng nhiều hơn từ bí danh dự đoán so với đa giác có độ dốc nông (so với ánh sáng ). Bởi vì điều này, mỗi giá trị độ sâu bản đồ có thể cần một sự khác biệt bù đắp tùy thuộc vào độ dốc của đa giác liên quan đến ánh sáng.

Phần cứng Direct3D 10+ có khả năng thiên vị đa giác dựa trên độ dốc của nó theo hướng xem. Điều này có ảnh hưởng của áp dụng độ lệch lớn cho đa giác được xem cạnh trên theo hướng ánh sáng, nhưng không áp dụng bất kỳ sai lệch nào cho đa giác đối diện với ánh sáng trực tiếp.Hình 10 minh họa cách hai điểm ảnh lân cận có thể luân phiên giữa bóng mờ và không bị che khuất khi thử nghiệm trên cùng một độ dốc không thiên vị .

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

Vấn đề là để xác định tối ưu bù đắp cho mỗi sâu trong bóng tối bản đồ . Nếu bạn áp dụng không đủ bù đắp, z-fighting sẽ vẫn còn hiện diện. Nếu bạn áp dụng chênh lệch rất lớn thì Peter Panning sẽ trở thành đáng chú ý. Bù đắp sẽ phụ thuộc vào độ chính xác của bản đồ bóng và trên độ dốc của bề mặt so với hướng của nguồn sáng.

OpenGL có thể tự động tính toán và thêm bù đắp cho các giá trị được được lưu trữ trong bộ đệm Z. Bạn có thể thiết lập bù đắp với chức năng glPolygonOffset . Hai thông số có sẵn: nhân cho bù đắp mà phụ thuộc vào độ dốc của bề mặt, và giá trị xác định lượng thêm offsets nhỏ nhất có thể (phụ thuộc vào định dạng của bóng bản đồ):

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