Pixel shader - have a need to reuse
coal

Two days ago I discovеred this pretty framework Wade. It's awesome and allows to do much things.Here some my examples from simple to complex

http://seganelservice.ru/WebGL/Wade1

http://seganelservice.ru/WebGL/Wade2

http://seganelservice.ru/WebGL/Wade4

http://seganelservice.ru/WebGL/Wade5

http://seganelservice.ru/WebGL/Wade6

http://seganelservice.ru/WebGL/Wade7

 

1. In all examples I hardly used custom pixel shaders for animation. And now I want to reuse shaders, save them as project file, as javascript file in project and apply files to another sprites. But now there is no option... There is real need to do that - save shader content as file with uniforms, and reuse it on other sprites by aplying to sprites shaders list.

Also, multishaders (multipass) on one sprite and on postprocess - will be very useful for some multipass techniques as bluring and another complex effects.

Also, it seems that postprocess on scene doesn't work on sprites with custom shader. May be I'm wrong.

2. There is some problem to deploy source code on server (seganelservice.ru) by copy source code to folder. As is - server show error 404. You can found it on browser console at address http://seganelservice.ru/WebGL/WadeError/ where I simply copied source code, downloaded from Wade.

Errors from console:

/WebGL/WadeError/scene1_night_glows_posteffect_hard_rain.wsc:1 Failed to load resource: the server responded with a status of 404 (Not Found)
wade.js:469 Failed to load JSON data from scene1_night_glows_posteffect_hard_rain.wsc : SyntaxError: Unexpected token < in JSON at position 0
Wade.error @ wade.js:469
wade.js:469 Unable to load json file scene1_night_glows_posteffect_hard_rain.wsc

I solved this problem by renaming scene1_night_glows_posteffect_hard_rain.wsc то *.js and by patching app.js. But error is strange, could you help me - how to solve it right?

Comments 31 to 45 (71 total)
coal

examples of Particles, which can be used in games as idea:

interactive water http://madebyevan.com/webgl-water/

autumn http://oos.moxiecode.com/js_webgl/autumn/

snow http://oos.moxiecode.com/js_webgl/snowfall/

leaves http://www.bongiovi.tw/experiments/webgl/blossom/

stars http://kluster.j38.net/

magick https://www.iamnop.com/particles/

fluid http://edankwan.com/experiments/icicle-bubbles/

fire https://ethanhjennings.github.io/webgl-fire-particles/

 

and that all anyone can apply to 2D, by fantasy

coal

One more example: here you can see 3 trees planes scrolling with different speed. Currently this is sprites with custom shaders. But I can do the same with particles with no impact, 3 times faster. http://seganelservice.ru/WebGL/Wade1

Scroll speed here - is index function in shader, where I have 3 particles in system.

This is just example, but for backs (tree layers with perspective imitation) is useful

Gio

So basically you'd like to have a particle system in Wade.

I think it's a good idea and it's already been planned for a future version, but it'll be in 4.3 so it's going to be a while.

You realize though that this won't let you do what you originally wanted to do with your tree sprites, right? For that you'd need one set of uniforms for each sprite, as I think you said you want different offsets and different parameters for each tree,

coal

>You realize though that this won't let you do what you originally wanted to do with your tree sprites, right?

I only made some tests. I don't worry about time to wait, I found that I can do all what I want. I can make effects now, can design scenes and so on... Currently I'll make effects with less objects, and later migrate to particles. 

 

 

>For that you'd need one set of uniforms for each sprite, as I think you said you want different offsets and different parameters for each tree,For that you'd need one set of uniforms for each sprite, as I think you said you want different offsets and different parameters for each tree,

This not true. I try to explain what I mean:

Here you can see new particles demo with 100000 trees. Every tree has different color and different wind animation (if you notice). And can have any different transform/effect with one shader only.

 

http://seganelservice.ru/WebGL/HundredThousandTrees2/

 

Shaders code:

<script type="x-shader/x-vertex" id="vertexshader">

            attribute float size;
            attribute vec3 customColor;

            varying vec3 vColor;
            varying vec3 vPosition;

            void main() {

            vColor = customColor;
	    vPosition = position;

            vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );

            gl_PointSize = size * ( 300.0 / length( mvPosition.xyz ) );

            gl_Position = projectionMatrix * mvPosition;

            }

        </script>

      

        <script type="x-shader/x-fragment" id="fragmentshader">

	    uniform float time;
            uniform vec3 color;
            uniform sampler2D texture;
            varying vec3 vColor;
            varying vec3 vPosition;

            void main() {

	    vec2 uv = gl_PointCoord;
	    
	    uv.x+=(1.0-uv.y)*sin(vPosition.x+(sqrt(uv.y)+time/3.0)/0.3)/10.0;
	    uv.x=fract(uv.x);
            uv.y=1.0-uv.y;

	    vec4 color = texture2D(texture, uv);
	    float alpha = 1.0;
	    if (color.b<0.14){    discard;}
	    color.r=1.0-color.r;
            color.g=1.0-color.g;
	    color.b=1.0-color.b;
	    
             
            color.r*=fract(vPosition.x/100.0);
            color.g*=fract(vPosition.z/100.0);
	    
	    gl_FragColor=color;

            }

        </script>

 

All trees are pure particles. Are pure clones. And all have the same uniforms:

uniform float time;
uniform vec3 color;
uniform sampler2D texture;

There is no custom individual uniform for each sprite/particle. But animation and color differs... How it done?

This is very simple math magic with vPosition (position of particle on screen. It needs to transform to 0..1, but I use absolute number)

wind differ:

uv.x+=(1.0-uv.y)*sin(vPosition.x+(sqrt(uv.y)+time/3.0)/0.3)/10.0;

color differ:

color.r*=fract(vPosition.x/100.0);
color.g*=fract(vPosition.z/100.0);

 

coal

you need only to pass position of particle from vertex shader to pixel shader. And that's all to add with both shaders.

varying vec2 vPosition;

also if you pass size and index of particle from vertex to pixel shader - this will be very useful too.

varying vec2 vSize;
varying float vIndex;

and all animation in pixel shader will be done by math of vPosition, vSize, vIndex and time.

Here you can found thousands pixelshader effect on pure math, without any texture and geometry.They only have one default sprite (plain geometry)

https://www.shadertoy.com/view/Ms2SD1

here is only pixel shader code. No attributes, no uniforms, no textures - pure math, nothing else absolutely... Math is power, but in my case I must know at minimal index/position of particle in pixel shader. Which are not uniforms, but varying

coal

Also, I can animate particles screen positions at onUpdate js. There is 100000 cycles on CPU, but only 1 geometry, 1 draw call, 1 texture, 1 shader, one common uniforms. And different clones animation/transformation/rendering. And this is very fast with 60 FPS

http://seganelservice.ru/WebGL/HundredThousandTrees3/

                    var pos = geometry.attributes.position.array;
                    for (var i = 0; i < particles; i++) {

                        UnitAI(i);

                        pos[i * 3] += units[i].deltax;
                        pos[i * 3 + 2] += units[i].deltay;
                    }

where in my code "geometry.attributes.position.array" is "Float32Array(particles * 3);"

This is only demo as example of capabilities.

coal

That techique I call "force field". There is some force on screen: wind, gravity, light, explosion and so on. Force is described in pixel shader by math. Initial particle values - are particles positions and sizes. Force parameters - are common uniforms. Time is common uniform. Sin/Cos do 90% of individual work...

And all on screen will become live. Imagine grass field on wind or clouds on sky, or rainy weather... No problem in 2D, effects are the same...

coal

Such particles effects (force fields) will allow to make 2D game like Ori (extreme beautiful, with fallen leaves and so on). I'm not sure that I can do such beauty, because I'm not professional in design. But other people will be able to do this.

coal

I want to say - editor allows to do all currently. Difference between sprites and particles is only in speed, in 100 times (and *100 objects). But I can do all with sprites now, using less sprites, not using shaders, using one texture of 1000 rain particles and moving it... Imitation not a problem now, but I show here way to speed up...

cleo

I haven't really followed the whole thread here, but it seems to me that what you want should be easy to achieve (Gio correct me if I'm wrong):

In layer.js you have a variable called vbForOneElement that is the vertex buffer data for one sprite in a batch. Could you just add one extra element there that is the sprite index in the batch? Then edit batchedVertexShaderSource to add a "varying int" that is passed to the pixel shader and contains the value of the sprite index.

coal

No, currently I can't implement particles myself in framework (If I understand correct)... Your information is very interesting and I'll play with it. But the main difference between current (sprites) and wanted (particles) is:

a) Look at scene with 1000 snow sprites, as http://seganelservice.ru/WebGL/Wade5/

You can suppose, that all is fast, but GPU load is 50%. This is load for super mega giper AAA+ game of top quality. But I have only snow and some scroll...

Why so? Because there is 1000 draw calls. Snow texture passes from CPU to GPU - 1000 times per frame. 60000 times per second. 600 000 000 Bytes per second are passed from CPU to GPU. This is bottleneck! And this is only for 10Kb texture. What if texture is 1Mb size (4000*4000pixels)?

And if I set snow with 10000 sprites - all will simply hang.

b) Scene with 1000 snow particles. Or with 1 000 000 snow particles.

GPU will stay 4-10% for any count! Because there is only 1 draw call for all particles, which can be rendered individually. But that needs patching of framework, I can't do this by any method.

P.S. with particles you can make all, that with sprites. But this will be full GPU calc, which is extreme fast. CPU calcs must be 0%, GPU calcs must be 100%. And no 1000 passings of one texture must present... This is how AAA+ games are done.

coal

I found bypass of that current restriction. I can draw all snow in one posteffect, through raymarching. But this is technique from another planet. Can you understand how that works with no textures, no attributes, no uniforms, no js, only pure math?

http://glslsandbox.com/e#53264.0

http://glslsandbox.com/e#52614.0

http://glslsandbox.com/e#52272.0

I think no... And I understand it only by 10%... It's very hard technique... Crazy and inside-out...

I'll learn it soon. But raymarching is very complex at GPU, and gives more GPU load, than particles... The same 40% GPU load, but calcs, not texture passing...

Gio

Interesting suggestion there cleo, thanks for that. I think it's spot on.

Let me clarify:

"Because there is 1000 draw calls. Snow texture passes from CPU to GPU - 1000 times per frame"

No! This is not true, I've already explained it above. The texture is sent to the GPU only once.

You have 1000 draw calls if and only if you use a custom shader (and even then, CPU to GPU transfer of textures is not done every time, just once). With the default shader, you have 1 single draw call for 1000 sprites. And you absolutely do not need a custom shader for those snow particles, it can easily be done with the default one.

Gio

Having said that, I think what we could do is add batching to custom shaders that do not use uniforms. That is relatively simple and, along with cleo's suggested modification should allow you to do most of the things you mentioned in this thread.

If we do that, even with a custom shader (if you don't use uniforms) you will still have 1 single draw call for your 1000 sprites.

coal

Yes, I mean custom shader. On demo there is custom shader on snowflake.

vec2 uv = uvAlphaTime.xy; 
vec4 color = texture2D(uDiffuseSampler, uv); 
float fAlpha = color.r/2.0; 
if (color.b<=0.1){fAlpha=0.0;}; 
gl_FragColor=color; 
gl_FragColor.w = fAlpha;

Look at 10000 snowflakes:

http://seganelservice.ru/WebGL/Wade26/

not hanging, but with breaks... But I've seen the same or more speed with 1 000 000 elephants on particles... http://seganelservice.ru/WebGL/OneMillionSprites/

That is the main difference - at 100 times... I try to say only about difference

Post a reply
Add Attachment
Submit Reply
Login to Reply