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 46 to 60 (71 total)
coal

I know - I can remove shader, I can optimize smth, can make other texture. I know, speech is not about that.

coal

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.

 

Thank's a lot! I don't speed up you, just discuss to make framework better. Thanks!

coal

And the last suggestion: if you could add to framework display of FPS and draw calls, as done in my demos - it would be great!

I used for that: stats.min.js (internet)

<script src="../js/libs/stats.min.js"></script>

stats = new Stats();
stats.domElement.style.position = 'absolute';
stats.domElement.style.top = '0px';
container.appendChild(stats.domElement);

and threex.renderstats.js
 

<script src="../js/threex.renderstats.js"></script>

var rendererStats = new THREEx.RendererStats();

rendererStats.domElement.style.position = 'absolute'
rendererStats.domElement.style.left = '0px'
rendererStats.domElement.style.bottom = '0px'
document.body.appendChild(rendererStats.domElement)

than onUpdate()

stats.update();

rendererStats.update(renderer);

That info is needed not only in debug, but in runtime too (may be some framework flag), because speed differs.

coal

or may be I can add them myself... But I don't know where, my js is so poor as english...

krumza

Here the snippet when i need to know fps:

App = function(){
  //define var as you wish
  var FPSmeter = 0;	    
  var fps = document.getElementById('fps');


  //inside init()
  this.init = function()    {
    update();
    setInterval(update, 1000);
    wade.setMainLoop(FpsonUpdate);

    var FpsonUpdate = function(){
	  FPSmeter++;      	
    };	   

    var update = function() {        
	  fps.innerHTML = 'FPS: ' + FPSmeter;
	  FPSmeter = 0
    };
  }
}

And dont forget  add 

<div id="topbar_fps">FPS: 60</div>

on the index.html

***

very interesting theme 

and if you interesting - here a test for particles in wade http://kardan2.smartinvestclub.ru/ 

~40k sprites whitout lose fps 

 

 

coal

Thanks a lot! Very much! )))

coal

But... With 40K... I have 20FPS on your demo. And brakes... This are not particles, unfortunetly. This are sprites with default shader, I guess. I've tested them already. Only 10K, maybe 20K, may be 40K. But not one million, which has the same speed as shown, when implemented as particles. Also, if you make your demo full screen - it will be still lower, I guess... 

But, anyway, I invented how to render very realistic snow in one wade post process shader without any texture and any sprite (1 sprite only for layer adding). I"ve implemented this with raymarching. I'll show that demo soon - it's pretty, but have no time to finish. Shader can be used for rain too, and, I think, in many other usages. But it is procedural (GPU intensive), and slower, than particles, even whith js cycle of all particles position change.

P.S. ru domain - it's funny ))))

coal

I can't get in how to show FPS in game... Very stupid ))) 

This is simply null, not found (I've added to index.html)

var fps = document.getElementById('fps');

But I've done raymarching snow in posteffect shader. No textures, no sprites, no particles. Any speed, any density, much layers, and any other... Ready at 90%, but needs some tuning. Can be used for rain and anything else with little modification.

http://seganelservice.ru/WebGL/Wade28/

I guess FPS here is about 60.

There are much parameters in shader. Only one uniform: float kScreen (screen width/screen height, set onResize from js)

float time = uvAlphaTime.w;
vec2 originaluv=uvAlphaTime.xy;// (gl_FragCoord.xy*2.-resolution.xy)/min(resolution.x,resolution.y); 
vec3 finalColor=vec3(0.0);

//back highlight
float c=0.0;//smoothstep(1.,0.3,clamp(originaluv.y*.3+.8,0.,.75));

//wind speed/direction
float wind=25.1;
//screen resolution koef
//const float kScreen = 2.;
//count of snow layers
const int layersCount = 10;

//radius of snowflake
float snowRadius = .1;
bool mix = true;

//начальный масштаб (top слоя)
float startScale = 5.;
//scale decrement for layers(i)
float scaleDecrement = 1.1;

//snow falling speed
float fallingSpeed=5.1;
//snow layer falling decrement
float fallingSpeedDecrement=0.5;
//начальный bottom, до которого падать
float startBottom=-0.;//0.5;

//common snow density
float density=.1;
//snow density layer increment
float densityIncrement=1.5;

//snow opacity
float snowOpacity=1.;
//snow opacity layer decrement
float snowOpacityDecrement=1.1;

//snow start glow
float glowRadius = 0.04;
//snow glow layer decrement
float snowGlowDecrement=1.;

//snow color
vec3 snowColor = vec3(1.0,1.,1.);

//snow color layer decrement
//TODO
//float snowColorDecrement = 2.;



//scale of top layer snow
float scale=startScale;

//самый крупный план - самый быстрый
for(int i=0;i<layersCount;++i)
{
    //восстанавливаем оригинальную координату текстуры
    vec2 uv=originaluv;
    //screen resolution koef
    uv.x*=kScreen;
    //add wind
    uv.x+=wind/float(i)*time/100.0;
    //uv.x=fract(uv.x);
    
    //bottom Y in current layer(i), z proection
    //float bottom = float(i)/float(layersCount)+startBottom;
    float bottom = 1.0-5.0/float(i)+startBottom;
    
    //decrement scale for layer, z proection
    scale*=scaleDecrement;
    
    //falling speed in layer(i), z proection
    //float layerFallingSpeed=fallingSpeed*1./float(i+1);
    fallingSpeed*=fallingSpeedDecrement;

    float snow;
    //restrict bottom y
    if(uv.y<bottom)
    {
        snow = 0.;
    }
    else
    {
        //чем ближе - тем больше размер и тем больше скорость падения!
        uv.y+=time*(1./scale+fallingSpeed);
        //ветер по x
        //uv.x+=(time/1.0+sin(uv.y+time)/2.0)/scale;
        //uv.x+=sin(uv.y+time*0.5)/scale;
        //uv.x+=uv.x+=(time/100.0+sin(uv.y+time/1.0)/2.0)/scale*10.0;
        
        //плотность на экране
        density*=densityIncrement;
        uv*=scale*density;
        vec2 s=floor(uv),f=fract(uv),p;
        float k=3.,d;
        p=.5+.35*sin(11.*fract(sin((s+p+scale)*mat2(7.,5.,16.,3.))*5.))-f;
        d=length(p);
        //inner snow
        if (d<snowRadius)
        {
            k=min(d,k);
            k=smoothstep(0.,k,.01);//sin(f.x+f.y)*glowRadius
            snow = k;
        }
        else
        {
            //outer snow glow - TODO!
            //k=min(d,k);
            //k=smoothstep(0.,k,sin(f.x+f.y)*glowRadius*d);
            //snow = k;
            //outer glow
        }
    }
    snowOpacity/=snowOpacityDecrement;
    c+=snow*snowOpacity;
    glowRadius/=snowGlowDecrement;
    
    finalColor=(snowColor*c);
}

vec4 realColor = texture2D(uDiffuseSampler, uvAlphaTime.xy);

if (mix)
{
    gl_FragColor = vec4(finalColor,1.0)+realColor;
}
else
{
    if (finalColor.r>0.)
    {
        gl_FragColor = vec4(finalColor,1.0);
    }
    else
    {
        gl_FragColor = realColor;
    }
}
//gl_FragColor.r=max(gl_FragColor.r,realColor.r);
//gl_FragColor.g=max(gl_FragColor.g,realColor.g);
//gl_FragColor.b=max(gl_FragColor.b,realColor.b);

 

coal
Only one uniform: float kScreen (screen width/screen height, set onResize from js)

Gio! If you can add that koef as predefined in shaders, it will be very useful. This is needed in any raymarching shader effect. 

If you add that koef in any shader, as you've done with uvAlphaTime - it will be great! This is strongly needed information in procedural effects with no texture

coal

raymarching snow with max color blending (not adding color)

http://seganelservice.ru/WebGL/Wade29/

krumza

You not full copy my snippet! You forgot add update function)

But if you use an editor  - it cant work because editor left only main div

try  another - create an object with text sprite and update it/

 

how it work :

we create 2 functions

var FpsonUpdate = function(){
	  FPSmeter++;      	
    };	   

It simple increment whitch we stick to wade main update in

wade.setMainLoop(FpsonUpdate);

That mean when wade global update canvas we launch our increment function

Then second important part - update function

var update = function() {        
        	  //some action with FPSmeter;
        	  FPSmeter = 0
            }; 

We launch this function with timeout that mean some action with FPSmeter variable and turn in to zero again

In yor case you can create some object, than add textsprite to it and change innerHTML method to textSprite.setText()

in your case it be:

       // load a scene
		wade.loadScene('your_scene.wsc', true, function()
        {         
            
            // the scene has been loaded, do something here 
            
            var FPSmeter = 0
            
            var FpsonUpdate = function(){
        	    FPSmeter++;      	
            };	
            
            var update = function() {
              //add scene object and give name it and look index of textsprite
        	  wade.getSceneObject('a').getSprite(0).setText('FPS: ' + FPSmeter);
        	  FPSmeter = 0
            };  
            
            wade.setInterval(update, 1000);
            
            wade.setMainLoop(FpsonUpdate);


        });

 

coal

That not works in wade, I tried to copy snippet full,

App = function()
{
  //define var as you wish
  var FPSmeter = 0;	    
  var fps = document.getElementById('fps');


  //inside init()
  this.init = function()    {
    update();
    setInterval(update, 1000);
    wade.setMainLoop(FpsonUpdate);

    var FpsonUpdate = function(){
	  FPSmeter++;      	
    };	   

   
  }
  
   var update = function() {        
	  fps.innerHTML = 'FPS: ' + FPSmeter;
	  FPSmeter = 0
    };
	
    this.onResize=function()
    {
        var k = wade.getScreenWidth()/wade.getScreenHeight();
        wade.setLayerCustomProperty(1,"kScreen",k);
    }
	

};

here is result

This is because  fps is null. I don't know why... I added to index.html such code:

<div id="fps">FPS: 60</div>

<div id="container" style="border:0; width:800px; height:600px;">
    <div id="wade_main_div" width="800" height="600" tabindex="1">
    </div>
    
</div>
<div id="fps">FPS: 60</div>

but it's not found from var fps = document.getElementById('fps'); 

krumza

This is because wade editor clean html and left only #container

maybe it feature but if you write in editor

<div id="container" style="border:0; width:800px; height:600px;">
    <div id="wade_main_div" width="800" height="600" tabindex="1">
    </div>
    
</div>
<div id="fps">FPS: 60</div>

 

editor left only 

<div id="container" style="border:0; width:800px; height:600px;">
    <div id="wade_main_div" width="800" height="600" tabindex="1">
    </div>
    
</div>

in iframe

Use solution on bottom of my previous post

coal
.setText('FPS: ' + FPSmeter);

This is the way! Thank you!

coal

I have success, and watch fps on TextSprite, but...

It shows 60FPS, when I set 3000 snow layers in shader and the real watched fps by eyes is 1 fps... Unfortunately that not works correctly in wade main loop (or with postprocessing shaders). Why - is mystic... In other cases may be it works...

Post a reply
Add Attachment
Submit Reply
Login to Reply