Help with shader

I’m working on a shader for rendering moving textures. The original one I set up where you simply pass in the offset, works just fine, however… when I updated it to pass in a the speed and direct… it still worked! hah… until… I alter the speed and direction. Then the texture jumps to new coords and begins acting normal again. I’m doing this on complete trial and error… so bare with any bad implementation issues. I have done no clean up, since I have had 0 luck tracking down why this happens.



Is this due to the shader being recompiled when updating these variables in the .vert? The alpha is being updated and effects nothing… but it is also only being used by the .frag.



Anyways… any help here would be greatly appreciated! Here is the .vert .frag files:



MovingTextured.vert:

[java]

uniform mat4 g_WorldViewProjectionMatrix;

uniform float g_Time;

attribute vec3 inPosition;

uniform float m_Alpha;

uniform float m_Speed;

uniform float m_Direction;



#if defined(HAS_COLORMAP) || (defined(HAS_LIGHTMAP) && !defined(SEPARATE_TEXCOORD))

#define NEED_TEXCOORD1

#endif

#if defined(IS_MOVING) && defined(HAS_DIRECTION)

#define MOVE

#endif



#ifdef NEED_TEXCOORD1

attribute vec2 inTexCoord;

varying vec2 texCoord1;

#endif



#ifdef SEPARATE_TEXCOORD

attribute vec2 inTexCoord2;

varying vec2 texCoord2;

#endif



#ifdef HAS_VERTEXCOLOR

attribute vec4 inColor;

varying vec4 vertColor;

#endif



void main(){

#ifdef NEED_TEXCOORD1

texCoord1 = inTexCoord;

#ifdef MOVE

float xInc = ((m_Speed*g_Time)sin(m_Direction));

float yInc = ((m_Speed
g_Time)*cos(m_Direction));

if (xInc > 1.0) xInc -= 1.0;

else if (xInc < 0.0) xInc += 1.0;

if (yInc > 1.0) yInc -= 1.0;

else if (yInc < 0.0) yInc += 1.0;

texCoord1 += vec2(xInc,yInc);

#endif

#endif



#ifdef SEPARATE_TEXCOORD

texCoord2 = inTexCoord2;

#endif



#ifdef HAS_VERTEXCOLOR

vertColor = inColor;

#endif



gl_Position = g_WorldViewProjectionMatrix * vec4(inPosition, 1.0);

}

[/java]



MovingTextured.frag:

[java]

uniform vec4 m_Color;

uniform float m_Alpha;



#if defined(HAS_GLOWMAP) || defined(HAS_COLORMAP) || (defined(HAS_LIGHTMAP) && !defined(SEPARATE_TEXCOORD))

#define NEED_TEXCOORD1

#endif

#if defined(IS_MOVING) && defined(HAS_DIRECTION)

#define MOVE

#endif



#ifdef HAS_COLORMAP

uniform sampler2D m_ColorMap;

#endif



#ifdef NEED_TEXCOORD1

#ifdef MOVE

varying vec2 texCoord1;

#endif

#endif



#ifdef HAS_LIGHTMAP

uniform sampler2D m_LightMap;

#ifdef SEPARATE_TEXCOORD

varying vec2 texCoord2;

#endif

#endif



#ifdef HAS_VERTEXCOLOR

varying vec4 vertColor;

#endif



void main(){

vec4 color = vec4(1.0);



#ifdef HAS_COLORMAP

#ifdef MOVE

color *= texture2D(m_ColorMap, texCoord1);

#endif

#endif



#ifdef HAS_VERTEXCOLOR

color *= vertColor;

#endif



#ifdef HAS_COLOR

vec4 n_Color = vec4((m_Color[0]*color.a),(m_Color[1]*color.a),(m_Color[2]*color.a),color.a);

color = mix(color, n_Color, 0.25f);

#endif



#ifdef HAS_LIGHTMAP

#ifdef SEPARATE_TEXCOORD

color.rgb *= texture2D(m_LightMap, texCoord2).rgb;

#else

color.rgb *= texture2D(m_LightMap, texCoord1).rgb;

#endif

#endif



#ifdef HAS_ALPHA

color.a *= m_Alpha;

#endif



gl_FragColor = color;

}

[/java]

[java]

float xInc = ((m_Speed*g_Time)sin(m_Direction));

float yInc = ((m_Speed
g_Time)*cos(m_Direction));

if (xInc > 1.0) xInc -= 1.0;

else if (xInc < 0.0) xInc += 1.0;

if (yInc > 1.0) yInc -= 1.0;

else if (yInc < 0.0) yInc += 1.0;

texCoord1 += vec2(xInc,yInc);

[/java]



This is an odd little bit of code. g_Time will keep increasing so you will go way way way above 1 pretty fast depending on m_Speed… so I suspect simply subtracting 1.0 at some point in is probably not what you want.



Basically, the magnitude of your curve will keeping getting larger and larger, and every time it crosses over 0 or over 1 you will get a big 1.0 jump.



What is it that you are trying to do? Usually I’d expect time to be a part of the period or some finite function of time being part of the magnitude.

@pspeed Hmmm… it doesn’t jump ever, unless I change the direction or speed. It runs nice & smooth. (constant speed)



m_Speed is a float set between .025 and .05 for my purposes (basically anything between 0 and 1 works).

m_Direction is between -HALF_PI and HALF_PI

the checks right below the first two lines cycle the xInc/yInc to stay between 0 and 1. Since the texture is tiled, it is a very smooth transition as it moves.



I just can’t figure out why when I update m_Speed or m_Direction I get a huge jump to new coords before it starts running smooth again.

@t0neg0d said:
the checks right below the first two lines cycle the xInc/yInc to stay between 0 and 1. Since the texture is tiled, it is a very smooth transition as it moves.


No, they don't. You think they do but they don't. They subtract 1 if it is greater than 1 and they add 1 if it is less than 0. That is _a lot_ different than clamping to 0-1. For example, what if xInc is 50?

There is actually a function called clamp() but it sounds like you really want a mod() though... to make sure it just goes 0-1, 0-1 over and over.

And by the way… if you have wrap mode on for your texture then you shouldn’t need to clamp/mod at all.

@pspeed said:
And by the way... if you have wrap mode on for your texture then you shouldn't need to clamp/mod at all.


And actually, that's the only way that you'll get right answers anyway. Otherwise, in the low numbers your texture will sometimes invert as x1 is 0.99 and x2 is 0.11 for example.

@pspeed I was under the assumption the g_Time was the time the shader took to render a frame (pass, whatever). Either way, I can fix that… but will it effect the issue I am seeing? I would think it would happen every time it renders… not just when I update those variables (which happens very infrequently).



I’ll try removing g_Time… and pass in the tpf from the update loop. Otherwise, it would speed up and slow down depending on CPU usage. But, I was hoping to avoid constantly updating the material.



Who knows… maybe that will fix it /shrug. Any other thoughts?

g_Time ever increases. It is time. g_tpf (I think is what it is called) will be the time of the last frame but is useless in a shader because there is not accumulation.



Imaginge if you were running at 60 FPS and using tpf, your texture would never move.



I think the reason your image jumps when you change direction is because you aren’t limiting g_Time. So say g_Time is 50 and direction is 1,0,0… when you switch direction to some other value it’s like waving the end of a long stick over the texture… wherever the end of the ever growing stick is, that’s the part of the texture that is used…



What affect is it that you are trying to achieve?

Just switch direction from the current point.



And… very funny, I was just about to post that g_Time was the whole reason it was working in the first place… but you beat me to it.



Soo… how do I use in / out variables? They are supposed to be the value from the last frame rendered. However, my attempts so far aren’t showing this to be the case. Wouldn’t this solve the issue? i.e. some in variable that is += g_TPF until it is greater than 1… then reset to 0. This would ensure that the m_Direction wouldn’t do what you said above.

@pspeed well… bad choice of words on reseting it to 0… cycle it I mean.

@pspeed I am starting to think this headache I have is making me temporarily retarded.



Basically what I would like to do is either:


  1. get texCoord1 from the previous rendered frame.

    OR
  2. get texCoord1 from the previous rendered frame.



    Thats pretty much what I need :wink:

You can’t, really. Not without knowing the previous time and direction.



What I meant by “what are you trying to do?” is what overall effect are you trying to achieve… not the shader specific stuff. What is the visual you are going for?

@pspeed Oh… sorry.



I am updating the shader I am using to move clouds. At the moment, I determine the offset from the original clamp in the update loop and pass it in to move the texture. However, it seems silly to continuously pass in an offset when the shader should be capable of doing it.



For instance…



if the current texCoord1 = 0.457, 0,0312

I need to += it by .055, -0.12 (these are the xInc, yInc variables)

If the direction or speed changes… the xInc, yInc should change by only a small fraction.



Basically it should look like this:



xInc += (speedsin(rotation));

yInc += (speed
cos(rotation));



But this complete depends on knowing the previous x,y coord. Unless the rotation or speed changes, xInc and yInc will always be constant.



According to GLSL references… variable types can be:



attribute, varying, uniform, in or out…



in reads in the previous value from the last render loop…





but I can’t seem to get it working right /boggle

@pspeed I meant storage qualifiers… or course.



Storage Qualifiers

Variable declarations may have at most one storage qualifier specified in front of the type. These are

summarized as

Storage Qualifier Meaning

< none: default > : local read/write memory, or an input parameter to a function

const : a variable whose value cannot be changed

in : linkage into a shader from a previous stage, variable is copied in

out : linkage out of a shader to a subsequent stage, variable is copied out

attribute : compatibility profile only and vertex language only; same as in when in a

vertex shader

uniform : value does not change across the primitive being processed, uniforms

form the linkage between a shader, OpenGL, and the application

varying : compatibility profile only and vertex and fragment languages only; same

as out when in a vertex shader and same as in when in a fragment shader



Not sure where you declare in and out… I assume in is in the .vert and out is in the .frag? Same variable name I take it?

I don’t think that in/out can be used the way you want since at best they are for multiple stages in the same render pass… not for accumulating state from one render pass to another.



Do all of your clouds move in the same direction?



If so then maybe it is probably better to move the geometry. Attach them all to a node and move them together. Mythruna puts its clouds on quads oriented in a giant sphere-like shape and then I can just rotate the center node. I have several layers that move slightly differently. In the vert shader I collapse the Z value and multiple x,y so the horizon looks really far away.



Otherwise, there is no way around passing an offset into your shaders, I think.

@pspeed All clouds in a single geometry are, yes. So, basically… single texture to single geom, however, I am not using a flat geometry… or a sphere… so moving the geometry might not be possible in my current setup.



shouldn’t I be able to determine the time needed for what I want to do by using g_Time and whatever the variable for tpf (which I can’t seem to track down) is?



Maybe like:



xInc = ((speed*g_Time)*sin(direction))tpf;

yInc = ((speed
g_Time)*cos(direction))*tpf;



and then cycle the output so it is always between 0 and 1?



I’m a little cloudy still without coffee… but shouldn’t this have the effect I am looking for for switch directions properly? Basically remove the waving stick effect on change.



I’d love to try it, but I am not sure what the name of the material WorldParamter is. Tfp? TPF? Something like this?

Yeah… I’m pretty much resolved to this is impossible after all…



This will allow for adjust speed… and setting any initial direction. However, switching directions jumps the texture to new coords. before continuing and doesn’t look the best when it happens.



[java]

float xInc = ((g_Time*m_Speed)sin(m_Direction));

float yInc = ((g_Time
m_Speed)*cos(m_Direction));

texCoord1 += vec2(xInc,yInc);

[/java]