Bản đồ bóng phương sai không muốn hiển thị đúng


8

Tôi đã triển khai VSM (và cả ESM) trong công cụ của mình nhưng kết quả đối với tôi không như tôi mong đợi và thấy trong nhiều ví dụ được công bố trên mạng.

Tôi đặt tính năng lọc bản đồ bóng thành GL_LINEAR nhưng khi tôi so sánh kết quả với bản đồ bóng bình thường thì nó rõ ràng tệ hơn.

Màn

Tôi đã thử tính toán các khoảnh khắc trực tiếp trong shader ánh sáng điểm hoặc lấy nó từ kết cấu như trong hầu hết các hướng dẫn nhưng kết quả là như nhau.

Mã số:

uniform samplerCubeShadow shadowMap;

...

vec4 worldSpace=inverse(ViewMatrix)*vec4(pos,1);

vec4 coord=LightViewMatrix*worldSpace;
vec4 abs_coord=abs(coord);

float fs_z=-max(abs_coord.x, max(abs_coord.y, abs_coord.z));

vec4 clip=LightProjectionMatrix*vec4(0.0,0.0,fs_z,1.0);
float d2=(clip.z / clip.w)*0.5+0.5; // clamp to [0..1]

...

float shadowTexel=texture(shadowMap,vec4(coord.xyz,d2));

// VSM (Variance Shadow Map)
// get partial derivatives
float dx = dFdx(d2);
float dy = dFdy(d2);
vec2 moments = vec2(d2, d2*d2+0.25*(dx*dx+dy*dy));
return chebychevInequality(moments, shadowTexel);

Sử dụng mã này tôi nhận được kết quả như trên hình ảnh. Tôi cũng đã cố gắng không sử dụng samplerCubeShadow nhưng samplerCube nhưng kết quả thậm chí còn tồi tệ hơn. Đầu tiên, tôi có bóng cứng. Thứ hai, bóng đổ không lấp đầy diện tích như bình thường khi có được khoảnh khắc từ kết cấu khác. Nhìn vào màn hình thứ hai. Đây cũng là nhìn vào bản đồ khối tạo ra. Nó không giống với những gì trong bản đồ độ sâu ngay cả khi tôi đặt độ sâu / khoảnh khắc1 ở cả 3 kênh.

Shader để có được khoảnh khắc:

// Vartex shader
gl_Position=ModelViewProjectionMatrix*Vertex;
v_position=gl_Position;

// Fragment shader
float depth = v_position.z / v_position.w ;
depth = depth * 0.5 + 0.5;          //Don't forget to move away from unit cube ([-1,1]) to [0,1] coordinate system

float moment1 = depth;
float moment2 = depth * depth;

// Adjusting moments (this is sort of bias per pixel) using derivative
float dx = dFdx(depth);
float dy = dFdy(depth);
moment2 += 0.25*(dx*dx+dy*dy) ;

FragColor = vec4( moment1,moment2, 0.0, 0.0 );

Màn

Tôi thực sự bế tắc. Tôi hy vọng bạn sẽ giúp mi giải quyết vấn đề của tôi.

BIÊN TẬP:

Tôi đã tìm thấy giải pháp cho vấn đề thứ hai. Tôi đã kích hoạt pha trộn và nó cho tôi bản đồ độ sâu sai.

Tôi cũng nhận được kết quả tốt hơn cho vấn đề đầu tiên nhưng bây giờ tôi đang chiến đấu với độ sâu phù hợp để so sánh nó với độ sâu từ bản đồ bóng tối.

Trong SM đơn giản tôi sử dụng mã này:

vec4 worldSpace=inverse(ViewMatrix)*vec4(pos,1);

vec4 coord=LightViewMatrix*worldSpace;
vec4 abs_coord=abs(coord);

float fs_z=-max(abs_coord.x, max(abs_coord.y, abs_coord.z));

vec4 clip=LightProjectionMatrix*vec4(0.0,0.0,fs_z,1.0);
float d=(clip.z / clip.w)*0.5+0.5; // clamp to [0..1]

trong đó pos là vị trí trong View Space. Sau đó, tôi đọc các giá trị từ bản đồ bóng bằng cách sử dụng:

texture(shadowMap,vec4(coord.xyz,d))

Trong VSM, tôi lưu trữ độ sâu trong kênh R trong kết cấu RG32F. Giá trị độ sâu được tính theo cách này:

// VS
gl_Position=ModelViewProjectionMatrix*Vertex;
v_position=gl_Position;

// FS
float depth = v_position.z/v_position.w;
depth = depth * 0.5 + 0.5;

Sau đó, trong shader cho ánh sáng điểm, tôi sử dụng vectơ tọa độ (như trong SM tiêu chuẩn) để đọc các giá trị từ bản đồ bóng và điều này hoạt động tốt. Nhưng vấn đề là ở phần này:

// No shadow if depth of fragment is in front
if ( moments.x <= distance)
    return 1.0;

Trong khoảng cách tọa độ nên được nhận? Trong tọa độ nào tôi có chiều sâu từ bản đồ bóng tối? Nó nên tuyến tính? Ai đó có thể giải thích cho tôi điều đó? Bây giờ tôi hơi bối rối, tôi đã thử nhiều cách để có được điều này và tất cả các kết quả không như tôi mong đợi.

EDIT2: Theo mẹo của JarkkoL và hướng dẫn này tôi đã thay đổi mã của mình. Bây giờ tôi đang lưu trữ độ sâu bằng cách sử dụng mã này:

// VS
v_position=ModelViewMatrix*Vertex;
gl_Position=ProjectionMatrix*v_position;

// FS
const float Near = 0.1;
const float Far = 90.0; // camera far plane
const float LinearDepthConstant = 1.0 / (Far - Near);

float depth = length(v_position)*LinearDepthConstant;

Và tôi so sánh nó với giá trị mà tôi có được theo cách này:

float dist=length( vec3(inverse(ViewMatrix)*vec4(pos,1.0)) - PointLight.position )*LinearDepthConstant; // pos is read from depth buffer and is in view space so I want invert it to world space as it was in tutorial

Và đây là kết quả:

Màn hình3

Trong vòng tròn màu đỏ, tôi đánh dấu đường viền có thể nhìn thấy giữa các mặt bản đồ khối. Vẫn còn một cái gì đó sai. Tôi nghĩ rằng điều đó có thể xảy ra khi đảo ngược View Matrix nhưng tôi không chắc chắn.


Tôi đã thêm thông tin về tiến trình hiện tại của mình.
Harry

1
Bạn không nên sử dụng độ sâu phi tuyến tính mà bạn hiện đang sử dụng
JarkkoL

Cảm ơn vì tiền hỗ trợ. Tôi đã cố gắng làm theo nó và tôi đã chỉnh sửa bài đăng với kết quả mới của tôi.
Harry

Hãy thử cài đặt chế độ địa chỉ để kẹp cho sơ đồ khối
JarkkoL

Điều này thực sự giúp. Tôi đặt GL_REPEAT cho hình khối và hoàn toàn quên mất điều đó. Dù sao, bóng vsm vẫn không hiển thị như bản đồ bóng đơn giản.
Harry

Câu trả lời:


1

Về đường nối cubemap, bạn chỉ có thể lọc qua các cạnh.

Xem: glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS);

Theo như chất lượng bóng thực tế của bạn, toàn bộ lợi ích của các kỹ thuật VSM và ESM đến từ hình thức đặc biệt mà bài kiểm tra khả năng hiển thị thực hiện. Bạn có thể muốn giới thiệu một yếu tố không đổi cho bóng tối quá hoặc dưới, để cạnh không quá khó.

Đối với dữ liệu ESM, điều này rất đơn giản:

light = exp(factor * (occluder - receiver));
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.