cbuffer _180 { int2 _180_offset : packoffset(c0); int _180_level : packoffset(c0.z); int _180_pass : packoffset(c0.w); }; Texture2D tex : register(t0); SamplerState _tex_sampler : register(s0); static float4 gl_FragCoord; static uint4 fragColor; static float2 vUV; struct SPIRV_Cross_Input { float2 vUV : TEXCOORD0; float4 gl_FragCoord : SV_Position; }; struct SPIRV_Cross_Output { uint4 fragColor : SV_Target0; }; static float3 block[16]; static float blockAlpha[16]; float4 toLinear(float4 sRGB_A) { float a = sRGB_A.w; float rcpA = 1.0f / ((a != 0.0f) ? a : 1.0f); float3 sRGB = sRGB_A.xyz * rcpA; bool3 cutoff = bool3(sRGB.x < 0.040449999272823333740234375f.xxx.x, sRGB.y < 0.040449999272823333740234375f.xxx.y, sRGB.z < 0.040449999272823333740234375f.xxx.z); float3 higher = pow((abs(sRGB) + 0.054999999701976776123046875f.xxx) / 1.05499994754791259765625f.xxx, 2.400000095367431640625f.xxx); float3 lower = sRGB / 12.9200000762939453125f.xxx; return float4(float3(cutoff.x ? lower.x : higher.x, cutoff.y ? lower.y : higher.y, cutoff.z ? lower.z : higher.z) * a, a); } float4 fromLinear(float4 linearRGB_A) { float a = linearRGB_A.w; float rcpA = 1.0f / ((a != 0.0f) ? a : 1.0f); float3 linearRGB = linearRGB_A.xyz * rcpA; bool3 cutoff = bool3(linearRGB.x < 0.003130800090730190277099609375f.xxx.x, linearRGB.y < 0.003130800090730190277099609375f.xxx.y, linearRGB.z < 0.003130800090730190277099609375f.xxx.z); float3 higher = (1.05499994754791259765625f.xxx * pow(abs(linearRGB), 0.4166666567325592041015625f.xxx)) - 0.054999999701976776123046875f.xxx; float3 lower = linearRGB * 12.9200000762939453125f.xxx; return float4(float3(cutoff.x ? lower.x : higher.x, cutoff.y ? lower.y : higher.y, cutoff.z ? lower.z : higher.z) * a, a); } void fetchBlock() { int side = 1 << _180_level; int2 baseCoord = ((side * 4).xx * int2(gl_FragCoord.xy)) + _180_offset; for (int by = 0; by < 4; by++) { for (int bx = 0; bx < 4; bx++) { float4 color = 0.0f.xxxx; float alpha = 0.0f; int2 coord = baseCoord + (int2(bx, by) << _180_level.xx); for (int y = 0; y < side; y++) { for (int x = 0; x < side; x++) { float4 t1 = tex.Load(int3(coord + int2(x, y), 0)); float4 param = t1; color += toLinear(param); alpha += t1.w; } } float4 param_1 = color * (1.0f / float(side * side)); block[(by * 4) + bx] = fromLinear(param_1).xyz; blockAlpha[(by * 4) + bx] = alpha * (1.0f / float(side * side)); } } } void FindMinMaxColorsBox(inout float3 mincol, inout float3 maxcol) { mincol = 1.0f.xxx; maxcol = 0.0f.xxx; for (int i = 0; i < 16; i++) { mincol = min(mincol, block[i]); maxcol = max(maxcol, block[i]); } } void SelectDiagonal(inout float3 mincol, inout float3 maxcol) { float3 center = (mincol + maxcol) * 0.5f; float2 cov = 0.0f.xx; for (int i = 0; i < 16; i++) { float3 t = block[i] - center; cov.x += (t.x * t.z); cov.y += (t.y * t.z); } if (cov.x < 0.0f) { float temp = maxcol.x; maxcol.x = mincol.x; mincol.x = temp; } if (cov.y < 0.0f) { float temp_1 = maxcol.y; maxcol.y = mincol.y; mincol.y = temp_1; } } void InsetBBox(inout float3 mincol, inout float3 maxcol) { float3 inset = ((maxcol - mincol) / 16.0f.xxx) - 0.00196078442968428134918212890625f.xxx; mincol = clamp(mincol + inset, 0.0f.xxx, 1.0f.xxx); maxcol = clamp(maxcol - inset, 0.0f.xxx, 1.0f.xxx); } float3 RoundAndExpand(float3 v, out uint w) { int3 c = int3(round(v * float3(31.0f, 63.0f, 31.0f))); w = uint(((c.x << 11) | (c.y << 5)) | c.z); int2 _490 = (c.xz << int2(3, 3)) | (c.xz >> int2(2, 2)); c = int3(_490.x, c.y, _490.y); c.y = (c.y << 2) | (c.y >> 4); return float3(float3(c) * 0.0039215688593685626983642578125f); } uint EmitEndPointsDXT1(inout float3 mincol, inout float3 maxcol) { float3 param = maxcol; uint param_1; float3 _516 = RoundAndExpand(param, param_1); uint2 result; result.x = param_1; maxcol = _516; float3 param_2 = mincol; uint param_3; float3 _522 = RoundAndExpand(param_2, param_3); result.y = param_3; mincol = _522; if (result.x < result.y) { float3 tmp = mincol; mincol = maxcol; maxcol = tmp; return result.y | (result.x << uint(16)); } return result.x | (result.y << uint(16)); } float colorDistance(float3 c0, float3 c1) { return dot(c0 - c1, c0 - c1); } uint EmitIndicesDXT1(float3 mincol, float3 maxcol) { float3 c[4]; c[0] = maxcol; c[1] = mincol; c[2] = lerp(c[0], c[1], 0.3333333432674407958984375f.xxx); c[3] = lerp(c[0], c[1], 0.666666686534881591796875f.xxx); uint indices = 0u; for (int i = 0; i < 16; i++) { float3 param = block[i]; float3 param_1 = c[0]; float4 dist; dist.x = colorDistance(param, param_1); float3 param_2 = block[i]; float3 param_3 = c[1]; dist.y = colorDistance(param_2, param_3); float3 param_4 = block[i]; float3 param_5 = c[2]; dist.z = colorDistance(param_4, param_5); float3 param_6 = block[i]; float3 param_7 = c[3]; dist.w = colorDistance(param_6, param_7); bool4 _628 = bool4(dist.xyxy.x > dist.wzzw.x, dist.xyxy.y > dist.wzzw.y, dist.xyxy.z > dist.wzzw.z, dist.xyxy.w > dist.wzzw.w); uint4 b = uint4(_628.x ? uint4(1u, 1u, 1u, 1u).x : uint4(0u, 0u, 0u, 0u).x, _628.y ? uint4(1u, 1u, 1u, 1u).y : uint4(0u, 0u, 0u, 0u).y, _628.z ? uint4(1u, 1u, 1u, 1u).z : uint4(0u, 0u, 0u, 0u).z, _628.w ? uint4(1u, 1u, 1u, 1u).w : uint4(0u, 0u, 0u, 0u).w); uint b4 = uint(dist.z > dist.w); uint index = (b.x & b4) | (((b.y & b.z) | (b.x & b.w)) << uint(1)); indices |= (index << uint(i * 2)); } return indices; } void InsetYBBox(inout float mincol, inout float maxcol) { float inset = ((maxcol - mincol) / 32.0f) - 0.00196078442968428134918212890625f; mincol = clamp(mincol + inset, 0.0f, 1.0f); maxcol = clamp(maxcol - inset, 0.0f, 1.0f); } uint EmitAlphaEndPointsYCoCgDXT5(inout float mincol, inout float maxcol) { float param = mincol; float param_1 = maxcol; InsetYBBox(param, param_1); mincol = param; maxcol = param_1; uint c0 = uint(round(mincol * 255.0f)); uint c1 = uint(round(maxcol * 255.0f)); return (c0 << uint(8)) | c1; } uint2 EmitAlphaIndicesYCoCgDXT5(float minAlpha, float maxAlpha) { float mid = (maxAlpha - minAlpha) / 14.0f; float ab1 = minAlpha + mid; float ab2 = (((6.0f * maxAlpha) + (1.0f * minAlpha)) * 0.14285714924335479736328125f) + mid; float ab3 = (((5.0f * maxAlpha) + (2.0f * minAlpha)) * 0.14285714924335479736328125f) + mid; float ab4 = (((4.0f * maxAlpha) + (3.0f * minAlpha)) * 0.14285714924335479736328125f) + mid; float ab5 = (((3.0f * maxAlpha) + (4.0f * minAlpha)) * 0.14285714924335479736328125f) + mid; float ab6 = (((2.0f * maxAlpha) + (5.0f * minAlpha)) * 0.14285714924335479736328125f) + mid; float ab7 = (((1.0f * maxAlpha) + (6.0f * minAlpha)) * 0.14285714924335479736328125f) + mid; uint2 indices = uint2(0u, 0u); uint index = 0u; for (int i = 0; i < 6; i++) { float a = blockAlpha[i]; index = 1u; index += uint(a <= ab1); index += uint(a <= ab2); index += uint(a <= ab3); index += uint(a <= ab4); index += uint(a <= ab5); index += uint(a <= ab6); index += uint(a <= ab7); index &= 7u; index ^= uint(2u > index); indices.x |= (index << uint((3 * i) + 16)); } indices.y = index >> uint(1); for (int i_1 = 6; i_1 < 16; i_1++) { float a_1 = blockAlpha[i_1]; index = 1u; index += uint(a_1 <= ab1); index += uint(a_1 <= ab2); index += uint(a_1 <= ab3); index += uint(a_1 <= ab4); index += uint(a_1 <= ab5); index += uint(a_1 <= ab6); index += uint(a_1 <= ab7); index &= 7u; index ^= uint(2u > index); indices.y |= (index << uint((3 * i_1) - 16)); } return indices; } uint4 compress_DXT5_fp() { float3 param; float3 param_1; FindMinMaxColorsBox(param, param_1); float3 mincol = param; float3 maxcol = param_1; float3 param_2 = mincol; float3 param_3 = maxcol; SelectDiagonal(param_2, param_3); mincol = param_2; maxcol = param_3; float3 param_4 = mincol; float3 param_5 = maxcol; InsetBBox(param_4, param_5); mincol = param_4; maxcol = param_5; float3 param_6 = mincol; float3 param_7 = maxcol; uint _944 = EmitEndPointsDXT1(param_6, param_7); mincol = param_6; maxcol = param_7; uint4 result; result.z = _944; float3 param_8 = mincol; float3 param_9 = maxcol; result.w = EmitIndicesDXT1(param_8, param_9); float minAlpha = blockAlpha[0]; float maxAlpha = blockAlpha[0]; for (int i = 1; i < 16; i++) { minAlpha = min(minAlpha, blockAlpha[i]); maxAlpha = max(maxAlpha, blockAlpha[i]); } float param_10 = minAlpha; float param_11 = maxAlpha; uint _984 = EmitAlphaEndPointsYCoCgDXT5(param_10, param_11); minAlpha = param_10; maxAlpha = param_11; result.x = _984; float param_12 = minAlpha; float param_13 = maxAlpha; uint2 indices = EmitAlphaIndicesYCoCgDXT5(param_12, param_13); result.x |= indices.x; result.y = indices.y; return result; } void frag_main() { fetchBlock(); fragColor = compress_DXT5_fp(); } SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input) { gl_FragCoord = stage_input.gl_FragCoord; vUV = stage_input.vUV; frag_main(); SPIRV_Cross_Output stage_output; stage_output.fragColor = fragColor; return stage_output; }