분기 코드는 런타임 분기(동적 분기)로 인해 파이프라인에 따라 비용이 커질 수 있습니다.
프러퍼티.
[Enum(R,0,G,1,B,2,A,3)]_OutlineVertexColorChannel("Outline Vertex Color Channel", Float) = 0
float outlinceVertexColorMask = 0.0;
if (_OutlineVertexColorChannel == 0)
outlinceVertexColorMask = vertexColor.r;
else if (_OutlineVertexColorChannel == 1)
outlinceVertexColorMask = vertexColor.g;
else if (_OutlineVertexColorChannel == 2)
outlinceVertexColorMask = vertexColor.b;
else if (_OutlineVertexColorChannel == 3)
outlinceVertexColorMask = vertexColor.a;
이런 분기 코드를 최적화 한다면...분기 없이 인덱스에서 원-핫(one-hot) 마스크를 만들고 dot을 사용.
// _OutlineVertexColorChannel: float 또는 int (0,1,2,3)
float c = (float)_OutlineVertexColorChannel;
// 0,1,2,3과의 거리를 이용해 원-핫 마스크 생성 (분기 없음)
float4 mask = saturate(1.0 - abs(float4(0.0, 1.0, 2.0, 3.0) - c));
// vertexColor: float4/half4 (r,g,b,a)
float outlineVertexColorMask = dot(vertexColor, mask);
이 코드는 조건문(분기) 없이 버텍스 컬러에서 특정 채널을 선택하는 셰이더 기법
_OutlineVertexColorChannel 값에 따라 vertexColor에서 특정 채널(R, G, B, A 중 하나)을 선택.
- 채널 인덱스
- c는 선택할 채널을 나타냅니다:
- 0 = 빨강(Red) 채널
- 1 = 초록(Green) 채널
- 2 = 파랑(Blue) 채널
- 3 = 알파(Alpha) 채널
- c는 선택할 채널을 나타냅니다:
- 원-핫 마스크 생성
hlsl
float4 mask = saturate(1.0 - abs(float4(0.0, 1.0, 2.0, 3.0) - c));
- c = 0이면: mask는 (1, 0, 0, 0)
- c = 1이면: mask는 (0, 1, 0, 0)
- c = 2이면: mask는 (0, 0, 1, 0)
- c = 3이면: mask는 (0, 0, 0, 1)
- 채널 선택
hlsl
float outlineVertexColorMask = dot(vertexColor, mask);
추가.
abs 함수는 채널 인덱스(0,1,2,3)와 선택하려는 채널 값 c 사이의 절댓값 거리를 계산.
선택된 채널에서는 0이 되고, 다른 채널에서는 양수가 되도록 하여, saturate(1.0 - abs(...)) 연산을 통해 정확히 하나의 채널만 1이고 나머지는 0인 마스크를 만든다.
- c = 1일 때: abs(float4(0,1,2,3) - 1) = float4(1,0,1,2)
- 이것이 saturate(1.0 - ...) 연산을 거치면 (0,1,0,0) 마스크가 됨.
장점
- GPU 친화적: 분기문(if/else)이 없어서 GPU 성능 저하를 방지
- 벡터화: SIMD 연산을 효율적으로 활용
- 유연성: 런타임에 쉽게 채널 변경 가능
이 기법은 버텍스 컬러의 특정 채널에 아웃라인 두께나 다른 속성을 저장하고 동적으로 선택할 때 활용.
One-hot - Wikipedia
From Wikipedia, the free encyclopedia Bit-vector representation where only one bit can be set at a time Decimal Binary Unary One-hot 0 000 00000000 00000001 1 001 00000001 00000010 2 010 00000011 00000100 3 011 00000111 00001000 4 100 00001111 00010000 5 1
en.wikipedia.org
GPU-friendly one-hot encoding
Given a vector of indices I want to get a matrix where only one element with corresponding index is one and others are zeros. On CPU it’s pretty easy, e.g.: function onehot(s::AbstractVector, n_dims::Int=maximum(s)) x = zeros(Int, n_dims, length(s)) for
discourse.julialang.org
'GRAPHICS PROGRAMMING' 카테고리의 다른 글
셰이더 프로그래밍에서 ## 연산자. 토큰 결합 연산자(token-pasting operator) (0) | 2025.05.30 |
---|---|
PBR Neutral Tone Mapping 코드 해설. (1) | 2025.05.28 |
헤어 메시카드의 버텍스 소팅과 SIMD 프로그래밍 토론 기록 (5) | 2025.05.13 |
DualKwaseBlur (0) | 2025.04.22 |
VXGI for advanced render mode on mobile devices (0) | 2025.04.15 |