Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- Shader "Vita/EPXUpscaleNonPixelArt"
- {
- Properties
- {
- _MainTex ("LowRes Texture", 2D) = "white" {}
- _InputRes ("Input Resolution", Vector) = (400,230,0,0)
- _OutputRes ("Output Resolution", Vector) = (640,368,0,0)
- // Threshold for treating two colors as equal (tweak as needed)
- _Threshold ("Color Threshold", Float) = 0.1
- }
- SubShader
- {
- Pass
- {
- CGPROGRAM
- // Vertex and fragment entry points:
- #pragma vertex vert
- #pragma fragment frag
- #include "UnityCG.cginc"
- sampler2D _MainTex;
- float2 _InputRes; // e.g. (400,230)
- float2 _OutputRes; // e.g. (640,368)
- float _Threshold; // Threshold for approximate equality
- struct appdata
- {
- float4 vertex : POSITION;
- float2 uv : TEXCOORD0;
- };
- struct v2f
- {
- float2 uv : TEXCOORD0;
- float4 vertex : SV_POSITION;
- };
- v2f vert (appdata v)
- {
- v2f o;
- o.vertex = UnityObjectToClipPos(v.vertex);
- o.uv = v.uv;
- return o;
- }
- // Sample _MainTex using pixel coordinates, adding 0.5 to sample at pixel centers.
- float4 SampleTex(float2 pixelPos)
- {
- float2 uv = (pixelPos + 0.125) / _InputRes;
- return tex2D(_MainTex, uv);
- }
- // Clamp pixel positions so that we don't sample outside the texture.
- float4 SampleTexClamp(float2 pixelPos)
- {
- pixelPos = clamp(pixelPos, float2(0.0, 0.0), _InputRes - 1.0);
- return SampleTex(pixelPos);
- }
- // Helper functions for approximate color comparisons.
- // We compare only the RGB components and use a squared threshold (to avoid sqrt).
- bool approxEqual(float4 a, float4 b)
- {
- float3 diff = a.rgb - b.rgb;
- return dot(diff, diff) < (_Threshold * _Threshold);
- }
- bool approxNotEqual(float4 a, float4 b)
- {
- float3 diff = a.rgb - b.rgb;
- return dot(diff, diff) > (_Threshold * _Threshold);
- }
- // EPX fragment shader with coordinate remapping.
- float4 frag (v2f i) : SV_Target
- {
- // Compute output pixel coordinate (in target resolution, e.g. 640x368).
- float2 outCoord = i.uv * _OutputRes;
- // Compute the “ideal” 2x upscaled resolution (doubling 400x230 yields 800x460).
- float2 upscaledRes = _InputRes * 2.0;
- // Handle non 2x scales
- float2 scaleMapping = upscaledRes / _OutputRes;
- float2 upCoord = outCoord * scaleMapping;
- // Undo the doubling:
- // - The integer part (ipos) selects a pixel in the low‑res image.
- // - The fractional part (fpos) tells you which quadrant of the 2x block.
- float2 srcCoord = upCoord / 2.0;
- float2 ipos = floor(srcCoord);
- float2 fpos = frac(srcCoord);
- // Sample the center pixel (E) and its four neighbors.
- float4 P = SampleTexClamp(ipos);
- float4 A = SampleTexClamp(ipos + float2(-1.0, 0.0)); // Left neighbor
- float4 B = SampleTexClamp(ipos + float2( 0.0, 1.0)); // Top neighbor
- float4 C = SampleTexClamp(ipos + float2( 1.0, 0.0)); // Right neighbor
- float4 D = SampleTexClamp(ipos + float2( 0.0, -1.0)); // Bottom neighbor
- // Compute EPX candidates using approximate comparisons.
- float4 P1 = ((approxEqual(A,B)) && (approxNotEqual(B, D))) ? B : P; // Top-left candidate
- float4 P2 = ((approxEqual(B,C)) && (approxNotEqual(B, D))) ? C : P; // Top-right candidate
- float4 P3 = ((approxEqual(A, D)) && (approxNotEqual(A, C))) ? A : P; // Bottom-left candidate
- float4 P4 = ((approxEqual(C, D)) && (approxNotEqual(C, B))) ? C : P; // Bottom-right candidate
- // Use explicit if/else statements for each possible quadrant.
- float4 result;
- if (fpos.x < 0.5 && fpos.y > 0.5)
- {
- result = P1;//2
- }
- else if (fpos.x > 0.5 && fpos.y > 0.5)
- {
- result = P2;
- }
- else if (fpos.x < 0.5 && fpos.y < 0.5)
- {
- result = P3;
- }
- else if (fpos.x >= 0.5 && fpos.y < 0.5)
- {
- result = P4;//p4
- }
- else
- {
- result = P; // Fallback; this case should not be reached.
- }
- return result;
- }
- ENDCG
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement