티스토리 뷰

Game/Graphics

Area light

newpolaris 2018. 2. 19. 17:14

RBRT의 경우 적분 형태이고;

PBR 관련 문서 중에 FrostBite였나 거긴 shader code가 첨부되어있다

하지만 바로 이해가 안되므로 설명을 찾아다녔다

GameDev 2009

https://www.gamedev.net/forums/topic/552315-glsl-area-light-implementation/

여러곳에서 사용되었다. 문제점은 존재하는 듯

댓글 중에 "FWIW, ever read this? It's mathematically correct and should be entirely feasible for real-time use. You can even do spherical and n-sided polygonal lights :)"

저기에 this는 아래 논문이다. 길고 이해도 안되서 접음

Area Light Sources for Real-Time Graphics, John Snyder

우선 구현부를 보면

vec3 right = normalize(vec3(gl_ModelViewMatrix*gl_LightSource.ambient));

구형 방식에다가 right를 ambient에 넣어서 대신 전달해서 먼지 이해하기 힘들다

좀 정리된 소스는 아래서 찾을 수 있었다

https://github.com/darrenmothersele/openFrameworks/blob/master/gl/ofMaterial.cpp

main branch에서는 shader로 분리된듯?

https://github.com/openframeworks/openFrameworks/blob/master/libs/openFrameworks/gl/shaders/phong.frag

"areaLight"로 검색하면 된다

https://github.com/openframeworks/openFrameworks/tree/master/examples/gl/areaLightExample

해당 라이트는 우선 diffuse/specular로 나뉘는데 주요 연산은 단순히 light plane에

project 하여 벡터의 크기와 비교하는 것이다.

specular는 반사된 광원을 그리게 되는데

vec3 lightPos = light.position.xyz;
vec3 right = light.right;
// light plane normal, front direction
vec3 direction = light.spotDirection;
vec3 up = light.up;

float width = light.width * 0.5;
float height = light.height * 0.5;

vec3 r = reflect(normalize(uCameraPos - positionW), normalW);
vec3 e = linePlaneIntersect(positionW, r, lightPos, direction);
float specAngle = dot(r, direction);

if (specAngle > 0.0)
{
    vec3 dirSpec = e - lightPos;
    vec2 dirSpec2D = vec2(dot(dirSpec, right), dot(dirSpec, up));
    vec2 nearestSpec2D = vec2(clamp(dirSpec2D.x, -width, width), clamp(dirSpec2D.y, -height, height));
    // to get sharp edge line
    float edgeFactor = 5.0;
    specular += clamp(length(nearestSpec2D - dirSpec2D)*edgeFactor, 0, 1);
}

무식하게 단순화 시키면 결국 아래서 부터 시작한 거다

vec3 right = vec3(1, 0, 0);
// plane normal, front direction
vec3 planeNormal = vec3(0, -1, 0);
vec3 up = vec3(0, 0, 1);

float width = 5 * 0.5;
float height = 5 * 0.5;

if (positionW.x < width && positionW.x > -width &&
    positionW.z < height && positionW.z > -height)
    specular = vec3(1, 0, 0);

GPU Pro 5 - kill zone

specular/diffuse를 위해 one sample importance sampling을 한다는데 찾아보자

Ray-MMD

Area light의 소스는 Ray-MMD에서 최초로 봄. Referece는 FrostBite 라고 함.

https://computergraphics.stackexchange.com/questions/4139/physically-based-area-lights

twitter를 보면, LTC도 있다

https://twitter.com/Rui_cg/status/948148339530452992

GameDev 2013

https://www.gamedev.net/forums/topic/644255-improved-area-lighting-algorithm/

2013년의 three.js에는 ArKano22 방식으로 구현되어있었나 봄

https://va3c.github.io/three.js/examples/webgldeferred_arealights.html

Three.js

현재의 RectAreaLight 는 'Real-Time Polygonal-Light Shading with Linearly Transformed Cosines' 기반으로 되어있나 봄

https://github.com/mrdoob/three.js/issues/8718

Real-Time Area Lighting: a Journey From Research to Production

http://blog.selfshadow.com/publications/s2016-advances/

확실히 linear transform으로 90에 가까워질수록 오차가 크다

Real-Time Polygonal-Light Shading with Linearly Transformed Cosines

https://eheitzresearch.wordpress.com/415-2/

'Game > Graphics' 카테고리의 다른 글

Shader Uniform variable  (0) 2018.02.22
Framebuffer  (0) 2018.02.20
GLSL include handling  (0) 2018.02.15
OpenGL profiler  (0) 2018.02.14
Modernize OpenGL (DSA)  (0) 2018.02.14
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크