3
\$\begingroup\$

Think about minecraft - all the textures in minecraft have a very nice crisp pixelated look. Well, I'm trying to write a shader that will do this but it appears "sampler2d" returns some sort of interpolation between pixels of the underlying texture. I'm pretty new to shader writing and I'm not even sure if it can be done - but I'm hoping to get a nice crisp blow up of small textures rather than a blurry one like this:

Blurry Pixels in CG

If anyone knows a way to make a shader crisp rather than interpolated like this (using Unity), I'd be thrilled to know as this hitch is pretty detrimental to what I'm trying to accomplish...

Here's the subshader as it is right now (it's skipping all the light calculations and just outputting the sampler as I'm just trying to resolve the blurry texture sampling):

SubShader
{
    Pass
    {
        Tags { "LightMode" = "ForwardBase" }
        CGPROGRAM
        #pragma vertex vert
        #pragma fragment frag

        //user
        uniform float _BlendVal;
        uniform sampler2D _DiffuseTex;
        uniform sampler2D _NMTex;
        uniform sampler2D _PixelMap;
        uniform float4 _DiffuseTex_SV;
        uniform float4 _SpecColor;
        uniform float _SpecIntensity;
        uniform float4 _RimColor;
        uniform float _RimIntensity;
        uniform float _RimCoefficient;

        //unity     
        uniform float4 _LightColor0;

        struct vI
        {
            float4 pos : POSITION;
            float3 norm : NORMAL;
            float4 uv : TEXCOORD0;
        };

        struct vO
        {
            float4 pos : SV_POSITION;
            float4 uv : TEXCOORD0;
            float3 worldPos : TEXCOORD1;
            float3 normDir : TEXCOORD2;
        };

        vO vert(vI i)
        {
            vO o;

            o.uv = i.uv;
            o.worldPos = mul(_Object2World, i.pos).xyz;
            o.normDir = normalize(mul( float4(i.norm, 0.0), _World2Object).xyz);
            o.pos = mul(UNITY_MATRIX_MVP, i.pos);

            return o;
        }

        float4 frag(vO i) : COLOR
        {
            float3 lightDir;
            float3 viewDir = normalize( i.worldPos - _WorldSpaceCameraPos.xyz);
            float atten;
            float3 normDir = normalize(i.normDir); 
            float4 RimLight;
            float4 DiffuseLight;
            float4 SpecularLight;
            float2 UVCoord = i.uv.xy;

            float4 test = tex2D(_PixelMap, UVCoord);

            //float4 Clrx0 = lerp(

            //Directional Light
            if(_WorldSpaceLightPos0.w == 0)
            {
                lightDir = normalize(_WorldSpaceLightPos0.xyz);
                atten = dot(lightDir, normDir);
            }
            //point light
            else
            {
                float3 dist = i.worldPos.xyz - _WorldSpaceLightPos0.xyz;
                lightDir = normalize(dist);
                atten = (1/length(dist))*(dot(lightDir, normDir));
            }

            DiffuseLight = atten * _LightColor0;
            SpecularLight = atten * _LightColor0 * _SpecColor * _SpecIntensity * pow(max(0.0,dot(reflect(lightDir, normDir), viewDir)), 1)*(1-tex2D(_DiffuseTex, i.uv.xy).w);
            RimLight = atten * _LightColor0 * _RimColor * _RimCoefficient* pow((1-saturate(dot(-viewDir, normDir))),_RimIntensity)*saturate(dot(lightDir, normDir)); 

            float4 totalLight = DiffuseLight + SpecularLight + RimLight;

            float4 fin = float4(UVCoord.xy,0,0);

            return test; ///Fin * totalLight;           
        }

        ENDCG
\$\endgroup\$

3 Answers 3

7
\$\begingroup\$

Set the filterMode of your textures to FilterMode.Point.

This will use nearest-neighbor interpolation, which will result in blocky rendering.

Note: Your Texture2D must also have a suitable graphicsFormat. The default is R8G8B8A8_UNorm which does not work with filterMode set to FilterMode.Point for some reason.

TextureFormat.RGBA32 and other 32bit formats have worked for me. This is a read-only property, but you can set this format in the constructor of the Texture2D.

\$\endgroup\$
2
  • \$\begingroup\$ I just found that online before I saw you answer - thanks a lot... I spent like three hours searching for it using the wrong terms because I had assumed it was something within the shader rather than set from within Unity. (I guess technically Unity is passing the options to the GPU, but you understand...) \$\endgroup\$ Feb 9, 2015 at 17:17
  • \$\begingroup\$ Note: Your Texture2D must also have a suitable graphicsFormat. The default is R8G8B8A8_UNorm which does not work with filterMode set to FilterMode.Point for some reason. TextureFormat.RGBA32 and other 32bit formats have worked for me. This is a read-only property, but you can set this format in the constructor of the Texture2D. \$\endgroup\$
    – roob
    Oct 4, 2019 at 16:08
2
\$\begingroup\$

If you want to do this without a script, simply in the Project Window:

  • Select your image in the Assets folder
  • The Import Settings will now be visible in the Inspector Window
  • In Import Settings, Find "Filter Mode" below the Advanced section
  • Change Filter Mode to "Point (no filter)"
  • Click "Apply"

Import Settings

\$\endgroup\$
3
  • \$\begingroup\$ I'm having trouble following these steps. Are these directions still relevant in recent Unity versions? \$\endgroup\$
    – roob
    Oct 4, 2019 at 2:59
  • \$\begingroup\$ @roob Hi, I haven't used Unity in a long time, but you definitely should look at the accepted answer as it contains more references. Otherwise, check the Unity API as it might help. \$\endgroup\$ Oct 4, 2019 at 3:20
  • \$\begingroup\$ Thanks. The accepted answer is a programatic solution. I have figured out how to do it in the UI and will edit your answer for clarity. \$\endgroup\$
    – roob
    Oct 4, 2019 at 16:16
0
\$\begingroup\$

My Stupid: apparently you can change the filtering mode of your textures by using: "(TextureName).filterMode = FilterMode.Point" and that will take care of this problem. Had nothing to do with the shader.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .