디퍼 드 셰이딩-여러 라이트를 결합하는 방법?


9

GLSL로 시작하고 위치, 법선 및 알베도로 G 버퍼를 출력하는 간단한 지연 음영을 구현했습니다.

간단한 포인트 라이트 셰이더도 작성했습니다.

이제 포인트 라이트를위한 구를 그리고 출력은 라이팅 버퍼로 들어갑니다.

문제는 여러 조명을 그릴 때 조명 버퍼의 결과를 어떻게 결합합니까?

예를 들어 포인트 라이트 셰이더를 사용하여 라이트 버퍼에 두 번째 라이트를 그릴 때 조명 버퍼의 두 번째 라이트에 첫 번째 라이트를 추가하는 방법은 무엇입니까? 같은 출력 버퍼에서 읽고 쓸 수 없습니까?

답변:


12

첨가제 혼합, 즉 glBlendFunc (GL_ONE, GL_ONE) 및 glEnable (GL_BLEND).


이를 위해 깊이 테스트를 비활성화해야합니까?
woojoo666

1
@ woojoo666 아니요. 실제로 이전 패스와 정확하게 일치하는 표면이 통과 할 수 있도록 깊이 테스트를 동일하지 않은 상태로 활성화해야합니다. 수심 테스트가 꺼져 있으면 표면이 뒤에있는 것으로부터 빛을 잘못 축적합니다. :)
Nathan Reed

흠, 그것은 정확히 무슨 일이 일어나고있는 것 같습니다. 블렌딩을 켜면 심도 테스트를 활성화 한 경우에도 전면과 후면이 혼합됩니다. 깊이 마스크로 무언가를해야합니까?
woojoo666

조금 더 많은 테스트를 수행했으며, 그리기 순서 문제처럼 보입니다 (앞에서 뒤로 그리기하면 깊이 테스트가 올바르게 작동하고 블렌드가 얼굴이 평평한 경우에만, 뒤에서 앞면으로 모든 것이 혼합됩니다). 모든 것을 정렬하지 않고이 작업을 수행 할 수 있습니까?
woojoo666

2
@ woojoo666 Aha, 스스로 해결 한 것 같습니다. 예, 모든 종류의 블렌딩을 사용하려면 먼저 불투명 패스에 깊이를 배치해야합니다. 색상 쓰기가 비활성화 된 z 프리 패스 일 수도 있고, 또 다른 일반적인 방법은 블렌딩없이 첫 번째 패스에서 주변 / 방향 라이트를 수행 한 다음 블렌딩을 사용하여 나중에 패스에 포인트 / 스폿 라이트를 추가하는 것입니다.
Nathan Reed

2

지연 렌더러의 경우 g- 버퍼의 정보를 사용하여 모든 라이트를 하나의 라이트 렌더 타겟으로 집계 한 다음 최종 백 버퍼 이미지를 만드는 동안 라이트 렌더를 위해 해당 렌더 타겟을 샘플링합니다.

기본적으로 지오메트리 패스를 통해 모든 게임 지오메트리를 실행하여 g- 버퍼를 만듭니다. 거기서부터 g- 버퍼를 라이트 패스 셰이더에 공급합니다. 각 라이트는 전체 화면 쿼드를 사용하여 패스를 통과합니다. 이렇게하면 픽셀 셰이더가 g- 버퍼에서 보이는 모든 표면의 광 강도를 계산 한 다음이를 렌더 렌더 대상에 추가 할 수 있습니다. 각 라이트의 라이트 강도를 라이트 버퍼에 추가하기 만하면 강도를 0에서 1로 고정해야합니다.

서로 다른 유형의 조명 (점, 스포트라이트, 평행)을 처리하기 위해 수행해야 할 것은 일정한 버퍼를 사용하여 실행할 조명 절차를 지정하여 조명을 더욱 견고하게 만드는 것입니다.


예, 문제는-라이트 렌더 타겟에 어떻게 추가합니까? Nathan Reed가 제안한대로 알파 블렌딩을 사용하십니까? 내가 아는 한 동일한 출력 버퍼 (이 경우 라이트 버퍼)에서 읽고 쓸 수 없기 때문입니다.
JBeurer

네 출력 병합 기에서 부가 블렌딩으로 처리하도록했습니다. 최종 이미지 샘플링은 표면이받을 수있는 최대 광량으로 작동하는 값으로 클램프하려는 경우입니다. 거기에서 필요에 따라 조명의 크기를 조절할 수 있습니다.
KlashnikovKid

빛이 벽 뒤에 있고 벽의 다른쪽에있는 물건을 비추 지 않아야하는 경우를 어떻게 처리합니까?
jjxtra

@PsychoDad 그림자의 영역입니다. 더 복잡한 주제입니다. :)
Nathan Reed

0

이것보다 더 나은 대답이있을 수 있지만, 쉐이더에서 두 번째 조명을 수행하는 데 필요한 코드를 반복하면 하나의 객체 대신 두 개의 조명을 처리 할 수 ​​있습니다. 두 번째 조명과 이음새에 대한 많은 코드를 작성해야하지만 약간의 중복이 필요하지만 작동한다는 것을 알고 있습니다. 그러나 누군가가 희망적으로 지적 할 때보 다 우아한 해결책이있을 것이라고 믿습니다.


아니, 그건 그런 식으로 작동하지 않습니다. 각 포인트 라이트마다 구를 그립니다. 제 2 포인트 광이 제 1 광의 영향의 영역에 놓여 있지 않으면, 제 2 광은 단순히 그려지지 않을 것이다. 모든 포인트 라이트에 대해 전체 화면 쿼드를 그리는 경우 방법이 효과적이지만 전체 화면 쿼드가 전역 조명에 사용되기 때문에 올바른 접근 방식이 아닙니다. 16 개의 작은 점 조명이 있는데, 픽셀이 켜져 있지 않더라도 각 픽셀마다 통과해야한다고 가정 해보십시오. 일반적으로 각 픽셀에는 하나 또는 두 개의 조명이 켜집니다. 100 개의 조명이 있으면 어떻게해야합니까? 아니오
JBeurer 23.58에

내가 이것을 말한 주된 이유는 두 개 또는 몇 개의 조명 만 사용하면 도움이 될 수 있기 때문입니다. 특히 많은 오브젝트를 렌더링하는 경우 블렌드를 사용하면 각 라이트마다 장면을 다시 그려야하므로 백만 또는 천만 또는 십억과 같은 모양이 많은 경우 각 드로우 비용이 더 많이 발생합니다. . 셰이더에서이 기능을 사용하면 많은 조명을 원할 경우 문제가 발생하지만 블렌드를 사용하면 많은 모양이 필요합니다. 둘 다 많이있는 경우 중간 지점을 찾아야하지만 일반적으로 게임에 몇 개의 조명과 많은 개체가 있습니다.
CodeNeko

아니, 지연된 쉐이딩은 그런 식으로 작동하지 않습니다. 장면을 한 번만 그려야하고 관련 정보를 G-Buffer에 저장해야합니다. 그런 다음 각 라이트에 영향을 미치는 구를 라이트 버퍼와 혼합하십시오. 마지막으로 라이트 버퍼와 컬러 버퍼를 결합하여 최종 음영 처리 된 컬러 버퍼를 얻습니다. 조명 계산량은 장면 복잡성에 의존하지 않습니다. 이것이 디퍼 드 셰이딩의 주요 장점입니다.
JBeurer

아, 그것은 훨씬 더 의미가 있고 상당히 나을 것입니다.
CodeNeko
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.