TECHARTNOMAD TECHARTFLOW.IO

UNREAL ENGINE

[짜투리] 커스텀 셰이더 익스프레션 사용할 때 Pow(a,b)

jplee 2023. 12. 16. 22:17

일단 유니티 에서는 아래와 같은 매크로 형식으로 정의 되어 있다.

// Using pow often result to a warning like this
// "pow(f, e) will not work for negative f, use abs(f) or conditionally handle negative values if you expect them"
// PositivePow remove this warning when you know the value is positive or 0 and avoid inf/NAN.
// Note: https://msdn.microsoft.com/en-us/library/windows/desktop/bb509636(v=vs.85).aspx pow(0, >0) == 0
TEMPLATE_2_REAL(PositivePow, base, power, return pow(abs(base), power))

// pow를 사용하면 종종 다음과 같은 경고가 표시됩니다. 
// "pow(f, e)는 음수 f에 작동하지 않으므로, 음수 값이 예상되는 경우 abs(f)를 사용하거나 조건부로 처리하십시오." 
// PositivePow는 값이 양수 또는 0이라는 것을 알면 이 경고를 제거하고 inf/NAN을 피합니다.

암튼... 나같은 경우에는

언리얼 엔진의 내장 셰이더를 보면 common.ush 에서 찾을 수 있다.

#define POW_CLAMP 0.000001f

// Clamp the base, so it's never <= 0.0f (INF/NaN).
MaterialFloat ClampedPow(MaterialFloat X,MaterialFloat Y)
{
	return pow(max(abs(X),POW_CLAMP),Y);
}
MaterialFloat2 ClampedPow(MaterialFloat2 X,MaterialFloat2 Y)
{
	return pow(max(abs(X),MaterialFloat2(POW_CLAMP,POW_CLAMP)),Y);
}
MaterialFloat3 ClampedPow(MaterialFloat3 X,MaterialFloat3 Y)
{
	return pow(max(abs(X),MaterialFloat3(POW_CLAMP,POW_CLAMP,POW_CLAMP)),Y);
}  
MaterialFloat4 ClampedPow(MaterialFloat4 X,MaterialFloat4 Y)
{
	return pow(max(abs(X),MaterialFloat4(POW_CLAMP,POW_CLAMP,POW_CLAMP,POW_CLAMP)),Y);
} 

/* Pow function that will return 0 if Base is <=0. This ensures that no compiler expands pow into exp(Exponent * log(Base)) with Base=0 */
MaterialFloat PositiveClampedPow(MaterialFloat Base, MaterialFloat Exponent)
{
	return (Base <= 0.0f) ? 0.0f : pow(Base, Exponent);
}
MaterialFloat2 PositiveClampedPow(MaterialFloat2 Base, MaterialFloat2 Exponent)
{
	return MaterialFloat2(PositiveClampedPow(Base.x, Exponent.x), PositiveClampedPow(Base.y, Exponent.y)); 
}
MaterialFloat3 PositiveClampedPow(MaterialFloat3 Base, MaterialFloat3 Exponent)
{
	return MaterialFloat3(PositiveClampedPow(Base.xy, Exponent.xy), PositiveClampedPow(Base.z, Exponent.z)); 
}  
MaterialFloat4 PositiveClampedPow(MaterialFloat4 Base, MaterialFloat4 Exponent)
{
	return MaterialFloat4(PositiveClampedPow(Base.xy, Exponent.xy), PositiveClampedPow(Base.zw, Exponent.zw)); 
}

 

개인적으로 Utility.ush 파일을 따로 만들어서 사용하는 편인지라... 

#pragma once
#include "/Engine/Public/Platform.ush"
#include"/Engine/Private/Common.ush"

#define POSITIVEPOW ClampedPow

간단히 이렇게 디파인 해서 익스프레션으로 셰이더 작성할 때 사용하는 편을 선호 한다.

만약 Common.ush 를 include 해서 사용하지 않을 경우에는..

#pragma once
// Utility shader
#define HALF_MAX        65504.0 // (2 - 2^-10) * 2^15
#define HALF_MAX_MINUS1 65472.0 // (2 - 2^-9) * 2^15
#define EPSILON         1.0e-4
#define PI              3.14159265359
#define TWO_PI          6.28318530718
#define FOUR_PI         12.56637061436
#define INV_PI          0.31830988618
#define INV_TWO_PI      0.15915494309
#define INV_FOUR_PI     0.07957747155
#define HALF_PI         1.57079632679
#define INV_HALF_PI     0.636619772367

#define FLT_EPSILON     1.192092896e-07 // Smallest positive number, such that 1.0 + FLT_EPSILON != 1.0
#define FLT_MIN         1.175494351e-38 // Minimum representable positive floating-point number
#define FLT_MAX         3.402823466e+38 // Maximum representable floating-point number

// pow를 사용하면 종종 다음과 같은 경고가 표시됩니다.
// "pow(f, e)는 음수 f에 대해 작동하지 않으므로, 음수 값이 예상되는 경우 abs(f)를 사용하거나 조건부로 처리하십시오."
// 값이 양수라는 것을 알면 PositivePow는 이 경고를 제거하고 inf/NAN을 피합니다.

float PositivePow(float base, float power)
{
    return pow(max(abs(base), float(FLT_EPSILON)), power);
}

float2 PositivePow(float2 base, float2 power)
{
    return pow(max(abs(base), float2(FLT_EPSILON, FLT_EPSILON)), power);
}

float3 PositivePow(float3 base, float3 power)
{
    return pow(max(abs(base), float3(FLT_EPSILON, FLT_EPSILON, FLT_EPSILON)), power);
}

float4 PositivePow(float4 base, float4 power)
{
    return pow(max(abs(base), float4(FLT_EPSILON, FLT_EPSILON, FLT_EPSILON, FLT_EPSILON)), power);
}

#define POSITIVEPOW PositivePow

//--------------------------------------------------------------------------------------------------

뭐 이런 식으로 만들어서 사용했었는데... 내 생각에 굳이 만들어 쓸 일은 없는 것 같고... 원래 언리얼 엔진에서 제공하는 common.ush 있는거 바로 활용하면 되겠다.