webgl实现canvas生命游戏三维进化动画代码
代码语言:html
所属分类:动画
代码描述:webgl实现canvas生命游戏三维进化动画代码
代码标签: webgl canvas 生命 游戏 三维 进化 动画 代码
下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开
<!DOCTYPE html> <html lang="en" > <head> <meta charset="UTF-8"> <style> html { --side: max(100vw, 100vh); } html, body { width: 100%; height: 100%; } body { margin: 0; overflow: hidden; position: fixed; background-color: #111; } canvas { left: 50%; top: 50%; transform: translate(-50%, -50%); width: var(--side); height: var(--side); position: fixed; } </style> </head> <body translate="no"> <script>console.clear()</script> <canvas id="canvas"></canvas> <script > "use strict"; //////// SETUP const settings = [ [32, 64, 0.02, 0.67], [64, 64, 0.02, 0.67], [128, 64, 0.01, 0.33], // 2 ]; // settings index const S = 1; const side = settings[S][0]; const height = settings[S][1]; const scale = settings[S][2]; const y_offset = settings[S][3]; // total number of cubes const N = side * side * height; // texture side const t_side = Math.sqrt(N); // grid (of chunks on texture) side const g_side = t_side / side; // half side const h_side = side / 2; // coordinate of last chunk (life chunk) const l_chunk = t_side - side; //////// PREPARE WEBGL CONTEXT const gl = (() => { const dpr = Math.min(2, devicePixelRatio); let c_side = Math.max(innerWidth, innerHeight); c_side = Math.max(c_side * dpr, t_side); canvas.width = c_side; canvas.height = c_side; return canvas.getContext("webgl2", { preserveDrawingBuffer: true, alpha: false, }); })(); gl.enable(gl.DEPTH_TEST); gl.clearColor(0.067, 0.067, 0.067, 1); //////// ATTRIBUTES // indices var A; (function (A) { A[A["QUAD"] = 0] = "QUAD"; A[A["ID"] = 1] = "ID"; A[A["POS"] = 2] = "POS"; A[A["IPOS"] = 3] = "IPOS"; A[A["NORM"] = 4] = "NORM"; })(A || (A = {})); { // quad from a triangle const quad = new Float32Array([ -1, -3, 3, 1, -1, 1, ]); set_attrib(quad, [A.QUAD, 2]); // cube data -> pos, norm const cube = new Float32Array([ // face, face, normal [0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, -1], [1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0], [1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 1], [0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, -1, 0, 0], [1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0], ].reduce((arr, e) => { const n = e.slice(18), data = []; for (let i = 0; i < 18; i += 3) { e[i + 0] -= 0.5; e[i + 1] -= 0.5; e[i + 2] -= 0.5; data.push(e[i], e[i + 1], e[i + 2], ...n); } return arr.concat(data); }, [])); set_attrib(cube, [A.POS, 3], [A.NORM, 3]); // instanced cubes data -> ipos, id const icubes = new ArrayBuffer(N * 6 * 4); for (let i = 0; i < N; i++) { const x = i % side; const z = (i / t_side | 0) % side; const y = (() => { // grid id — coord of chunk on texture const x = (i % t_side) / side | 0; const y = i / (t_side * side) | 0; return y * g_side + x; })(); const o = i * 6 * 4; const ipos = new Float32Array(icubes, o, 3); ipos[0] = x - h_side; ipos[1] = y - height; ipos[2] = h_side - z; const id = new Int32Array(icubes, o + 12, 3); id[0] = x; id[1] = y; id[2] = z; } set_attrib(icubes, [A.IPOS, 3, 1], [A.ID, 3, 1, true]); } //////// MESH PROGRAM const mesh = (() => { const vert = /*glsl*/ `#version 300 es layout(location=${A.ID}) in ivec3 id; layout(location=${A.POS}) in vec3 pos; layout(location=${A.IPOS}) in vec3 ipos; layout(location=${A.NORM}) in vec3 norm; uniform mat4 proj; uniform mat4 wmat; uniform mat4 rmat; uniform sampler2D map; out vec3 color; void main() { ivec2 uv = id.xz; uv.x += (id.y % ${g_side}) * ${side}; uv.y += (id.y / ${g_side}) * ${side}; float is_alive = texelFetch(map, uv, 0).r; vec4 p = rmat * vec4((pos + ipos) * is_alive, 1); // AO, SELF SHADOW // height float h = float(id.y) / ${height}.0; // length from far corner float l = length(vec2(-${h_side}, ${h_side}) - p.xz); l = min(1.0, l / ${side}.0); l *= l; l = mix(1.0, l, sqrt(1.0 - h) - 0.1); // radius from center float r = length(vec2(id.xz) / ${side}.0 - 0.5); r = min(1.0, r * 2.0); r = mix(1.0, r, sqrt(1.0 - h) - 0.1); h = mix(h, 1.0, (l + h) / 5.0); color = vec3(l * r * sqrt(h)); color *= color; color = 0.087 + color * (1.0 - 0.087); // LIGHT vec3 n = mat3(rmat) * norm; vec3 light_dir = normalize(vec3(1, 3, -2)); float diff = max(dot(n, light_dir), 0.0); color *= sqrt(0.67 + diff * 0.33); gl_Position = proj * wmat * vec4(p.xyz * ${scale}, 1); }`; const frag = /*glsl*/ `#version 300 es precision highp float; in vec3 color; out vec3 Color; void main() { Color = color; }`; const pr = new_program(vert, frag); gl.useProgram(pr); gl.uniformMatrix4fv(uloc(pr, "proj"), !1, ortho_proj()); gl.uniform1i(uloc(pr, "map"), 0); return pr; })(); const wmat = new_mat(); rot_x(wmat, -Math.PI / 4 + 0.17); rot_y(wmat, Math.PI / 4); mov_y(wmat, -y_offset); const wmat_loc = uloc(mesh, "wmat"); gl.uniformMatrix4fv(wmat_loc, false, wmat); const rmat = new_mat(); const rmat_loc = uloc(mesh, "rmat"); //////// LIFE PROGRAM const life = (() => { const vert = /*glsl*/ `#version 300 es layout(location=${A.QUAD}) in vec2 pos; void main() { gl_Position = v.........完整代码请登录后点击上方下载按钮下载查看
网友评论0