純GLSL分步實現電影般畫面的湖光山色: 豔陽藍天和碧水(WebGL實現)
阿新 • • 發佈:2019-02-03
這一篇加了水,模擬了水面的反射和折射。
precision highp float; // u_param.xy: (stageWidth,stageHeight), u_param.z>1.0: mouse_down,u_param.z<1.0: mouse_up uniform vec4 u_param; // u_mouse.x: mouse x offset from mouseDown position x, // u_mouse.y: mouse y offset from mouseDown position y, // u_mouse.z: mouse x accumulation from mouseDown position x, // u_mouse.w: mouse y accumulation from mouseDown position y uniform vec4 u_mouse; // mat2 rotY(const in float a) { return mat2(cos(a),sin(a),-sin(a),cos(a)); } // light direction vec3 lightDirection = normalize(vec3( 0.3,0.7, 0.6)); // create the sky and a sun vec3 createSkyAndSun( const in vec3 ray ) { float sunDensity = clamp( dot(lightDirection, ray), 0.0, 1.0 ); // sky color vec3 color = vec3(0.2,0.4,0.6) - ray.y*0.3*vec3(0.1,0.5,1.0) + 0.13; // sun and sun's halo color += vec3(0.8,.7,0.2)*pow( sunDensity, 8.0 ) * 0.4 + vec3(1.0,.7,0.2)*pow( sunDensity, 16.0 ) * 0.6; color *= 0.95; return color; } // Intersection of the ray and the lake plane bool intersectLakePlane(const in vec3 ro, const in vec3 ray, const in float height, inout float dis) { if (ray.y < 0.0) { float d = -(ro.y - height)/ray.y; d = min(10000.0, d); if( d > 0. && d < dis ) { dis = d; return true; } } return false; } // create a matrix33 of camera space to world space mat3 viewMatrix3(vec3 eye, vec3 center, vec3 up) { vec3 f = normalize(center - eye); vec3 s = normalize(cross(f, up)); vec3 u = cross(s, f); return mat3(s, u, -f); } // return gradient noise (in x) and its derivatives (in yz) vec3 random3(vec3 c) { float j = 4096.0*sin(dot(c,vec3(0.1,0.2,0.3))); vec3 r; r.z = fract(512.0*j); j *= .125; r.x = fract(512.0*j); j *= .125; r.y = fract(512.0*j); return r-0.5; } /* skew constants for 3d simplex functions */ const float F3 = 0.3333333; const float G3 = 0.1666667; // thanks: https://www.shadertoy.com/view/XsX3zB /* 3d simplex noise */ float simplex3d(vec3 p) { /* 1. find current tetrahedron T and it's four vertices */ /* s, s+i1, s+i2, s+1.0 - absolute skewed (integer) coordinates of T vertices */ /* x, x1, x2, x3 - unskewed coordinates of p relative to each of T vertices*/ /* calculate s and x */ vec3 s = floor( p + dot(p, vec3(F3)) ); vec3 x = p - s + dot(s, vec3(G3)); /* calculate i1 and i2 */ vec3 e = step(vec3(0.0), (x - x.yzx)); vec3 i1 = e*(1.0 - e.zxy); vec3 i2 = 1.0 - e.zxy*(1.0 - e); /* x1, x2, x3 */ vec3 x1 = x - i1 + G3; vec3 x2 = x - i2 + 2.0*G3; vec3 x3 = x - 1.0 + 3.0*G3; /* 2. find four surflets and store them in d */ vec4 w, d; /* calculate surflet weights */ w.x = dot(x, x); w.y = dot(x1, x1); w.z = dot(x2, x2); w.w = dot(x3, x3); /* w fades from 0.6 at the center of the surflet to 0.0 at the margin */ w = max(0.6 - w, 0.0); // /* calculate surflet components */ d.x = dot(random3(s), x); d.y = dot(random3(s + i1), x1); d.z = dot(random3(s + i2), x2); d.w = dot(random3(s + 1.0), x3); /* multiply d by w^4 */ w *= w; w *= w; d *= w; /* 3. return the sum of the four surflets */ return dot(d * 0.5, vec4(56.0)); } void main() { vec2 coord = gl_FragCoord.xy / u_param.xy; vec2 q = coord; q = -1.0 + 2.0*q; q.x *= u_param.x/ u_param.y; // float inTime = u_param.z * 2.0; vec3 lookAtCenter = vec3(0.0, 0.3, 0.0); // vec3 eye = vec3(0.0, 0.3, 3.0); inTime += 0.1 * u_mouse.z; eye.xz *= rotY( mod(inTime * 0.03, 6.2831852) ); // vec3 ray = normalize(vec3(q.x,q.y,1.5)); ray = viewMatrix3(eye, lookAtCenter, vec3(0.0,1.0,0.0)) * ray; // color1 is sky color vec3 color2,color1 = createSkyAndSun( ray ); // float fresnelFactor = 0.0; float reflectDis = 550.0; vec3 normal = vec3(0.0,1.0,0.0); if( intersectLakePlane( eye, ray, 0.0, reflectDis )) { vec3 pv = eye + reflectDis*ray; float t = u_param.z * 0.1; vec3 irv = vec3(pv.xz * 0.5,t); normal.x = simplex3d(30.0 * irv) * 0.13; normal.z = simplex3d(40.0 * irv) * 0.12; normal = normalize(normal); float nDotR = dot(normal,ray); // Simulating the change of reflected light and refraction fresnelFactor = clamp(pow(1.0 - abs(nDotR), 3.0),0.0,1.0); // calculate sun linght on the lake surface ray = reflect( ray, normal); vec3 reflectSkyColor = createSkyAndSun( ray ); // float k = (clamp(abs(reflectDis), 8.0, 30.0) - 8.0) / 22.0; //k *= k; // create the lake water surface color vec3 waterReflectColor = vec3(0.4,0.4,0.5); vec3 waterEmitColor = vec3(0.05,0.1,0.0); color2 = (reflectSkyColor * 2.0 + waterReflectColor) * 0.2 * fresnelFactor + (1.0 - fresnelFactor) * waterEmitColor; // calculate water color and sky color weights color1 = color2 * (1.0 - k) + k * color1; } // gl_FragColor = vec4( color1 * vec3(1.0,1.0,1.4), 1.0 ); }
precision highp float; // texture is cobble.jpg uniform sampler2D u_sampler0; // u_param.xy: (stageWidth,stageHeight), u_param.z>1.0: mouse_down,u_param.z<1.0: mouse_up uniform vec4 u_param; // u_mouse.x: mouse x offset from mouseDown position x, // u_mouse.y: mouse y offset from mouseDown position y, // u_mouse.z: mouse x accumulation from mouseDown position x, // u_mouse.w: mouse y accumulation from mouseDown position y uniform vec4 u_mouse; // mat2 rotY(const in float a) { return mat2(cos(a),sin(a),-sin(a),cos(a)); } // light direction vec3 lightDirection = normalize(vec3( 0.3,0.7, 0.6)); // create the sky and a sun vec3 createSkyAndSun( const in vec3 ray ) { float sunDensity = clamp( dot(lightDirection, ray), 0.0, 1.0 ); // sky color vec3 color = vec3(0.2,0.4,0.6) - ray.y*0.3*vec3(0.1,0.5,1.0) + 0.13; // sun and sun's halo color += vec3(0.8,.7,0.2)*pow( sunDensity, 8.0 ) * 0.4 + vec3(1.0,.7,0.2)*pow( sunDensity, 16.0 ) * 0.6; color *= 0.95; return color; } // Intersection of the ray and the lake plane bool intersectLakePlane(const in vec3 ro, const in vec3 ray, const in float height, inout float dis) { if (ray.y < 0.0) { float d = -(ro.y - height)/ray.y; d = min(10000.0, d); if( d > 0. && d < dis ) { dis = d; return true; } } return false; } // create a matrix33 of camera space to world space mat3 viewMatrix3(vec3 eye, vec3 center, vec3 up) { vec3 f = normalize(center - eye); vec3 s = normalize(cross(f, up)); vec3 u = cross(s, f); return mat3(s, u, -f); } // return gradient noise (in x) and its derivatives (in yz) vec3 random3(vec3 c) { float j = 4096.0*sin(dot(c,vec3(0.1,0.2,0.3))); vec3 r; r.z = fract(512.0*j); j *= .125; r.x = fract(512.0*j); j *= .125; r.y = fract(512.0*j); return r-0.5; } /* skew constants for 3d simplex functions */ const float F3 = 0.3333333; const float G3 = 0.1666667; // thanks: https://www.shadertoy.com/view/XsX3zB /* 3d simplex noise */ float simplex3d(vec3 p) { /* 1. find current tetrahedron T and it's four vertices */ /* s, s+i1, s+i2, s+1.0 - absolute skewed (integer) coordinates of T vertices */ /* x, x1, x2, x3 - unskewed coordinates of p relative to each of T vertices*/ /* calculate s and x */ vec3 s = floor( p + dot(p, vec3(F3)) ); vec3 x = p - s + dot(s, vec3(G3)); /* calculate i1 and i2 */ vec3 e = step(vec3(0.0), (x - x.yzx)); vec3 i1 = e*(1.0 - e.zxy); vec3 i2 = 1.0 - e.zxy*(1.0 - e); /* x1, x2, x3 */ vec3 x1 = x - i1 + G3; vec3 x2 = x - i2 + 2.0*G3; vec3 x3 = x - 1.0 + 3.0*G3; /* 2. find four surflets and store them in d */ vec4 w, d; /* calculate surflet weights */ w.x = dot(x, x); w.y = dot(x1, x1); w.z = dot(x2, x2); w.w = dot(x3, x3); /* w fades from 0.6 at the center of the surflet to 0.0 at the margin */ w = max(0.6 - w, 0.0); // /* calculate surflet components */ d.x = dot(random3(s), x); d.y = dot(random3(s + i1), x1); d.z = dot(random3(s + i2), x2); d.w = dot(random3(s + 1.0), x3); /* multiply d by w^4 */ w *= w; w *= w; d *= w; /* 3. return the sum of the four surflets */ return dot(d * 0.5, vec4(56.0)); } void main() { vec2 coord = gl_FragCoord.xy / u_param.xy; vec2 q = coord; q = -1.0 + 2.0*q; q.x *= u_param.x/ u_param.y; // float inTime = u_param.z * 2.0; vec3 lookAtCenter = vec3(0.0, 0.3, 0.0); // vec3 eye = vec3(0.0, 0.3, 3.0); inTime += 0.1 * u_mouse.z; eye.xz *= rotY( mod(inTime * 0.03, 6.2831852) ); // vec3 ray = normalize(vec3(q.x,q.y,1.5)); ray = viewMatrix3(eye, lookAtCenter, vec3(0.0,1.0,0.0)) * ray; // color1 is sky color vec3 color2,color1 = createSkyAndSun( ray ); // float fresnelFactor = 0.0; float reflectDis = 550.0; vec3 normal = vec3(0.0,1.0,0.0); if( intersectLakePlane( eye, ray, 0.0, reflectDis )) { vec3 pv = eye + reflectDis*ray; float t = u_param.z * 0.1; vec3 irv = vec3(pv.xz * 0.5,t); normal.x = simplex3d(30.0 * irv) * 0.13; normal.z = simplex3d(40.0 * irv) * 0.12; normal = normalize(normal); float nDotR = dot(normal,ray); // Simulating the change of reflected light and refraction fresnelFactor = clamp(pow(1.0 - abs(nDotR), 3.0),0.0,1.0); // calculate sun linght on the lake surface vec3 tempRay = reflect( ray, normal); vec3 reflectSkyColor = createSkyAndSun( tempRay ); // Smooth the boundary between the sky and the water surface float k = (clamp(abs(reflectDis), 5.0, 30.0) - 5.0) / 25.0; //k *= k; // create the lake water surface color vec3 waterReflectColor = vec3(0.4,0.4,0.5); vec3 waterEmitColor = vec3(0.05,0.1,0.0); color2 = (reflectSkyColor * 2.0 + waterReflectColor) * 0.2 * fresnelFactor + (1.0 - fresnelFactor) * waterEmitColor; // calculate water color and sky color weights color1 = color2 * (1.0 - k) + k * color1; // Simulating refraction of the lake bottom vec3 refr = refract( ray, normal, 1./1.3330 ); intersectLakePlane( pv, refr, -2., reflectDis ); color1 += mix( texture2D( u_sampler0, (eye+reflectDis*refr).xz*1.3 ).xyz * vec3(1.,.9,0.6), vec3(1.,.9,0.8)*0.5, clamp( reflectDis / 3., 0., 1.) ) * (1.-fresnelFactor)*0.125; } // gl_FragColor = vec4( color1 * vec3(1.0,1.0,1.4), 1.0 ); } //下面這一對標識是我這裡識別資源資料的標識 //##config texUrls = [ "static/voxgl/engine2/sdftest/column/res/cobble.jpg" ] //##end
相關的知識點: