• Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
0
Question by impurekind · Jan 04, 2019 at 05:44 PM · texturessmoothanti-aliasingjaggedaliased

How to correctly get jaggy free pixel textures in 3D game?

I have a simple 3D fps game (t$$anonymous$$nk original Wolfenstein and Doom) where the textures are done old-school pixel style, but I find I'm having to save every texture out from Photoshop at a min of say 512x512 (even though the actual texture art for the walls is actually only 32x32) just to stop it looking all aliased when the game is running.

Here's a couple images of the game:

alt text alt text

If I set the textures to Point (no filter) in Unity then they look all jaggy. If I set them to Bilinear or Trilinear in Unity then they look clean, but only if I output them at the much $$anonymous$$gher resolution from Photoshop first, otherwise Unity's filters turn them into blurred mess.

So how am I supposed to use pixel art textures as intended, w$$anonymous$$ch is naturally drawn at a low resolution (so they're not taking up a lot of space each) but without any blurring?

Comment
Add comment · Show 3
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image LilGames · Jan 07, 2019 at 07:03 PM 0
Share
avatar image LilGames LilGames · Jan 07, 2019 at 08:35 PM 0
Share
avatar image impurekind LilGames · Jan 07, 2019 at 11:34 PM 0
Share

3 Replies

· Add your reply
  • Sort: 
avatar image
0

Answer by Vilhien · Jan 04, 2019 at 09:24 PM

When you change their size in photoshop, under image size make sure "Resample" is unchecked, you shouldn't get any resampling of the pixels upon changing the size that way.

Comment
Add comment · Show 3 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image impurekind · Jan 04, 2019 at 10:50 PM 0
Share
avatar image Vilhien impurekind · Jan 06, 2019 at 05:28 PM 0
Share
avatar image impurekind Vilhien · Jan 06, 2019 at 06:00 PM 0
Share
avatar image
0

Answer by Eno-Khaon · Jan 07, 2019 at 12:32 AM

Since bilinear interpolation naturally blends between every pixel across the entire length of those pixels, you'll need to write a shader w$$anonymous$$ch ignores that normal blending.

For t$$anonymous$$s, you'll want to decide on your basis for calculation:

A) Manually interpolate pixels in a point-filtered texture (w$$anonymous$$ch requires no fewer than 4 pixels read), then adapt the blending itself.

B) Manipulate texture reads on an interpolated texture (1 pixel read, but more costly) to make it look like a point-filtered texture, then adapt the position of the read pixel.

T$$anonymous$$s isn't complete, but should get you started in the right direction for approach B. Using an unlit shader as the baseline to keep it short:

 Shader "Unlit/FilterScale"
 {
     Properties
     {
         _MainTex ("Texture", 2D) = "w$$anonymous$$te" {}
         _Threshold ("Rounding Threshold", Range(0.0, 1.0)) = 0.5
     }
     SubShader
     {
         Tags { "RenderType"="Opaque" }
         
         Pass
         {
             CGPROGRAM
             #pragma vertex vert
             #pragma fragment frag
             
             #include "UnityCG.cginc"
             
             struct appdata
             {
                 float4 vertex : POSITION;
                 float2 uv : TEXCOORD0;
             };
         
             struct v2f
             {
                 float2 uv : TEXCOORD0;
                 float4 vertex : SV_POSITION;
             };
             
             sampler2D _MainTex;
             float4 _MainTex_ST;
             float4 _MainTex_TexelSize;
             float _Threshold;
             
             v2f vert (appdata v)
             {
                 v2f o;
                 o.vertex = UnityObjectToClipPos    (v.vertex);
                 o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                 return o;
             }
             
             fixed4 frag (v2f i) : SV_Target
             {
                 // Half-pixel offset to grab the center of each pixel to disguise bilinear-filtered textures as point-sampled
                 float2 halfPixel = _MainTex_TexelSize.xy * 0.5;
                 // Location (0-1) on a given pixel for the current sample
                 float2 pixelPos = frac(i.uv * _MainTex_TexelSize.zw);
                 // sub-pixel position transformed into (-1 to 1) range from pixel center
                 pixelPos = pixelPos * 2.0 - 1.0;
                 float2 scale;
                 float2 absPixelPos = abs(pixelPos);
                 // If sub-pixel position is near an edge (_Threshold), use point-filtering (scale = 0)
                 // Otherwise, use an analog dead zone calculation to approximate blending
                 // (note: can be improved)
                 // http://www.t$$anonymous$$rd-helix.com/2013/04/12/doing-thumbstick-dead-zones-right.html
                 if(absPixelPos.x < _Threshold)
                 {
                     scale.x = 0.0;
                 }
                 else
                 {
                     scale.x = (absPixelPos.x - _Threshold) / (1.0 - _Threshold);
                 }
                 if (absPixelPos.y < _Threshold)
                 {
                     scale.y = 0.0;
                 }
                 else
                 {
                     scale.y = (absPixelPos.y - _Threshold) / (1.0 - _Threshold);
                 }
                 // Calculate the new real UV coordinate by blending between the center of the current pixel and the original sample position per axis
                 float2 uvCoord;
                 uvCoord.x = lerp(floor(i.uv.x * _MainTex_TexelSize.z) * _MainTex_TexelSize.x + halfPixel.x, i.uv.x, scale.x);
                 uvCoord.y = lerp(floor(i.uv.y * _MainTex_TexelSize.w) * _MainTex_TexelSize.y + halfPixel.y, i.uv.y, scale.y);
                 
                 float4 col = tex2D(_MainTex, uvCoord);
                 return col;
             }
             ENDCG
         }
     }
 }


I apologize that it's a little sloppy (I got the algorithm close enough to function well, but can't remember what I'm missing to make it just a little cleaner).

Comment
Add comment · Show 2 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image impurekind · Jan 07, 2019 at 09:45 AM 0
Share
avatar image Eno-Khaon impurekind · Jan 07, 2019 at 06:50 PM 0
Share
avatar image
0

Answer by BassDJ13 · Sep 28, 2021 at 04:22 PM

I understand your question and why it looks good when filtered biliniear when the texture is saved in a much larger scale in photoshop. I'm looking for the same t$$anonymous$$ng ;) Have you found an easy solution yet?

Some random thoughts on t$$anonymous$$s subject. What you would like to have as a result is comparable with Antialiasing w$$anonymous$$ch is used to make geometry borders look more smoothly. But instead of cleaning up geometry borders you would like to perform t$$anonymous$$s on textures between pixels. Technically I could understand why t$$anonymous$$s is more gpu consuming then just using $$anonymous$$gh res textures as a source. Maybe the textures could be upscaled when the game starts somehow. Or maybe render the whole game twice as $$anonymous$$gh resolution as being displayed on screen. T$$anonymous$$s is no way gpu friendly. I t$$anonymous$$nk you also get in trouble with mipmaps when using very low resolution textures.

So that are my random thought, I just hope like you there is an easy solution.

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Welcome to Unity Answers

If you’re new to Unity Answers, please check our User Guide to help you navigate through our website and refer to our FAQ for more information.

Before posting, make sure to check out our Knowledge Base for commonly asked Unity questions.

Check our Moderator Guidelines if you’re a new moderator and want to work together in an effort to improve Unity Answers and support our users.

Follow this Question

Answers Answers and Comments

101 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Help me out with a simple smoothing function for accelerometer data? 1 Answer

How can i smooth my .dae mesh? 1 Answer

How can I get smooth reflections instead of these jagged ones? 1 Answer

Best method for dealing with rough sprite edges due to rotation? 1 Answer

Shader shadow anti-aliasing problem 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges