Công thức GLSL Light (Độ suy giảm, Màu sắc và cường độ)


17

Tôi đang triển khai đèn điểm trong động cơ Voxel của mình và tôi thực sự đang nỗ lực để có được luồng ánh sáng tốt, từ 100% gần nguồn sáng đến 0% ở bán kính ánh sáng.

Tôi có 5 đối số cho hàm:

  1. Màu sáng (Vec3)
  2. Cường độ ánh sáng (khoảng cách từ ánh sáng cho đến khoảng cách 100%)
  3. Khoảng cách từ ánh sáng đến mảnh
  4. Góc từ mảnh bình thường đến ánh sáng
  5. Vị trí của ánh sáng

Bất cứ ai có thể đẩy tôi đi đúng hướng để tạo ra một hàm cho việc tính toán màu của mảnh?

Hình ảnh về một trong những thí nghiệm của tôi:

Thử nghiệm chiếu sáng động cơ Voxel Per-Fragment

Chỉnh sửa (mã hiện tại do Byte yêu cầu) Lưu ý rằng đây chỉ là một số mã thử nghiệm từ phía tôi. Tôi đã nhận được float từ một trang web, và nó hoạt động, nhưng không hoàn hảo. :

void main()
{
// Light color
vec3 torchColor = vec3(1.0f, 1.0f, 1.0f);

float lightAdd = 0.0f;
for (int i=0; i<5; i++) {
    vec3 pos = lights[i];
    if (pos.x == 0.0f) continue;

    float dist = distance(vertex_pos, pos);
    if (dist < 9) {
        float att=1.0/(1.0+0.1*dist+0.01*dist*dist);
        vec3 surf2light = normalize(pos - vertex_pos);
        vec3 norm = normalize(normal);
        float dcont=max(0.0,dot(norm,surf2light));
        lightAdd += att*(dcont+0.4);
    }
}

vec3 textureColor = texture2D(texture, texture_coordinate).rgb;
vec3 torch_output = lightAdd * torchColor;

vec3 final_color = ((0.1+torch_output) * textureColor);

gl_FragColor = vec4(final_color, 1.0f); 
}

6
Bạn vẫn đang nói những điều như "đấu tranh để có được vẻ ngoài đẹp , ánh sáng tự nhiên " và "hoạt động, nhưng không hoàn hảo ". Bạn cần bao gồm ngôn ngữ cụ thể, chính xác. Chúng tôi không biết những gì tốt đẹp đối với bạn, hoặc ánh sáng tự nhiên trông như thế nào đối với bạn, hoặc hoàn hảo là gì.
MichaelHouse

2
Bạn đã thử loại bỏ if (dist < 9)? Hoặc bạn có thể tính toán attvới một hàm trả về 1 khi khoảng cách là 0 và 0 khi khoảng cách là 9. Ví dụ:mix(1.0, 0.0, dist / 9.0)
msell

Câu trả lời:


39

Hàm suy giảm mà bạn có,

att = 1.0 / (1.0 + 0.1*dist + 0.01*dist*dist)

là một thứ khá phổ biến trong đồ họa máy tính - hay nói chung hơn là 1.0 / (1.0 + a*dist + b*dist*dist))đối với một số thông số có thể điều chỉnh ab. Để hiểu cách thức hoạt động của đường cong này, thật hữu ích khi chơi với các tham số tương tác . Đường cong này là tốt bởi vì nó tiếp cận luật bình phương nghịch đảo vật lý chính xác ở khoảng cách lớn, nhưng nó không bắn lên đến vô tận ở khoảng cách ngắn. Trong thực tế, với a = 0nó là một mô hình khá tốt của ánh sáng khu vực hình cầu.

Tuy nhiên, một nhược điểm của nó là ánh sáng không bao giờ hoàn toàn về 0 ở bất kỳ khoảng cách hữu hạn nào. Đối với các mục đích thực tế trong CG thời gian thực, chúng ta thường cần phải cắt đèn ở khoảng cách hữu hạn, như bạn đang làm với if (dist < 9)mệnh đề. Tuy nhiên, bán kính 9 quá ngắn - với các cài đặt của bạn trong chức năng suy giảm, ánh sáng không gần bằng 0 cho đến khi khoảng cách khoảng 100.

Bạn có thể tính bán kính của ánh sáng từ btham số trong hàm suy giảm (vì thuật ngữ bậc hai chiếm ưu thế ở khoảng cách lớn). Giả sử bạn muốn tắt đèn khi độ suy giảm đạt đến một số giá trị minLight, như 0,01. Sau đó thiết lập

radius = sqrt(1.0 / (b * minLight))

Điều đó cho bán kính 100 cho b = 0.01minLight = 0.01. Ngoài ra, bạn có thể đặt bán kính và tính toán bđể khớp:

b = 1.0 / (radius*radius * minLight)

Cho radius = 9minLight = 0.01, điều đó mang lại b = 1.23. Bạn có thể thiết lập nó theo bất kỳ cách nào, nhưng điều quan trọng là làm cho bán kính và chức năng suy giảm khớp với nhau để bạn không tắt đèn cho đến khi chức năng suy giảm rất thấp, do đó bạn sẽ không thấy cạnh sắc nét.


Tất cả những gì đã nói, có những chức năng suy giảm thay thế mà bạn có thể sử dụng. Một điều khá phổ biến khác là:

att = clamp(1.0 - dist/radius, 0.0, 1.0); att *= att

hoặc người hâm mộ hơi:

att = clamp(1.0 - dist*dist/(radius*radius), 0.0, 1.0); att *= att

Chơi với các thông số cho những người quá. Những đường cong này có lợi thế là chính xác về 0 tại bán kính nhất định, trong khi vẫn trông giống như luật bình phương nghịch đảo tự nhiên.


Tuyệt quá! Mặc dù, tôi muốn sử dụng maxtrên clampchỉ lý do hiệu suất.
Mike Weir

4
@Mikeweir Kẹp vào [0, 1] thực sự miễn phí trên nhiều GPU. Đó là một hoạt động phổ biến đến nỗi họ có nó như một công cụ sửa đổi hướng dẫn.
Nathan Reed
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.