From 2dd88e5bcd8aaa23702851153fd80a56a974ed54 Mon Sep 17 00:00:00 2001 From: BlackYps <52536103+BlackYps@users.noreply.github.com> Date: Sun, 23 Jun 2024 09:02:32 +0200 Subject: [PATCH] Rotate every other texture layer (#5810) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I discovered that rotating some texture layers makes the repeating texture pattern less visible. Now not all textures are aligned in the same direction and the 30° rotation from the horizonal/vertical grid also seems to make it harder for the eye to notice repeating features. The effect is not amazing, but it's almost free, so it still seems like a good deal. The only question is, on which shaders do we want to apply that? Before: ![Screenshot 2024-01-07 015257](https://github.com/FAForever/fa/assets/52536103/358478f2-ce0b-4d33-b2bf-a7a8fdb111fa) After: ![Screenshot 2024-01-07 015310](https://github.com/FAForever/fa/assets/52536103/db69370e-aa1e-4571-8c1f-2ba2112fef7e) --- changelog/snippets/graphics.5810.md | 3 +++ effects/terrain.fx | 38 +++++++++++++++++------------ 2 files changed, 25 insertions(+), 16 deletions(-) create mode 100644 changelog/snippets/graphics.5810.md diff --git a/changelog/snippets/graphics.5810.md b/changelog/snippets/graphics.5810.md new file mode 100644 index 0000000000..ce351ae1f3 --- /dev/null +++ b/changelog/snippets/graphics.5810.md @@ -0,0 +1,3 @@ +- (#5810) Rotate every other texture layer in the Terrain301 shader + +By rotating every other texture layer by 30° we can make it harder to spot texture repetition. At the moment the Terrain301 shader is only used by the Sunset biome of the map generator. Hand-made maps don't use it yet, because there is no support in the map editor. diff --git a/effects/terrain.fx b/effects/terrain.fx index 597fccb634..95ccd4a7fe 100644 --- a/effects/terrain.fx +++ b/effects/terrain.fx @@ -2707,6 +2707,9 @@ technique Terrain151 < float4 Terrain301NormalsPS ( VS_OUTPUT inV, uniform bool halfRange ) : COLOR { float4 position = TerrainScale * inV.mTexWT; + // 30° rotation + float2x2 rotationMatrix = float2x2(float2(0.866, -0.5), float2(0.5, 0.866)); + position.zw = mul(position.xy, rotationMatrix); float4 mask0 = tex2D(UtilitySamplerA, position.xy); float4 mask1 = tex2D(UtilitySamplerB, position.xy); @@ -2717,21 +2720,21 @@ float4 Terrain301NormalsPS ( VS_OUTPUT inV, uniform bool halfRange ) : COLOR } float3 lowerNormal = normalize(tex2D(LowerNormalSampler, position.xy * LowerAlbedoTile.xy ).rgb * 2 - 1); - float3 stratum0Normal = normalize(tex2D(Stratum0NormalSampler, position.xy * Stratum0AlbedoTile.xy).rgb * 2 - 1); + float3 stratum0Normal = normalize(tex2D(Stratum0NormalSampler, position.zw * Stratum0AlbedoTile.xy).rgb * 2 - 1); float3 stratum1Normal = normalize(tex2D(Stratum1NormalSampler, position.xy * Stratum1AlbedoTile.xy).rgb * 2 - 1); - float3 stratum2Normal = normalize(tex2D(Stratum2NormalSampler, position.xy * Stratum2AlbedoTile.xy).rgb * 2 - 1); + float3 stratum2Normal = normalize(tex2D(Stratum2NormalSampler, position.zw * Stratum2AlbedoTile.xy).rgb * 2 - 1); float3 stratum3Normal = normalize(tex2D(Stratum3NormalSampler, position.xy * Stratum3AlbedoTile.xy).rgb * 2 - 1); - float3 stratum4Normal = normalize(tex2D(Stratum4NormalSampler, position.xy * Stratum4AlbedoTile.xy).rgb * 2 - 1); + float3 stratum4Normal = normalize(tex2D(Stratum4NormalSampler, position.zw * Stratum4AlbedoTile.xy).rgb * 2 - 1); float3 stratum5Normal = normalize(tex2D(Stratum5NormalSampler, position.xy * Stratum5AlbedoTile.xy).rgb * 2 - 1); - float3 stratum6Normal = normalize(tex2D(Stratum6NormalSampler, position.xy * Stratum6AlbedoTile.xy).rgb * 2 - 1); + float3 stratum6Normal = normalize(tex2D(Stratum6NormalSampler, position.zw * Stratum6AlbedoTile.xy).rgb * 2 - 1); - float stratum0Height = sampleHeight(position.xy, Stratum0AlbedoTile.xy, Stratum0NormalTile.xy, float2(0.5, 0.0), true); + float stratum0Height = sampleHeight(position.zw, Stratum0AlbedoTile.xy, Stratum0NormalTile.xy, float2(0.5, 0.0), true); float stratum1Height = sampleHeight(position.xy, Stratum1AlbedoTile.xy, Stratum1NormalTile.xy, float2(0.0, 0.5), true); - float stratum2Height = sampleHeight(position.xy, Stratum2AlbedoTile.xy, Stratum2NormalTile.xy, float2(0.5, 0.5), true); + float stratum2Height = sampleHeight(position.zw, Stratum2AlbedoTile.xy, Stratum2NormalTile.xy, float2(0.5, 0.5), true); float stratum3Height = sampleHeight(position.xy, Stratum3AlbedoTile.xy, Stratum3NormalTile.xy, float2(0.0, 0.0), false); - float stratum4Height = sampleHeight(position.xy, Stratum4AlbedoTile.xy, Stratum4NormalTile.xy, float2(0.5, 0.0), false); + float stratum4Height = sampleHeight(position.zw, Stratum4AlbedoTile.xy, Stratum4NormalTile.xy, float2(0.5, 0.0), false); float stratum5Height = sampleHeight(position.xy, Stratum5AlbedoTile.xy, Stratum5NormalTile.xy, float2(0.0, 0.5), false); - float stratum6Height = sampleHeight(position.xy, Stratum6AlbedoTile.xy, Stratum6NormalTile.xy, float2(0.5, 0.5), false); + float stratum6Height = sampleHeight(position.zw, Stratum6AlbedoTile.xy, Stratum6NormalTile.xy, float2(0.5, 0.5), false); float3 normal = lowerNormal; normal = splatBlendNormal(normal, stratum0Normal, stratum0Height, mask0.x, SpecularColor.r); @@ -2749,6 +2752,9 @@ float4 Terrain301AlbedoPS ( VS_OUTPUT inV, uniform bool halfRange ) : COLOR { // height is now in the z coordinate float4 position = TerrainScale * inV.mTexWT; + // 30° rotation + float2x2 rotationMatrix = float2x2(float2(0.866, -0.5), float2(0.5, 0.866)); + position.zw = mul(position.xy, rotationMatrix); // do arithmetics to get range from (0, 1) to (-1, 1) as normal maps store their values as (0, 1) float3 normal = normalize(2 * SampleScreen(NormalSampler,inV.mTexSS).xyz - 1); @@ -2763,21 +2769,21 @@ float4 Terrain301AlbedoPS ( VS_OUTPUT inV, uniform bool halfRange ) : COLOR // This shader wouldn't compile because it would have to store too many variables if we didn't use this trick in the vertex shader float4 lowerAlbedo = sampleAlbedo(LowerAlbedoSampler, position.xy, LowerAlbedoTile.xy, float2(0.0, 0.0), true); - float4 stratum0Albedo = sampleAlbedo(Stratum0AlbedoSampler, position.xy, inV.nearScales.xx, float2(0.5, 0.0), true); + float4 stratum0Albedo = sampleAlbedo(Stratum0AlbedoSampler, position.zw, inV.nearScales.xx, float2(0.5, 0.0), true); float4 stratum1Albedo = sampleAlbedo(Stratum1AlbedoSampler, position.xy, inV.nearScales.yy, float2(0.0, 0.5), true); - float4 stratum2Albedo = sampleAlbedo(Stratum2AlbedoSampler, position.xy, inV.nearScales.zz, float2(0.5, 0.5), true); + float4 stratum2Albedo = sampleAlbedo(Stratum2AlbedoSampler, position.zw, inV.nearScales.zz, float2(0.5, 0.5), true); float4 stratum3Albedo = sampleAlbedo(Stratum3AlbedoSampler, position.xy, inV.nearScales.ww, float2(0.0, 0.0), false); - float4 stratum4Albedo = sampleAlbedo(Stratum4AlbedoSampler, position.xy, Stratum4AlbedoTile.xy, float2(0.5, 0.0), false); + float4 stratum4Albedo = sampleAlbedo(Stratum4AlbedoSampler, position.zw, Stratum4AlbedoTile.xy, float2(0.5, 0.0), false); float4 stratum5Albedo = sampleAlbedo(Stratum5AlbedoSampler, position.xy, Stratum5AlbedoTile.xy, float2(0.0, 0.5), false); - float4 stratum6Albedo = sampleAlbedo(Stratum6AlbedoSampler, position.xy, Stratum6AlbedoTile.xy, float2(0.5, 0.5), false); + float4 stratum6Albedo = sampleAlbedo(Stratum6AlbedoSampler, position.zw, Stratum6AlbedoTile.xy, float2(0.5, 0.5), false); - float stratum0Height = sampleHeight(position.xy, inV.nearScales.xx, inV.farScales.xx, float2(0.5, 0.0), true); + float stratum0Height = sampleHeight(position.zw, inV.nearScales.xx, inV.farScales.xx, float2(0.5, 0.0), true); float stratum1Height = sampleHeight(position.xy, inV.nearScales.yy, inV.farScales.yy, float2(0.0, 0.5), true); - float stratum2Height = sampleHeight(position.xy, inV.nearScales.zz, inV.farScales.zz, float2(0.5, 0.5), true); + float stratum2Height = sampleHeight(position.zw, inV.nearScales.zz, inV.farScales.zz, float2(0.5, 0.5), true); float stratum3Height = sampleHeight(position.xy, inV.nearScales.ww, inV.farScales.ww, float2(0.0, 0.0), false); - float stratum4Height = sampleHeight(position.xy, Stratum4AlbedoTile.xy, Stratum4NormalTile.xy, float2(0.5, 0.0), false); + float stratum4Height = sampleHeight(position.zw, Stratum4AlbedoTile.xy, Stratum4NormalTile.xy, float2(0.5, 0.0), false); float stratum5Height = sampleHeight(position.xy, Stratum5AlbedoTile.xy, Stratum5NormalTile.xy, float2(0.0, 0.5), false); - float stratum6Height = sampleHeight(position.xy, Stratum6AlbedoTile.xy, Stratum6NormalTile.xy, float2(0.5, 0.5), false); + float stratum6Height = sampleHeight(position.zw, Stratum6AlbedoTile.xy, Stratum6NormalTile.xy, float2(0.5, 0.5), false); float4 albedo = lowerAlbedo; albedo = splatLerp(albedo, stratum0Albedo, stratum0Height, mask0.x, SpecularColor.r);