일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- Cell Look
- working set
- 프로그래밍 기초
- OculusMotionVectorPass
- C언어
- 가상 바이트
- Cartoon Rendering
- AppSW
- 작업 집합
- 개인 바이트
- Three(Two) Tone Shading
- 3d
- URP
- Toon Shader
- 벡터
- Virtual Byte
- 게임 수학
- Rim Light
- Specular
- URP로 변경
- 메모리 누수
- VR
- Cell Shader
- ColorGradingLutPass
- Windows Build
- ASW(Application SpaceWarp)
- Private Bytes
- Today
- Total
WinCNT
URP에서 HDR 텍스처 사용해보기 본문
서론
현재 수정 작업을 맡은 셰이더가 있는데, Emissive를 추가하려고 보니 Emissive Color 프로퍼티가 없었다
사수에게 확인해보니 이 셰이더는 Emissive는 HDR 텍스처로 컨트롤할 방침이라는 얘기를 들었다
그럼 뭐다? 구현은 내가 찾아서 해야 한다는 거지…
HDR Texture
테스트용 HDR Texture는 아트 팀장님이 포토샵으로 만들어주셨다
포토샵의 컬러 피커로 Cyan색에 강도를 추가한 단색 텍스처이다
사실 아트 팀장님께 부탁하기 전에 혼자서 Photopea에서 만들어 보려고 했지만, HDR 관련 항목을 찾지 못해 실패했다
이게 될지 안 될지는 해봐야 안다…
DecodeHDR 함수와 _HDR
HDR 파일을 임포트 해서 텍스처로 사용하면!
놀랍게도 아무 일도 일어나지 않는다…
이것은 유니티의 디폴트 셰이더인 Lit 셰이더 또한 마찬가지였다
즉 나나 커스텀 셰이더의 문제는 아니라는 뜻
역시 별도의 처리가 필요한 것 같았다
그래서 인터넷을 찾아보니 다음과 같은 공식 문서의 문구를 발견할 수 있었다
Cg/HLSL でシェーダープロパティを参照する - Unity マニュアル
💡 텍스처 HDR 파라미터
{TextureName}_HDR
사용되는 색 공간에 따라 HDR(예: RGBM으로 인코딩된) 텍스처를 잠재적으로 어떻게 디코딩할지에 대한 정보를 포함한 float4 프로퍼티입니다.
UnityCG.cginc 셰이더 포함 파일에서 DecodeHDR 함수를 참조하십시오.
조금 살펴보니 hdr를 사용할 텍스처의 이름에 _HDR를 붙인 변수를 따로 선언해야 하고, DecodeHDR 함수 등을 이용해서 HDR의 값을 얻어야 하는 것 같았다
UnityCG.cginc의 코드로 테스트
매우 귀찮게도 URP에서는 여러 이유로 UnityCG.cginc를 사용이 권장되지 않는다…
그래서 DecodeHDR 함수를 복붙해서 테스트를 해보기로 했다
다음은 여러가지를 생략한 테스트 코드이다
// ...전략...
HLSLPROGRAM
CBUFFER_START(UnityPerMaterial)
// ...중략...
float4 _EmissionMap_HDR;
// ...중략...
CBUFFER_END
// ...중략...
// Decodes HDR textures
// handles dLDR, RGBM formats
inline half3 DecodeHDR(half4 data, half4 decodeInstructions, int colorspaceIsGamma)
{
// Take into account texture alpha if decodeInstructions.w is true(the alpha value affects the RGB channels)
half alpha = decodeInstructions.w * (data.a - 1.0) + 1.0;
// If Linear mode is not supported we can skip exponent part
if(colorspaceIsGamma)
return (decodeInstructions.x * alpha) * data.rgb;
#if defined(UNITY_USE_NATIVE_HDR)
return decodeInstructions.x * data.rgb; // Multiplier for future HDRI relative to absolute conversion.
#else
return (decodeInstructions.x * pow(alpha, decodeInstructions.y)) * data.rgb;
#endif
}
// Decodes HDR textures
// handles dLDR, RGBM formats
inline half3 DecodeHDR (half4 data, half4 decodeInstructions)
{
#if defined(UNITY_COLORSPACE_GAMMA)
return DecodeHDR(data, decodeInstructions, 1);
#else
return DecodeHDR(data, decodeInstructions, 0);
#endif
}
// ...중략...
float3 frag(v2f i) : SV_Target
{
float4 emissiveColor = tex2D(_EmissionMap, i.uv);
emissiveColor.rgb = DecodeHDR(emissiveColor, _EmissionMap_HDR);
return emissiveColor;
}
ENDHLSL
// ...후략...
상수 버퍼에 _EmissionMap_HDR를 추가했고, DecodeHDR 함수는 UnityCG.cginc에서 가져왔으며, 사용은 다른 셰이더랑 인터넷의 레퍼런스를 참고했다
그 결과는…
URP에서는 뭘 써야 할까?
문제는 코드를 복붙하는 방식을 피하고 싶다는 것!
이거 Meta Passd에서도 써야한다고~!!
그리고 잘 생각해면 이러한 처리가 URP에서 사라질리 없다…어딘가에 이름만 다른 함수가 존재할 것이다…라고 생각해서 무작정 쳐보니 라이더가 딱 봐도 그럴듯한 함수를 알려주었다
다행히 현재 수정 중인 셰이더는 Lighting.hlsl를 인클루드하고 있어서 EntityLighting.hlsl에 있는 DecodeHDREnvironment() 함수를 사용할 수 있었다
그래도 혹시 몰라 어떤 처리를 하는지 살펴보니…
real3 DecodeHDREnvironment(real4 encodedIrradiance, real4 decodeInstructions)
{
// Take into account texture alpha if decodeInstructions.w is true(the alpha value affects the RGB channels)
real alpha = max(decodeInstructions.w * (encodedIrradiance.a - 1.0) + 1.0, 0.0);
// If Linear mode is not supported we can skip exponent part
return (decodeInstructions.x * PositivePow(alpha, decodeInstructions.y)) * encodedIrradiance.rgb;
}
DecodeHDR와 거의 비슷했길래 DecodeHDREnvironment() 를 사용해보기로 했다
inline half3 DecodeHDR(half4 data, half4 decodeInstructions, int colorspaceIsGamma)
{
// Take into account texture alpha if decodeInstructions.w is true(the alpha value affects the RGB channels)
half alpha = decodeInstructions.w * (data.a - 1.0) + 1.0;
// If Linear mode is not supported we can skip exponent part
if(colorspaceIsGamma)
return (decodeInstructions.x * alpha) * data.rgb;
#if defined(UNITY_USE_NATIVE_HDR)
return decodeInstructions.x * data.rgb; // Multiplier for future HDRI relative to absolute conversion.
#else
return (decodeInstructions.x * pow(alpha, decodeInstructions.y)) * data.rgb;
#endif
}
이쪽은 마찬가지로 여러가지 생략한 테스트 코드이다
(Meta Pass도 같은 처리로 변경했다)
// ...전략...
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
HLSLPROGRAM
CBUFFER_START(UnityPerMaterial)
// ...중략...
float4 _EmissionMap_HDR;
// ...중략...
CBUFFER_END
// ...중략...
float3 frag(v2f i) : SV_Target
{
float4 emissiveColor = tex2D(_EmissionMap, i.uv);
emissiveColor.rgb = DecodeHDREnvironment(emissiveColor, _EmissionMap_HDR);
return emissiveColor;
}
ENDHLSL
// ...후략...
그 결과는…
마무리
단색 HRDI 텍스처 만들기부터 잘 안 되서 삽질을 좀 했다
처음부터 아트 팀장님께 부탁하면 삽질을 안 했겠지만, 아무리 그래도 바쁜 사람에게 단색 HDR Texture 만들어 주세요!라고 하는 건 쪽팔리지미안하지 않는가!
그리고 HDRI를 금방 만들었다고 해도 그 뒤에 별도의 처리가 필요한지 몰랐으니 어차피 삽질은 예정되어 있었다
반대로 HDRI가 이상하지 않다는 확신이 없었으면 별도의 처리가 필요한지 깨닫기까지 수많은 삽질이 있었을 것이다
개발은 참으로 어렵다…
참고 사이트
Cg/HLSL でシェーダープロパティを参照する - Unity マニュアル
モバイルでのHDRテクスチャの扱い - BeXide Tech Blog
'Unity > URP or Shader 관련' 카테고리의 다른 글
유니티의 Built-in Shader의 소스 코드를 다운로드 하기 (0) | 2023.07.18 |
---|---|
URP에서 Overdraw 확인하기 (0) | 2023.07.10 |
유니티에서 커스텀 셰이더의 머티리얼에 라이트 맵을 적용해보기 (0) | 2023.06.30 |
기존 프로젝트를 URP로 변경하기 (0) | 2023.05.30 |
URP로 Toon Shader 만들기 -Rim Light 2- (0) | 2023.05.26 |