95 lines
No EOL
4 KiB
HLSL
95 lines
No EOL
4 KiB
HLSL
#if !defined(SLZ_TRIPLANAR_INCLUDED)
|
|
#define SLZ_TRIPLANAR_INCLUDED
|
|
//#define TEXTURE2D_PARAM(textureName, samplerName) Texture2D textureName, sampler samplerName
|
|
|
|
/**
|
|
* Struct containg the ddx and ddy of the uvs combined into one half4 for each axis
|
|
*/
|
|
struct tpDerivatives
|
|
{
|
|
half4 ddX;
|
|
half4 ddY;
|
|
half4 ddZ;
|
|
};
|
|
|
|
/**
|
|
* Gets the derivatives of the worldspace coordinates reduced to 3 2 dimensional planes defined by each axis
|
|
*
|
|
* @param wPos Worldspace position
|
|
* @param[out] dd struct containing the x and y derivatives of each plane
|
|
*/
|
|
void GetDirectionalDerivatives(float3 wPos, out tpDerivatives dd)
|
|
{
|
|
dd.ddX.xy = ddx(wPos.zy);
|
|
dd.ddY.xy = ddx(wPos.xz);
|
|
dd.ddZ.xy = ddx(wPos.xy);
|
|
dd.ddX.zw = ddy(wPos.zy);
|
|
dd.ddY.zw = ddy(wPos.xz);
|
|
dd.ddZ.zw = ddy(wPos.xy);
|
|
}
|
|
|
|
/**
|
|
* Determines the worldspace axis that the given mesh normal is most closely aligned to, and returns the coordinates of the
|
|
* pixel in the plane aligned with that axis and the derivatives associated with that plane. Also generates a tangent to world
|
|
* matrix using the axes orthogonal to the dominant axis as the tangent and bitangent.
|
|
*
|
|
* @param[out] triplanarUV Coordinates of the fragment in the plane aligned with the dominant axis
|
|
* @param[out] ddxMax X derivatives of the coordinates of the fragment in the plane aligned with the dominant axis
|
|
* @param[out] ddyMax Y derivatives of the coordinates of the fragment in the plane aligned with the dominant axis
|
|
* @param[out] tanToWrld Tangent to world matrix composed of the other two axes as tangent and bitangent, and the mesh normal as the normal
|
|
* @param wPos World-space position of the fragment
|
|
* @param wNorm World-space mesh normal
|
|
* @param dd derivatives of the fragment's coordinates in each axis aligned plane
|
|
*/
|
|
void GetTPUVExpensive(out float2 triplanarUV, out half2 ddxMax, out half2 ddyMax, out half3x3 tanToWrld, float3 wPos, half3 wNorm,
|
|
tpDerivatives dd)
|
|
{
|
|
half3 dir;
|
|
dir.x = abs(wNorm.x) > abs(wNorm.y) && abs(wNorm.x) > abs(wNorm.z) ? 1 : 0;
|
|
dir.y = abs(wNorm.y) >= abs(wNorm.x) && abs(wNorm.y) > abs(wNorm.z) ? 1 : 0;
|
|
dir.z = abs(wNorm.z) >= abs(wNorm.y) && abs(wNorm.z) >= abs(wNorm.x) ? 1 : 0;
|
|
half3 dirSign = sign(wNorm);
|
|
dirSign.z = -dirSign.z; // u should be flipped on Z
|
|
ddxMax = dir.x * dd.ddX.xy + dir.y * dd.ddY.xy + dir.z * dd.ddZ.xy;
|
|
ddyMax = dir.x * dd.ddX.zw + dir.y * dd.ddY.zw + dir.z * dd.ddZ.zw;
|
|
//half3 maxDir = half3(dirX, dirY, dirZ);
|
|
float2 uvX = wPos.zy * float2(dirSign.x, 1.0);
|
|
triplanarUV = dir.x * uvX;
|
|
float2 uvY = wPos.xz * float2(dirSign.y, 1.0);
|
|
triplanarUV = mad(dir.y, uvY, triplanarUV);
|
|
float2 uvZ = wPos.xy * float2(dirSign.z, 1.0);
|
|
triplanarUV = mad(dir.z, uvZ, triplanarUV);
|
|
|
|
|
|
tanToWrld = half3x3(
|
|
dir.y * dirSign.y + dir.z * dirSign.z, 0, wNorm.x,
|
|
0, dir.x + dir.z, wNorm.y,
|
|
dir.x * dirSign.x, dir.y, wNorm.z
|
|
);
|
|
|
|
}
|
|
|
|
void GetTPUVCheap(out float2 triplanarUV, out half3x3 tanToWrld, float3 wPos, half3 wNorm)
|
|
{
|
|
half3 dir;
|
|
dir.x = abs(wNorm.x) > abs(wNorm.y) && abs(wNorm.x) > abs(wNorm.z) ? 1 : 0;
|
|
dir.y = abs(wNorm.y) >= abs(wNorm.x) && abs(wNorm.y) > abs(wNorm.z) ? 1 : 0;
|
|
dir.z = abs(wNorm.z) >= abs(wNorm.y) && abs(wNorm.z) >= abs(wNorm.x) ? 1 : 0;
|
|
half3 dirSign = sign(wNorm);
|
|
dirSign.z = -dirSign.z; // u should be flipped on Z
|
|
//half3 maxDir = half3(dirX, dirY, dirZ);
|
|
float2 uvX = wPos.zy * float2(dirSign.x, 1.0);
|
|
triplanarUV = dir.x * uvX;
|
|
float2 uvY = wPos.xz * float2(dirSign.y, 1.0);
|
|
triplanarUV = mad(dir.y, uvY, triplanarUV);
|
|
float2 uvZ = wPos.xy * float2(dirSign.z, 1.0);
|
|
triplanarUV = mad(dir.z, uvZ, triplanarUV);
|
|
|
|
tanToWrld = half3x3(
|
|
dir.y * dirSign.y + dir.z * dirSign.z, 0, wNorm.x,
|
|
0, dir.x + dir.z, wNorm.y,
|
|
dir.x * dirSign.x, dir.y, wNorm.z
|
|
);
|
|
}
|
|
|
|
#endif |