NasimiAsl

ShaderBuilder alpha version

Recommended Posts

Hi NasimiAsl, 

I'm wondering if shaderBuilder could handle vertex   shader easily ? In fact I need to rotate faces ,locally around their normal vector.

I made a little playground here : http://www.babylonjs-playground.com/#GXVL3#4  

Is it possible to rotate 'arrow' individually with shaderbuilder ? I succeed to do it by updating the vertex data (I have more than 30000 arrows). I think perf will be improved with a vertex shader. Maybe I'm wrong ?

Any idea are welcome !

 

sam

Maybe this screenshot of my project helps you to  better understand what I mean !

wind.jpg

Share this post


Link to post
Share on other sites

wwaaaaooowww nice

I guess the SPS can do this CPU side, I did once a PG with solid particles rotating around the axis sphere center - particle (just can't retrieve it) using the quaternion property and the BJS RotationAxis() method

Actually 30K arrows (so 240K vertices) is quite a huge number. Do you really need to rotate all of them each frame ?

Share this post


Link to post
Share on other sites

Hi Jérôme,

 

In fact it's less, just 217440 vertices  :) (could be easealy divide by 2 arrow is 2 faces). You're right about sps, but I totally forget we have this feature now. I will have a look.  It will be update 'only' each second, in fact it will depends about the time factor you decide.

So I'm looking for the best solution and do you know  if vertexshader can handle that (in fact I never took some time to learn  this graal).

 

.

 

 

 

Share this post


Link to post
Share on other sites

Yeah, nice, SG!  Assuming these arrows represent migration patterns of Mackerel (which it surely does), one should think about the future.  The arrows and their colors have force.  Mackerel herding force.  Your users might someday... want to swim with the fishes... in the herd... being pulled along by herding tendencies.  You know how it goes, Sam.  You are a God of crowd experiments.  ;)

SO... one might ponder that each arrow... is actually an object... a hybrid.  Sure, each has a target-able and color-able arrow shape, and a position.  But the core of that arrow object... is a thing.  A forceManager class object.  One of its many interchangeable snap-on 'views' is an SPS particle view.  Another view... a simple sprite.  Another view... produces a html <TD> element with a dump of all the force properties in html table view.  You get the idea.  It might start with a base class called affectArea

Just an idea.  Detach the presentation of the arrow... from the goods that make it point/push.  Perhaps, think about each affectArea being able to produce an applyImpulse, so you (a camera) can be "carried along with the flow".  It's a future feature.  :)

Pardon?  Ohhh.  Mackerel "school", not "herd".  I gotcha.

Share this post


Link to post
Share on other sites

That's just what I was about to propose : to divide the arrow  so is it is only two triangles instead of 8 vertices

For the SPS use, there is a dedicated couple of parameters (start, end) to make the computation on a given subset of particles each call with the ability to NOT update the global mesh : particle properties are computed by bunch and the mesh can be updated only at the end.

This allow to balance a heavy computations among many frames (so no global FPS drop) and to finally update the mesh only when it needs to be. Say, you compute 6K arrow rotations each frame, this would run very fast even on older computers and you update the global mesh every 5 frames (6K * 5 = 30K). You would have still a 60 FPS global rendering, for the cam, the scene rotation, and the arrow system updated only each 5 frames, so 12 times per second, what seems acceptable.

http://doc.babylonjs.com/overviews/Solid_Particle_System#start-and-end-indexes-for-setparticles

 

You can also change each arrow color and texture of course ;-)

[EDIT] I didn't dig into vertex shaders either, but I know they can do this with a very high performance.

Actually, the vertex shader can do quite anything to set the vertices where you want. It's just a matter of choice : 

CPU side == easy logic implementation (context data, forces, physics, AI, etc), no multithreaded computations, so less fast

GPU side == ultra fast pure geometry computation, less  or quite no logic handling

I guess it's easy to compute vertex rotation GPU side but far more difficult to set how this rotation is valued from external data/context for each arrow.  

Share this post


Link to post
Share on other sites

just started quickly something with a sps : http://www.babylonjs-playground.com/#E6IX1#30

 

more than 30K triangles at 55 fps here (update each 10 frames) : http://www.babylonjs-playground.com/#E6IX1#31

 

the same with the particles scaled according to their latitude : http://www.babylonjs-playground.com/#E6IX1#32

Share this post


Link to post
Share on other sites

i still close but need time for fix that :)

need more mathematical for find center :)

http://www.babylonjs-playground.com/#8GYTC#10

http://www.babylonjs-playground.com/#8GYTC#11

the i cant get count but less than 1000000 arrow

 

fix Rotation Problem : 

http://www.babylonjs-playground.com/#8GYTC#12

Share this post


Link to post
Share on other sites

I'm not asking you to do this @NasimiAsl , but how could you make the arrows point toward the mouse or the last clicked position of the sphere?  I imagine you'd need to somehow pass the mouse position to the shader and then create some additional inline code to rotate the arrow, right?

Share this post


Link to post
Share on other sites
1 hour ago, adam said:

I'm not asking you to do this @NasimiAsl , but how could you make the arrows point toward the mouse or the last clicked position of the sphere?  I imagine you'd need to somehow pass the mouse position to the shader and then create some additional inline code to rotate the arrow, right?

i  know this arrows can be rotate  with a part of Color Map Like (red or green or blue or alpha)

than last range is 0 and 1. and i use that to find angle*360. 

so we just need make a texture and set it for the rotate arrows

and 1 pic for arrow

we need one color pic for make last color result i don't use that and set it myself by angle

Share this post


Link to post
Share on other sites

can't stop playing ...

Well, not so fast and smooth than the good ones from NasimiAsI, but still funny :

added a x rotation : http://www.babylonjs-playground.com/#E6IX1#34

tetrahedrons instead of triangles (aren't we a 3D framework ?) : http://www.babylonjs-playground.com/#E6IX1#35  

hypnotic : http://www.babylonjs-playground.com/#E6IX1#36

horrific : http://www.babylonjs-playground.com/#E6IX1#37

whirly : http://www.babylonjs-playground.com/#E6IX1#38

can't-find-a-name : http://www.babylonjs-playground.com/#E6IX1#39 :D

[EDIT] http://www.babylonjs-playground.com/#E6IX1#40

Guys, if too slow on your machine, just reduce the value of the var tess at the line 18

Share this post


Link to post
Share on other sites

th

23 minutes ago, jerome said:

can't stop playing ...

Well, not so fast and smooth than the good ones from NasimiAsI, but still funny :

added a x rotation : http://www.babylonjs-playground.com/#E6IX1#34

tetrahedrons instead of triangles (aren't we a 3D framework ?) : http://www.babylonjs-playground.com/#E6IX1#35  

hypnotic : http://www.babylonjs-playground.com/#E6IX1#36

horrific : http://www.babylonjs-playground.com/#E6IX1#37

whirly : http://www.babylonjs-playground.com/#E6IX1#38

can't-find-a-name : http://www.babylonjs-playground.com/#E6IX1#39 :D

 

Guys, if too slow on your machine, just reduce the value of the var tess at the line 18

this is SPS POWER :)

Share this post


Link to post
Share on other sites
On 4/8/2016 at 6:48 PM, Samuel Girardin said:

Hi NasimiAsl, 

I'm wondering if shaderBuilder could handle vertex   shader easily ? In fact I need to rotate faces ,locally around their normal vector.

I made a little playground here : http://www.babylonjs-playground.com/#GXVL3#4  

Is it possible to rotate 'arrow' individually with shaderbuilder ? I succeed to do it by updating the vertex data (I have more than 30000 arrows). I think perf will be improved with a vertex shader. Maybe I'm wrong ?

Any idea are welcome !

 

sam

Maybe this screenshot of my project helps you to  better understand what I mean !

wind.jpg

  var len = 120;   // arrow count in row of uv
		  sp.material = new BABYLON.ShaderBuilder() // create Instance
		 .InLine('float len = '+BABYLON.Shader.Print(len)+';') // def len
		 .Map({ path: 'http://i.imgur.com/2Arp6so.png', // get Flow Map Color (green is angle)
		  uv:'vec2( floor(vuv.x*len)/len    , floor(vuv.y*len)/len   )' }) // correct Step of rotate
          .InLine('float angle = result.g;')// get corrected angle [0 -- 1]
          .InLine(' vec2 ce = vec2( floor(vuv.x*len)/len    , floor(vuv.y*len)/len   );')// find center of each arrow
         .Map({ path: 'http://i.imgur.com/gaqRD7U.png', // path of arrow image
		  scaleX: len, scaleY: len,  // scale to count
		  indexCount:3,rowIndex:3,columnIndex:3, // chose cursor
	 	  uv:'rotate_xy(  ce+vec2( 0.5/len ),vuv,angle*180.)' }) // rotate arrow 
         .InLine('if(length(result.xyz)> 0.1){ discard;}')// hide empty space
         .InLine('if( angle > 0.1){ result = vec4(angle,0.,1.,pow(angle*2.,3.));}') // create needed color for rotated arrow
		 .InLine('else{ result = vec4(0.,0.,1.,0.2);}') // set unrotated arrow
		  .Transparency() // use alpha for hide unrotated arrow
		 .BuildMaterial(scene);

aasd.png

 

http://www.babylonjs-playground.com/#8GYTC#22

Share this post


Link to post
Share on other sites

 

@NasimiAsl @jerome

Finally did it by writing my first vertexshader ! In fact I think each solution you gave me was both performant. But I really want to do it by myself and begin learning vertexshader. And maybe with this first approach better understand shaderbuilder.ts

It runs smooth at 60fps. I'm able to display world winds for 100 days every 6 hours at a resolution of 1° (about every 60 nautical miles,  about 54000 arrows (4 vertices, two faces,  with orientation size and color). I need now to optimize the way I deal with all this datas for memory management. My wind datas are hidden in png files (one by 'snapshot'). For the moment I preprocess this 400 png files , extract needed informations with a context2d  and use uv and uv2 vertexbuffer to pass datas and update the vertex shader. So to avoid this precomputing,  I try to send directly the png file as texture and read for each vertex,  wind informations I need. Wip for the moment.

Here is two shorts video (can't post a live demo for the moment). The first one, updating each 5 frames. The second is every  frames. 

 

 

 

 

 

 

 

Share this post


Link to post
Share on other sites

wwwaaaaahhhh that's really great !!! and so smooth !

and you say this is your very first attempt at vertex shader coding ???

just tell me what you eat or smoke and I'll do the same jump in shader programing asap ! :D

Share this post


Link to post
Share on other sites

@jerome

Yes it is !

In fact I only convert the way I built the geometry in ts/js with bjs to do the same with a vertexshader and bjs.. Sure shaders help because they do it fast. My math level is low but quite 'intuitive' and 'pragmatic'. I'm sure, we can do it differentl and faster. But for the moment it works ! 

Here is the main part of the shader : 

vec3 spherify(float xi, float yi, float angle, float factor, float X, float Y) {

//Offset vertex 2d
float x = xi*factor+X ; 
float y = yi*factor+Y ; 
float cx = 3. * factor + X; 
float cy = 3.5 * factor + Y; 
float rad= radians(angle); 
float _cos = cos(rad); 
float _sin = sin(rad); 
float radius = 16.37; 

//Rotate vertex 2d -> calculate orientation for each arrow vertex by vertex  
float phi = radians(90. - ((_cos * (x - cx)) + (_sin * (y - cy)) + cx)); 
float theta = radians(((_cos * (y - cy)) - (_sin * (x - cx)) + cy) + 180.); 

//spherify vertex to 3d vertex by vertex
vec3 pos = vec3((radius) * sin(phi) * cos(theta), (radius) * cos(phi), (radius) * sin(phi) * sin(theta)); 
return pos ;
}
void main(void) {
    vec3 position3d = spherify(position.x,position.z,uv.s,uv.t,uv2.s,uv2.t);
    gl_Position = worldViewProjection * vec4(position3d, 1.0);
    // finaly pass vertex color to fragment shader
    vcol = color;
}

 

It takes in entry as vertexdata's position an array of vertex arrows geometry (in my case 360*151 arrows). There is no offset, just imagine each arrow is drawn at the same place on x & z with y = 0.

In main, for each vertex we call the spherify method. Position x&z are vertex part arrow in 2d mode, uv.s is the wind angle in degree, uv.t is wind 'force' , all this datas are precomputed and pass to vertex as uv.kind for each update.

uv2.s and uv2.t are the offset X and Y ( for(latitude)  { for (longitude) {x++}y++} pass as uv2.kind, After that we go to 3d with vec3 pos. And finally pass the vertex color to the fragment shader.

 

With the cpu mode 'bjs type script' I do the same thing with this 2 methods :

// rotate and offset in 2dmode

 private rotate(x:number, y:number, angle:number, factor: number, X:number, Y:number) {
        
        this.cx = 3 * factor + X;
        this.cy = 3.5 * factor + Y;
        this.radians = (Math.PI / 180) * angle;
        this.cos = Math.cos(this.radians);
        this.sin = Math.sin(this.radians);        

        this.new3dpoint[0] = (this.cos * (x - this.cx)) + (this.sin * (y - this.cy)) + this.cx;
        this.new3dpoint[1] = 0;
        this.new3dpoint[2] = (this.cos * (y - this.cy)) - (this.sin * (x - this.cx)) + this.cy;
        return this.new3dpoint;
}


// spherify
 privateLatLongToVec3(lat:number, lon:number, offset?: number): BABYLON.Vector3 {

        var radiusOffset: number
        if (offset) {
            radiusOffset = Constant.EarthDiameter + offset;
        } else {
            // the earth
           radiusOffset = Constant.EarthDiameter + 0.37;  
        }
           

        var phi = (90 - lat) * (Math.PI / 180);
        var theta = (lon + 180) * (Math.PI / 180);

        var x = ((radiusOffset) * Math.sin(phi) * Math.cos(theta));
        var y = ((radiusOffset) * Math.cos(phi));
        var z = ((radiusOffset) * Math.sin(phi) * Math.sin(theta));
       

        return new BABYLON.Vector3(x,y,z);
    }

 So i'm not really sure I did it right with my vertex shader. But with those two last methods I was at 10 fps...

 

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Recently Browsing   0 members

    No registered users viewing this page.