Files
Test/Assets/ColbyO/VNTG/Shaders/HLSL/N64Sampler.hlsl
T
2026-11-01 23:39:55 +02:00

257 lines
7.5 KiB
HLSL

//-----------------------------------------------------------------------
// Author: Colby-O
// File: N64Sampler.hlsl
//-----------------------------------------------------------------------
#ifndef COLBYO_VNTG_N64_SAMPLER_INCLUDED
#define COLBYO_VNTG_N64_SAMPLER_INCLUDED
void N64Sampler_float(UnityTexture2D Texture, UnitySamplerState Sampler, float4 TexelSize, float2 UV, out float4 Out)
{
uint width, height;
Texture.tex.GetDimensions(width, height);
TexelSize = float4(1.0 / width, 1.0 / height, width, height);
float2 texels = UV * TexelSize.zw;
//TexelSize.xy *= -1.0;
texels = texels - 0.5;
float2 fracTexel = frac(texels);
float3 blend = float3(
abs(fracTexel.x + fracTexel.y - 1),
min(abs(fracTexel.xx - float2(0.0, 1.0)), abs(fracTexel.yy - float2(1.0, 0.0)))
);
float2 uvA = (floor(texels + fracTexel.yx) + 0.5) * TexelSize.xy;
float2 uvB = (floor(texels) + float2(1.5, 0.5)) * TexelSize.xy;
float2 uvC = (floor(texels) + float2(0.5, 1.5)) * TexelSize.xy;
float4 A = SAMPLE_TEXTURE2D_LOD(Texture.tex, Sampler.samplerstate, uvA, 0.0);
float4 B = SAMPLE_TEXTURE2D_LOD(Texture.tex, Sampler.samplerstate, uvB, 0.0);
float4 C = SAMPLE_TEXTURE2D_LOD(Texture.tex, Sampler.samplerstate, uvC, 0.0);
Out = A * blend.x + B * blend.y + C * blend.z;
}
void N64Sampler_half(UnityTexture2D Texture, UnitySamplerState Sampler, half4 TexelSize, half2 UV, out half4 Out)
{
half width, height;
Texture.tex.GetDimensions(width, height);
TexelSize = half4(1.0 / width, 1.0 / height, width, height);
half2 texels = UV * TexelSize.zw;
//TexelSize.xy *= -1.0;
texels = texels - 0.5;
half2 fracTexel = frac(texels);
half3 blend = half3(
abs(fracTexel.x + fracTexel.y - 1),
min(abs(fracTexel.xx - half2(0.0, 1.0)), abs(fracTexel.yy - half2(1.0, 0.0)))
);
half2 uvA = (floor(texels + fracTexel.yx) + 0.5) * TexelSize.xy;
half2 uvB = (floor(texels) + half2(1.5, 0.5)) * TexelSize.xy;
half2 uvC = (floor(texels) + half2(0.5, 1.5)) * TexelSize.xy;
half4 A = SAMPLE_TEXTURE2D_LOD(Texture, Sampler, uvA, 0.0);
half4 B = SAMPLE_TEXTURE2D_LOD(Texture, Sampler, uvB, 0.0);
half4 C = SAMPLE_TEXTURE2D_LOD(Texture, Sampler, uvC, 0.0);
Out = A * blend.x + B * blend.y + C * blend.z;
}
void DirToCubeFaceUV_float(float3 dir, out int faceIndex, out float2 uv)
{
float3 absDir = abs(dir);
float maxAxis;
if (absDir.x >= absDir.y && absDir.x >= absDir.z)
{
faceIndex = (dir.x > 0.0) ? 0 : 1;
maxAxis = absDir.x;
uv = float2((dir.x > 0.0) ? -dir.z : dir.z, -dir.y);
}
else if (absDir.y >= absDir.x && absDir.y >= absDir.z)
{
faceIndex = (dir.y > 0.0) ? 2 : 3;
maxAxis = absDir.y;
uv = float2(dir.x, (dir.y > 0.0) ? dir.z : -dir.z);
}
else
{
faceIndex = (dir.z > 0.0) ? 4 : 5;
maxAxis = absDir.z;
uv = float2((dir.z > 0.0) ? dir.x : -dir.x, -dir.y);
}
uv = 0.5 * (uv / maxAxis + 1.0);
}
void DirToCubeFaceUV_half(half3 dir, out int faceIndex, out half2 uv)
{
half3 absDir = abs(dir);
half maxAxis;
if (absDir.x >= absDir.y && absDir.x >= absDir.z)
{
faceIndex = (dir.x > 0.0) ? 0 : 1;
maxAxis = absDir.x;
uv = half2((dir.x > 0.0) ? -dir.z : dir.z, -dir.y);
}
else if (absDir.y >= absDir.x && absDir.y >= absDir.z)
{
faceIndex = (dir.y > 0.0) ? 2 : 3;
maxAxis = absDir.y;
uv = half2(dir.x, (dir.y > 0.0) ? dir.z : -dir.z);
}
else
{
faceIndex = (dir.z > 0.0) ? 4 : 5;
maxAxis = absDir.z;
uv = half2((dir.z > 0.0) ? dir.x : -dir.x, -dir.y);
}
uv = 0.5 * (uv / maxAxis + 1.0);
}
float3 CubeFaceUVToDir_float(int faceIndex, float2 uv)
{
float2 uc = uv * 2.0 - 1.0;
float3 dir = float3(0, 0, 0);
switch (faceIndex)
{
case 0:
dir = float3(1.0, -uc.y, -uc.x);
break;
case 1:
dir = float3(-1.0, -uc.y, uc.x);
break;
case 2:
dir = float3(uc.x, 1.0, uc.y);
break;
case 3:
dir = float3(uc.x, -1.0, -uc.y);
break;
case 4:
dir = float3(uc.x, -uc.y, 1.0);
break;
case 5:
dir = float3(-uc.x, -uc.y, -1.0);
break;
}
return normalize(dir);
}
half3 CubeFaceUVToDir_half(int faceIndex, half2 uv)
{
half2 uc = uv * 2.0 - 1.0;
half3 dir = half3(0, 0, 0);
switch (faceIndex)
{
case 0:
dir = half3(1.0, -uc.y, -uc.x);
break;
case 1:
dir = half3(-1.0, -uc.y, uc.x);
break;
case 2:
dir = half3(uc.x, 1.0, uc.y);
break;
case 3:
dir = half3(uc.x, -1.0, -uc.y);
break;
case 4:
dir = half3(uc.x, -uc.y, 1.0);
break;
case 5:
dir = half3(-uc.x, -uc.y, -1.0);
break;
}
return normalize(dir);
}
void N64SamplerCube_float(
UnityTextureCube Cube,
UnitySamplerState Sampler,
float3 Dir,
out float4 Out
)
{
uint width, height;
Cube.tex.GetDimensions(width, height);
int faceIndex;
float2 UV;
DirToCubeFaceUV_float(Dir, faceIndex, UV);
float4 TexelSize = float4(1.0 / width, 1.0 / height, width, height);
float2 texels = UV * TexelSize.zw - 0.5;
float2 fracTexel = frac(texels);
float3 blend = float3(
abs(fracTexel.x + fracTexel.y - 1.0),
min(abs(fracTexel.xx - float2(0.0, 1.0)), abs(fracTexel.yy - float2(1.0, 0.0)))
);
float2 uvA = (floor(texels + fracTexel.yx) + 0.5) * TexelSize.xy;
float2 uvB = (floor(texels) + float2(1.5, 0.5)) * TexelSize.xy;
float2 uvC = (floor(texels) + float2(0.5, 1.5)) * TexelSize.xy;
float3 dirA = CubeFaceUVToDir_float(faceIndex, uvA);
float3 dirB = CubeFaceUVToDir_float(faceIndex, uvB);
float3 dirC = CubeFaceUVToDir_float(faceIndex, uvC);
float4 A = SAMPLE_TEXTURECUBE_LOD(Cube.tex, Sampler.samplerstate, dirA, 0.0);
float4 B = SAMPLE_TEXTURECUBE_LOD(Cube.tex, Sampler.samplerstate, dirB, 0.0);
float4 C = SAMPLE_TEXTURECUBE_LOD(Cube.tex, Sampler.samplerstate, dirC, 0.0);
Out = A * blend.x + B * blend.y + C * blend.z;
}
void N64SamplerCube_half(
UnityTextureCube Cube,
UnitySamplerState Sampler,
half3 Dir,
out half4 Out
)
{
uint width, height;
Cube.tex.GetDimensions(width, height);
int faceIndex;
half2 UV;
DirToCubeFaceUV_half(Dir, faceIndex, UV);
half4 TexelSize = half4(1.0 / width, 1.0 / height, width, height);
half2 texels = UV * TexelSize.zw - 0.5;
half2 fracTexel = frac(texels);
half3 blend = half3(
abs(fracTexel.x + fracTexel.y - 1.0),
min(abs(fracTexel.xx - half2(0.0, 1.0)), abs(fracTexel.yy - half2(1.0, 0.0)))
);
half2 uvA = (floor(texels + fracTexel.yx) + 0.5) * TexelSize.xy;
half2 uvB = (floor(texels) + half2(1.5, 0.5)) * TexelSize.xy;
half2 uvC = (floor(texels) + half2(0.5, 1.5)) * TexelSize.xy;
half3 dirA = CubeFaceUVToDir_half(faceIndex, uvA);
half3 dirB = CubeFaceUVToDir_half(faceIndex, uvB);
half3 dirC = CubeFaceUVToDir_half(faceIndex, uvC);
half4 A = SAMPLE_TEXTURECUBE_LOD(Cube.tex, Sampler.samplerstate, dirA, 0.0);
half4 B = SAMPLE_TEXTURECUBE_LOD(Cube.tex, Sampler.samplerstate, dirB, 0.0);
half4 C = SAMPLE_TEXTURECUBE_LOD(Cube.tex, Sampler.samplerstate, dirC, 0.0);
Out = A * blend.x + B * blend.y + C * blend.z;
}
#endif