Hi, I had this issue for quite some time now and I am unable to solve it. When using this tile, with black on one side, and white on the other... When I move the camera, I see these white pixels coming and going along the tile. But this only seems to happen with tiles that have extreme black and extreme white on opposite sides. Other tiles with varying colors do not experience this problem... If I add a 1px black line on the white side, the issue disappears... but obviously then there will be a black line on the white side, which I don't want. The tiles are read from a texture atlas. I have tried to add padding/margins/empty space between the tiles, but this has no effect. I have tried to change the texture settings to anything imaginable, but this has no effect. I have tried to read smaller parts of the tile (in the Shader), but this has no effect. Anyone has any clues?
The fact the issue disappears when adding a pixel line to the left side implies that how your sampling the sub-texture of the atlas is creating a scenario where sometimes the UV value loops back over to the other side of the sampling region instead of simply clamping. This gradient is part of a larger image that is imported and sliced using the Sprite Editor right? If not, then make sure the Texture Repeat settings are set to Clamp as well.
Well, there is something like that going on... This is a 4096x4096 PNG file (tile atlas) I made myself. I changed the texture shape to 2D array to see if UNITY_SAMPLE_TEX2DARRAY made any difference - It did not. The texture is clamp. There is no filter. There is no compression. There are no mipmaps. I tried adding space (everything between 1px and 100px) between tiles, transparent and filled black. But nothing seems to help. I should mention that this is a procedurally generated mesh, and I am using a Surface Shader. There are no UVS on this mesh, so I am using world coordinates as UV. Then I am adding data into the Uv, Uv1, Uv2 etc, which I then read in the shader to figure out what tiles to paint. I am painting 16x16 tiles on each mesh. What I actually want to accomplish here is to use this gradient to blend between biomes. In this case Forest <> Desert. And this works well in my opinion except for these small random white pixels...
I will paste my Shader code here, if anyone can see anything obviously wrong. (I am not very good at shaders). Code (CSharp): Shader "Custom/testshader" { Properties { _DiffuseMap("Diffuse Map", 2D) = "white" {} _DiffuseMap2("Diffuse Map 2", 2D) = "white" {} _DiffuseMap3("Diffuse Map 3", 2D) = "white" {} _DiffuseMap4("Diffuse Map 4", 2D) = "white" {} _DiffuseMap5("Diffuse Map 5", 2D) = "white" {} } SubShader { Tags{ "RenderType" = "Opaque" "Queue" = "Geometry" } LOD 0 CGPROGRAM #pragma surface surf Standard fullforwardshadows #pragma target 4.0 sampler2D _DiffuseMap; struct Input { float4 screenPos; float3 worldPos; float3 worldNormal; float2 uv_DiffuseMap : TEXCOORD0; float2 uv2_DiffuseMap2 : TEXCOORD1; float2 uv3_DiffuseMap3 : TEXCOORD2; float2 uv4_DiffuseMap4 : TEXCOORD3; }; void surf(Input IN, inout SurfaceOutputStandard o) { float originalTileOffset = 0.0625f; // tilesize(256) / texturesize(4096) float yCoord = (1 - (IN.uv_DiffuseMap.y * originalTileOffset)); // Biome float xCoord = (IN.uv_DiffuseMap.x * originalTileOffset); // X TILE POS float xCoordOther = (2 * originalTileOffset); // X TILE POS for the "other biome" float2 offsetY = float2(xCoord, yCoord); float2 offsetX = float2(0, yCoord ); float2 offsetZ = float2(0, yCoord ); // UVs are just world coordinates float2 yUV = IN.worldPos.xz; float2 xUV = IN.worldPos.zy; float2 zUV = IN.worldPos.xy; // For blending towards sand at water level float blendAmount = (1 - IN.worldNormal.y) / 4.0f; // If we are below 10, we are just sand. if (IN.worldPos.y < 10) { offsetY = float2(originalTileOffset, yCoord); offsetX = float2(originalTileOffset, yCoord); offsetZ = float2(originalTileOffset, yCoord); } // SIDE X float4 x = tex2D(_DiffuseMap, frac(xUV) * originalTileOffset + offsetX); // SIDE Z float4 z = tex2D(_DiffuseMap, frac(zUV) * originalTileOffset + offsetZ); // TOP / BOTTOM float4 y = tex2D(_DiffuseMap, frac(yUV) * originalTileOffset + offsetY); // Biome blending if (IN.uv3_DiffuseMap3.x >= 0) { // Other biome tile (normal tile) float4 newy = y; float4 newx = x; float4 newz = z; if (IN.worldPos.y > 10) { // Recalculate for other-biome yCoord = (1 - (IN.uv3_DiffuseMap3.y * originalTileOffset)); offsetY = float2(xCoordOther, yCoord); offsetX = float2(0, yCoord); offsetZ = float2(0, yCoord); newy = tex2D(_DiffuseMap, frac(yUV) * originalTileOffset + offsetY); newx = tex2D(_DiffuseMap, frac(xUV) * originalTileOffset + offsetX); newz = tex2D(_DiffuseMap, frac(zUV) * originalTileOffset + offsetZ); } // Blackwhite tile float blackWhiteTile_Y = (1 - (IN.uv2_DiffuseMap2.y * originalTileOffset)); float4 y2 = tex2D(_DiffuseMap, frac(yUV) * originalTileOffset + float2(IN.uv3_DiffuseMap3.x * originalTileOffset, blackWhiteTile_Y)); y = lerp(y, newy, y2); x = lerp(x, newx, y2); z = lerp(z, newz, y2); } // BLEND SAND WATER LEVEL if (IN.worldPos.y > 10 && IN.worldPos.y < 12) { // Sand float4 yy = tex2D(_DiffuseMap, frac(yUV) * originalTileOffset + float2(originalTileOffset, yCoord)); // sand float blendAmountS = (12 - IN.worldPos.y) / 2.0f; y = lerp(y, yy, blendAmountS); x = lerp(x, y, blendAmountS); z = lerp(z, y, blendAmountS); } // Dark waters if (IN.worldPos.y < 5) { float blendAmountW = (5 - IN.worldPos.y) / 2.0f; y = lerp(y, 0, blendAmountW); x = lerp(x, 0, blendAmountW); z = lerp(z, 0, blendAmountW); } // Noise to "randomly" darken spots, making it more "realistic" or "varied" y = lerp(y - IN.uv2_DiffuseMap2.x, y, y); float3 projNormal = saturate(pow(IN.worldNormal, 2)); o.Albedo = lerp(o.Albedo, y, projNormal.y); o.Albedo = lerp(o.Albedo, z, projNormal.z); o.Albedo = lerp(o.Albedo, x, projNormal.x); } ENDCG } Fallback "Diffuse" }