Dải đặc biệt với sức mạnh cao


8

Chúng tôi đang gặp một số vấn đề với việc dò tia của chúng tôi trong DirectX, đặc biệt là với một số vấn đề về dải nghiêm trọng với đặc điểm kỹ thuật. Với sức mạnh đầu cơ cao (trên 8) bắt đầu dải. Tôi đang tự hỏi liệu đây có phải là sự cố HDR / LDR hay có thể liên quan đến vấn đề khác, chẳng hạn như quy tắc hoặc các vectơ khác không?

CẬP NHẬT

Nhìn bên dưới để cập nhật.

Đây là mã shader có liên quan cho Blinn-Phong trên một hình cầu:

float3 hitPoint = thisRay.origin + thisRay.direction * bestHit.hitT;
float3 normal = normalize(hitPoint - spheres[bestHit.hitID].center);
float3 toLight = pointLights[0].position.xyz - hitPoint;
float d = length(toLight);
toLight = normalize(toLight);

float diffuse = max(dot(normal, toLight), 0.0f);

float3 v = normalize(thisRay.origin - hitPoint);
float3 h = normalize(v + toLight);

float spec = 0;
if (diffuse > 0)
    spec = pow(max(dot(normal, h), 0.0f), specPower) * diffuse;

output[threadID.xy] = spheres[bestHit.hitID].colour * diffuse + spheres[bestHit.hitID].specColour * spec;

specPower bằng 8 trong hình ảnh này specPower bằng 8 trong hình ảnh này

specPower bằng 9 trong hình ảnh này specPower bằng 9 trong hình ảnh này

Đây có phải là đơn giản như một vấn đề HDR / LDR hoặc nó bằng cách nào đó liên quan đến độ chính xác bình thường? Tôi tin rằng tôi đã gặp phải vấn đề này trước đây trong một trình kết xuất bị trì hoãn trong đó các thông số có độ chính xác thấp và được đóng gói / giải nén không đúng cách nhưng trong trường hợp này, các quy tắc được tạo ra một cách nhanh chóng và toàn bộ mọi thứ được đưa trực tiếp vào bộ đệm.

Cập nhật 1

Tôi muốn thêm vào ở trên rằng các hình tam giác phải chịu cùng một tạo tác và chúng có hiện tại bình thường theo cách sau:

float3 normal = normalize(cross(triangles[bestHit.hitID].vertices[1] - triangles[bestHit.hitID].vertices[0],
                                    triangles[bestHit.hitID].vertices[2] - triangles[bestHit.hitID].vertices[0]));

Tôi muốn nói điều này làm cho nhiều khả năng rằng sự bình thường của bề mặt là vấn đề. Hình ảnh sau đây cho thấy những gì xảy ra khi specPower đạt 2048.

nhập mô tả hình ảnh ở đây


1
chỉ cần đoán: thử float3 h = normalize( reflect(toLight,normal) );spec = pow(dot(v, h) * 0.5 + 0.5, specPower) * diffuse;
Raxvan

Xin lỗi để nói điều này sản xuất cùng một tạo tác.
Bentebent

4
Trông giống như một vấn đề tràn. Giá trị của bạn sẽ về 0, nhưng thay vào đó là khoảng 1. Hãy thử xuất giá trị spectrực tiếp và cả max(dot(normal, h), 0.0f). Hãy tìm giá trị này cho giá trị 1 trong cả hai phép tính.

Hình ảnh này cho thấy tại điểm nào thông số kỹ thuật vượt quá 0,9f để có vẻ như nó có thể là thủ phạm. imgur.com/YbTS8m5
Bentebent

Trong khi đó, max (dấu chấm (bình thường, h), 0,0f) trông như thế này ( imgur.com/YV22egw ) khi xuất các giá trị trên 0,99f.
Bentebent

Câu trả lời:


1

Có vẻ như là một vấn đề với việc thực hiện chức năng pow trên GPU cụ thể này.

Khi nghi ngờ một lỗi trong hàm toán học thay thế hàm toán học bằng hàm tương đương, ví dụ: thay thế:

spec = pow(max(dot(normal, h), 0.0f), specPower) * diffuse;

Với lỗi hiển thị tại specPower = 9.0, hãy mã hóa nó thành

float temp = max(dot(normal, h), 0.0f);
spec = pow(temp, 8.0) * temp * diffuse;

Hoặc là

float temp = max(dot(normal, h), 0.0f);
spec = temp * temp * temp * temp * temp * temp * temp * temp * temp * diffuse;

Nếu sự cố không còn nữa, điều này có nghĩa là có thể có lỗi tràn trong hàm pow liên quan đến số mũ trên GPU hoặc trình điều khiển này.

Những gì bạn có thể làm như một công việc xung quanh, giả sử tính toán shader mảnh được thực hiện bên trong với số float 16bit. Nếu tôi tính đúng thì bạn nên làm

pow(max(temp, (Nth root of (1.0/16384.0))), N);

Nó có thể là 32768 hoặc 8192: Tôi có thể tắt một bit hoặc GPU có thể sử dụng độ chính xác nhiều hơn hoặc ít hơn. đối với pow (x, 9.0), kẹp sẽ là pow (max (temp, 0.3401975), 9.0) Các giá trị của X bên dưới này sẽ vượt quá phạm vi số mũ (+15 đến -14) của các điểm nổi IEEE 16 bit (một lần nữa, tôi giả sử đây là những gì GPU sử dụng.)

từ mã rosetta ( http://rosettacode.org/wiki/Nth_root#C.2B.2B )

double NthRoot(double value, double degree)
{
    return pow(value, (double)(1 / degree));
};

my_shader->SetUniform("specular_minimum", NthRoot((1.0/16384.0), specPower));

Bạn sẽ phải tính toán điều này trên CPU và cung cấp giá trị một cách thống nhất: GPU có thể sẽ có cùng một vấn đề chính xác nếu bạn tính toán điều này ngay trong trình đổ bóng.

Nếu bạn có thể xác nhận điều này, hãy thử liên hệ với nhóm trình điều khiển GPU với mã nguồn shader mẫu sao chép vấn đề, cung cấp cho họ phiên bản trình điều khiển chính xác, HĐH và sửa đổi mô hình GPU, một tệp thực thi có thể giúp nhưng đừng gửi nó vì email của bạn sẽ bị mắc kẹt trong trình kiểm tra virus / spam. Chỉ cần xây dựng một và giữ một bản sao trong trường hợp họ yêu cầu một mẫu thực thi được xây dựng trước. Như một phép lịch sự, hãy cho họ cơ hội sửa nó trước khi đặt tên công khai. Nó đơn giản có thể là một lỗi tối ưu hóa trong trình biên dịch shader của chúng chỉ xảy ra với trình đổ bóng cụ thể của bạn. Có thể mất một thời gian (vài tháng) để liên lạc với họ, những kẻ này thường không được bảo vệ.

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.