Jump to content

Shader Loop Question


Pryme8
 Share

Recommended Posts

ok so I have three textures one is the texture to display one is the locations of the tiles, and the third is a reference sheet for the animations on the sprite sheet.

so I am able to get the coordinates of the correct 'sprite' by sampling the tiles texture:
vec4 tile = texture2D(tiles, texCoord);
if(tile.x == 1.0 && tile.y == 1.0) { discard; }

then I check the animation map for an animation refrence

vec4 aTile = texture2D(animationMap, tile.xy);
if(aTile.a == 1.0 ){

I have the flags on the alpha channel for if this is an animation or not the z or blue channel as the "timing" for the frame and the red green as the x,y of the next frame.
What I want to happen is a loop so something like:

float _t = sin(time);
float aS = aTile.z;

    while(aS > _t){    
        aTile = texture2D(animationMap, aTile .xy);
        aS = aTile.z;
    }
 tile.xy = aTile.xy;   

but when I do something like this it crashes the webGL which I am guessing is do to the loop never exiting or something.

If I do something like:

vec4 tile = texture2D(tiles, texCoord);
if(tile.x == 1.0 && tile.y == 1.0) { discard; }
vec4 aTile = texture2D(animationMap, tile.xy);
if(aTile.a == 1.0){
    float _t = sin(time);
    float aS = aTile.z;    
    if(aS < _t){    
    tile.xy = aTile.xy;
    }        
}

I can toggle between two frames, but I want to support more!

Link to comment
Share on other sites

vec4 tile = texture2D(tiles, texCoord);
if(tile.x == 1.0 && tile.y == 1.0) { discard; }
vec4 aTile = texture2D(animationMap, tile.xy);
if(aTile.a != 0.0) { 
float aS = aTile.b;	
float _t = sin(time);
while(aS < _t && aTile.a > 0.){
	aTile = texture2D(animationMap, aTile.xy);	
	aS = aTile.b;
}
}

which does not crash anything, but effectively does nothing but prove the loop is not making it crash.

but the second I add this

vec4 tile = texture2D(tiles, texCoord);
if(tile.x == 1.0 && tile.y == 1.0) { discard; }
vec4 aTile = texture2D(animationMap, tile.xy);
if(aTile.a != 0.0) { 
float aS = aTile.b;	
float _t = sin(time);
while(aS < _t && aTile.a > 0.){
	aTile = texture2D(animationMap, aTile.xy);	
	aS = aTile.b;
}
if(aS > _t){
tile.xy = aTile.xy;
}
}

it crashes after the first "frame"

if I do this:
 

vec4 tile = texture2D(tiles, texCoord);
if(tile.x == 1.0 && tile.y == 1.0) { discard; }
vec4 aTile = texture2D(animationMap, tile.xy);
if(aTile.a != 0.0) { 
float aS = aTile.b;	
float _t = sin(time);
if(aS > _t){
tile.xy = aTile.xy;
}
}

It toggles between the frames but I need to support more then two frames.

Link to comment
Share on other sites

Ok so that kicks it out and stops it from freezing, but I still cant get the "animation" to work.

Here is the idea:

I have 3 textures for the animation test I am using:
the atlas which is the art

ani_atlas_test.png.099221c667fe4cfe8c50b2125bbb0443.png

The layer which gives the shader the location of the original sprite placed.  In the example I am going to provide it is set to repeat when I make the texture so this 1 by 1 tile covers the whole screen multiple times.
ani_layer.png.8a27a570ecc96396545654648a3e36d3.png
^ hopefully you see the one pxl above its colors are r:0:g:0:b:0:a:1 which represents the number 1 tile on the atlas (r:1:g:0:b:0:a:1 would be 2) r is x and g is y, blue/alpha are unused right now.

And lastly where I am trying to make the magic happen is the animation look up texture, this uses the same idea as the layer but holds different information and is a 1x1pxl equivalent to the atlas:
animation_atlas_test.png.108e8acd53e690506adc166fe926fe28.png
Right now I have the bottom blank, I just want to get through the 1234... so the information stored on these are the x:y of the next tile held in the red green, the 'step' of the tile is in the blue.  the step I am using in a very rudimentary way right now, it is just a number between 0-1 that says when to go to the next tile dependent on right now a time calculation.  Later I will use the alpha as a scaler for that timing, and will pass another global variable to it as well to fine tune timing on each client as well but that's later down the road....

https://pryme8.github.io/TileMaster/ani-test.html <- for the nonworking animation example.
 

https://github.com/Pryme8/TileMaster/blob/gh-pages/ani-test.html <- Line 174

If I uncomment line 166 through 170 then it will toggle between tiles... but like I said unless the super duper retro look is what your going for this is not going to work.
 

Link to comment
Share on other sites

Hello @Pryme8

let my rephrase, for my own understanding, the goal - deserved look is to loop through the nummers 1 -4, - more generally speaking through a specific area

and simpel if statment : http://musician-elephant-31700.bitballoon.com/

is not enough, you want to test for a specific color value in an area, and when it's present, then cut out the object, - like in photoshop select area by color ?

Link to comment
Share on other sites

Ok I finally got to look at your example with: 
float _t = sin(time);
if(0.5<=_t)tile.xy += aTile.xy; // 1
if(0.25<=_t)tile.xy += aTile.xy; // 2 ;
if(-0.25<=_t)tile.xy += aTile.xy;// 3 ;
if(-0.5<=_t)tile.xy =tile.xy;// 4 ;


And that is fine, for hard coding the animations in, but what I want is to sample the blue channel from aTile check if its > then _t and if so stop on that tile.  I know this seems weird to do but there is a really good idea behind this that I just don't feel like explaining at this juncture.  

The proccess that I am looking for would be like:

1) Check the layer texture for what sprite to reference;
2) With the X:Y value of tile, check the value on that sprite on the animation sheet;

3) If the alpha is 0 on the animation sheet do nothing but return the base sprite;
3a) Else if the Alpha is > 0 on the animation sheet get the blue value and test;

4) if its > then _t, set the red and green channels (or the xy) of the aTile to the tile.xy and output that sprite.
5) if its < then _t get the current aTile.xy and re-sample that coordinate off the animation sheet to get the tile data agian on the animation texture;
6) repeat steps 3-5 as necessary until the blue channel meets the requirements or you run into a 0 alpha tile.

you need to shift the _t into a range of 0-1 though because the blue channel is in that range.

This will make it so any tile can reference any other tile on the sheet for animations and once I put together the editor it will be seamless I am hoping if I can figure this one part out.

Link to comment
Share on other sites

Yes, now its more descriptive! And also sorry i'm out of time. I can give you only suggestions.

first littele playground update: check if this works on other platforms like ios, i looks a bit weird to me:
https://playground.babylonjs.com/#PYK67E#4

if you are looking for tiles also check how babylon is mapping your texture
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);

you could easily run in an error becourse of the "hidden" default behavior

Link to comment
Share on other sites

so why does this one not kick out of the while loop then?
Figured that is what I was doing with this one.

On 10/21/2017 at 6:29 PM, Pryme8 said:

vec4 tile = texture2D(tiles, texCoord); if(tile.x == 1.0 && tile.y == 1.0) { discard; } vec4 aTile = texture2D(animationMap, tile.xy); if(aTile.a != 0.0) { float aS = aTile.b; float _t = sin(time); while(aS < _t && aTile.a > 0.){ aTile = texture2D(animationMap, aTile.xy); aS = aTile.b; } if(aS > _t){ tile.xy = aTile.xy; } }

 

Link to comment
Share on other sites

https://pryme8.github.io/TileMaster/ani-test.html

Ok so it "works" but the positions are wrong... I just gotta figure out why I'm referencing the wrong tiles when I use the animation map samples...  uhh but hopefully this gets me in the right direction

*update*
vec4 tile = texture2D(tiles, texCoord);
if(tile.x == 1.0 && tile.y == 1.0) { discard; }
vec4 aTile = texture2D(animationMap, tile.xy);
if(aTile.a != 0.0) { 
float aS = aTile.b;    
float _t = (tan(time)+1.0)/2.0;

if(aS>_t){    
    for(int i=0; i<maxFrames; i++){
        aTile = texture2D(animationMap, aTile.xy);
            if(aTile.a == 0.0)break;
            aS = aTile.b;
            if(aS>_t){
                tile.xy = aTile.xy;
                break;
            }
        }
    }
}


this is pretty close, but I can not get it to go past the second frame... it just seems to toggle back and forth between the first frame and the second.

Im starting to think its really close... I just am to much of a dummy at glsl to figure it out.

Link to comment
Share on other sites

hi

http://www.babylonjs-playground.com/#2BJAXD#6

why you don't use Mod and floor
 
time = >                                  0 - 1 - 2 - 3 - 4 - 5 - 6 - ...
mod(time,1.) =>                        0 - 1 - 1 - 1 - 1 - 1 - ...
mod(time *10.,1.)/10. =>         0 , 0.1 , 0.2 , 0.3 , 0.4 ,0.5 ,0.6 , ... 
 
vec2( mod( (p.x*4. ),1.)/4.   /*take one column */     +  floor(_t*4.)/4.    /*move columns (step by step )*/        ,p.y)
 
 

 

 

Link to comment
Share on other sites

what If the number of frames is dynamic and they have different timings?
the whole point of this, is to reference the animation texture file for what tile to go to and "when" to go there.
What if the texture animation sheet says the tile goes from number 1 to number 4 to one of the squiggly blue lines back to 1 ect...

 

Maybe the answer is here I just don't understand it?
 

Link to comment
Share on other sites

Did you read the above post about what I am trying to do with the 3 different sampler2d uniforms? 

How could I use your method with that principal? I’m trying to basically make a way to turn any texture atlas into a animated sheet.   

Thanks so much guys for helping me with ideas on this, it may just be a bad formatted idea but I’m pretty sure if I can explain it well enough it will click, or I will get enough info to figure it out myself. 

Ive got other ways I could do it that are more traditional but I have a greater goal at mind.

Link to comment
Share on other sites

@Pryme8 

"what If the number of frames is dynamic and they have different timings?"

Yes, you need to make a grid[row,colums] and then Access the values. - different timings -> then will be calculated based on grid[row,colums] .length  

frame:      0     1     2   3 
texPos: 0.2,.0.4,.0.8. 1.0
or -> firstpos 0.2 +firstpos 0.2 = frame 1

// prev.pos PLUS=MOVE TO NEXT POSTION
float _t = sin(time);
if(0.5<=_t)tile.xy += aTile.xy;
if(0.25<=_t)tile.xy += aTile.xy; 
 

 

// NEXT POSTION
if(aS>_t){    
    for(int i=0; i<maxFrames; i++){
        aTile = texture2D(animationMap, aTile.xy);
            if(aTile.a == 0.0)break;
            aS = aTile.b;
            if(aS>_t){
                tile.xy = aTile.xy;
                break;
 

NasimiAsl
vec2( mod( (p.x*4. ),1.)/4.   /*take one column */     +  _t * 0.25    /*move columns (t = frame  )*/        ,p.y)

+ make a grid on a texture
+ specify a singel element(char) [width,height]
+ move the singel element position along the grid to get the next element

B)

 

 

Link to comment
Share on other sites

can you do this one https://playground.babylonjs.com/#PYK67E#13 as webgl 1.0 instead of 2.0 please? 

I tried but am getting some weird errors.

Also I dont see how this method is going to work in situations like this:

example.jpg.08d3ec7b4a28b66b6602a6fc92a27bb9.jpg

So this sheet has several different animation sequences on it, what I am trying to do is use the Animation Map texture to define where these different 'zones' are.

Maybe use your method with a combination of mine?  Where the Animation map has the data structure of r -> xCount of tiles, g -> y count of tiles, b -> speed Adjustment, a -> is it animated or not.

And then use that data to control the mod method you have demonstrated?

I think we are getting closer.

The whole point of this, is to be able to animate whole atlas files without passing a bunch of other information to the shader.
 

Link to comment
Share on other sites

@Pryme8
Yes, i know. I was placing the #version derivative a second time ( it's already done by babylonjs ) becourse gl_FragColor in WebGL2.0 is deprecated  and now is is able  to have multiple outputs, so you can write directly from shader to shader etc.

So my custom shader is compete with babylonjs the default material https://github.com/BabylonJS/Babylon.js/blob/407b2d3f0ffe9d7e80ecc670ebab7fc3f14bae9d/src/Shaders/default.fragment.fx#L420 
( but im not sure about this )

Compatibility Mode Solution 1 (quick and dirty)
#if __VERSION__ >= 300 https://playground.babylonjs.com/#PYK67E#17


Compatibility Mode Solution 2
Their a function i forgot like scene.StandartMaterial=null, or scene.hasDefaultMaterial(NO);

Ok,
so this is a webgl1.0 shader - when i done it right, should work
https://playground.babylonjs.com/#PYK67E#16

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...