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 매개 변수 ab. 이 곡선의 작동 방식을 이해하려면 매개 변수를 대화식으로 사용하는 것이 좋습니다 . 이 곡선은 장거리에서 물리적으로 올바른 역 제곱 법칙에 접근하기 때문에 좋지만 단거리에서 무한대로 쏘지 않습니다. 사실, 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 = 9minLight = 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.