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