webgl实现三维3d洞穴效果代码
代码语言:html
所属分类:三维
代码描述:webgl实现三维3d洞穴效果代码
下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开
<!DOCTYPE html> <html lang="en" > <head> <meta charset="UTF-8"> </head> <body> <!-- partial:index.partial.html --> <canvas id="webgl" width="500" height="1758"></canvas> <script id="vertexShader" type="x-shader/x-vertex"> attribute vec4 a_position; uniform mat4 u_modelViewMatrix; uniform mat4 u_projectionMatrix; void main() { gl_Position = a_position; } </script> <script id="fragmentShader" type="x-shader/x-fragment"> precision highp float; precision highp int; uniform vec2 u_resolution; uniform vec2 u_mouse; uniform float u_time; uniform sampler2D u_noise; // movement variables vec3 movement = vec3(.0); const int maxIterations = 256; const float stopThreshold = 0.002; const float stepScale = .5; const float eps = 0.002; const vec3 clipColour = vec3(1.); const vec3 fogColour = vec3(1.); const vec3 light1_position = vec3(0, 1., -1.); const vec3 light1_colour = vec3(.8, .8, .85); struct Surface { int object_id; float distance; vec3 position; vec3 onsurface_position; vec3 colour; float steps; float ambient; float spec; float fog; }; // Distance function copyright Inigo Quilez float opExtrusion( in vec3 p, in float primitive, in float h ) { float d = primitive; vec2 w = vec2( d, abs(p.z) - h ); return min(max(w.x,w.y),0.0) + length(max(w,0.0)); } float sdBox( in vec2 p, in vec2 b ) { vec2 d = abs(p)-b; return length(max(d,0.0)) + min(max(d.x,d.y),0.0); } vec3 path(float z) { // return vec3(0,0,0.); return vec3(sin(z * .1) * 4., sin(z * .05) * 10., z); } float getBlock(vec3 position, inout int object_id, inout vec3 p) { // position.z = fract(position.z) - .5; // object_id = int(id); float id = float(object_id); float r = sin(id * .3 + u_time) * .5; r = sin(texture2D(u_noise, vec2((id*2.)/255.)).x * 2. + u_time - id) * .25; float rw = texture2D(u_noise, vec2((id*2.)/255.)).x - .5; // // position.xy += r; float s = sin(r); float c = cos(r); position.xy *= mat2(c, -s, s, c); p = position; float box = sdBox(position.xy, vec2(1.5 + rw, 1.)) * -1.; float world = opExtrusion(position, box, .45) - .005; // world += smoothstep(.04, 0., abs(sin(p.x * 4.))) * .01; // world += smoothstep(.02, 0., abs(sin(p.y * 2.))) * .01; return world; } // This function describes the world in distances from any given 3 dimensional point in space float world(in vec3 position, inout int object_id, inout vec3 p) { position.xy -= path(position.z).xy; float id = floor(position.z); position.z = fract(position.z) - .5; int oid1 = int(id); vec3 p1; float block1 = getBlock(position, oid1, p1); int oid2 = int(id+1.); vec3 p2; float block2 = getBlock(position + vec3(0,0,-1), oid2, p2); object_id = oid1; p = p1; if(block2 < block1) { block1 = block2; object_id = oid2; p = p2; } return block1; } float world(in vec3 position, inout int object_id) { vec3 p; return world(position, object_id, p); } float world(in vec3 position) { int dummy = 0; return world(position, dummy); } Surface getSurface(int object_id, float rayDepth, vec3 sp, float steps, vec3 onsurface_pos, float fog) { return Surface( object_id, rayDepth, sp, onsurface_pos, vec3(1.), steps, .5, 1000., fog); } // The raymarch loop Surface rayMarch(vec3 ro, vec3 rd, float start, float end) { float sceneDist = 1e4; float rayDepth = start; int object_id = 0; float steps = 0.; float fog = 0.; vec3 p; for(int i = 0; i < maxIterations; i++) { sceneDist = world(ro + rd * rayDepth, object_id, p); rd += (texture2D(u_noise, (p.xy)*255.).rgb-.5)*.0005; steps++; fog += max(sceneDist, 0.); if(sceneDist < stopThreshold || rayDepth > end) { break; } rayDepth += sceneDist * stepScale; } return getSurface(object_id, rayDepth, ro + rd * rayDepth, steps, p, fog); } // Calculated the normal of any given point in space. Intended to be cast from the point of a surface vec3 calculate_normal(in vec3 position) { vec3 grad = vec3( world(vec3(position.x + eps, position.y, position.z)) - world(vec3(position.x - eps, position.y, position.z)), world(vec3(position.x, position.y + eps, position.z)) - world(vec3(position.x, position.y - eps, position.z)), world(vec3(position.x, position.y, position.z + eps)) - world(vec3(position.x, position.y, position.z - eps)) ); return normalize(grad); } vec3 lighting(Surface surface_object, vec3 cam) { // start with black vec3 sceneColour = vec3(0); // Surface normal vec3 normal = calculate_normal(surface_object.position); normal += smoothstep(.02, 0., abs(sin(surface_object.onsurface_position.x * 4.))) * .5; normal += smoothstep(.01, 0., abs(sin(surface_object.onsurface_position.y * 2.))) * .5; // Light position vec3 lp = path(u_time*3.+15.); // Light direction vec3 ld = lp - surface_object.position; // light attenuation // For brightly lit scenes or global illumination (like sunlit), this can be limited to just normalizing the ld float len = length( ld ); ld = normalize(ld); float lightAtten = min( 1.0 / ( 0.15*len ), 1.0 ); lightAtten = 1.; // The surface's light reflection normal vec3 reflection_normal = reflect(-ld, normal); // Ambient Occlusion float ao = (surface_object.steps*.01*(1./(surface_object.fog*.07))); ao *= ao*2.; ao = clamp( .........完整代码请登录后点击上方下载按钮下载查看
网友评论0