Need Help Getting Tileable Shader to Tile Seamlessly

So I have been using this great water shader, but I have been struggling for days to get it to tile properly. All of the noise and source images it uses do tile correctly and have continuous edges so I am not sure why this issue is occurring. I can see how they mostly match up, but subtle variations cause a noticeable seem. I believe the issue has to do with the uv values and getting them to reflect global coordinates instead of local ones, but I am having a lot of trouble implementing this. Could someone please help me fix this issue? I am going crazy trying to figure this out myself haha. I have also tried using a TextureRect, and while this does allow seamless infinite tiling, it only works in the positive x and y directions, not in all directions. Thanks! Here is my shader code:

shader_type canvas_item;

uniform vec2 global_position;

uniform vec2 tile_offset = vec2(0.0, 0.0);

uniform float aspectRatio = 1.0f;

uniform float pixelization = 12048.0f;

uniform sampler2D waterDepthGradient : hint_default_black;

uniform vec4 causticColor = vec4(0.455f, 0.773f, 0.765f, 1.0f);

uniform vec4 causticHighlightColor = vec4(0.741f, 0.494f, 0.898f, 1.0f);

uniform sampler2D causticTexture : hint_default_white, repeat_enable;

uniform sampler2D causticHighlightTexture : hint_default_white, repeat_enable;

uniform sampler2D causticNoiseTexture : hint_default_white, repeat_enable;

uniform sampler2D causticFadeNoiseTexture : hint_default_white, repeat_enable;

uniform float causticScale = 12.0f;

uniform float causticSpeed = 0.005f;

uniform float causticMovementAmount = 0.15f;

uniform float causticFaderMultiplier = 1.45f;

uniform vec4 specularColor = vec4(1.0f, 1.0f, 1.0f, 1.0f);

uniform sampler2D specularNoiseTexture : hint_default_white, repeat_enable;

uniform sampler2D specularMovementLeftNoiseTexture : hint_default_white, repeat_enable;

uniform sampler2D specularMovementRightNoiseTexture : hint_default_white, repeat_enable;

uniform float specularThreshold = 0.35f;

uniform float specularSpeed = 0.025f;

uniform float specularScale = 15.0f;

uniform vec4 foamColor = vec4(1.0f, 1.0f, 1.0f, 1.0f);

uniform sampler2D foamTexture : hint_default_white, repeat_enable;

uniform float foamIntensity = 0.2f;

uniform float foamScale = 15.0f;

uniform vec4 outlineColor = vec4(0.675f, 0.86f, 1.0f, 1.0f);

uniform float generalTransparency = 1.0f;

uniform vec2 offset;

// ------------------------------------------------------------------------------------

// Helper functions

// Blends two vec2’s by subtracting them. Compare this to Photoshop blend mode “Subtract”.

// Source:

// Blend Node | Shader Graph | 6.9.2

vec2 blendSubtract_vec2(vec2 base, vec2 blend, float opacity)

{

vec2 result = base - blend;

return mix(base, result, opacity);
}

// Blends two floats by subtracting them. Compare this to Photoshop blend mode “Subtract”.

// Source:

// Blend Node | Shader Graph | 6.9.2

float blendSubtract_float(float base, float blend, float opacity)

{

float result = base - blend;

return mix(base, result, opacity);
}

// Blends two vec2’s by overlaying them. Compare this to Photoshop blend mode “Overlay”.

// Source:

// Blend Node | Shader Graph | 6.9.2

float blendOverlay_float(float base, float blend, float opacity)

{

float result1 = 1.0f - 2.0f * (1.0f - base) * (1.0f - blend);
float result2 = 2.0f * base * blend;

float zeroOrOne = step(0.5f, base);

float res = result2 * zeroOrOne + (1.0 - zeroOrOne) * result1;

return mix(base, res, opacity);

}

// Pixelizes the given coordinate.

vec2 pixelizeCoordinates(vec2 coordinates)

{

return floor(coordinates * pixelization) / pixelization;
}

// Applies the aspect ratio to the coordinates.

vec2 applyAspectRatio(vec2 coordinates)

{

return vec2(coordinates.x, coordinates.y * aspectRatio);
}

// ------------------------------------------------------------------------------------

// Shader layers

vec4 caustics(vec2 pixelizedCoordinates)

{

vec4 causticNoise = texture(causticNoiseTexture, TIME * causticSpeed + pixelizedCoordinates);

vec2 noiseCoordinates = blendSubtract_vec2(pixelizedCoordinates * causticScale, causticNoise.rg, causticMovementAmount);

vec4 causticHighlight = texture(causticHighlightTexture, noiseCoordinates) * causticHighlightColor;

vec4 caustic = texture(causticTexture, noiseCoordinates) * causticColor;

vec4 interpolatedCaustics = mix(caustic, causticHighlight, causticHighlight.a);

float fadeNoise = texture(causticFadeNoiseTexture, noiseCoordinates).r * causticFaderMultiplier;

return vec4(interpolatedCaustics.r, interpolatedCaustics.g, interpolatedCaustics.b, clamp(interpolatedCaustics.a - fadeNoise, 0.0, 1.0));
}

vec4 specular(vec2 pixelizedCoordinates)

{

vec2 scaledCoordinates = pixelizedCoordinates * specularScale;

float specularNoise = texture(specularNoiseTexture, scaledCoordinates).r;

float leftScrollingNoise = texture(specularMovementLeftNoiseTexture, scaledCoordinates + vec2(TIME * specularSpeed, 0.0f)).r;

float rightScrollingNoise = texture(specularMovementRightNoiseTexture, scaledCoordinates + vec2(TIME * specularSpeed * -1.0f, 0.0f)).r;

return step(specularThreshold, blendSubtract_float(blendOverlay_float(leftScrollingNoise, rightScrollingNoise, 1.0f), specularNoise, 1.0f)) * specularColor;
}

vec4 foam(vec2 pixelizedCoordinates, vec4 mainTexColor)

{

vec4 colorizedFoam = texture(foamTexture, pixelizedCoordinates * foamScale) * foamColor;

float intensity = clamp(mainTexColor.g * mainTexColor.a - foamIntensity, 0.0f, 1.0f);

return vec4(colorizedFoam.r, colorizedFoam.g, colorizedFoam.b, colorizedFoam.a * intensity);
}

// ------------------------------------------------------------------------------------

// Fragment Shader code

void fragment()

{

//vec2 global_position = vec2(TRANSFORM[2].x, TRANSFORM[2].y);

vec2 uv = FRAGCOORD.xy / SCREEN_PIXEL_SIZE + tile_offset;

uv += offset;

//uv += global_position;

uv = mod(uv, 1.0); // Wrap UV to range [0, 1)

vec2 pixelizedCoordinates = pixelizeCoordinates(applyAspectRatio(UV));

vec4 mainTex = texture(TEXTURE, UV);

vec4 depthBasedWaterColor = texture(waterDepthGradient, vec2(1.0f - mainTex.b, 1.0f));

vec4 finalCaustics = caustics(pixelizedCoordinates);

vec4 finalSpecular = specular(pixelizedCoordinates);

vec4 finalFoam = foam(pixelizedCoordinates, mainTex);

vec4 waterWithCausticLayer = mix(depthBasedWaterColor, finalCaustics, finalCaustics.a);

vec4 waterWithCausticAndSpecularLayer = mix(waterWithCausticLayer, finalSpecular, ceil(finalCaustics.a) * finalSpecular.a);

vec4 waterWithCausticAndSpecularAndFoamLayer = mix(waterWithCausticAndSpecularLayer, finalFoam, finalFoam.a);

float outline = mainTex.a * mainTex.r;

vec4 finalOutlineColor = outline * outlineColor;

vec4 finalRGBColor = mix(waterWithCausticAndSpecularAndFoamLayer, finalOutlineColor, outline);

float brightness_threshold = 0.4;

float brightness = (finalRGBColor.r + finalRGBColor.g + finalRGBColor.b) / 3.0;

float old_transparency = mainTex.b * generalTransparency;

// Calculate brightness based on the RGB values

// Calculate the factor by which to adjust alpha only if brightness exceeds the threshold

float alpha_factor = step(brightness_threshold, brightness) * (brightness - brightness_threshold) / (1.0 - brightness_threshold);

// Blend alpha between old transparency and full opacity based on the adjusted factor

float adjusted_alpha = mix(old_transparency, 1.0, alpha_factor * 1.2);

COLOR = vec4(finalRGBColor.r, finalRGBColor.g, finalRGBColor.b, adjusted_alpha);

did you turned on the seamless option for the noises?

What do you mean seamless option? The noise are just png files that are already seamless, I don’t see that option anywhere?

so you are not using the fastnoiselite which is built in, then it could be your generated noise is not actually seamless
the seamless option:

I ended up figuring it out, I had the whole thing scaled down slightly which cut off the edges. Thanks tho!

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.