Atlas - D3D12_PixelShader_Common.hlsli
Home / ext / SDL / src / render / direct3d12 Lines: 1 | Size: 8317 bytes [Download] [Show on GitHub] [Search similar files] [Raw] [Raw (proxy)][FILE BEGIN]1#include "D3D12_Shader_Common.hlsli" 2 3Texture2D texture0 : register(t0); 4Texture2D texture1 : register(t1); 5Texture2D texture2 : register(t2); 6SamplerState sampler0 : register(s0); 7SamplerState sampler1 : register(s1); 8 9struct PixelShaderInput 10{ 11 float4 pos : SV_POSITION; 12 float2 tex : TEXCOORD0; 13 float4 color : COLOR0; 14}; 15 16// These should mirror the definitions in SDL_render_d3d12.c 17static const float TONEMAP_NONE = 0; 18static const float TONEMAP_LINEAR = 1; 19static const float TONEMAP_CHROME = 2; 20 21static const float TEXTURETYPE_NONE = 0; 22static const float TEXTURETYPE_RGB = 1; 23static const float TEXTURETYPE_RGB_PIXELART = 2; 24static const float TEXTURETYPE_PALETTE_NEAREST = 3; 25static const float TEXTURETYPE_PALETTE_LINEAR = 4; 26static const float TEXTURETYPE_PALETTE_PIXELART = 5; 27static const float TEXTURETYPE_NV12 = 6; 28static const float TEXTURETYPE_NV21 = 7; 29static const float TEXTURETYPE_YUV = 8; 30 31static const float INPUTTYPE_UNSPECIFIED = 0; 32static const float INPUTTYPE_SRGB = 1; 33static const float INPUTTYPE_SCRGB = 2; 34static const float INPUTTYPE_HDR10 = 3; 35 36cbuffer Constants : register(b1) 37{ 38 float scRGB_output; 39 float texture_type; 40 float input_type; 41 float color_scale; 42 float4 texel_size; 43 44 float tonemap_method; 45 float tonemap_factor1; 46 float tonemap_factor2; 47 float sdr_white_point; 48 49 float4 Yoffset; 50 float4 Rcoeff; 51 float4 Gcoeff; 52 float4 Bcoeff; 53}; 54 55static const float3x3 mat709to2020 = { 56 { 0.627404, 0.329283, 0.043313 }, 57 { 0.069097, 0.919541, 0.011362 }, 58 { 0.016391, 0.088013, 0.895595 } 59}; 60 61static const float3x3 mat2020to709 = { 62 { 1.660496, -0.587656, -0.072840 }, 63 { -0.124547, 1.132895, -0.008348 }, 64 { -0.018154, -0.100597, 1.118751 } 65}; 66 67float sRGBtoLinear(float v) 68{ 69 if (v <= 0.04045) { 70 v = (v / 12.92); 71 } else { 72 v = pow(abs(v + 0.055) / 1.055, 2.4); 73 } 74 return v; 75} 76 77float sRGBfromLinear(float v) 78{ 79 if (v <= 0.0031308) { 80 v = (v * 12.92); 81 } else { 82 v = (pow(abs(v), 1.0 / 2.4) * 1.055 - 0.055); 83 } 84 return v; 85} 86 87float3 PQtoLinear(float3 v) 88{ 89 const float c1 = 0.8359375; 90 const float c2 = 18.8515625; 91 const float c3 = 18.6875; 92 const float oo_m1 = 1.0 / 0.1593017578125; 93 const float oo_m2 = 1.0 / 78.84375; 94 95 float3 num = max(pow(abs(v), oo_m2) - c1, 0.0); 96 float3 den = c2 - c3 * pow(abs(v), oo_m2); 97 return (10000.0 * pow(abs(num / den), oo_m1) / sdr_white_point); 98} 99 100float3 ApplyTonemap(float3 v) 101{ 102 if (tonemap_method == TONEMAP_LINEAR) { 103 v *= tonemap_factor1; 104 } else if (tonemap_method == TONEMAP_CHROME) { 105 if (input_type == INPUTTYPE_SCRGB) { 106 // Convert to BT.2020 colorspace for tone mapping 107 v = mul(mat709to2020, v); 108 } 109 110 float vmax = max(v.r, max(v.g, v.b)); 111 if (vmax > 0.0) { 112 float scale = (1.0 + tonemap_factor1 * vmax) / (1.0 + tonemap_factor2 * vmax); 113 v *= scale; 114 } 115 116 if (input_type == INPUTTYPE_SCRGB) { 117 // Convert to BT.709 colorspace after tone mapping 118 v = mul(mat2020to709, v); 119 } 120 } 121 return v; 122} 123 124float4 SamplePaletteNearest(float2 uv) 125{ 126 float index = texture0.Sample(sampler0, uv).r * 255; 127 return texture1.Sample(sampler1, float2((index + 0.5) / 256, 0.5)); 128} 129 130// Implementation with thanks from bgolus: 131// https://discussions.unity.com/t/how-to-make-data-shader-support-bilinear-trilinear/598639/8 132float4 SamplePaletteLinear(float2 uv) 133{ 134 // scale & offset uvs to integer values at texel centers 135 float2 uv_texels = uv * texel_size.zw + 0.5; 136 137 // get uvs for the center of the 4 surrounding texels by flooring 138 float4 uv_min_max = float4((floor(uv_texels) - 0.5) * texel_size.xy, (floor(uv_texels) + 0.5) * texel_size.xy); 139 140 // blend factor 141 float2 uv_frac = frac(uv_texels); 142 143 // sample all 4 texels 144 float4 texelA = SamplePaletteNearest(uv_min_max.xy); 145 float4 texelB = SamplePaletteNearest(uv_min_max.xw); 146 float4 texelC = SamplePaletteNearest(uv_min_max.zy); 147 float4 texelD = SamplePaletteNearest(uv_min_max.zw); 148 149 // bilinear interpolation 150 return lerp(lerp(texelA, texelB, uv_frac.y), lerp(texelC, texelD, uv_frac.y), uv_frac.x); 151} 152 153float2 GetPixelArtUV(float2 uv) 154{ 155 // box filter size in texel units 156 float2 boxSize = clamp(fwidth(uv) * texel_size.zw, 1e-5, 1); 157 158 // scale uv by texture size to get texel coordinate 159 float2 tx = uv * texel_size.zw - 0.5 * boxSize; 160 161 // compute offset for pixel-sized box filter 162 float2 txOffset = smoothstep(1 - boxSize, 1, frac(tx)); 163 164 // compute bilinear sample uv coordinates 165 return (floor(tx) + 0.5 + txOffset) * texel_size.xy; 166} 167 168float4 GetInputColor(PixelShaderInput input) 169{ 170 float4 rgba; 171 172 if (texture_type == TEXTURETYPE_NONE) { 173 rgba = 1.0; 174 } else if (texture_type == TEXTURETYPE_RGB) { 175 rgba = texture0.Sample(sampler0, input.tex); 176 } else if (texture_type == TEXTURETYPE_RGB_PIXELART) { 177 float2 uv = GetPixelArtUV(input.tex); 178 rgba = texture0.SampleGrad(sampler0, uv, ddx(input.tex), ddy(input.tex)); 179 } else if (texture_type == TEXTURETYPE_PALETTE_NEAREST) { 180 rgba = SamplePaletteNearest(input.tex); 181 } else if (texture_type == TEXTURETYPE_PALETTE_LINEAR) { 182 rgba = SamplePaletteLinear(input.tex); 183 } else if (texture_type == TEXTURETYPE_PALETTE_PIXELART) { 184 float2 uv = GetPixelArtUV(input.tex); 185 rgba = SamplePaletteLinear(uv); 186 } else if (texture_type == TEXTURETYPE_NV12) { 187 float3 yuv; 188 yuv.x = texture0.Sample(sampler0, input.tex).r; 189 yuv.yz = texture1.Sample(sampler0, input.tex).rg; 190 191 yuv += Yoffset.xyz; 192 rgba.r = dot(yuv, Rcoeff.xyz); 193 rgba.g = dot(yuv, Gcoeff.xyz); 194 rgba.b = dot(yuv, Bcoeff.xyz); 195 rgba.a = 1.0; 196 } else if (texture_type == TEXTURETYPE_NV21) { 197 float3 yuv; 198 yuv.x = texture0.Sample(sampler0, input.tex).r; 199 yuv.yz = texture1.Sample(sampler0, input.tex).gr; 200 201 yuv += Yoffset.xyz; 202 rgba.r = dot(yuv, Rcoeff.xyz); 203 rgba.g = dot(yuv, Gcoeff.xyz); 204 rgba.b = dot(yuv, Bcoeff.xyz); 205 rgba.a = 1.0; 206 } else if (texture_type == TEXTURETYPE_YUV) { 207 float3 yuv; 208 yuv.x = texture0.Sample(sampler0, input.tex).r; 209 yuv.y = texture1.Sample(sampler0, input.tex).r; 210 yuv.z = texture2.Sample(sampler0, input.tex).r; 211 212 yuv += Yoffset.xyz; 213 rgba.r = dot(yuv, Rcoeff.xyz); 214 rgba.g = dot(yuv, Gcoeff.xyz); 215 rgba.b = dot(yuv, Bcoeff.xyz); 216 rgba.a = 1.0; 217 } else { 218 // Error! 219 rgba.r = 1.0; 220 rgba.g = 0.0; 221 rgba.b = 1.0; 222 rgba.a = 1.0; 223 } 224 return rgba; 225} 226 227float4 GetOutputColor(float4 rgba) 228{ 229 float4 output; 230 231 output.rgb = rgba.rgb * color_scale; 232 output.a = rgba.a; 233 234 return output; 235} 236 237float3 GetOutputColorFromSRGB(float3 rgb) 238{ 239 float3 output; 240 241 if (scRGB_output) { 242 rgb.r = sRGBtoLinear(rgb.r); 243 rgb.g = sRGBtoLinear(rgb.g); 244 rgb.b = sRGBtoLinear(rgb.b); 245 } 246 247 output.rgb = rgb * color_scale; 248 249 return output; 250} 251 252float3 GetOutputColorFromLinear(float3 rgb) 253{ 254 float3 output; 255 256 output.rgb = rgb * color_scale; 257 258 if (!scRGB_output) { 259 output.r = sRGBfromLinear(output.r); 260 output.g = sRGBfromLinear(output.g); 261 output.b = sRGBfromLinear(output.b); 262 output.rgb = saturate(output.rgb); 263 } 264 265 return output; 266} 267 268float4 AdvancedPixelShader(PixelShaderInput input) 269{ 270 float4 rgba = GetInputColor(input); 271 float4 output; 272 273 if (input_type == INPUTTYPE_HDR10) { 274 rgba.rgb = PQtoLinear(rgba.rgb); 275 } 276 277 if (tonemap_method != TONEMAP_NONE) { 278 rgba.rgb = ApplyTonemap(rgba.rgb); 279 } 280 281 if (input_type == INPUTTYPE_SRGB) { 282 output.rgb = GetOutputColorFromSRGB(rgba.rgb); 283 output.a = rgba.a; 284 } else if (input_type == INPUTTYPE_SCRGB) { 285 output.rgb = GetOutputColorFromLinear(rgba.rgb); 286 output.a = rgba.a; 287 } else if (input_type == INPUTTYPE_HDR10) { 288 rgba.rgb = mul(mat2020to709, rgba.rgb); 289 output.rgb = GetOutputColorFromLinear(rgba.rgb); 290 output.a = rgba.a; 291 } else { 292 output = GetOutputColor(rgba); 293 } 294 295 return output * input.color; 296} 297[FILE END](C) 2025 0x4248 (C) 2025 4248 Media and 4248 Systems, All part of 0x4248 See LICENCE files for more information. Not all files are by 0x4248 always check Licencing.