I’m writing a shader that will scroll a single texture horizontally while flipping every other iteration so 1 texture can appear to be a much larger continuous texture. I’m doing to in attempt to reduce the number of textures I need to get a nice scrolling space nebula background.
The shader works great except for 1 problem, each point where the texture edges meet a small black flickering line shows as you can see below:
Shader "Custom/Additive/Scrolling UV" {
Properties {
_MainTex ("Base (RGB)", 2D) = "white" {}
_offsetDirectionX ("X Scroll Direction", Range (-1, 1)) = 0
_offsetDirectionY ("Y Scroll Direction", Range (-1, 1)) = 0
_offsetSpeedX ("X Scroll Speed", Range (0, 1)) = 0
_offsetSpeedY ("Y Scroll Speed", Range (0, 1)) = 0
_Color ("Main Color", Color) = (1,1,1,1)
}
Category {
// We must be transparent, so other objects are drawn before this one.
Tags { "Queue"="Transparent" }
SubShader
{
Blend SrcAlpha One
Cull Off Lighting Off ZWrite Off Fog { Color (0,0,0,0) }
Pass
{
Name "BASE"
Tags { "LightMode" = "Always" }
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma fragmentoption ARB_precision_hint_fastest
#include "UnityCG.cginc"
float4 _MainTex_ST;
float4 _Color;
float _offsetDirectionX;
float _offsetDirectionY;
float _offsetSpeedX;
float _offsetSpeedY;
struct v2f{
float4 vertex : POSITION;
float2 texcoord : TEXCOORD0;
float3 color : COLOR;
};
v2f vert (appdata_base v) {
v2f o;
o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
o.texcoord = v.texcoord;
return o;
}
sampler2D _MainTex;
half4 frag(v2f i) :COLOR0
{
float2 offset = float2((_Time.y * _offsetDirectionX * _offsetSpeedX), (_Time.y * _offsetDirectionY * _offsetSpeedY));
float2 coords = float2(i.texcoord.x + offset.x, i.texcoord.y + offset.y);
if (fmod(floor(i.texcoord.x + offset.x), 2) == 0)
coords.x *= -1;
return _Color * tex2D(_MainTex, coords);
}
ENDCG
} // end pass
} // end subshader
} // end category
} // end shader
Any idea if its possible to get rid of that seam somehow? I know I could just add transparency to the texture around the edges but then it will lose the continuous look.
You can temporarily solve your problem by disabling mipmapping on the texture you want to use, and setting the filter mode to point (you can do this if you set your texture type to advanced). Unfortunately, those are both used to reduce aliasing.
MipMapping reduces jagged edges in scaled textures(for example, when it is used on a wall in the distance), and texture filtering makes them look less ‘blocky’, by mixing multiple pixels together when the texture coordinates don’t map exactly to the pixels on the image.
Both these techniques mix the pixel values with neighbours. In your shader, the edge pixels are supposed to be their own neighbour, which these techniques don’t account for, so the pixels aren’t mixed correctly.
I think the easiest way to get the effect you’re after is to simply place multiple planes next to each other, with half of em scaled by -1, so their textures line up.
These textures will be used on a plane in the background at a constant distance from an orthographic camera,it looks good so far on my galaxy s3. What kind of issues will it cause?
There will be aliasing in textures that aren’t displayed at their original resolution. (The description I gave yesterday was jagged edges, but now that I’m more awake I realize that’s not quite the correct description)
It’s easier to show. This article shows an example of what you could see if you don’t use mipmapping.
You can also see what it does for yourself, by placing a high resolution texture on a plane, far away from the camera, and compare the version with mipmapping to the one without.