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