However, none of the solutions make much, if any sense to me.
I’m making a shader for a game engine that isn’t my own, so changes on the C++ side of things, such as using GL_REPEAT isn’t possible, not to mention I need to make this scroll effect work on things that don’t have GL_REPEAT.
My shader code:
vec4 Process(vec4 color)
{
vec2 basetex = gl_TexCoord[0].st;
vec2 fliptex = gl_TexCoord[0].st*-1; // Flip
// Scroll
basetex.y -= timer * 0.25;
fliptex.y += timer * 0.50;
basetex.y = fract(basetex.y);
fliptex.y = fract(fliptex.y);
// This is how I'd normally do things
// but due to the fract() above, it creates
// a seam thanks to mipmapping... ugh.
vec4 baseTexel = getTexel(basetex);
vec4 flipTexel = getTexel(fliptex);
// Workaround for mipmap seam by using the base LOD.
//vec4 baseTexel = texture2DLod(tex, basetex, 0);
//vec4 flipTexel = texture2DLod(tex, fliptex, 0);
// Darken layers.
baseTexel.rgb *= 0.75;
flipTexel.rgb *= 0.25;
vec4 finalTexel = baseTexel+flipTexel;
return finalTexel;
}
Also, this engine uses #version 120, so my options are limited. Anyhow, in short, I need to make this shader mipmap-friendly, at the very least, find some way to hide that 1px seam, with an example that makes sense. (I learn by actually being shown things, so preferably in the form of a modified version of my shader there… Not just “hey, use this function, but I’m not going to explain how to use it logically in your situation.”)
If you know that basetex.y and fliptex.y will be in the range [0,1], then:
// these are guaranteed to be in the range [0,2]
// the fractional part will match the original version
basetex.y += fract(-timer * 0.25);
fliptex.y += fract(timer * 0.50);
// for the range [0,1]
vec4 baseTexel1 = getTexel(basetex);
vec4 flipTexel1 = getTexel(fliptex);
// for the range [1,2]
vec4 baseTexel2 = getTexel(basetex-vec2(0,1));
vec4 flipTexel2 = getTexel(fliptex-vec2(0,1));
vec4 baseTexel = basetex.y<1 ? baseTex1 : baseTex2;
vec4 flipTexel = fliptex.y<1 ? flipTex1 : flipTex2;
[/QUOTE]
Don’t do this. Derivatives (including the implicit derivatives used for LoD calculation) are undefined within non-uniform control flow. So texture lookups with implicit derivatives (which basically means all texture lookups in 1.2) shouldn’t occur inside conditionals.
[QUOTE=GClements;1291704]
Don’t do this. Derivatives (including the implicit derivatives used for LoD calculation) are undefined within non-uniform control flow. So texture lookups with implicit derivatives (which basically means all texture lookups in 1.2) shouldn’t occur inside conditionals.[/QUOTE]
In english? (No offense, but this is terminology that only someone advanced would understand. Layman’s terms, please.)
I don’t exactly understand what you’re trying to say, but going on a pure guess, would this be better?
Any way to do this for both axis (x and y) at the same time?
Yeah, back to the drawing board… because I found that I need to be able to wrap in both axes.
Tried this, causes the same seam issue as just using fract on the coordinates… not sure why though, it’s doing essentially the exact same thing as the code in my last post.
Non-uniform control flow means any expression which may be evaluated for one fragment (or vertex) but not for another. So anything inside if/else or ?:.
Yes.
Sample at 4 points then use two nested conditionals, one for x and one for y.
That’s a typical solution for later versions, but the textureGrad() functions don’t exist in GLSL 1.2 (and the textureLod() functions can’t be used in fragment shaders in 1.2).
[QUOTE=GClements;1291714]
That’s a typical solution for later versions, but the textureGrad() functions don’t exist in GLSL 1.2 (and the textureLod() functions can’t be used in fragment shaders in 1.2).[/QUOTE]
Seems that, from what I’m finding in documentation, texture2DGrad and texture2DLod are valid in 1.2, but were deprecated in 1.3 in exchange for textureGrad and textureLod.