Combine two Shaders

Demo showcase godot4 shader merging.

Shader code
//originally https://www.shadertoy.com/view/ltcGDl
//originally https://www.shadertoy.com/view/ldSBRc
// with mainly https://github.com/jayaarrgh/shadertoy2godot and hand fixing

shader_type canvas_item;
uniform vec2 iMouse;
//--------------------------------------------------HUD

//originally https://www.shadertoy.com/view/ldSBRc
// with mainly https://github.com/jayaarrgh/shadertoy2godot and hand fixing

float getBox(vec2 st, float left, float bottom, float width, float height) {
    float sm = 0.002;
    float x_range = smoothstep(left - sm, left, st.x) - smoothstep(left + width, left + width + sm, st.x);
    float y_range = smoothstep(bottom - sm, bottom, st.y) - smoothstep(bottom + height,bottom + height + sm, st.y);
    
    return x_range * y_range;
}

float getCircle(vec2 st, vec2 center, float radius, float thickness, float sm) {
    float distance = distance(st, center);
    return smoothstep(radius, radius + sm, distance) - smoothstep(radius + thickness, radius + thickness + sm, distance);
}

float getDottedCircle(vec2 st, vec2 center, float radius, float thickness, float sm) {
    float distance = distance(st, center);
    float circle = smoothstep(radius, radius + sm, distance) - smoothstep(radius + thickness, radius + thickness + sm, distance);
    
    vec2 vector = center - st;
    float angle = atan(vector.y, vector.x);
    angle = ((angle * 0.5) + (3.14 * 0.5)) / 3.14;
    circle *= step(8., mod(floor(angle / 0.001), 10.0));
    
    return circle;
}

mat2 rotate(in float angle) {
    return mat2(vec2(cos(angle), -sin(angle)), vec2(sin(angle), cos(angle)));
}

vec2 getRotation(vec2 st, vec2 origin, float angle) {
    vec2 rotatedCoord = st - vec2(origin);
    rotatedCoord = rotate(angle) * rotatedCoord;
    rotatedCoord += vec2(origin);
    
    return rotatedCoord;
}

mat2 scale(in float x, in float y) {
    return mat2(vec2(x, 0.0),vec2(.0, y));
}

vec2 getScaling(vec2 st, vec2 origin, float x, float y) {
    vec2 scaledCoord = st - vec2(origin);
    scaledCoord = scale(x, y) * scaledCoord;
    scaledCoord += vec2(origin);
    
    return scaledCoord;
}

float getInnetDial(vec2 st, float center, float radius) {
 	float lineThickness = 0.002;
    float sm = 0.003;
    
    float circle2 = getCircle(st, vec2(center), radius - 0.015, lineThickness, sm);
    circle2 *= step(st.x, -0.254);
    
    float circle2dash1 = getBox(st, -0.254, 0.134, 0.100, lineThickness);
    circle2 += circle2dash1;
    float circle2dash1_2 = getBox(st, -0.204, 0.134, 0.052, lineThickness * 2.);
    circle2 += circle2dash1_2;
    float circle2dash2 = getBox(st, -0.288, 0.068, 0.031, lineThickness);
    circle2 += circle2dash2;
    float circle2dash2_2 = getBox(st, -0.247, 0.068, 0.096, lineThickness);
    circle2 += circle2dash2_2;
    float circle2dash3 = getBox(st, -0.350, 0.0, 0.215, lineThickness);
    circle2 += circle2dash3;
    float circle2dash3_2 = getBox(st, -0.19, 0.0, 0.055, lineThickness * 2.);
    circle2 += circle2dash3_2;
    float circle2dash3_3 = getBox(st, -0.36, 0.0, lineThickness * 2., lineThickness * 2.);
    circle2 += circle2dash3_3;
    float circle2dash4 = getBox(st, -0.288, -0.068, 0.031, lineThickness);
    circle2 += circle2dash4;
    float circle2dash4_2 = getBox(st, -0.247, -0.068, 0.096, lineThickness);
    circle2 += circle2dash4_2;
    
    float circle2dash5 = getBox(st, -0.13, 0.0, 0.01, lineThickness);
    circle2 += circle2dash5;
    float circle2dash5_1 = getBox(st, -0.12, -0.03, lineThickness, 0.06);
    circle2 += circle2dash5_1;
    float circle2dash5_2 = getBox(st, -0.118, 0.03, 0.01, lineThickness);
    circle2 += circle2dash5_2;
    float circle2dash5_3 = getBox(st, -0.118, -0.03, 0.01, lineThickness);
    circle2 += circle2dash5_3;
    
    return circle2;
}

float getSideLine(vec2 st, float left, float top, float lineThickness) {
    float lineEdgeLength = 0.008;
    float sideLine = getBox(st, left, top, lineThickness, 0.236);
    sideLine += getBox(st, left + lineThickness, top + 0.234, lineEdgeLength, lineThickness);
    sideLine += getBox(st, left + lineThickness, top, lineEdgeLength, lineThickness);
    sideLine += getBox(st, left + lineThickness + 0.006, 0.0, lineThickness, lineThickness);
    
    return sideLine;
}

vec4 HUD_fragment(vec2 SPS, vec4 FC, vec4 C) {//SPS SCREEN_PIXEL_SIZE,  FC FRAGCOORD
	vec2 st = FC.xy.xy / (1.0/SPS).xy;
    st -= 0.5;
    st.x *= (1.0/SPS).x/(1.0/SPS).y;
	vec4 c1 = vec4(st,0.5+0.5*sin(TIME),1.0);
    
    float center = 0.0;
    float radius = 0.3;
    float sm = 0.003;
    float lineThickness = 0.002;
    float angle = atan(st.y, st.x);
    angle = (angle + 3.1416) / (2.0 * 3.1416);

    vec3 color = vec3(0.);
    
    st = getRotation(st, vec2(center), -TIME);
    float circle1 = getCircle(st, vec2(0.), radius, lineThickness, sm);
    circle1 *= (step(st.x, -0.25) + step(0.25, st.x));
    st = getRotation(st, vec2(center), TIME);
    
    
    
    float dottedCircle = getDottedCircle(st, vec2(center), radius + 0.015, lineThickness + 0.002, sm);
    dottedCircle *= (
        (step(0.02, angle) - step(0.08, angle)) +
        (step(0.09, angle) - step(0.16, angle)) +
        (step(0.32, angle) - step(0.4, angle)) +
        (step(0.41, angle) - step(0.48, angle)) +
        
        (step(0.52, angle) - step(0.59, angle)) +
        (step(0.6, angle) - step(0.66, angle)) +
        (step(0.83, angle) - step(0.89, angle)) +
        (step(0.9, angle) - step(0.98, angle))
    );
    
    float timeFactor = 3.14 * 0.2 * cos(TIME * 0.5);
    st = getRotation(st, vec2(center), timeFactor);
    float dial1 = getDottedCircle(st, vec2(center), radius + 0.04, lineThickness + 0.01, sm);
    
    float dial2 = getDottedCircle(st, vec2(center), radius + -0.04, lineThickness + 0.01, sm);
    dial2 += getDottedCircle(st, vec2(center), radius + -0.02, lineThickness + 0.001, sm);
    st = getRotation(st, vec2(center), -timeFactor);
    
    
    dial1 *= (step(0.662, angle) - step(0.84, angle));
    dial2 *= (step(0.682, angle) - step(0.82, angle));
    
    
    float sideLine = getSideLine(st, -0.4, -0.116, 0.002);
    st = getScaling(st, vec2(0.0), -1.0, 1.0);
    sideLine += getSideLine(st, -0.4, -0.116, 0.002);
    st = getScaling(st, vec2(0.0), -1.0, 1.0);
    
    st = getRotation(st, vec2(center), 3.14 * 0.1 * sin(TIME));
    
    float innerDial = getInnetDial(st, center, radius);
    st = getScaling(st, vec2(0.0), -1.0, 1.0);
    innerDial += getInnetDial(st, center, radius);
    st = getScaling(st, vec2(0.0), -1.0, 1.0);
    
    
    st = getRotation(st, vec2(center), 3.14 / 4.);
    float box = getBox(st, -0.068, -0.057, 0.004, 0.115);
    box += getBox(st, 0.066, -0.057, 0.004, 0.115);
    box += getBox(st, -0.057, 0.070, 0.115, 0.004);
    box += getBox(st, -0.057, -0.070, 0.115, 0.004);
    box -= getBox(st, -0.036, -0.036, 0.072, 0.072);
    
    box += getBox(st, -0.05, -0.05, 0.006, 0.006);
    box += getBox(st, 0.048, -0.05, 0.006, 0.006);
    box += getBox(st, 0.048, 0.046, 0.006, 0.006);
    box += getBox(st, -0.05, 0.046, 0.006, 0.006);
    
    float innerBox = getBox(st, -0.04, -0.04, 0.08, 0.08);
    innerBox -= getBox(st, -0.036, -0.036, 0.072, 0.072);
    innerBox += getBox(st, -0.07, -0.07, 0.006, 0.006);
    innerBox += getBox(st, 0.066, -0.07, 0.006, 0.006);
    innerBox += getBox(st, 0.066, 0.066, 0.006, 0.006);
    innerBox += getBox(st, -0.07, 0.066, 0.006, 0.006);
    st = getRotation(st, vec2(center), -3.14 / 4.);
    
    st = getRotation(st, vec2(center), -3.14 * 0.1 * sin(TIME));
    
    float sideMarks = step(18., mod(floor((st.y + 0.1 * sin(TIME)) / 0.002), 20.0));
    sideMarks *= (
        (step(-0.44, st.x) - step(-0.415, st.x)) +
        (step(0.415, st.x) - step(0.44, st.x))
    );
    sideMarks *= (step(-0.12, st.y) - step(0.12, st.y));
    
    float sideMarksBox = getBox(st, -0.45, -0.015, 0.04, 0.03);
    sideMarksBox -= getBox(st, -0.448, -0.013, 0.036, 0.026);
    st = getScaling(st, vec2(0.0), -1.0, 1.0);
    sideMarksBox += getBox(st, -0.45, -0.015, 0.04, 0.03);
    sideMarksBox -= getBox(st, -0.448, -0.013, 0.036, 0.026);
    st = getScaling(st, vec2(0.0), -1.0, 1.0);
    
    sideMarksBox += getBox(st, -0.0025, 0.33, 0.005, 0.005);
    sideMarksBox += getBox(st, -0.0025, 0.25, 0.005, 0.005);
    
    box *= (0.2 + 0.8 * pow(abs(sin(TIME * 4.)), 2.));

    color += vec3(1.000,0.345,0.287) * circle1;
    color += vec3(0.39,0.61,0.65) * dottedCircle;
    color += vec3(0.39,0.61,0.65) * dial1;
    color += vec3(0.39,0.61,0.65) * dial2;
    color += vec3(0.39,0.61,0.65) * innerDial;
    color += vec3(0.39,0.61,0.65) * sideLine;
    color += vec3(0.39,0.61,0.65) * sideMarks;
    color += vec3(0.39,0.61,0.65) * sideMarksBox;
    color += vec3(0.995,0.425,0.003) * box;
    color += vec3(0.96, 0.98, 0.8) * innerBox;
    
	vec4 c2=vec4(color,1.0);
	vec4 a[]={vec4(0.,0.,0.,0.),vec4(0.,0.,0.,0.)};
    return c2;
}

//--------------------------------------------------sand

vec2 hash( vec2 p )
{
	p = vec2( dot(p,vec2(127.1,311.7)),
			  dot(p,vec2(269.5,183.3)) );

	return -1.0 + 2.0*fract(sin(p)*43758.5453123);
}

float noise( in vec2 p )
{
    vec2 i = floor( p );
    vec2 f = fract( p );
	
	vec2 u = f*f*(3.0-2.0*f);

    return mix( mix( dot( hash( i + vec2(0.0,0.0) ), f - vec2(0.0,0.0) ), 
                     dot( hash( i + vec2(1.0,0.0) ), f - vec2(1.0,0.0) ), u.x),
                mix( dot( hash( i + vec2(0.0,1.0) ), f - vec2(0.0,1.0) ), 
                     dot( hash( i + vec2(1.0,1.0) ), f - vec2(1.0,1.0) ), u.x), u.y);
}

float terrainH( in vec2 p)
{

    //small
	float valS = noise(p * 0.5) + 0.5;//0~1
    valS = 1.0 - abs(valS - 0.5) * 2.0;
    valS = pow(valS,2.0);

    //middle
    float valM = noise(p * 0.26) + 0.5;//0~1
    valM = 1.0 - abs(valM - 0.5) * 2.0;
    valM = pow(valM,2.0);
    
    //big
    float valB = smoothstep(0.0,1.0,noise(p * 0.2) + 0.5);//0~1

    float val = valS * 0.01 + valM * 0.19 + valB * 0.8;

    return val * 1.3 - 0.3;
}

float softShadow(in vec3 ro, in vec3 rd )
{
    // real shadows	
    float res = 1.0;
    float t = 0.001;
	for( int i=0; i<40; i++ )
	{
	    vec3  p = ro + t*rd;
        float h = p.y - terrainH( p.xz );
		res = min( res, 16.0*h/t );
		t += h;
		if( res<0.01 ||p.y>(200.0) ) break;
	}
	return clamp( res, 0.0, 1.0 );
}


float interesct( in vec3 ro, in vec3 rd, in float tmin, in float tmax )
{
    float t = tmin;
	for( int i=0; i<128; i++ )
	{
        vec3 pos = ro + t*rd;
		float h = pos.y - terrainH( pos.xz );
		if( h<(0.002*t) || t>tmax ) break;
		t += 0.5*h;
	}
	return t;
}


vec3 calcNormal( in vec3 pos, float t )
{
    vec2  eps = vec2( 0.002*t, 0.0 );
    return normalize( vec3( terrainH(pos.xz-eps.xy) - terrainH(pos.xz+eps.xy),
                            2.0*eps.x,
                            terrainH(pos.xz-eps.yx) - terrainH(pos.xz+eps.yx) ) );
}

vec3 render( in vec3 ro, in vec3 rd )
{   
    vec3 lightDir = normalize( vec3(-0.8,0.3,-0.3) );
    vec3 lightColor = vec3(1.0);
    vec3 sandColor = vec3(0.9,0.70,0.4);
    vec3 ambientColor = vec3(0.5);

    float tmin = 1.0;
    float tmax = 30.0;
    float t = interesct(ro,rd,tmin,tmax);

    vec3 col;
    if(t>tmax){
        vec3 sky0 = vec3(0.8,0.7,0.5) * 1.2;
        vec3 sky1 = vec3(0.4,0.6,0.8) * 1.2;
        col = mix(sky0,sky1,pow(max(rd.y + 0.15,0.0),0.5));
        col += vec3(pow(max(dot(rd,lightDir),0.0),50.0));
    }
    else{
        vec3 pos = ro + t*rd;
        
        float shadow = softShadow(pos + lightDir *0.01,lightDir);
        
        vec3 normal = calcNormal( pos, t );
        normal = normalize(normal + vec3(sin(pos.x * 100.0 + sin(pos.z * 31.0) + sin(pos.y) * 200.0) * 0.02,0,0));
        vec3 viewDir = -rd;

        float lambertian = max(dot(lightDir,normal), 0.0);

        float shininess =  20.0;
        vec3 halfDir = normalize(lightDir + viewDir);
        float specAngle = max(dot(halfDir, normal), 0.0);
        float specular1 = pow(specAngle, shininess);
        float specular2 = pow(specAngle, shininess / 2.0) * noise(pos.xz * 10000.0) * 1.0f;// * pow(texture(iChannel0,pos.xz * 10.0).x,3.0);

        vec3 diff = sandColor * lambertian * lightColor;
        vec3 spec = (specular1 *0.3 + specular2 * 0.2) * lightColor;
        vec3 ambient = ambientColor * sandColor;
        col = shadow * (diff + spec) + ambient;

    }
    return col;
}

vec4 sand_fragment(vec2 SPS, vec4 FC ) {//SPS SCREEN_PIXEL_SIZE,  FC FRAGCOORD

    float time = TIME * 0.5;
    //float yaw = time;//iMouse.x * 0.05;
    //float pitch = 1.2;//clamp(iMouse.y * 2.0 /(1.0/SCREEN_PIXEL_SIZE).y,-PI * 0.5,PI * 0.5);
    
    float yaw;
    float pitch;
    
    if(iMouse.x == 0.0 && iMouse.y == 0.0){
    	yaw = time;
    	pitch = 1.2;        
    }
    else{
        yaw = iMouse.x * 0.05;
    	pitch = clamp(iMouse.y  * 2.0 /(1.0/SPS).y,-PI * 0.5,PI * 0.5);
    }
    
	
	vec2 newFC = (1.0/SPS)- FC.xy;//screen orientation workaround
    //newFC.y = (1.0/SCREEN_PIXEL_SIZE).y - FRAGCOORD.xy.y;
	//newFC.x = (1.0/SCREEN_PIXEL_SIZE).x - FRAGCOORD.xy.x;
	
    vec2 p0 = newFC.xy.xy / (1.0/SPS).xy;
	
	
    p0.x *= (1.0/SPS).x/(1.0/SPS).y;
    
    vec3 ro = 1.1*vec3(2.5*sin(0.25*yaw),2.5 * cos(pitch),2.5*cos(0.25*yaw));
    vec3 ww = normalize(vec3(0.0) - ro);
    vec3 uu = normalize(cross( vec3(0.0,1.0,0.0), ww ));
    vec3 vv = normalize(cross(ww,uu));
    vec3 rd = normalize( p0.x*uu + p0.y*vv + 2.5*ww );

    vec3 col = render( vec3(time,1.8,0.0), rd );
    
    return vec4(col,1);
}


void fragment() {
	vec4 s = sand_fragment(SCREEN_PIXEL_SIZE,FRAGCOORD );
	vec4 h = HUD_fragment(SCREEN_PIXEL_SIZE,FRAGCOORD,COLOR);
	
    // Output to screen
    COLOR = s+h; //Note simple color summarising. //texture(iChannel0, uvA) + texture(iChannel1, uvB);
	//in case of more presize color controlling if statement needed.
}
Live Preview
Tags
godot4, merge, shader
This shader is a port from an existing Shadertoy project. Shadertoy shaders are by default protected under a Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported (CC BY-NC-SA 3.0) license unless anything else has been stated by the author. For more info, see our License terms.

More from TechnoLukas

Related shaders

guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments