GLSL Light (감쇠, 색 및 강도) 공식


17

Voxel 엔진에서 포인트 라이트를 구현하고 있으며 광원 근처에서 100 %에서 빛 반경에서 0 %까지 좋은 빛의 흐름을 얻기 위해 고심하고 있습니다.

함수에 대한 5 개의 인수가 있습니다.

  1. 연한 색 (Vec3)
  2. 빛의 강도 (감쇠가 100 % 인 거리까지 빛으로부터의 거리)
  3. 빛에서 조각까지의 거리
  4. 파편 법선에서 빛까지의 각도
  5. 빛의 위치

누구든지 올바른 방향으로 밀어서 조각 색상 계산 기능을 만들 수 있습니까?

내 실험 중 하나의 이미지 :

복셀 엔진 별 조명 테스트

편집 (Byte가 요청한 현재 코드) 이것은 내 측면의 실험 코드 일뿐입니다. 나는 웹 사이트에서 float att를 얻었고 종류는 작동하지만 완벽하지는 않습니다. :

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
당신은 여전히 "는 고군분투 같은 것을 말하고있는 좋은 찾고 , 자연 조명 "하지만, 작품을 " 까지 완벽한에서 ". 구체적이고 정확한 언어를 포함해야합니다. 우리는 당신에게 잘 어울리는 것이 무엇인지, 자연광이 당신에게 어떤 모양인지, 어떤 것이 완벽한 지 모릅니다.
— MichaelHouse

2
제거를 시도 했습니까 if (dist < 9)? 또는 당신은 계산할 수있는 att거리가 9 예 때 거리가 0, 0 일 때 반환 한하는 기능mix(1.0, 0.0, dist / 9.0)
— msell

답변:


39

당신이 가진 감쇠 기능,

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

더 일반적이나, - 매우 일반적인 컴퓨터 그래픽의 하나입니다 1.0 / (1.0 + a*dist + b*dist*dist))일부 tweakable 매개 변수 a및 b. 이 곡선의 작동 방식을 이해하려면 매개 변수를 대화식으로 사용하는 것이 좋습니다 . 이 곡선은 장거리에서 물리적으로 올바른 역 제곱 법칙에 접근하기 때문에 좋지만 단거리에서 무한대로 쏘지 않습니다. 사실, a = 0구형 영역 라이트의 아주 좋은 모델입니다.

그러나 한 가지 단점은 유한 한 거리에서 빛이 절대로 0이되지 않는다는 것입니다. 실시간 CG에서의 실제적인 목적을 위해, 우리는 일반적으로 당신이 if (dist < 9)절에서 하는 것처럼 유한 한 거리에서 조명을 차단해야합니다 . 그러나 반지름 9는 너무 짧습니다. 감쇠 기능 설정으로 인해 거리가 약 100이 될 때까지 빛이 0에 가까워지지 않습니다.

b감쇠 함수 의 매개 변수에서 빛의 반경을 계산할 수 있습니다 (2 차 항이 먼 거리를 차지하기 때문에). 감쇠가 minLight0.01과 같은 값에 도달하면 조명을 차단한다고 가정 해 봅시다 . 그런 다음 설정

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

b = 0.01와에 대해 반지름이 100입니다 minLight = 0.01. 또는 반경을 설정하고 다음 b과 일치하도록 계산할 수 있습니다 .

b = 1.0 / (radius*radius * minLight)

들어 radius = 9와 minLight = 0.01, 그 준다 b = 1.23. 어느 쪽이든 설정할 수 있지만, 핵심은 반경과 감쇠 기능을 일치시켜 감쇠 기능이 이미 매우 낮을 때까지 빛을 차단하지 않으므로 날카로운 모서리가 표시되지 않는 것입니다.


그러나, 대체 감쇠 기능을 사용할 수 있습니다. 상당히 일반적인 또 하나는 다음과 같습니다.

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

또는 약간 더 멋진 :

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

그 파라미터 들도 함께 연주하십시오 . 이 곡선들은 주어진 반지름에서 정확히 0 이되는 장점을 가지 면서도 자연의 역 제곱 법과 비슷하게 보입니다.


큰! 비록, 내가 사용하는 것 max이상의 clamp성능상의 이유로 만.
— Mike Weir

4
@MikeWeir [0, 1] 로의 클램핑은 실제로 많은 GPU에서 무료입니다. 명령 수정 자로 사용하는 것은 일반적인 작업입니다.
— Nathan Reed
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.