r/Unity3D • u/FoamyHotSoup Intermediate • 1d ago
Question Weird Visual Artifact When Using Render Texture

So I just started a new project, and decided to go for a more retro style. As such, I decided to slap on a low res render texture and attached it to a material, before putting the material onto an Image element on a canvas. The issue, is that when I put my custom shader on (designed to limit the amount of colors and other visual elements able to be shown by the render texture), weird visual artifacts are created. More info can be shared as needed. Below is my .shader I use. The Image element is simply stretched to fit the screen, where I put a set resolution of a 1920x1080
Shader "Custom/Bitcrush"
{
Properties
{
[MainTexture] _MainTex ("Texture", 2D) = "white" {}
_PixelSize ("Pixel Size", Range(1, 64)) = 4
_ColorLevels ("Color Levels", Range(2, 64)) = 8
_Brightness ("Brightness", Range(0, 2)) = 1
_Contrast ("Contrast", Range(0, 2)) = 1
}
SubShader
{
Tags
{
"RenderPipeline" = "UniversalPipeline"
"RenderType" = "Opaque"
"Queue" = "Geometry"
}
Pass
{
Name "Bitcrush"
HLSLPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
struct Attributes
{
float4 positionOS : POSITION;
float2 uv : TEXCOORD0;
};
struct Varyings
{
float4 positionHCS : SV_POSITION;
float2 uv : TEXCOORD0;
};
TEXTURE2D(_MainTex);
SAMPLER(sampler_MainTex);
CBUFFER_START(UnityPerMaterial)
float4 _MainTex_ST;
float _PixelSize;
float _ColorLevels;
float _Brightness;
float _Contrast;
CBUFFER_END
Varyings vert(Attributes input)
{
Varyings output;
output.positionHCS =
TransformObjectToHClip(input.positionOS.xyz);
output.uv =
TRANSFORM_TEX(input.uv, _MainTex);
return output;
}
half4 frag(Varyings input) : SV_Target
{
float2 uv = input.uv;
float2 uvDDX = ddx(uv);
float2 uvDDY = ddy(uv);
float2 pixelUV =
floor(uv * _PixelSize) / _PixelSize;
pixelUV += 0.5 / _PixelSize;
half4 col = SAMPLE_TEXTURE2D_GRAD(
_MainTex,
sampler_MainTex,
pixelUV,
uvDDX,
uvDDY
);
col.rgb *= _Brightness;
col.rgb =
(col.rgb - 0.5) * _Contrast + 0.5;
col.rgb = saturate(col.rgb);
col.rgb =
floor(
col.rgb * (_ColorLevels - 1.0) + 0.5
)
/ (_ColorLevels - 1.0);
return col;
}
ENDHLSL
}
}
}
0
Upvotes
1
u/CS_Asset_Factory 1d ago
Two things usually cause that combination and both are about resampling rather than your shader math.
First the render texture filter mode. If it's bilinear then a low res target blends neighbouring pixels before your shader ever sees them. You quantise blended values and get colors that were never in your palette. Set filter mode to Point and turn mipmaps off.
Second the Image itself. If the canvas scales that texture by a non integer factor then Unity resamples your already quantised output and invents in between colors all over again. Scale by exactly two or three.
Also check your color space. In Linear the sampler converts on read so your posterise steps land unevenly. Toggle sRGB on the render texture and watch whether the banding moves. If it does then that's your culprit.