by 꽈배기
알파 블렌딩은 각 픽셀에 투명도 값 (알파채널)을 적용하여 두 개 이상의 이미지를 결합하는 프로세스를 말합니다. 이렇게 하면 이미지가 부분적으로 겹쳐져 매끄러운 블렌딩을 만들 수 있습니다.
다음은 알파 블렌딩이 일반적으로 사용되는 몇 가지 상황입니다:
다음은 단계별 분석입니다:
투명도가 있는 이미지를 렌더링할 때 컴퓨터는 덧셈 프로세스를 사용하여 두 이미지의 픽셀을 결합합니다.
알파 블렌딩의 옵션
// AlphaBlendShader.hlsl
float4 main(float2 uv : TEXCOORD0, float4 color : COLOR) : SV_Target
{
// UV 좌표에서 텍스처 샘플
float4 texColor = tex2D(TextureSampler, uv);
// 샘플링된 텍스처에서 알파 값 계산하기
float alpha = texColor.a;
// 텍스처의 알파 값과 입력 색상을 혼합합니다.
return lerp(color, color * alpha, alpha);
}
알파 정렬은 알파 채널에 따라 오브젝트를 정렬하는 데 사용되는 알고리즘입니다. 불투명 개체를 우선적으로 그리고 이를 통해 투명한 오브젝트가 올바른 순서로 올바르게 렌더링 되도록 할 수 있습니다. 알파 블렌딩과 함께 작동하여 투명한 요소가 올바르게 렌더링 되도록 합니다.
알파 정렬을 사용하는 이유:
두 개의 투명 오브젝트의 순서가 같고(즉, 둘 다 동시에 그려짐) 위치가 동일하면(즉, 정확히 동일한 픽셀 좌표를 차지함) Z-파이팅으로 알려진 시각적 아티팩트가 발생할 수 있습니다. 이 문제를 해결하려면 이러한 개체가 깊이 측면에서 겹치지 않도록 해야 합니다.
Z 버퍼링을 사용한 알파 블렌딩: (애디티브 블렌딩이라고도 함)을 사용하고 z-버퍼가 겹치는 픽셀을 올바르게 처리할 수 있도록 설정합니다.
알파 테스트는 개체의 픽셀이 완전히 불투명한지 또는 투명한지를 결정하는 데 사용되는 기법입니다. 렌더링 엔진이 먼저 렌더링할 개체를 결정하고 투명도 효과가 올바르게 나타나는지 확인하는 데 도움이 됩니다.
작동 방식은 다음과 같습니다:
알파 테스트는 렌더링을 최적화 합니다.
// AlphaTestShader.hlsl
float4 main(float2 uv : TEXCOORD0, float4 color : COLOR) : SV_Target
{
// UV 좌표에서 텍스처 샘플
float4 texColor = tex2D(TextureSampler, uv);
// 샘플링된 텍스처에서 알파값을 계산합니다.
float alpha = texColor.a;
// 픽셀의 알파 값이 특정 임계값보다 큰지 테스트합니다
if (alpha > 0.5f) {
return color;
} else {
clip; // 픽셀이 잘려서 렌더링되지 않음
}
}
아래에서는 각 상황을 케이스로 분류하여 분석합니다.
- Transparency 는 T, Opaque는 O로 표기합니다.
- 각 개체는 카메라 기준점으로 부터 거리가 N(near), F(far)로 표기됩니다.
- Opaque는 render queue에 의해 T 개체보다 먼저 그려집니다.
예시 : T(50 % 알파)->O 결과 : O의 색이 T의 색으로 덮어 씌워집니다.
예시 :O->T(50 % 알파) 결과 : 불투명 개체의 색이 투명 개체의 색으로 덮어 씌워집니다.
렌더링 순서 : Alpah sorting으로 정렬된 개체 중 가장 먼 개체를 우선적으로 렌더링 합니다. 이후 먼 곳에서 가까운 곳으로 순차적으로 렌더링 됩니다.
알파 블렌딩 : 두 개체 모두 투명하므로 색상 값이 이전 렌더링 된 결과값과 블렌딩됩니다. 결과 알파 값은 두 개체의 투명도를 고려합니다.
투명 개체 렌더링시 순서가 반대로 렌더링 되는것은 3D 그래픽에서 원근 투영이 작동하는 방식 때문입니다. Z 버퍼링과 뎁스 테스트가 함께 작동하는 방식 때문에 카메라에 가까운 오브젝트는 멀리 있는 오브젝트보다 늦게 렌더링됩니다.
예시: TransparentObject1 (50% 알파) -> TransparentObject2 (30% 알파)
결과 : 최종 알파 값은 원래 알파 값에 곱하고 색상 값과 혼합하여 계산됩니다. 이 경우 결과는 15% 투명 개체(0.5 * 0.3)가 됩니다.
Z 버퍼(깊이 버퍼라고도 함)는 카메라로부터의 거리를 기준으로 오브젝트를 정렬하는 데 사용되는 기법입니다. 이를 통해 투명 또는 반투명 오브젝트의 올바른 렌더링 순서를 보장할 수 있습니다.
깊이 테스트는 각 픽셀의 계산된 깊이 값을 Z 버퍼에 저장된 깊이 값과 비교하는 프로세스입니다. 이를 통해 픽셀을 렌더링할지 아니면 폐기할지 여부를 결정합니다.
계산된 깊이 값?
픽셀 위치를 기준으로 각 픽셀이 카메라로부터 떨어진 거리를 나타냅니다.
저장된 깊이 값?
이전에 다른 픽셀이나 오브젝트에 의해 z-버퍼에 기록된 카메라로부터의 거리입니다.
이후 래스터화 과정중 계산된 깊이 값과 z 버퍼에 저장된 깊이 값을 비교하여 계산 결과가 z 버퍼에 기록된 값보다 카메라에 가까우면 z 버퍼에 기록하고 렌더를 수행합니다.
아닐경우 (더 가까운 오브젝트가 이미 렌더 되었을 때) 픽셀을 폐기합니다. 해당 과정을 depth buffering 또는 z buffering이라고 합니다.
float CalculatedValue;
float StoredValueZbuffer;
if(CalculatedValue > StoredValueZbuffer)
// 계산된 깊이 값이 카메라로부터 멀게되므로 픽셀을 그리지 않습니다.
else if(CalculatedValue < StoredValueZbuffer)
// 계산된 깊이 값이 카메라로부터 가까우므로 렌더를 진행합니다.
작동 방식은 다음과 같습니다
오버드로우 줄이기: 렌더러는 깊이를 기준으로 오브젝트를 정렬하여 다른 오브젝트에 가려진 픽셀을 렌더링하는 것을 건너뛸 수 있습니다.
성능 향상: Z-버퍼링은 렌더링 및 처리할 픽셀 수를 줄여 프레임 속도를 높입니다.
반면 Transparency 개체를 렌더할 때는 블렌딩 조건에 의해 Z buffer를 쓸 수 없습니다. (작동하지 않는다는 것은 아닙니다) 아래와 같은 이유로 알파 소팅, 알파 테스팅 등의 추가적인 기술을 필요로 합니다.
카메라와의 거리가 고정되어 있지 않기에 동작하지 않습니다.
뎁스 버퍼링: 투명 오브젝트의 불투명도는 배경이 얼마나 보이는지에 영향을 미치기 때문에 렌더러는 단순히 투명 오브젝트의 뎁스 버퍼 값을 계산할 수 없습니다.
블렌딩: 렌더링 엔진은 투명도를 올바르게 처리하기 위해 블렌딩 공식을 사용하여 겹치는 픽셀의 색상을 결합합니다(예: 반투명 오브젝트가 다른 오브젝트와 겹치는 경우).
순서 독립적 정렬 (OIT): 투명 오브젝트는 렌더러가 깊이 버퍼 값에 따라 어떤 오브젝트를 먼저 렌더링할지 결정하는 순서 독립적 정렬이 필요한 경우가 많습니다
이러한 Transparency 개체에 대한 예외와 최적화가 있습니다.
여러 오브젝트가 서로 교차하는 경우 공간 분할이라는 기술을 사용하여 경계를 분류해야 합니다. 여기에는 장면을 더 작은 영역으로 나눈 다음 해당 영역 내에 어떤 오브젝트가 있는지 확인하는 작업이 포함됩니다.
한 가지 일반적인 방법은 각 노드가 3D 공간의 영역을 나타내는 옥트리(나무와 같은 데이터 구조)를 사용하는 것입니다. 두 개체가 교차하면 같은 노드에 속하는지 여부를 확인합니다.
뎁스 버퍼의 경우 깊이가 다른 여러 개체를 렌더링할 때 GPU는 깊이 버퍼를 사용하여 카메라에 더 가까운 개체를 결정하고 이를 먼저 렌더링합니다.
불투명한 물체(빛이 통과하지 못하는 물체)가 투명한 물체와 교차하는 경우 이 상황을 신중하게 처리해야 합니다. 알파 블렌딩이나 오클루전 컬링과 같은 기술을 사용하여 적절한 렌더링을 보장할 수 있습니다.
유니티와 언리얼 같은 엔진은 다양한 알고리즘과 데이터 구조를 사용하여 내부적으로 오브젝트 소팅을 처리합니다.
유니티에서는 공간 분할(옥트리)과 바운딩 볼륨(구체 또는 박스 등)을 조합하여 카메라의 뷰 프러스텀에 표시되는 오브젝트를 빠르게 결정할 수 있습니다.
언리얼 엔진은 자체 렌더링 파이프라인에서 비슷한 접근 방식을 사용합니다. 또한 오클루전 컬링 및 레벨 오브 디테일(LOD) 같은 기술을 사용하여 성능을 최적화합니다.
Z-fighting이란 무엇인가요?
컴퓨터 그래픽에서는 비슷한 깊이를 가진 두 개 이상의 객체가 동일한 픽셀 위치에서 렌더될 때 Z-fighting(깊이 버퍼 정밀도 문제라고도 함)이 발생합니다. 이는 깊이 값을 계산하는 데 사용되는 부동 소수점 연산의 제한으로 인해 발생할 수 있습니다.
이 경우 렌더러가 한 객체를 다른 객체 위에 렌더링하여 다음과 같은 시각적 아티팩트가 발생할 수 있습니다:
CG에서 Z-fighting은 언제 발생했나요?
Z-fighting은 컴퓨터 그래픽 초기부터 문제가 되어왔습니다. 특히 1990년대 후반과 2000년대 초반 3D 그래픽 붐이 일었을 때 많은 게임과 애플리케이션에서 깊이 계산에 고정 소수점 또는 저정밀 부동 소수점 연산을 사용했을 때 널리 퍼졌습니다.
투명성에서 Z-fighting이 발생할 수 있나요?
투명도는 Z-파이팅 문제를 악화시킬 수 있습니다. 투명한 개체가 서로 겹치는 경우 개체의 위치, 크기 및 재질 속성(예: 알파 블렌딩) 간의 복잡한 상호 작용으로 인해 깊이를 정확하게 계산하기 어려울 수 있습니다.
두 개 이상의 반투명 오브젝트가 동일한 픽셀 위치에 비슷한 깊이로 렌더링되는 경우 고정밀 부동 소수점 연산을 사용하는 경우에도 Z-파이팅이 발생할 수 있습니다. 반올림 오류로 인해 깊이 값의 작은 차이가 손실될 수 있기 때문입니다.
이러한 문제를 완화하기 위해 시간이 지남에 따라 다양한 기술이 개발되었습니다:
투명성 시나리오에서 Z-fighting 처리하기:
서로 겹치는 반투명 오브젝트를 처리할 때 몇 가지 기술을 사용하면 Z-파이팅 문제를 완화하거나 제거할 수 있습니다:
렌더링 엔진 및 라이브러리:
투명도와 겹치는 오브젝트를 잘 처리하는 인기 있는 렌더링 엔진과 라이브러리에는 다음과 같은 것들이 있습니다:
“fixed-point or low-precision floating-point arithmetic for depth calculations.”
why cg use their?
CG (Computer Graphics) uses fixed-point or low-precision floating-point arithmetic for depth calculations because it provides a good balance between precision and performance.
Fixed-point arithmetic is fast, simple to implement, and requires minimal memory. However, it has limited range and accuracy compared to floating-point numbers. This can lead to issues with large scenes or complex geometry where the depth buffer overflows or underflows.
Low-precision floating-point arithmetic (e.g., 16-bit floats) offers better precision than fixed-point but is still more efficient than full IEEE754-compliant floating-point numbers (32-bit or 64-bit). It provides a good trade-off between accuracy and performance, making it suitable for many real-time graphics applications.
In CG, the depth buffer typically uses an unsigned integer value to represent the distance from the camera. This allows for fast and simple calculations using bitwise operations and shifts. However, this approach can lead to issues with large scenes or complex geometry where the depth values exceed the range of the unsigned integer type (e.g., 0-65535).
To mitigate these limitations, various techniques are used in CG:
By using fixed-point or low-precision floating-point arithmetic for depth calculations and employing these techniques, CG applications can achieve a good balance between performance and accuracy in real-time graphics rendering.assistant
The use of fixed-point or low-precision floating-point arithmetic for depth calculations in Computer Graphics (CG) is due to the need for a trade-off between precision and performance.
Fixed-point arithmetic is fast, simple to implement, and requires minimal memory. However, it has limited range and accuracy compared to floating-point numbers. This can lead to issues with large scenes or complex geometry where the depth buffer overflows or underflows.
Low-precision floating-point arithmetic (e.g., 16-bit floats) offers better precision than fixed-point but is still more efficient than full IEEE754-compliant floating-point numbers (32-bit or 64-bit). It provides a good trade-off between accuracy and performance, making it suitable for many real-time graphics applications.
In CG, the depth buffer typically uses an unsigned integer type to store the depth values. This means that the precision of the depth values is limited by the number of bits used to represent them (e.g., 8-bit or 16-bit). To mitigate this limitation, various techniques are employed:
By using fixed-point or low-precision floating-point arithmetic for depth calculations and employing these techniques, CG applications can achieve a good balance between performance and accuracy in real-time graphics rendering
To address these challenges, various techniques are employed:
In addition to these techniques, there are other methods used for rendering transparent or translucent materials: