Created
September 16, 2022 10:16
-
-
Save ufna/d28b84efa5afec90b8401fbb83c409d3 to your computer and use it in GitHub Desktop.
Coastal Landscape Shadertoy UE4
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Author: bitless | |
// Title: Coastal Landscape | |
// Thanks to Patricio Gonzalez Vivo & Jen Lowe for "The Book of Shaders" | |
// and Fabrice Neyret (FabriceNeyret2) for https://shadertoyunofficial.wordpress.com/ | |
// and Inigo Quilez (iq) for https://iquilezles.org/www/index.htm | |
// and whole Shadertoy community for inspiration. | |
#define p(t, a, b, c, d) ( a + b*cos( 6.28318*(c*t+d) ) ) //IQ's palette function (https://www.iquilezles.org/www/articles/palettes/palettes.htm) | |
#define sp(t) p(t,float3(.26,.76,.77),float3(1,.3,1),float3(.8,.4,.7),float3(0,.12,.54)) //sky palette | |
#define hue(v) ( .6 + .76 * cos(6.3*(v) + float4(0,23,21,0) ) ) //hue | |
struct Functions | |
{ | |
// "Hash without Sine" by Dave_Hoskins. | |
// https://www.shadertoy.com/view/4djSRW | |
float hash12(float2 p) | |
{ | |
float3 p3 = frac(float3(p.xyx) * .1031); | |
p3 += dot(p3, p3.yzx + 33.33); | |
return frac((p3.x + p3.y) * p3.z); | |
} | |
float2 hash22(float2 p) | |
{ | |
float3 p3 = frac(float3(p.xyx) * float3(.1031, .1030, .0973)); | |
p3 += dot(p3, p3.yzx+33.33); | |
return frac((p3.xx+p3.yz)*p3.zy); | |
} | |
//////////////////////// | |
float2 rotate2D (float2 st, float a){ | |
return mul(float2x2(cos(a),-sin(a),sin(a),cos(a)), st); | |
} | |
float st(float a, float b, float s) //AA bar | |
{ | |
return smoothstep (a-s, a+s, b); | |
} | |
float noise( in float2 p ) //gradient noise | |
{ | |
float2 i = floor( p ); | |
float2 f = frac( p ); | |
float2 u = f*f*(3.-2.*f); | |
return lerp( lerp( dot( hash22( i+float2(0,0) ), f-float2(0,0) ), | |
dot( hash22( i+float2(1,0) ), f-float2(1,0) ), u.x), | |
lerp( dot( hash22( i+float2(0,1) ), f-float2(0,1) ), | |
dot( hash22( i+float2(1,1) ), f-float2(1,1) ), u.x), u.y); | |
} | |
}; | |
Functions func; | |
float4 O; | |
float2 g = fragCoord;//(fragCoord.xy * 2.0 - iResolution.xy) / min(iResolution.x, iResolution.y); | |
float2 r = iResolution.xy | |
,uv = (g+g-r)/r.y | |
,sun_pos = float2(r.x/r.y*.42,-.53) //sun position | |
,tree_pos = float2(-r.x/r.y*.42,-.2) //tree position | |
,sh, u, id, lc, t; | |
float3 f = float3(0,0,0); | |
float3 c; | |
float xd, yd, h, a, l; | |
float4 C; | |
float sm = 3./r.y; //smoothness factor for AA | |
sh = func.rotate2D(sun_pos, func.noise(uv+iTime*.25)*.3); //big noise on the sky | |
if (uv.y > -.4) //drawing the sky | |
{ | |
u = uv + sh; | |
yd = 60.; //number of rings | |
id = float2((length(u)+.01)*yd,0); //segment id: x - ring number, y - segment number in the ring | |
xd = floor(id.x)*.09; //number of ring segments | |
h = (func.hash12(floor(id.xx))*.5+.25)*(iTime+10.)*.25; //ring shift | |
t = func.rotate2D (u,h); //rotate the ring to the desired angle | |
id.y = atan2(t.y,t.x)*xd; | |
lc = frac(id); //segment local coordinates | |
id -= lc; | |
// determining the coordinates of the center of the segment in uv space | |
t = float2(cos((id.y+.5)/xd)*(id.x+.5)/yd,sin((id.y+.5)/xd)*(id.x+.5)/yd); | |
t = func.rotate2D(t,-h) - sh; | |
h = func.noise(t*float2(.5,1)-float2(iTime*.2,0)) //clouds | |
* step(-.25,t.y); //do not draw clouds below -.25 | |
h = smoothstep (.052,.055, h); | |
lc += (func.noise(lc*float2(1,4)+id))*float2(.7,.2); //add fine noise | |
f = lerp (sp(sin(length(u)-.1))*.35, //sky background | |
lerp(sp(sin(length(u)-.1)+(func.hash12(id)-.5)*.15),float3(1,1,1),h), //lerp sky color and clouds | |
func.st(abs(lc.x-.5),.4,sm*yd)*func.st(abs(lc.y-.5),.48,sm*xd)); | |
}; | |
if (uv.y < -.35) //drawing water | |
{ | |
float cld = func.noise(-sh*float2(.5,1) - float2(iTime*.2,0)); //cloud density opposite the center of the sun | |
cld = 1.- smoothstep(.0,.15,cld)*.5; | |
u = uv*float2(1,15); | |
id = floor(u); | |
for (float i = 1.; i > -1.; i--) //drawing a wave and its neighbors from above and below | |
{ | |
if (id.y+i < -5.) | |
{ | |
lc = frac(u)-.5; | |
lc.y = (lc.y+(sin(uv.x*12.-iTime*3.+id.y+i))*.25-i)*4.; //set the waveform and divide it into four strips | |
h = func.hash12(float2(id.y+i,floor(lc.y))); //the number of segments in the strip and its horizontal offset | |
xd = 6.+h*4.; | |
yd = 30.; | |
lc.x = uv.x*xd+sh.x*9.; //divide the strip into segments | |
lc.x += sin(iTime * (.5 + h*2.))*.5; //add a cyclic shift of the strips horizontally | |
h = .8*smoothstep(5.,.0,abs(floor(lc.x)))*cld+.1; //determine brightness of the sun track | |
f = lerp(f,lerp(float3(0,.1,.5),float3(.35,.35,0),h),func.st(lc.y,0.,sm*yd)); //lerp the color of the water and the color of the track for the background of the water | |
lc += func.noise(lc*float2(3,.5))*float2(.1,.6); //add fine noise to the segment | |
f = lerp(f, //lerp the background color | |
lerp(hue(func.hash12(floor(lc))*.1+.56).rgb*(1.2+floor(lc.y)*.17),float3(1,1,0),h) //and the stroke color | |
,func.st(lc.y,0.,sm*xd) | |
*func.st(abs(frac(lc.x)-.5),.48,sm*xd)*func.st(abs(frac(lc.y)-.5),.3,sm*yd) | |
); | |
} | |
} | |
} | |
O = float4(f,1); | |
////////////////////// drawing the grass | |
a = 0.; | |
u = uv+func.noise(uv*2.)*.1 + float2(0,sin(uv.x*1.+3.)*.4+.8); | |
f = lerp(float3(.7,.6,.2),float3(0,1,0),sin(iTime*.2)*.5+.5); //color of the grass, changing from green to yellow and back again | |
O = lerp(O,float4(f*.4,1),step(u.y,.0)); //draw grass background | |
xd = 60.; //grass size | |
u = u*float2(xd,xd/3.5); | |
if (u.y < 1.2) | |
{ | |
for (float y = 0.; y > -3.; y--) | |
{ | |
for (float x = -2.; x <3.; x++) | |
{ | |
id = floor(u) + float2(x,y); | |
lc = (frac(u) + float2(1.-x,-y))/float2(5,3); | |
h = (func.hash12(id)-.5)*.25+.5; //shade and length for an individual blade of grass | |
lc-= float2(.3,.5-h*.4); | |
lc.x += sin(((iTime*1.7+h*2.-id.x*.05-id.y*.05)*1.1+id.y*.5)*2.)*(lc.y+.5)*.5; | |
t = abs(lc)-float2(.02,.5-h*.5); | |
l = length(max(t,0.)) + min(max(t.x,t.y),0.); //distance to the segment (blade of grass) | |
l -= func.noise (lc*7.+id)*.1; //add fine noise | |
C = float4(f*.25,func.st(l,.1,sm*xd*.09)); //grass outline | |
C = lerp(C,float4(f //grass foregroud | |
*(1.2+lc.y*2.) //the grass is a little darker at the root | |
*(1.8-h*2.5),1.) //brightness variations for individual blades of grass | |
,func.st(l,.04,sm*xd*.09)); | |
O = lerp (O,C,C.a*step (id.y,-1.)); | |
a = max (a, C.a*step (id.y,-5.)); //a mask to cover the trunk of the tree with grasses in the foreground | |
} | |
} | |
} | |
float T = sin(iTime*.5); //tree swing cycle | |
if (abs(uv.x+tree_pos.x-.1-T*.1) < .6) // drawing the tree | |
{ | |
u = uv + tree_pos; | |
// draw the trunk of the tree first | |
u.x -= sin(u.y+1.)*.2*(T+.75); //the trunk bends in the wind | |
u += func.noise(u*4.5-7.)*.25; //trunk curvature | |
xd = 10., yd = 60.; | |
t = u * float2(1,yd); //divide the trunk into segments | |
h = func.hash12(floor(t.yy)); //horizontal shift of the segments and the color tint of the segment | |
t.x += h*.01; | |
t.x *= xd; | |
lc = frac(t); //segment local coordinates | |
float m = func.st(abs(t.x-.5),.5,sm*xd)*step(abs(t.y+20.),45.); //trunk mask | |
C = lerp(float4(.07, .07, .07, .07) //outline color | |
,float4(.5,.3,0,1)*(.4+h*.4) //foreground color | |
,func.st(abs(lc.y-.5),.4,sm*yd)*func.st(abs(lc.x-.5),.45,sm*xd)); | |
C.a = m; | |
xd = 30., yd = 15.; | |
for (float xs =0.;xs<4.;xs++) //drawing four layers of foliage | |
{ | |
u = uv + tree_pos + float2 (xs/xd*.5 -(T +.75)*.15,-.7); //crown position | |
u += func.noise(u*float2(2,1)+float2(-iTime+xs*.05,0))*float2(-.25,.1)*smoothstep (.5,-1.,u.y+.7)*.75; //leaves rippling in the wind | |
t = u * float2(xd,1.); | |
h = func.hash12(floor(t.xx)+xs*1.4); //number of segments for the row | |
yd = 5.+ h*7.; | |
t.y *= yd; | |
sh = t; | |
lc = frac(t); | |
h = func.hash12(t-lc); //segment color shade | |
t = (t-lc)/float2(xd,yd)+float2(0,.7); | |
m = (step(0.,t.y)*step (length(t),.45) //the shape of the crown - the top | |
+ step (t.y,0.)*step (-0.7+sin((floor(u.x)+xs*.5)*15.)*.2,t.y)) //the bottom | |
*step (abs(t.x),.5) //crown size horizontally | |
*func.st(abs(lc.x-.5),.35,sm*xd*.5); | |
lc += func.noise((sh)*float2(1.,3.))*float2(.3,.3); //add fine noise | |
f = hue((h+(sin(iTime*.2)*.5+.5))*.2).rgb-t.x; //color of the segment changes cyclically | |
C = lerp(C, | |
float4(lerp(f*.15,f*.6*(.7+xs*.2), //lerp outline and foreground color | |
func.st(abs(lc.y-.5),.47,sm*yd)*func.st(abs(lc.x-.5),.2,sm*xd)),m) | |
,m); | |
} | |
O = lerp (O,C,C.a*(1.-a)); | |
} | |
return O; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
https://www.shadertoy.com/view/fstyD4