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