simple question about shaders
krumza

Hi! I try to marriage some shader from shadertoy in wade - and i cant do it.

Please say how insert webgl shader from shadertoy in wade project.

As examle i want insert this in space shoote game https://www.shadertoy.com/view/Xdl3D2 

All 5 Comments
Gio

Hi

Not a very simple question :) You can do that, but it's not as simple as copying an pasting, you need to convert the shader so you must understand what it's doing.

First of all, what you have in a wade shader is just the contents of the main function - you can't define functions and call them like that shadertoy shader is doing. Instead, you'd have to replace the function calls with the definition of the function itself. So for example, in that shader it defines a function like this:

#define GAMMA (2.2)
vec3 ToGamma( in vec3 col )
{
	// convert back into colour values, so the correct light will come out of the monitor
	return pow( col, vec3(1.0/GAMMA) );
}

And later, in the main function, it uses it like this:

fragColor = vec4(ToGamma(col),1.0);

Instead, you should not define ToGamma, and do directly

fragColor = vec4(pow(col, vec3(1.0/2.2)), 1.0);

Same thing for all the other functions.

After that, some things will need renaming. Instead of fragColor, you want to use gl_FragColor, instead of fragCoord you want uvAlphaTime.xy and instead of iGlobalTime you want uvAlphaTime.w

That shader also relies on some other values - iResolution and iChannel0. These must be set as shader uniforms for you shader. The iChannel0 texture should be a sampler2D uniform, whereas iResolution is a vec2. For the texture, you just set the uniform value to the texture file name (the texture must be in your project and must also be included in the scene's image list), and it will work. For iResolution, you can set some fixed values like 1024x768, but ultimately I think you'll want to update the values at runtime based on the actual resolution that you get with wade.getScreenWidth() and wade.getScreenHeight().

So yeah, not very simple, but if you understand how the shader works it's not very complicated either, it can be done in 10 minutes or so. Let me know if you need more help with that.

 

Shri

Gio,

I have a question about shaders too. When jquery was part of the wade package, I used this to read in the shader strings using jquery get

$.get('./backgroundShader.fs',function(data) {
        bgShaderString = data;
        bgShaderString = bgShaderString.replace(/(\/\*([\s\S]*?)\*\/)|(\/\/(.*)$)/gm, '');
});

This allowed me to write my shaders into files like backgroundShader.fs

/*
* The fragment shader code
* Texture with spatial distortion
* uv.y changes amount of left right bounce,  8 look like jello, 80 heat distortion
* time multiple is speed of distortion
* final constant is amout of x direction shift
* scroll the texture by multiplying the uv.x with a small time shift
*/

float time = uvAlphaTime.w;			// get time
vec2 uv = uvAlphaTime.xy;			// get xy coord of current pixel
uv.x = uv.x + time*0.02;			// scroll in the positive x direction
uv.y = uv.y + sin(uv.x*4. + time*1.6) * 0.03;	// provide  wiggle based on the sine function
vec4 texColor = texture2D(uDiffuseSampler, uv);	// load texture 1:1 with the modified uv values
gl_FragColor =  texColor;			// blast off

Now that there is no more jquery,  I have switched over to using wade.ajax

While trying to get this to work, I noticed that if the dataType is not defined, the success callback is not called. The api documentation says "dataType: string (set to 'json' to get the response as a JSON object". But it doesn't say that you have to set a dataType. Since I just want the raw string data, I was not setting this to anything and couldn't get it to work. Finally,  I looked at the code and noticed that if dataType is not set, then the success function is not called (line 3639 of wade.js). So, I set the dataType to 'string' and it all works. Not sure if that is a bug in the code or not ?

Anyway, this is how I define the shaderCallback function, get the shader via wade.ajax() and then use the fsString as the pixelShader for a sprite

this.shaderCallback = function(response) {
    fsString = response;
	fsString = fsString.replace(/(\/\*([\s\S]*?)\*\/)|(\/\/(.*)$)/gm, '');
};

// get shader source with wade ajax
this.loadShaders = function() {
    console.log('load Shaders');	
    var params = { 
        url: './shaderCode.fs',
        cache: false,
        type: 'GET',
        dataType: 'string',
        success:  function(response){ wade.app.shaderCallback(response); }
    };
    wade.ajax(params);
};

// create a single segment
this.createSegment = function() {
    var segmentSprite = new Sprite(
    {
        layer: self.GAME_LAYER,
        autoResize: false,
        image: "./alien_20.jpg",
        alwaysDraw: true,
        pixelShader: fsString,
        size: {x: 500,y: 500}
    });
	
    segment = new SceneObject(segmentSprite);
    wade.addSceneObject(segment);
}

cheers - shri

Gio

Good spot Shri, there is a bug there. I'll get that fixed now.

However from version 3.6 you'll be able to simply do wade.loadText() to load your shaders from text files.

krumza

Hi, Gio 

I dont understand it. In example i use simplest shader from shadertoy https://www.shadertoy.com/view/4tcGRn


void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    vec2 ndc = (fragCoord - iResolution.xy / 2.0) / min(iResolution.x, iResolution.y);
    vec3 lens = normalize(vec3(ndc, 0.015));
	vec3 location = lens * 15.0 + vec3(0.6, 1.0, iGlobalTime);
	vec3 cellId = floor(location);
	vec3 relativeToCell = fract(location);
    vec3 locationOfStarInCell = fract(cross(cellId, vec3(2.154, -6.21, 0.42))) * 0.15 + 0.25;
	float star = max(0.0, 15.0 * (0.1 - distance(relativeToCell, locationOfStarInCell)));
	fragColor = vec4(star, star, star, 1.0);
}

And i transorm it to :

vec2 ndc = (uvAlphaTime.xy - iResolution.xy/2.0)/min(iResolution.x, iResolution.y);
vec3 lens = normalize(vec3(ndc, 0.015));
vec3 location = lens * 15.0 + vec3(0.6, 1.0, uvAlphaTime.w);
vec3 cellId = floor(location);
vec3 relativeToCell = fract(location);
vec3 locationOfStarInCell = fract(cross(floor(location), vec3(2.154, -6.21, 0.42))) * 0.15 + 0.25;
float star = max(0.0, 15.0 * (0.1 - distance(relativeToCell, locationOfStarInCell)));
gl_FragColor = vec4(star, star, star, 1.0);

BUt nothing rederening:

You say that  should not define functions, and do it directly in code.

But how do it if function is:

//code from https://www.shadertoy.com/view/4ljXDt


float Cell(vec2 c) {
	vec2 uv = fract(c);c -= uv;
	return (1.-length(uv*2.-1.)) * step(fract(sin(c.x+c.y*1e2)*1e3), .04);
}

void mainImage( out vec4 fragColor, in vec2 fragCoord ) {

	vec2 p = fragCoord.xy / iResolution.xy -.5;
	float a = fract(atan(p.x, p.y) / 6.2832);
	float d = length(p);
	
	vec2 coord = vec2(pow(d, .04), a)*256.;
	vec2 delta = vec2(1. + iGlobalTime*10., 2.);
	
	float c = Cell(coord-=delta);
	c += Cell(coord-=delta);
	
	fragColor = vec4(c*d*4.);
}

I do directly - but the same result as in previous shader/

What i do wrong?

Gio

Hi

It's quite close. But in the original shader, on the first line you have fragCoord, and you are replacing it directly with uvAlphaTime.xy.

The problem is that fragCoord is a vector with values ranging from (0, 0) to however many pixels you have, so in your case probably (1024, 768). This is usually a bit difficult to work with, because in most cases you want your effect to be resolution-independent. Which is why the shader author is dividing by iResolution and all that.

On the other hand, uvAlphaTime.xy is a vector ranging from (0, 0) to (1, 1).It's already resolution-independent, so you don't need your iResolution vector to normalize it.Another difference is the fact that in OpenGL, the Y axis goes from the bottom to the top. In WADE it's the opposite.

So in short, to do what you want, you should replace the first line with

vec2 ndc = uvAlphaTime.xy - 0.5;

And I'm not sure, but I think you'll want to divide this by the aspect ratio (width of your sprite / height of your sprite) to avoid any distortion.

Also make sure your sprite is set to AlwaysDraw to see it animating.

Post a reply
Add Attachment
Submit Reply
Login to Reply