├── README.md ├── LICENSE ├── jackrabbit (mouse and keyboard, 1 player) ├── game.js ├── game.html ├── ball.js ├── animation.js ├── rendering.js ├── player.js ├── libs.js └── graphics.js └── jackrabbit (Controller, 2 player) ├── game.html ├── ball.js ├── game.js ├── animation.js ├── rendering.js ├── libs.js ├── player.js └── graphics.js /README.md: -------------------------------------------------------------------------------- 1 | # Jackrabbit 2 | 3D Game using SDFs for rendering. 3 | I know that it works on Chrome on my laptop but WebGL 2.0 is not very widely supported so I'm unsure about how well it'll work on other browsers. 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 CarterSemrad 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /jackrabbit (mouse and keyboard, 1 player)/game.js: -------------------------------------------------------------------------------- 1 | renderer.addUniform("res", "vec2", [window.innerWidth, window.innerHeight]); 2 | 3 | renderer.addUniform("camPos", "vec3", [0,5,0]); 4 | 5 | renderer.addUniform("camAngle", "vec2", [0,0]); 6 | 7 | renderer.addUniform("t", "float", 0); 8 | 9 | renderer.addUniform("ballPos", "vec3", [0,0,0]); 10 | 11 | renderer.addUniform("ballAngle", "vec2", [0,0]); 12 | 13 | renderer.addUniform("playerPos", "vec3", [0,0,0]); 14 | 15 | renderer.addUniform("playerAngle", "vec2", [0,0]); 16 | 17 | renderer.addUniform("ballRotMat", "mat3", I()); 18 | 19 | renderer.draw(); 20 | 21 | let t = performance.now()/1000; 22 | let dt = 1/120; 23 | 24 | function update(){ 25 | try{ 26 | dt = performance.now() / 1000 - t; 27 | if(dt > 1/20){ 28 | dt = 1/120; 29 | } 30 | 31 | t = performance.now()/1000; 32 | 33 | player.update(); 34 | 35 | ball.update(); 36 | 37 | renderer.setUni("t", t); 38 | renderer.draw(); 39 | 40 | keyPressed = []; 41 | mousePressed = []; 42 | } catch(e) { 43 | console.log(e); 44 | } 45 | requestAnimationFrame(update); 46 | } 47 | 48 | update(); -------------------------------------------------------------------------------- /jackrabbit (mouse and keyboard, 1 player)/game.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Jackrabbit 8 | 33 | 34 | 35 |
36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /jackrabbit (Controller, 2 player)/game.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Jackrabbit 8 | 55 | 56 | 57 |
58 |
59 |
0 - 0
60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /jackrabbit (Controller, 2 player)/ball.js: -------------------------------------------------------------------------------- 1 | /* 2 | todo: make it look good, not in this file 3 | */ 4 | 5 | function Ball(pos){ 6 | this.pos = pos; 7 | this.gravity = 50; 8 | 9 | this.rotVel = 0; 10 | this.rotAxis = [0,0,0]; 11 | this.rotMat = I(); 12 | 13 | this.yFriction = 0.3; 14 | this.xFriction = 0.5; 15 | 16 | this.velocity = [0,0,0]; 17 | this.size = 3; 18 | 19 | this.onGround = () => { 20 | return de(plus(this.pos, [0, -this.size, 0])) < 0.2; 21 | } 22 | 23 | this.update = () => { 24 | if(de(this.pos) <= this.size){ 25 | this.velocity = times(reflect(this.velocity, deNormal(this.pos)), 1); 26 | this.velocity[1] *= 1-this.yFriction; 27 | this.rotVel = -Math.hypot(this.velocity[0], this.velocity[2])/this.size; 28 | this.rotAxis = (cross(normalize([this.velocity[0], 0, this.velocity[2]]), [0, 1, 0])); 29 | } 30 | 31 | while(de(this.pos) < this.size){ 32 | this.pos = plus(this.pos, times(deNormal(this.pos), -(de(this.pos) - this.size))); 33 | } 34 | 35 | if(this.onGround() && abs(this.velocity[1]) < 0.5){ 36 | this.velocity[1] = 0; 37 | this.velocity[0] *= 1-this.xFriction*dt; 38 | this.velocity[2] *= 1-this.xFriction*dt; 39 | 40 | this.rotVel = -Math.hypot(this.velocity[0], this.velocity[2])/this.size; 41 | this.rotAxis = (cross(normalize([this.velocity[0], 0, this.velocity[2]]), [0, 1, 0])); 42 | 43 | } else { 44 | this.velocity = plus(this.velocity, [0, -this.gravity * dt, 0]); 45 | } 46 | this.pos = plus(this.pos, times(this.velocity, dt)); 47 | 48 | this.rotAxis = (cross(normalize([this.velocity[0], 0, this.velocity[2]]), [0, 1, 0])); 49 | 50 | this.rotMat = matTimesMat(rotAxisMat(this.rotVel*dt, this.rotAxis), this.rotMat); 51 | 52 | 53 | 54 | this.updateUniforms(); 55 | } 56 | 57 | this.updateUniforms = () => { 58 | renderer.setUni("ballPos", this.pos); 59 | renderer.setUni("ballRotMat", this.rotMat); 60 | } 61 | 62 | this.de = (p) => { 63 | return len(plus(p, times(this.pos, -1))) - this.size; 64 | } 65 | } 66 | 67 | let ball = new Ball([0, 10, 0]); -------------------------------------------------------------------------------- /jackrabbit (mouse and keyboard, 1 player)/ball.js: -------------------------------------------------------------------------------- 1 | /* 2 | todo: make it look good, not in this file 3 | */ 4 | 5 | function Ball(pos){ 6 | this.pos = pos; 7 | this.gravity = 50; 8 | 9 | this.rotVel = 0; 10 | this.rotAxis = [0,0,0]; 11 | this.rotMat = I(); 12 | 13 | this.yFriction = 0.3; 14 | this.xFriction = 0.5; 15 | 16 | this.velocity = [0,0,0]; 17 | this.size = 3; 18 | 19 | this.onGround = () => { 20 | return de(plus(this.pos, [0, -this.size, 0])) < 0.2; 21 | } 22 | 23 | this.update = () => { 24 | if(de(this.pos) <= this.size){ 25 | this.velocity = times(reflect(this.velocity, deNormal(this.pos)), 1); 26 | this.velocity[1] *= 1-this.yFriction; 27 | this.rotVel = -Math.hypot(this.velocity[0], this.velocity[2])/this.size; 28 | this.rotAxis = (cross(normalize([this.velocity[0], 0, this.velocity[2]]), [0, 1, 0])); 29 | } 30 | 31 | while(de(this.pos) < this.size){ 32 | this.pos = plus(this.pos, times(deNormal(this.pos), -(de(this.pos) - this.size))); 33 | } 34 | 35 | if(this.onGround() && abs(this.velocity[1]) < 0.5){ 36 | this.velocity[1] = 0; 37 | this.velocity[0] *= 1-this.xFriction*dt; 38 | this.velocity[2] *= 1-this.xFriction*dt; 39 | 40 | this.rotVel = -Math.hypot(this.velocity[0], this.velocity[2])/this.size; 41 | this.rotAxis = (cross(normalize([this.velocity[0], 0, this.velocity[2]]), [0, 1, 0])); 42 | 43 | } else { 44 | this.velocity = plus(this.velocity, [0, -this.gravity * dt, 0]); 45 | } 46 | this.pos = plus(this.pos, times(this.velocity, dt)); 47 | 48 | this.rotAxis = (cross(normalize([this.velocity[0], 0, this.velocity[2]]), [0, 1, 0])); 49 | 50 | this.rotMat = matTimesMat(rotAxisMat(this.rotVel*dt, this.rotAxis), this.rotMat); 51 | 52 | 53 | 54 | this.updateUniforms(); 55 | } 56 | 57 | this.updateUniforms = () => { 58 | renderer.setUni("ballPos", this.pos); 59 | renderer.setUni("ballRotMat", this.rotMat); 60 | } 61 | 62 | this.de = (p) => { 63 | return len(plus(p, times(this.pos, -1))) - this.size; 64 | } 65 | } 66 | 67 | let ball = new Ball([0, 10, 0]); -------------------------------------------------------------------------------- /jackrabbit (Controller, 2 player)/game.js: -------------------------------------------------------------------------------- 1 | renderer.addUniform("res", "vec2", [window.innerWidth, window.innerHeight]); 2 | 3 | renderer.addUniform("camPos", "vec3", [0,5,0]); 4 | renderer.addUniform("camPos2", "vec3", [0,5,0]); 5 | 6 | renderer.addUniform("camAngle", "vec2", [0,0]); 7 | renderer.addUniform("camAngle2", "vec2", [0,0]); 8 | 9 | renderer.addUniform("t", "float", 0); 10 | 11 | renderer.addUniform("ballPos", "vec3", [0,0,0]); 12 | 13 | renderer.addUniform("ballAngle", "vec2", [0,0]); 14 | 15 | renderer.addUniform("playerPos", "vec3", [0,0,0]); 16 | 17 | renderer.addUniform("playerAngle", "vec2", [0,0]); 18 | 19 | renderer.addUniform("playerPos2", "vec3", [0,0,0]); 20 | 21 | renderer.addUniform("playerAngle2", "vec2", [0,0]); 22 | 23 | renderer.addUniform("ballRotMat", "mat3", I()); 24 | 25 | renderer.draw(); 26 | 27 | let t = performance.now()/1000; 28 | let dt = 1/120; 29 | 30 | let scores = [0, 0]; 31 | 32 | function update(){ 33 | try{ 34 | dt = performance.now() / 1000 - t; 35 | if(dt > 1/20){ 36 | dt = 1/120; 37 | } 38 | 39 | t = performance.now()/1000; 40 | 41 | doInputs(); 42 | 43 | player.update(); 44 | player2.update(); 45 | 46 | ball.update(); 47 | 48 | if(ball.pos[2] - 2 * ball.size > 50){ 49 | scores[1]++; 50 | initPos(); 51 | } 52 | 53 | if(ball.pos[2] + 2 * ball.size < -50){ 54 | scores[0]++; 55 | initPos(); 56 | } 57 | 58 | 59 | 60 | renderer.setUni("t", t); 61 | renderer.draw(); 62 | 63 | keyPressed = []; 64 | mousePressed = []; 65 | } catch(e) { 66 | console.log(e); 67 | } 68 | requestAnimationFrame(update); 69 | } 70 | 71 | function updateScores(){ 72 | document.getElementById("scoreboard").innerHTML = `${scores[0]} - ${scores[1]}`; 73 | } 74 | 75 | function initPos(){ 76 | ball.pos = [0,20,0]; 77 | ball.velocity = [0,0,0]; 78 | ball.rotMat = I(); 79 | ball.rotVel = 0; 80 | ball.rotAxis = [0,0,0]; 81 | updateScores(); 82 | player.pos = [0, 5, 15]; 83 | player.angle = [Math.PI, 0]; 84 | player.bodyAngle = [Math.PI, 0]; 85 | 86 | player2.pos = [0, 5, -15]; 87 | player2.angle = [0, 0]; 88 | player2.bodyAngle = [0,0]; 89 | player.velocity = [0,0,0]; 90 | player2.velocity = [0,0,0]; 91 | } 92 | 93 | update(); -------------------------------------------------------------------------------- /jackrabbit (Controller, 2 player)/animation.js: -------------------------------------------------------------------------------- 1 | function Animator(uniforms, interp){ 2 | this.uniforms = uniforms; 3 | this.interp = lerp; 4 | this.states = []; 5 | this.changingStates = false; 6 | this.state = -1; 7 | this.stateT = 0; 8 | this.totalStateT = 0; 9 | this.stateFrames = []; 10 | 11 | if(interp != undefined){ 12 | this.interp = interp; 13 | } 14 | 15 | this.t = 0; 16 | this.totalAnimTime = 0; 17 | 18 | this.keyFrames = []; 19 | 20 | this.addKeyFrame = (nodes, t, state) => { 21 | if(this.states[state] == undefined){ 22 | this.states[state] = {keyFrames: [], totalAnimTime: 0}; 23 | } 24 | this.states[state].keyFrames.push({nodes, "t": t}); 25 | if(t > this.states[state].totalAnimTime){ 26 | this.states[state].totalAnimTime = t; 27 | } 28 | if(this.states.length == 1){ 29 | this.keyFrames = this.states[state].keyFrames; 30 | this.totalAnimTime = this.states[state].totalAnimTime; 31 | } 32 | } 33 | this.currentPos = () => { 34 | return this.getPos(this.t); 35 | } 36 | this.setState = (state, changeT) => { 37 | if(this.state != state){ 38 | this.state = state; 39 | this.t = 0; 40 | this.stateFrames = [ 41 | this.getPos(this.t) 42 | ] 43 | this.keyFrames = this.states[state].keyFrames; 44 | this.totalAnimTime = this.states[state].totalAnimTime; 45 | this.stateT = changeT; 46 | this.totalStateT = changeT; 47 | this.stateFrames.push(this.keyFrames[0].nodes); 48 | } 49 | } 50 | 51 | this.getPos = (time) => { 52 | if(this.stateT <= 0){ 53 | if(this.keyFrames.length == 1){ 54 | return this.keyFrames[0].nodes; 55 | } 56 | time %= this.totalAnimTime; 57 | 58 | let index = 0; 59 | 60 | if(time > this.keyFrames[this.keyFrames.length - 2]){ 61 | index = this.keyFrames.length - 2; 62 | } else { 63 | while(time >= this.keyFrames[index].t){ 64 | index++; 65 | } 66 | index--; 67 | } 68 | 69 | let nodePositions = []; 70 | 71 | 72 | for(let i in this.keyFrames[index].nodes){ 73 | nodePositions.push(this.interp( 74 | this.keyFrames[index].nodes[i], 75 | this.keyFrames[index+1].nodes[i], 76 | (time - this.keyFrames[index].t)/(this.keyFrames[index+1].t-this.keyFrames[index].t) 77 | )); 78 | } 79 | 80 | return nodePositions; 81 | } else { 82 | this.stateT -= dt; 83 | let nodePositions = []; 84 | 85 | for(let i in this.stateFrames[0]){ 86 | nodePositions.push(interp( 87 | this.stateFrames[0][i], 88 | this.stateFrames[1][i], 89 | 1-(this.stateT/this.totalStateT) 90 | )); 91 | } 92 | 93 | this.t = 0; 94 | 95 | return nodePositions; 96 | 97 | } 98 | } 99 | this.update = () => { 100 | this.t += dt; 101 | let nodePositions = this.getPos(this.t); 102 | 103 | for(let i in this.uniforms){ 104 | renderer.setUni(this.uniforms[i], nodePositions[i]); 105 | } 106 | } 107 | } 108 | 109 | //animator test 110 | 111 | let test = new Animator([]); 112 | test.addKeyFrame([[0,0,0], [1,2,3]], 0); 113 | test.addKeyFrame([[0,0,2], [2,4,6]], 1); 114 | test.addKeyFrame([[0,0,1], [-1, -5, -10]], 2); -------------------------------------------------------------------------------- /jackrabbit (mouse and keyboard, 1 player)/animation.js: -------------------------------------------------------------------------------- 1 | function Animator(uniforms, interp){ 2 | this.uniforms = uniforms; 3 | this.interp = lerp; 4 | this.states = []; 5 | this.changingStates = false; 6 | this.state = -1; 7 | this.stateT = 0; 8 | this.totalStateT = 0; 9 | this.stateFrames = []; 10 | 11 | if(interp != undefined){ 12 | this.interp = interp; 13 | } 14 | 15 | this.t = 0; 16 | this.totalAnimTime = 0; 17 | 18 | this.keyFrames = []; 19 | 20 | this.addKeyFrame = (nodes, t, state) => { 21 | if(this.states[state] == undefined){ 22 | this.states[state] = {keyFrames: [], totalAnimTime: 0}; 23 | } 24 | this.states[state].keyFrames.push({nodes, "t": t}); 25 | if(t > this.states[state].totalAnimTime){ 26 | this.states[state].totalAnimTime = t; 27 | } 28 | if(this.states.length == 1){ 29 | this.keyFrames = this.states[state].keyFrames; 30 | this.totalAnimTime = this.states[state].totalAnimTime; 31 | } 32 | } 33 | this.currentPos = () => { 34 | return this.getPos(this.t); 35 | } 36 | this.setState = (state, changeT) => { 37 | if(this.state != state){ 38 | this.state = state; 39 | this.t = 0; 40 | this.stateFrames = [ 41 | this.getPos(this.t) 42 | ] 43 | this.keyFrames = this.states[state].keyFrames; 44 | this.totalAnimTime = this.states[state].totalAnimTime; 45 | this.stateT = changeT; 46 | this.totalStateT = changeT; 47 | this.stateFrames.push(this.keyFrames[0].nodes); 48 | } 49 | } 50 | 51 | this.getPos = (time) => { 52 | if(this.stateT <= 0){ 53 | if(this.keyFrames.length == 1){ 54 | return this.keyFrames[0].nodes; 55 | } 56 | time %= this.totalAnimTime; 57 | 58 | let index = 0; 59 | 60 | if(time > this.keyFrames[this.keyFrames.length - 2]){ 61 | index = this.keyFrames.length - 2; 62 | } else { 63 | while(time >= this.keyFrames[index].t){ 64 | index++; 65 | } 66 | index--; 67 | } 68 | 69 | let nodePositions = []; 70 | 71 | 72 | for(let i in this.keyFrames[index].nodes){ 73 | nodePositions.push(this.interp( 74 | this.keyFrames[index].nodes[i], 75 | this.keyFrames[index+1].nodes[i], 76 | (time - this.keyFrames[index].t)/(this.keyFrames[index+1].t-this.keyFrames[index].t) 77 | )); 78 | } 79 | 80 | return nodePositions; 81 | } else { 82 | this.stateT -= dt; 83 | let nodePositions = []; 84 | 85 | for(let i in this.stateFrames[0]){ 86 | nodePositions.push(interp( 87 | this.stateFrames[0][i], 88 | this.stateFrames[1][i], 89 | 1-(this.stateT/this.totalStateT) 90 | )); 91 | } 92 | 93 | this.t = 0; 94 | 95 | return nodePositions; 96 | 97 | } 98 | } 99 | this.update = () => { 100 | this.t += dt; 101 | let nodePositions = this.getPos(this.t); 102 | 103 | for(let i in this.uniforms){ 104 | renderer.setUni(this.uniforms[i], nodePositions[i]); 105 | } 106 | } 107 | } 108 | 109 | //animator test 110 | 111 | let test = new Animator([]); 112 | test.addKeyFrame([[0,0,0], [1,2,3]], 0); 113 | test.addKeyFrame([[0,0,2], [2,4,6]], 1); 114 | test.addKeyFrame([[0,0,1], [-1, -5, -10]], 2); -------------------------------------------------------------------------------- /jackrabbit (mouse and keyboard, 1 player)/rendering.js: -------------------------------------------------------------------------------- 1 | function createGraphics(de, colors, otherfunctions, uniforms){ 2 | 3 | let c = document.createElement("canvas"); 4 | 5 | let scale = 1; 6 | 7 | c.width = scale * window.innerWidth; 8 | c.height = scale * window.innerHeight; 9 | 10 | document.body.appendChild(c); 11 | 12 | c.onclick = (e) => { 13 | c.requestPointerLock(); 14 | } 15 | 16 | let gl = c.getContext("webgl2"); 17 | 18 | function makeShader(src, type){ 19 | let shader = gl.createShader(type); 20 | gl.shaderSource(shader, src); 21 | gl.compileShader(shader); 22 | 23 | if(gl.getShaderParameter(shader, gl.COMPILE_STATUS)){ 24 | return shader; 25 | } else { 26 | console.log(gl.getShaderInfoLog(shader)); 27 | gl.deleteShader(shader); 28 | } 29 | } 30 | 31 | function createProgram(vertShad, fragShad){ 32 | let program = gl.createProgram(); 33 | gl.attachShader(program, vertShad); 34 | gl.attachShader(program, fragShad); 35 | 36 | gl.linkProgram(program); 37 | 38 | return program; 39 | } 40 | 41 | let vertSrc = 42 | `#version 300 es 43 | 44 | in vec4 a_position; 45 | out vec4 pos4; 46 | 47 | void main(){ 48 | pos4 = a_position; 49 | gl_Position = a_position; 50 | }`; 51 | 52 | let fragSrc = 53 | `#version 300 es 54 | 55 | #define MIN_DIST 0.001 56 | #define MAX_ITERATIONS 100 57 | #define RANGE 1000. 58 | 59 | precision highp float; 60 | 61 | out vec4 color; 62 | in vec4 pos4; 63 | 64 | uniform vec2 res; 65 | uniform vec3 camPos; 66 | uniform vec2 camAngle; 67 | uniform float t; 68 | uniform vec3 playerPos; 69 | uniform vec3 ballPos; 70 | uniform vec2 ballAngle; 71 | uniform mat3 ballRotMat; 72 | uniform vec2 playerAngle; 73 | ${uniforms} 74 | 75 | ${libs} 76 | 77 | ${de} 78 | 79 | ${libsAfterDe} 80 | 81 | ${otherfunctions} 82 | 83 | void main(){ 84 | vec2 pos = pos4.xy; 85 | pos.x *= res.x/res.y; 86 | 87 | float fovX = .35; 88 | float fovY = .35; 89 | 90 | vec3 dir = normalize(vec3(pos.x*fovX, pos.y*fovY, 0.5515)); 91 | 92 | dir = rotX(dir, -camAngle.y); 93 | dir = rotY(dir, camAngle.x); 94 | 95 | vec3 p = camPos; 96 | 97 | float dist = de(p); 98 | float totDist = dist; 99 | float bloomDist = bloomDe(p); 100 | float bloomTemp = bloomDist; 101 | 102 | while(dist > MIN_DIST && totDist < RANGE){ 103 | p += dir*dist; 104 | dist = de(p); 105 | bloomTemp = bloomDe(p); 106 | if(bloomTemp < bloomDist){ 107 | bloomDist = bloomTemp; 108 | } 109 | totDist += dist; 110 | } 111 | 112 | ${colors} 113 | 114 | //color = vec4(abs(pos.x),1.-length(pos),abs(pos.y),1.); 115 | 116 | } 117 | ` 118 | 119 | vertShad = makeShader(vertSrc, gl.VERTEX_SHADER); 120 | fragShad = makeShader(fragSrc, gl.FRAGMENT_SHADER); 121 | 122 | let program = createProgram(vertShad, fragShad); 123 | 124 | let posLoc = gl.getAttribLocation(program, "a_position"); 125 | 126 | let posBuffer = gl.createBuffer(); 127 | 128 | gl.bindBuffer(gl.ARRAY_BUFFER, posBuffer); 129 | gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1,-1,-1,1,1,1,1,1,1,-1,-1,-1]), gl.STATIC_DRAW); 130 | 131 | 132 | let va = gl.createVertexArray(); 133 | 134 | gl.bindVertexArray(va); 135 | 136 | gl.enableVertexAttribArray(posLoc); 137 | 138 | gl.vertexAttribPointer(posLoc, 2, gl.FLOAT, false, 0, 0); 139 | 140 | gl.viewport(0, 0, c.width, c.height); 141 | 142 | gl.clearColor(0, 0, 0, 0); 143 | gl.clear(gl.COLOR_BUFFER_BIT); 144 | 145 | gl.useProgram(program); 146 | 147 | return {gl, program, c}; 148 | } 149 | 150 | function Renderer(de, colors, otherfunctions, uniforms){ 151 | let graphics = createGraphics(de, colors, otherfunctions, uniforms); 152 | this.gl = graphics.gl; 153 | this.canvas = graphics.c; 154 | this.program = graphics.program; 155 | 156 | this.uniforms = {}; 157 | 158 | this.addUniform = (name, type, value) => { 159 | if(value.length != undefined){ 160 | if(value[0].length == undefined){ 161 | value = new Float32Array(value); 162 | } 163 | } 164 | let uni = {location: "", t: type, name: name, value: value}; 165 | uni.location = this.gl.getUniformLocation(this.program, name); 166 | if(type == "vec2"){ 167 | uni.t = (loc, val)=>{this.gl.uniform2fv(loc, val)}; 168 | } 169 | if(type == "vec3"){ 170 | uni.t = (loc, val)=>{this.gl.uniform3fv(loc, val)}; 171 | } 172 | if(type == "vec4"){ 173 | uni.t = (loc, val)=>{this.gl.uniform4fv(loc, val)}; 174 | } 175 | if(type == "float"){ 176 | uni.t = (loc, val)=>{this.gl.uniform1f(loc, val)}; 177 | } 178 | if(type == "mat3"){ 179 | uni.t = (loc, val)=>{ 180 | let temp = []; 181 | for(let i of val){ 182 | for(let j of i){ 183 | temp.push(j); 184 | } 185 | } 186 | this.gl.uniformMatrix3fv(loc, false, new Float32Array(temp)); 187 | }; 188 | } 189 | 190 | this.uniforms[name] = uni; 191 | 192 | uni.t(uni.location, uni.value); 193 | } 194 | 195 | this.setUni = (name, value) => { 196 | if(value.length != undefined){ 197 | if(value.length == undefined){ 198 | value = new Float32Array(value); 199 | } 200 | } 201 | this.uniforms[name].value = value; 202 | this.uniforms[name].t(this.uniforms[name].location, value); 203 | } 204 | 205 | this.updateUniforms = () => { 206 | for(let i of this.uniforms){ 207 | i.t(i.location, i.value); 208 | } 209 | } 210 | 211 | this.draw = () => { 212 | this.gl.drawArrays(this.gl.TRIANGLES, 0, 6); 213 | } 214 | } -------------------------------------------------------------------------------- /jackrabbit (Controller, 2 player)/rendering.js: -------------------------------------------------------------------------------- 1 | function createGraphics(de, colors, otherfunctions, uniforms){ 2 | 3 | let c = document.createElement("canvas"); 4 | 5 | let scale = 1; 6 | 7 | c.width = scale * window.innerWidth; 8 | c.height = scale * window.innerHeight; 9 | 10 | document.body.appendChild(c); 11 | 12 | c.onclick = (e) => { 13 | c.requestPointerLock(); 14 | } 15 | 16 | let gl = c.getContext("webgl2"); 17 | 18 | function makeShader(src, type){ 19 | let shader = gl.createShader(type); 20 | gl.shaderSource(shader, src); 21 | gl.compileShader(shader); 22 | 23 | if(gl.getShaderParameter(shader, gl.COMPILE_STATUS)){ 24 | return shader; 25 | } else { 26 | console.log(gl.getShaderInfoLog(shader)); 27 | gl.deleteShader(shader); 28 | } 29 | } 30 | 31 | function createProgram(vertShad, fragShad){ 32 | let program = gl.createProgram(); 33 | gl.attachShader(program, vertShad); 34 | gl.attachShader(program, fragShad); 35 | 36 | gl.linkProgram(program); 37 | 38 | return program; 39 | } 40 | 41 | let vertSrc = 42 | `#version 300 es 43 | 44 | in vec4 a_position; 45 | out vec4 pos4; 46 | 47 | void main(){ 48 | pos4 = a_position; 49 | gl_Position = a_position; 50 | }`; 51 | 52 | let fragSrc = 53 | `#version 300 es 54 | 55 | #define MIN_DIST 0.001 56 | #define MAX_ITERATIONS 100 57 | #define RANGE 1000. 58 | 59 | precision highp float; 60 | 61 | out vec4 color; 62 | in vec4 pos4; 63 | 64 | uniform vec2 res; 65 | uniform vec3 camPos; 66 | uniform vec3 camPos2; 67 | uniform vec2 camAngle; 68 | uniform vec2 camAngle2; 69 | uniform float t; 70 | uniform vec3 playerPos; 71 | uniform vec3 playerPos2; 72 | uniform vec3 ballPos; 73 | uniform vec2 ballAngle; 74 | uniform mat3 ballRotMat; 75 | uniform vec2 playerAngle; 76 | uniform vec2 playerAngle2; 77 | ${uniforms} 78 | 79 | ${libs} 80 | 81 | ${de} 82 | 83 | ${libsAfterDe} 84 | 85 | ${otherfunctions} 86 | 87 | void main(){ 88 | vec2 pos = pos4.xy; 89 | pos.x *= res.x/res.y; 90 | 91 | float fovX = .35; 92 | float fovY = .35; 93 | 94 | float left = 0.; 95 | 96 | if(pos.x < 0.){ 97 | left = 1.; 98 | pos.x += 0.5 * res.x / res.y; 99 | } else { 100 | pos.x -= 0.5 * res.x / res.y; 101 | } 102 | 103 | pos *= 1.5; 104 | 105 | vec3 dir = normalize(vec3(pos.x*fovX, pos.y*fovY, 0.5515)); 106 | 107 | if(left != 0.){ 108 | dir = rotX(dir, -camAngle.y); 109 | dir = rotY(dir, camAngle.x); 110 | } else { 111 | dir = rotX(dir, -camAngle2.y); 112 | dir = rotY(dir, camAngle2.x); 113 | } 114 | 115 | vec3 p = camPos; 116 | 117 | if(left == 0.){ 118 | p = camPos2; 119 | } 120 | 121 | float dist = de(p); 122 | float totDist = dist; 123 | float bloomDist = bloomDe(p); 124 | float bloomTemp = bloomDist; 125 | 126 | while(dist > MIN_DIST && totDist < RANGE){ 127 | p += dir*dist; 128 | dist = de(p); 129 | bloomTemp = bloomDe(p); 130 | if(bloomTemp < bloomDist){ 131 | bloomDist = bloomTemp; 132 | } 133 | totDist += dist; 134 | } 135 | 136 | ${colors} 137 | 138 | //color = vec4(abs(pos.x),1.-length(pos),abs(pos.y),1.); 139 | 140 | } 141 | ` 142 | 143 | vertShad = makeShader(vertSrc, gl.VERTEX_SHADER); 144 | fragShad = makeShader(fragSrc, gl.FRAGMENT_SHADER); 145 | 146 | let program = createProgram(vertShad, fragShad); 147 | 148 | let posLoc = gl.getAttribLocation(program, "a_position"); 149 | 150 | let posBuffer = gl.createBuffer(); 151 | 152 | gl.bindBuffer(gl.ARRAY_BUFFER, posBuffer); 153 | gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1,-1,-1,1,1,1,1,1,1,-1,-1,-1]), gl.STATIC_DRAW); 154 | 155 | 156 | let va = gl.createVertexArray(); 157 | 158 | gl.bindVertexArray(va); 159 | 160 | gl.enableVertexAttribArray(posLoc); 161 | 162 | gl.vertexAttribPointer(posLoc, 2, gl.FLOAT, false, 0, 0); 163 | 164 | gl.viewport(0, 0, c.width, c.height); 165 | 166 | gl.clearColor(0, 0, 0, 0); 167 | gl.clear(gl.COLOR_BUFFER_BIT); 168 | 169 | gl.useProgram(program); 170 | 171 | return {gl, program, c}; 172 | } 173 | 174 | function Renderer(de, colors, otherfunctions, uniforms){ 175 | let graphics = createGraphics(de, colors, otherfunctions, uniforms); 176 | this.gl = graphics.gl; 177 | this.canvas = graphics.c; 178 | this.program = graphics.program; 179 | 180 | this.uniforms = {}; 181 | 182 | this.addUniform = (name, type, value) => { 183 | if(value.length != undefined){ 184 | if(value[0].length == undefined){ 185 | value = new Float32Array(value); 186 | } 187 | } 188 | let uni = {location: "", t: type, name: name, value: value}; 189 | uni.location = this.gl.getUniformLocation(this.program, name); 190 | if(type == "vec2"){ 191 | uni.t = (loc, val)=>{this.gl.uniform2fv(loc, val)}; 192 | } 193 | if(type == "vec3"){ 194 | uni.t = (loc, val)=>{this.gl.uniform3fv(loc, val)}; 195 | } 196 | if(type == "vec4"){ 197 | uni.t = (loc, val)=>{this.gl.uniform4fv(loc, val)}; 198 | } 199 | if(type == "float"){ 200 | uni.t = (loc, val)=>{this.gl.uniform1f(loc, val)}; 201 | } 202 | if(type == "mat3"){ 203 | uni.t = (loc, val)=>{ 204 | let temp = []; 205 | for(let i of val){ 206 | for(let j of i){ 207 | temp.push(j); 208 | } 209 | } 210 | this.gl.uniformMatrix3fv(loc, false, new Float32Array(temp)); 211 | }; 212 | } 213 | 214 | this.uniforms[name] = uni; 215 | 216 | uni.t(uni.location, uni.value); 217 | } 218 | 219 | this.setUni = (name, value) => { 220 | if(value.length != undefined){ 221 | if(value.length == undefined){ 222 | value = new Float32Array(value); 223 | } 224 | } 225 | this.uniforms[name].value = value; 226 | this.uniforms[name].t(this.uniforms[name].location, value); 227 | } 228 | 229 | this.updateUniforms = () => { 230 | for(let i of this.uniforms){ 231 | i.t(i.location, i.value); 232 | } 233 | } 234 | 235 | this.draw = () => { 236 | this.gl.drawArrays(this.gl.TRIANGLES, 0, 6); 237 | } 238 | } -------------------------------------------------------------------------------- /jackrabbit (mouse and keyboard, 1 player)/player.js: -------------------------------------------------------------------------------- 1 | let mouseDown = []; 2 | let mousePressed = []; 3 | let keyDown = []; 4 | let keyPressed = []; 5 | 6 | onmousemove = (e) => { 7 | let sens = [1/900, 1/900]; 8 | player.angle[0] += e.movementX * sens[0]; 9 | player.angle[1] -= e.movementY * sens[1]; 10 | 11 | if(player.angle[1] >= Math.PI/2){ 12 | player.angle[1] = Math.PI/2; 13 | } 14 | if(player.angle[1] <= -Math.PI/2){ 15 | player.angle[1] = -Math.PI/2; 16 | } 17 | } 18 | 19 | onmousedown = (e) => { 20 | mouseDown[e.button] = true; 21 | mousePressed[e.button] = true; 22 | } 23 | 24 | onmouseup = (e) => { 25 | mouseDown[e.button] = false; 26 | } 27 | 28 | onkeydown = (e) => { 29 | keyDown[e.key.toLowerCase()] = true; 30 | keyPressed[e.key.toLowerCase()] = true; 31 | } 32 | 33 | onkeyup = (e) => { 34 | keyDown[e.key.toLowerCase()] = false; 35 | } 36 | 37 | function Player(){ 38 | this.pos = [0,1.5,0]; 39 | 40 | this.camPos = [0,0,0]; 41 | 42 | this.angle = [0,0]; 43 | 44 | this.bodyAngle = [0,0]; 45 | 46 | this.gravity = 50; 47 | this.jumpVel = 15; 48 | this.terminalYVel = 30; 49 | this.speed = 7.5; 50 | 51 | this.velocity = [0,0,0]; 52 | this.jumpSpeed = 50; 53 | this.xFriction = 0.5; 54 | 55 | this.coyoteTime = 0.1; 56 | 57 | this.body2 = 0.5; //radius of body collision 58 | 59 | this.kickState = false; 60 | this.kickPos = undefined; 61 | this.kickPower = 50; //going to make kick more powerful w/ longer hold? idk controls but power should be a control 62 | 63 | this.update = () => { 64 | this.kick(); 65 | this.jump(); 66 | this.move(); 67 | 68 | this.legAnimator.update(); 69 | this.updateUniforms(); 70 | } 71 | 72 | this.jump = () => { 73 | if(mouseDown[2] && this.coyoteTime > 0){ 74 | this.coyoteTime = -1; 75 | let upOffset = [0, 0.5, 0]; 76 | let dir = dirFromAngle(...this.angle); 77 | 78 | dir = normalize(plus(dir, upOffset)); 79 | dir[0] /= 2; 80 | dir[2] /= 2; 81 | this.velocity = times(dir, this.jumpSpeed); 82 | } 83 | } 84 | 85 | this.kick = () => { 86 | let kickRange = 7; 87 | if(mouseDown[0] && ball.de(this.pos) < kickRange){ 88 | this.kickState = true; 89 | dt /= 10; 90 | let dir = dirFromAngle(...this.angle); 91 | let p = this.camPos; 92 | let marchRes = march(ball.de, p, dir); 93 | if(marchRes){ 94 | this.kickPos = marchRes; 95 | } else { 96 | this.kickPos = undefined; 97 | } 98 | 99 | } else if(this.kickState){ 100 | this.kickState = false; 101 | if(this.kickPos != undefined){ 102 | let upOffset = [0, -1, 0]; 103 | let kickDir = normalize(plus(ball.pos, times(plus(this.kickPos, upOffset), -1))); 104 | ball.velocity = times(kickDir, this.kickPower); 105 | 106 | ball.rotVel = -Math.hypot(ball.velocity[0], ball.velocity[2])/ball.size; 107 | ball.rotAxis = (cross(normalize([ball.velocity[0], 0, ball.velocity[2]]), [0, 1, 0])); 108 | } 109 | } 110 | } 111 | 112 | this.move = () => { 113 | let vel = [0,0,0]; 114 | 115 | if(keyDown["w"]){ 116 | vel[2] += cos(this.angle[0]); 117 | vel[0] += sin(this.angle[0]); 118 | } 119 | if(keyDown["s"]){ 120 | vel[2] -= cos(this.angle[0]); 121 | vel[0] -= sin(this.angle[0]); 122 | } 123 | if(keyDown["a"]){ 124 | vel[2] += sin(this.angle[0]); 125 | vel[0] -= cos(this.angle[0]); 126 | } 127 | if(keyDown["d"]){ 128 | vel[2] -= sin(this.angle[0]); 129 | vel[0] += cos(this.angle[0]); 130 | } 131 | 132 | if(len(vel) > 0){ 133 | this.bodyAngle[0] = aLerp(this.bodyAngle[0], Math.atan2(vel[0], vel[2]), 0.1 * (dt/(1/120))); 134 | renderer.setUni("playerAngle", [this.bodyAngle[0], 0]); 135 | } 136 | 137 | if(!this.onGround()){ 138 | if(this.velocity[1] > 10){ 139 | this.legAnimator.setState(2, 0.1); 140 | } else { 141 | this.legAnimator.setState(3, 1); 142 | } 143 | } else { 144 | if(len(vel) > 0){ 145 | this.legAnimator.setState(0, 0.1); 146 | } else { 147 | this.legAnimator.setState(1, 0.2); 148 | } 149 | } 150 | 151 | 152 | if(len(vel) == 0){ 153 | vel = [0, 0, 0]; 154 | } else { 155 | vel = times(vel, this.speed*dt/len(vel)); 156 | } 157 | 158 | this.coyoteTime -= dt; 159 | 160 | if(this.onGround()){ 161 | this.coyoteTime = 0.2; 162 | this.velocity[0] *= 0; 163 | this.velocity[2] *= 0; 164 | } 165 | 166 | if(keyPressed[" "] && this.coyoteTime > 0){ 167 | this.velocity[1] = this.jumpVel; 168 | this.coyoteTime = -1; 169 | } 170 | 171 | this.velocity[1] -= this.gravity*dt; 172 | vel = plus(times(this.velocity, dt), vel); 173 | 174 | this.pos = plus(vel, this.pos); 175 | 176 | while(de(this.pos) < this.body2){ 177 | let norm = deNormal(this.pos); 178 | this.pos = plus(this.pos, times(norm,-(de(this.pos) - this.body2))); 179 | this.velocity = plus(this.velocity, times(norm,-dot(this.velocity, norm))); 180 | } 181 | } 182 | 183 | this.onGround = () => { 184 | return de(plus(this.pos, [0,-this.body2,0])) < 0.1; 185 | } 186 | 187 | this.updateUniforms = () => { 188 | renderer.setUni("playerPos", this.pos); 189 | renderer.setUni("camAngle", this.angle); 190 | 191 | let camDir = [0, 0, -5]; 192 | 193 | camDir = rotX(camDir, -this.angle[1]); 194 | 195 | camDir = rotY(camDir, this.angle[0]); 196 | 197 | let camPos = plus(plus(this.pos, [0,1,0]), camDir); 198 | 199 | let iterations = 1000; 200 | 201 | while(de(camPos) < 0.5 && iterations > 0){ 202 | iterations--; 203 | camPos = plus(camPos, times(camDir, -0.005/5)); 204 | } 205 | 206 | renderer.setUni("camPos", camPos); 207 | this.camPos = camPos; 208 | } 209 | 210 | this.createAnimators = () => { 211 | let legUnis = [ 212 | "uhip1", "ujr1", "ujr2", "ujr3", "uhip2", "ujl1", "ujl2", "ujl3", "uHeadPos", "uChestPos", "uBodyAngle" 213 | ]; 214 | 215 | let legUniValues = [ 216 | [ 217 | [.1,-.1,-.12], 218 | [0.15, -0.26, 0.05], 219 | [0.13, -0.35, -0.15], 220 | [0.13, -0.46, 0], 221 | 222 | [-.1,-.1,-.12], 223 | [-0.15, -0.26, 0.05], 224 | [-0.13, -0.35, -0.15], 225 | [-0.13, -0.46, 0], 226 | [0,0,0], 227 | [0,0,0], 228 | [0,0,0], 229 | 1.2 230 | ], 231 | 232 | //left leg back 233 | [ 234 | [.1,-.1,-.12], 235 | [0.15, -0.2, 0.15], 236 | [0.13, -0.35, -0.], 237 | [0.13, -0.46, 0.15], 238 | 239 | [-.1,-.1,-.12], 240 | [-0.15, -0.28, -0.05], 241 | [-0.13, -0.3, -0.2], 242 | [-0.13, -0.46, -0.15], 243 | [0,0,0], 244 | [0,0,0], 245 | [0,-0.4,0], 246 | 1.2 247 | ], 248 | 249 | //left leg up 250 | [ 251 | [.1,-.1,-.12], 252 | [0.15, -0.26, 0.05], 253 | [0.13, -0.35, -0.15], 254 | [0.13, -0.46, 0], 255 | 256 | [-.1,-.1,-.12], 257 | [-0.15, -0.18, 0.05], 258 | [-0.13, -0.25, -0.15], 259 | [-0.13, -0.35, 0], 260 | [0,0,0], 261 | [0,0,0], 262 | [0,-0.35,0], 263 | 1.2 264 | ], 265 | 266 | //left leg front 267 | [ 268 | [.1,-.1,-.12], 269 | [0.15, -0.28, -0.05], 270 | [0.13, -0.3, -0.2], 271 | [0.13, -0.46, -0.15], 272 | 273 | [-.1,-.1,-.12], 274 | [-0.15, -0.2, 0.15], 275 | [-0.13, -0.35, -0.], 276 | [-0.13, -0.46, 0.15], 277 | [0,0,0], 278 | [0,0,0], 279 | [0,-0.3,0], 280 | 1.2 281 | ], 282 | 283 | //left leg down 284 | [ 285 | [.1,-.1,-.12], 286 | [0.15, -0.18, 0.05], 287 | [0.13, -0.25, -0.15], 288 | [0.13, -0.35, 0], 289 | 290 | [-.1,-.1,-.12], 291 | [-0.15, -0.26, 0.05], 292 | [-0.13, -0.35, -0.15], 293 | [-0.13, -0.46, 0], 294 | [0,0,0], 295 | [0,0,0], 296 | [0,-0.35,0], 297 | 1.2 298 | ], 299 | //both legs up 1 300 | [ 301 | [.1,-.1,-.12], 302 | [0.15, -0.18, 0.05], 303 | [0.13, -0.25, -0.15], 304 | [0.13, -0.35, 0], 305 | 306 | [-.1,-.1,-.12], 307 | [-0.15, -0.18, 0.05], 308 | [-0.13, -0.25, -0.15], 309 | [-0.13, -0.35, 0], 310 | [0,0,0], 311 | [0,0,0], 312 | [0,-0.2,0], 313 | 1.2 314 | ], 315 | //both legs up 2 316 | [ 317 | [.1,-.1,-.12], 318 | [0.15, -0.13, 0.05], 319 | [0.13, -0.2, -0.15], 320 | [0.13, -0.3, 0], 321 | 322 | [-.1,-.1,-.12], 323 | [-0.15, -0.13, 0.05], 324 | [-0.13, -0.2, -0.15], 325 | [-0.13, -0.3, 0], 326 | [0,0,0], 327 | [0,0,0], 328 | [0,-0.2,0], 329 | 1.2 330 | ] 331 | ]; 332 | 333 | for(let i in legUnis){ 334 | renderer.addUniform(legUnis[i], "vec3", legUniValues[0][i]); 335 | } 336 | renderer.addUniform("uLift", "float", 1.2); 337 | 338 | this.legAnimator = new Animator([...legUnis, "uLift"], sinLerp); 339 | 340 | //this.legAnimator.addKeyFrame(legUniValues[0], 0); 341 | let stepTime = 0.3; 342 | 343 | this.legAnimator.addKeyFrame(legUniValues[1], 0., 0); 344 | this.legAnimator.addKeyFrame(legUniValues[2], stepTime/4, 0); 345 | this.legAnimator.addKeyFrame(legUniValues[3], 2*stepTime/4, 0); 346 | this.legAnimator.addKeyFrame(legUniValues[4], 3*stepTime/4, 0); 347 | this.legAnimator.addKeyFrame(legUniValues[1], stepTime, 0); 348 | this.legAnimator.addKeyFrame(legUniValues[0], stepTime, 1); 349 | this.legAnimator.addKeyFrame(legUniValues[5], 0., 2); 350 | this.legAnimator.addKeyFrame(legUniValues[6], 0., 3); 351 | //this.legAnimator.setState(0, -1); 352 | 353 | 354 | //this.legAnimator.addKeyFrame(legUniValues[0], 1.2); 355 | } 356 | 357 | this.createAnimators(); 358 | } 359 | 360 | let player = new Player(); -------------------------------------------------------------------------------- /jackrabbit (Controller, 2 player)/libs.js: -------------------------------------------------------------------------------- 1 | let libs = 2 | ` 3 | //ty IQ for most of these 4 | float smin( float a, float b, float k ) 5 | { 6 | float h = max( k-abs(a-b), 0.0 )/k; 7 | return min( a, b ) - h*h*k*(1.0/4.0); 8 | } 9 | 10 | vec3 bend(vec3 p, float k) 11 | { 12 | float c = cos(k*p.x); 13 | float s = sin(k*p.x); 14 | mat2 m = mat2(c,-s,s,c); 15 | vec3 q = vec3(m*p.xy,p.z); 16 | return q; 17 | } 18 | vec3 rotAxis(vec3 p, float a, vec3 u){ 19 | mat3 m = mat3( 20 | cos(a) + u.x*u.x*(1.-cos(a)), u.x*u.y*(1.-cos(a))-u.z*sin(a), u.x*u.z*(1.-cos(a)) + u.y*sin(a), 21 | u.y*u.x*(1.-cos(a))+u.z*sin(a), cos(a) + u.y*u.y*(1.-cos(a)), u.y*u.z*(1.-cos(a))-u.x*sin(a), 22 | u.z*u.x*(1.-cos(a))-u.y*sin(a), u.z*u.y*(1.-cos(a))+u.x*sin(a), cos(a) + u.z*u.z*(1.-cos(a)) 23 | ); 24 | 25 | return m*p; 26 | } 27 | vec3 rotY(vec3 v, float a){ 28 | return vec3(v.x*cos(a)+v.z*sin(a),v.y,-v.x*sin(a) + v.z*cos(a)); 29 | } 30 | 31 | vec3 rotX(vec3 v, float a){ 32 | return vec3(v.x, v.y*cos(a)-v.z*sin(a), v.y*sin(a)+v.z*cos(a)); 33 | } 34 | vec3 twist( vec3 p, float k ) 35 | { 36 | float c = cos(k*p.y); 37 | float s = sin(k*p.y); 38 | mat2 m = mat2(c,-s,s,c); 39 | vec3 q = vec3(m*p.xz,p.y); 40 | return q; 41 | } 42 | 43 | vec3 palette( in float t, in vec3 a, in vec3 b, in vec3 c, in vec3 d ) 44 | { 45 | return a + b*cos( 6.28318*(c*t+d) ); 46 | } 47 | float dot2(in vec3 v ) { return dot(v,v); } 48 | 49 | float sdBox( vec3 p, vec3 b ){ 50 | vec3 q = abs(p) - b; 51 | return length(max(q,0.0)) + min(max(q.x,max(q.y,q.z)),0.0); 52 | } 53 | float sdBox( in vec2 p, in vec2 b ){ 54 | vec2 d = abs(p)-b; 55 | return length(max(d,0.0)) + min(max(d.x,d.y),0.0); 56 | } 57 | float sdCapsule( vec3 p, vec3 a, vec3 b, float r ) 58 | { 59 | vec3 pa = p - a, ba = b - a; 60 | float h = clamp( dot(pa,ba)/dot(ba,ba), 0.0, 1.0 ); 61 | return length( pa - ba*h ) - r; 62 | } 63 | float sdTorus( vec3 p, vec2 t ) 64 | { 65 | vec2 q = vec2(length(p.xz)-t.x,p.y); 66 | return length(q)-t.y; 67 | } 68 | float sdRoundCone( vec3 p, vec3 a, vec3 b, float r1, float r2 ) 69 | { 70 | // sampling independent computations (only depend on shape) 71 | vec3 ba = b - a; 72 | float l2 = dot(ba,ba); 73 | float rr = r1 - r2; 74 | float a2 = l2 - rr*rr; 75 | float il2 = 1.0/l2; 76 | 77 | // sampling dependant computations 78 | vec3 pa = p - a; 79 | float y = dot(pa,ba); 80 | float z = y - l2; 81 | float x2 = dot2( pa*l2 - ba*y ); 82 | float y2 = y*y*l2; 83 | float z2 = z*z*l2; 84 | 85 | // single square root! 86 | float k = sign(rr)*rr*rr*x2; 87 | if( sign(z)*a2*z2>k ) return sqrt(x2 + z2) *il2 - r2; 88 | if( sign(y)*a2*y2> 3U)); 138 | return vec3(p ^ (p >> 16U)) * (1.0 / vec3(0xffffffffU)); 139 | } 140 | vec3 stars(in vec3 p) { 141 | vec3 c = vec3(0.); 142 | float resX = 500.; 143 | 144 | for(float i = 0.; i < 5.; i++) { 145 | vec3 q = fract(p * (.15 * resX)) - 0.5; 146 | vec3 id = floor(p * (.15 * resX)); 147 | vec2 rn = nmzHash33(id).xy; 148 | float c2 = 1. - smoothstep(0., .6, length(q)); 149 | c2 *= step(rn.x, .0005 + i * 0.002); 150 | c += c2 * (mix(vec3(1.0, 0.49, 0.1), vec3(0.75, 0.9, 1.), rn.y) * 0.25 + 0.75); 151 | p *= 1.4; 152 | } 153 | return c * c; 154 | } 155 | 156 | `; 157 | 158 | let libsAfterDe = ` 159 | vec3 grad(vec3 p){ 160 | float eps = 0.01; 161 | return normalize(vec3((de(p+vec3(eps, 0., 0.)) - de(p-vec3(eps,0.,0.)))/(2.*eps), (de(p+vec3(0., eps, 0.)) - de(p-vec3(0.,eps,0.)))/(2.*eps), (de(p+vec3(0., 0., eps)) - de(p-vec3(0.,0.,eps)))/(2.*eps))); 162 | } 163 | float light(vec3 p, vec3 l){ 164 | return clamp(dot(grad(p), l), 0., 1.); 165 | } 166 | 167 | float specLight(vec3 p, vec3 l){ 168 | vec3 pos = normalize(p-camPos); 169 | vec3 ray = reflect(l, grad(p)); 170 | return clamp(dot(pos, ray), 0., 1.); 171 | } 172 | 173 | ` 174 | function rotY(v, a){ 175 | return [v[0]*cos(a) + v[2]*sin(a), v[1], -v[0]*sin(a) + v[2]*cos(a)]; 176 | } 177 | function rotX(v, a){ 178 | return [v[0], v[1]*cos(a)-v[2]*sin(a), v[1]*sin(a)+v[2]*cos(a)]; 179 | } 180 | function plus(a1, a2){ 181 | return [a1[0] + a2[0], a1[1] + a2[1], a1[2] + a2[2]]; 182 | } 183 | function times(a, s){ 184 | return [a[0]*s, a[1]*s, a[2]*s]; 185 | } 186 | function min(){ 187 | return Math.min(...arguments); 188 | } 189 | function max(){ 190 | return Math.max(...arguments); 191 | } 192 | function abs(x){ 193 | if(x.length != undefined){ 194 | let temp = []; 195 | for(let i of x){ 196 | temp.push(Math.abs(i)); 197 | } 198 | return temp; 199 | } 200 | return Math.abs(x); 201 | } 202 | function matPlus(a, b){ 203 | let temp = []; 204 | for(let i in a){ 205 | temp[i] = []; 206 | for(let j in a[i]){ 207 | temp[i][j] = a[i][j] + b[i][j]; 208 | } 209 | } 210 | 211 | return temp; 212 | } 213 | function matTimes(m, v){ 214 | return [ 215 | m[0][0]*v[0] + m[0][1]*v[1] + m[0][2]*v[2], 216 | m[1][0]*v[0] + m[1][1]*v[1] + m[1][2]*v[2], 217 | m[2][0]*v[0] + m[2][1]*v[1] + m[2][2]*v[2] 218 | ]; 219 | } 220 | function matTimesMat(a, b){ 221 | let temp = [[],[],[]]; 222 | for(let i in b){ 223 | let col = matTimes(a, [b[0][i], b[1][i], b[2][i]]); 224 | for(let j in col){ 225 | temp[j].push(col[j]); 226 | } 227 | } 228 | return temp; 229 | } 230 | function matTimesS(m, s){ 231 | let temp = []; 232 | for(let i in m){ 233 | temp[i] = []; 234 | for(let j in m[i]){ 235 | temp[i][j] = m[i][j]*s; 236 | } 237 | } 238 | return temp; 239 | } 240 | function I(){ 241 | return [[1,0,0],[0,1,0],[0,0,1]]; 242 | } 243 | //skew-symmetric cross-product matrix of v ?? (don't know what this means) 244 | function sscpm(v){ 245 | return [ 246 | [0, -v[2], v[1]], 247 | [v[2], 0, -v[0]], 248 | [-v[1], v[0], 0] 249 | ] 250 | } 251 | //https://math.stackexchange.com/questions/180418/calculate-rotation-matrix-to-align-vector-a-to-vector-b-in-3d 252 | function rotMatFromTwoVectors(a, b){ 253 | let v = cross(a,b); 254 | let s = len(v); 255 | let c = dot(a,b); 256 | 257 | let vx = sscpm(v); 258 | let vx2 = matTimesS(matTimesMat(vx, vx), (1/(1+c))); 259 | 260 | let R = matPlus(matPlus(I(), vx), vx2); 261 | 262 | return R; 263 | } 264 | function rotMatFromVec(v){ 265 | v = normalize(v); 266 | let u = [0,0,1]; 267 | let k = sscpm(u); 268 | let c = dot(v,u); 269 | let s = len(cross(v,u)); 270 | 271 | let k2 = matTimesMat(k, k); 272 | 273 | k = matTimesS(k, s); 274 | k2 = matTimesS(k2, (1-c)); 275 | 276 | let R = matPlus(I(), matPlus(k,k2)); 277 | 278 | return R; 279 | } 280 | function rotAxis(p, a, u){ 281 | let m = [ 282 | [cos(a)+u[0]*u[0]*(1-cos(a)), u[0]*u[1]*(1-cos(a))-u[2]*sin(a), u[0]*u[2]*(1-cos(a))+u[1]*sin(a)], 283 | [u[1]*u[0]*(1-cos(a))+u[2]*sin(a), cos(a)+u[1]*u[1]*(1-cos(a)), u[1]*u[2]*(1-cos(a))-u[0]*sin(a)], 284 | [u[2]*u[0]*(1-cos(a))-u[1]*sin(a), u[2]*u[1]*(1-cos(a))+u[0]*sin(a), cos(a)+u[2]*u[2]*(1-cos(a))] 285 | ]; 286 | 287 | return matTimes(m, p); 288 | } 289 | function rotAxisMat(a, u){ 290 | return [ 291 | [cos(a)+u[0]*u[0]*(1-cos(a)), u[0]*u[1]*(1-cos(a))-u[2]*sin(a), u[0]*u[2]*(1-cos(a))+u[1]*sin(a)], 292 | [u[1]*u[0]*(1-cos(a))+u[2]*sin(a), cos(a)+u[1]*u[1]*(1-cos(a)), u[1]*u[2]*(1-cos(a))-u[0]*sin(a)], 293 | [u[2]*u[0]*(1-cos(a))-u[1]*sin(a), u[2]*u[1]*(1-cos(a))+u[0]*sin(a), cos(a)+u[2]*u[2]*(1-cos(a))] 294 | ]; 295 | } 296 | function mod(x, m){ 297 | if(x.length != undefined){ 298 | let temp = []; 299 | for(let i of x){ 300 | temp.push(((i%m)+m)%m); 301 | } 302 | return temp; 303 | } 304 | return ((x%m)+m)%m; 305 | } 306 | function cos(x){ 307 | if(x.length != undefined){ 308 | let temp = []; 309 | for(let i of x){ 310 | temp.push(Math.cos(i)); 311 | } 312 | return temp; 313 | } 314 | return Math.cos(x); 315 | } 316 | function sin(x){ 317 | if(x.length != undefined){ 318 | let temp = []; 319 | for(let i of x){ 320 | temp.push(Math.sin(i)); 321 | } 322 | return temp; 323 | } 324 | return Math.sin(x); 325 | } 326 | function len(v){ 327 | return Math.hypot(...v); 328 | } 329 | function normalize(v){ 330 | if(len(v) == 0){ 331 | return [0,0,0]; 332 | } 333 | return times(v, 1/len(v)); 334 | } 335 | function dot(a, b){ 336 | return a[0]*b[0] + a[1]*b[1] + a[2]*b[2]; 337 | } 338 | function cross(a, b){ 339 | return [ 340 | a[1]*b[2]-a[2]*b[1], 341 | a[2]*b[0]-a[0]*b[2], 342 | a[0]*b[1]-a[1]*b[0] 343 | ]; 344 | } 345 | function reflect(d, n){ 346 | return plus(d, times(n, -2*dot(d,n))); 347 | } 348 | function deNormal(p){ 349 | let eps = 0.01; 350 | eps /= 2; 351 | return normalize([ 352 | de(plus(p, [eps, 0, 0])) - de(plus(p, [-eps, 0, 0])), 353 | de(plus(p, [0, eps, 0])) - de(plus(p, [0, -eps, 0])), 354 | de(plus(p, [0, 0, eps])) - de(plus(p, [0, 0, -eps])) 355 | ]); 356 | } 357 | function lerp(a,b,w){ 358 | if(a.length != undefined){ 359 | let temp = []; 360 | for(let i in a){ 361 | temp.push(a[i] + (b[i]-a[i])*w); 362 | } 363 | return temp; 364 | } 365 | return a+(b-a)*w; 366 | } 367 | 368 | function sinLerp(a,b,w){ 369 | return lerp(a,b, sin(Math.PI*(w-0.5))/2 + 0.5); 370 | } 371 | 372 | function aLerp(a,b,w){ 373 | a %= 2*Math.PI; 374 | b %= 2*Math.PI; 375 | if(abs(b-a) < Math.PI){ 376 | return lerp(a,b,w); 377 | } else { 378 | a += Math.sign(b-a)*2*Math.PI; 379 | return lerp(a,b,w); 380 | } 381 | } 382 | 383 | function sdBox3(p, b){ 384 | let q = plus(abs(p), times(b, -1)); 385 | return len([max(q[0], 0),max(q[1], 0),max(q[2], 0)]) + min(max(q[0],q[1],q[2]), 0); 386 | } 387 | 388 | function dirFromAngle(ax, ay){ 389 | let dir = [0,0,1]; 390 | dir = rotX(dir, -ay); 391 | dir = rotY(dir, ax); 392 | 393 | return dir; 394 | } 395 | 396 | function march(df, p, dir){ 397 | let eps = 0.01; 398 | let range = 10000; 399 | let totDist = 0; 400 | 401 | let dist = df(p); 402 | while(dist > eps && totDist < range){ 403 | p = plus(p, times(dir, dist)); 404 | totDist += dist; 405 | dist = df(p); 406 | } 407 | 408 | if(dist < eps){ 409 | return p; 410 | } else { 411 | return false; 412 | } 413 | } -------------------------------------------------------------------------------- /jackrabbit (mouse and keyboard, 1 player)/libs.js: -------------------------------------------------------------------------------- 1 | let libs = 2 | ` 3 | //ty IQ for most of these 4 | float smin( float a, float b, float k ) 5 | { 6 | //k = 0.; 7 | float h = max( k-abs(a-b), 0.0 )/k; 8 | return min( a, b ) - h*h*k*(1.0/4.0); 9 | } 10 | 11 | vec3 bend(vec3 p, float k) 12 | { 13 | float c = cos(k*p.x); 14 | float s = sin(k*p.x); 15 | mat2 m = mat2(c,-s,s,c); 16 | vec3 q = vec3(m*p.xy,p.z); 17 | return q; 18 | } 19 | vec3 rotAxis(vec3 p, float a, vec3 u){ 20 | mat3 m = mat3( 21 | cos(a) + u.x*u.x*(1.-cos(a)), u.x*u.y*(1.-cos(a))-u.z*sin(a), u.x*u.z*(1.-cos(a)) + u.y*sin(a), 22 | u.y*u.x*(1.-cos(a))+u.z*sin(a), cos(a) + u.y*u.y*(1.-cos(a)), u.y*u.z*(1.-cos(a))-u.x*sin(a), 23 | u.z*u.x*(1.-cos(a))-u.y*sin(a), u.z*u.y*(1.-cos(a))+u.x*sin(a), cos(a) + u.z*u.z*(1.-cos(a)) 24 | ); 25 | 26 | return m*p; 27 | } 28 | vec3 rotY(vec3 v, float a){ 29 | return vec3(v.x*cos(a)+v.z*sin(a),v.y,-v.x*sin(a) + v.z*cos(a)); 30 | } 31 | 32 | vec3 rotX(vec3 v, float a){ 33 | return vec3(v.x, v.y*cos(a)-v.z*sin(a), v.y*sin(a)+v.z*cos(a)); 34 | } 35 | vec3 twist( vec3 p, float k ) 36 | { 37 | float c = cos(k*p.y); 38 | float s = sin(k*p.y); 39 | mat2 m = mat2(c,-s,s,c); 40 | vec3 q = vec3(m*p.xz,p.y); 41 | return q; 42 | } 43 | 44 | vec3 palette( in float t, in vec3 a, in vec3 b, in vec3 c, in vec3 d ) 45 | { 46 | return a + b*cos( 6.28318*(c*t+d) ); 47 | } 48 | float dot2(in vec3 v ) { return dot(v,v); } 49 | 50 | float sdBox( vec3 p, vec3 b ){ 51 | vec3 q = abs(p) - b; 52 | return length(max(q,0.0)) + min(max(q.x,max(q.y,q.z)),0.0); 53 | } 54 | float sdBox( in vec2 p, in vec2 b ){ 55 | vec2 d = abs(p)-b; 56 | return length(max(d,0.0)) + min(max(d.x,d.y),0.0); 57 | } 58 | float sdCapsule( vec3 p, vec3 a, vec3 b, float r ) 59 | { 60 | vec3 pa = p - a, ba = b - a; 61 | float h = clamp( dot(pa,ba)/dot(ba,ba), 0.0, 1.0 ); 62 | return length( pa - ba*h ) - r; 63 | } 64 | float sdTorus( vec3 p, vec2 t ) 65 | { 66 | vec2 q = vec2(length(p.xz)-t.x,p.y); 67 | return length(q)-t.y; 68 | } 69 | float sdRoundCone( vec3 p, vec3 a, vec3 b, float r1, float r2 ) 70 | { 71 | // sampling independent computations (only depend on shape) 72 | vec3 ba = b - a; 73 | float l2 = dot(ba,ba); 74 | float rr = r1 - r2; 75 | float a2 = l2 - rr*rr; 76 | float il2 = 1.0/l2; 77 | 78 | // sampling dependant computations 79 | vec3 pa = p - a; 80 | float y = dot(pa,ba); 81 | float z = y - l2; 82 | float x2 = dot2( pa*l2 - ba*y ); 83 | float y2 = y*y*l2; 84 | float z2 = z*z*l2; 85 | 86 | // single square root! 87 | float k = sign(rr)*rr*rr*x2; 88 | if( sign(z)*a2*z2>k ) return sqrt(x2 + z2) *il2 - r2; 89 | if( sign(y)*a2*y2> 3U)); 139 | return vec3(p ^ (p >> 16U)) * (1.0 / vec3(0xffffffffU)); 140 | } 141 | vec3 stars(in vec3 p) { 142 | vec3 c = vec3(0.); 143 | float resX = 500.; 144 | 145 | for(float i = 0.; i < 5.; i++) { 146 | vec3 q = fract(p * (.15 * resX)) - 0.5; 147 | vec3 id = floor(p * (.15 * resX)); 148 | vec2 rn = nmzHash33(id).xy; 149 | float c2 = 1. - smoothstep(0., .6, length(q)); 150 | c2 *= step(rn.x, .0005 + i * 0.002); 151 | c += c2 * (mix(vec3(1.0, 0.49, 0.1), vec3(0.75, 0.9, 1.), rn.y) * 0.25 + 0.75); 152 | p *= 1.4; 153 | } 154 | return c * c; 155 | } 156 | 157 | `; 158 | 159 | let libsAfterDe = ` 160 | vec3 grad(vec3 p){ 161 | float eps = 0.01; 162 | return normalize(vec3((de(p+vec3(eps, 0., 0.)) - de(p-vec3(eps,0.,0.)))/(2.*eps), (de(p+vec3(0., eps, 0.)) - de(p-vec3(0.,eps,0.)))/(2.*eps), (de(p+vec3(0., 0., eps)) - de(p-vec3(0.,0.,eps)))/(2.*eps))); 163 | } 164 | float light(vec3 p, vec3 l){ 165 | return clamp(dot(grad(p), l), 0., 1.); 166 | } 167 | 168 | float specLight(vec3 p, vec3 l){ 169 | vec3 pos = normalize(p-camPos); 170 | vec3 ray = reflect(l, grad(p)); 171 | return clamp(dot(pos, ray), 0., 1.); 172 | } 173 | 174 | ` 175 | function rotY(v, a){ 176 | return [v[0]*cos(a) + v[2]*sin(a), v[1], -v[0]*sin(a) + v[2]*cos(a)]; 177 | } 178 | function rotX(v, a){ 179 | return [v[0], v[1]*cos(a)-v[2]*sin(a), v[1]*sin(a)+v[2]*cos(a)]; 180 | } 181 | function plus(a1, a2){ 182 | return [a1[0] + a2[0], a1[1] + a2[1], a1[2] + a2[2]]; 183 | } 184 | function times(a, s){ 185 | return [a[0]*s, a[1]*s, a[2]*s]; 186 | } 187 | function min(){ 188 | return Math.min(...arguments); 189 | } 190 | function max(){ 191 | return Math.max(...arguments); 192 | } 193 | function abs(x){ 194 | if(x.length != undefined){ 195 | let temp = []; 196 | for(let i of x){ 197 | temp.push(Math.abs(i)); 198 | } 199 | return temp; 200 | } 201 | return Math.abs(x); 202 | } 203 | function matPlus(a, b){ 204 | let temp = []; 205 | for(let i in a){ 206 | temp[i] = []; 207 | for(let j in a[i]){ 208 | temp[i][j] = a[i][j] + b[i][j]; 209 | } 210 | } 211 | 212 | return temp; 213 | } 214 | function matTimes(m, v){ 215 | return [ 216 | m[0][0]*v[0] + m[0][1]*v[1] + m[0][2]*v[2], 217 | m[1][0]*v[0] + m[1][1]*v[1] + m[1][2]*v[2], 218 | m[2][0]*v[0] + m[2][1]*v[1] + m[2][2]*v[2] 219 | ]; 220 | } 221 | function matTimesMat(a, b){ 222 | let temp = [[],[],[]]; 223 | for(let i in b){ 224 | let col = matTimes(a, [b[0][i], b[1][i], b[2][i]]); 225 | for(let j in col){ 226 | temp[j].push(col[j]); 227 | } 228 | } 229 | return temp; 230 | } 231 | function matTimesS(m, s){ 232 | let temp = []; 233 | for(let i in m){ 234 | temp[i] = []; 235 | for(let j in m[i]){ 236 | temp[i][j] = m[i][j]*s; 237 | } 238 | } 239 | return temp; 240 | } 241 | function I(){ 242 | return [[1,0,0],[0,1,0],[0,0,1]]; 243 | } 244 | //skew-symmetric cross-product matrix of v ?? (don't know what this means) 245 | function sscpm(v){ 246 | return [ 247 | [0, -v[2], v[1]], 248 | [v[2], 0, -v[0]], 249 | [-v[1], v[0], 0] 250 | ] 251 | } 252 | //https://math.stackexchange.com/questions/180418/calculate-rotation-matrix-to-align-vector-a-to-vector-b-in-3d 253 | function rotMatFromTwoVectors(a, b){ 254 | let v = cross(a,b); 255 | let s = len(v); 256 | let c = dot(a,b); 257 | 258 | let vx = sscpm(v); 259 | let vx2 = matTimesS(matTimesMat(vx, vx), (1/(1+c))); 260 | 261 | let R = matPlus(matPlus(I(), vx), vx2); 262 | 263 | return R; 264 | } 265 | function rotMatFromVec(v){ 266 | v = normalize(v); 267 | let u = [0,0,1]; 268 | let k = sscpm(u); 269 | let c = dot(v,u); 270 | let s = len(cross(v,u)); 271 | 272 | let k2 = matTimesMat(k, k); 273 | 274 | k = matTimesS(k, s); 275 | k2 = matTimesS(k2, (1-c)); 276 | 277 | let R = matPlus(I(), matPlus(k,k2)); 278 | 279 | return R; 280 | } 281 | function rotAxis(p, a, u){ 282 | let m = [ 283 | [cos(a)+u[0]*u[0]*(1-cos(a)), u[0]*u[1]*(1-cos(a))-u[2]*sin(a), u[0]*u[2]*(1-cos(a))+u[1]*sin(a)], 284 | [u[1]*u[0]*(1-cos(a))+u[2]*sin(a), cos(a)+u[1]*u[1]*(1-cos(a)), u[1]*u[2]*(1-cos(a))-u[0]*sin(a)], 285 | [u[2]*u[0]*(1-cos(a))-u[1]*sin(a), u[2]*u[1]*(1-cos(a))+u[0]*sin(a), cos(a)+u[2]*u[2]*(1-cos(a))] 286 | ]; 287 | 288 | return matTimes(m, p); 289 | } 290 | function rotAxisMat(a, u){ 291 | return [ 292 | [cos(a)+u[0]*u[0]*(1-cos(a)), u[0]*u[1]*(1-cos(a))-u[2]*sin(a), u[0]*u[2]*(1-cos(a))+u[1]*sin(a)], 293 | [u[1]*u[0]*(1-cos(a))+u[2]*sin(a), cos(a)+u[1]*u[1]*(1-cos(a)), u[1]*u[2]*(1-cos(a))-u[0]*sin(a)], 294 | [u[2]*u[0]*(1-cos(a))-u[1]*sin(a), u[2]*u[1]*(1-cos(a))+u[0]*sin(a), cos(a)+u[2]*u[2]*(1-cos(a))] 295 | ]; 296 | } 297 | function mod(x, m){ 298 | if(x.length != undefined){ 299 | let temp = []; 300 | for(let i of x){ 301 | temp.push(((i%m)+m)%m); 302 | } 303 | return temp; 304 | } 305 | return ((x%m)+m)%m; 306 | } 307 | function cos(x){ 308 | if(x.length != undefined){ 309 | let temp = []; 310 | for(let i of x){ 311 | temp.push(Math.cos(i)); 312 | } 313 | return temp; 314 | } 315 | return Math.cos(x); 316 | } 317 | function sin(x){ 318 | if(x.length != undefined){ 319 | let temp = []; 320 | for(let i of x){ 321 | temp.push(Math.sin(i)); 322 | } 323 | return temp; 324 | } 325 | return Math.sin(x); 326 | } 327 | function len(v){ 328 | return Math.hypot(...v); 329 | } 330 | function normalize(v){ 331 | if(len(v) == 0){ 332 | return [0,0,0]; 333 | } 334 | return times(v, 1/len(v)); 335 | } 336 | function dot(a, b){ 337 | return a[0]*b[0] + a[1]*b[1] + a[2]*b[2]; 338 | } 339 | function cross(a, b){ 340 | return [ 341 | a[1]*b[2]-a[2]*b[1], 342 | a[2]*b[0]-a[0]*b[2], 343 | a[0]*b[1]-a[1]*b[0] 344 | ]; 345 | } 346 | function reflect(d, n){ 347 | return plus(d, times(n, -2*dot(d,n))); 348 | } 349 | function deNormal(p){ 350 | let eps = 0.01; 351 | eps /= 2; 352 | return normalize([ 353 | de(plus(p, [eps, 0, 0])) - de(plus(p, [-eps, 0, 0])), 354 | de(plus(p, [0, eps, 0])) - de(plus(p, [0, -eps, 0])), 355 | de(plus(p, [0, 0, eps])) - de(plus(p, [0, 0, -eps])) 356 | ]); 357 | } 358 | function lerp(a,b,w){ 359 | if(a.length != undefined){ 360 | let temp = []; 361 | for(let i in a){ 362 | temp.push(a[i] + (b[i]-a[i])*w); 363 | } 364 | return temp; 365 | } 366 | return a+(b-a)*w; 367 | } 368 | 369 | function sinLerp(a,b,w){ 370 | return lerp(a,b, sin(Math.PI*(w-0.5))/2 + 0.5); 371 | } 372 | 373 | function aLerp(a,b,w){ 374 | a %= 2*Math.PI; 375 | b %= 2*Math.PI; 376 | if(abs(b-a) < Math.PI){ 377 | return lerp(a,b,w); 378 | } else { 379 | a += Math.sign(b-a)*2*Math.PI; 380 | return lerp(a,b,w); 381 | } 382 | } 383 | 384 | function sdBox3(p, b){ 385 | let q = plus(abs(p), times(b, -1)); 386 | return len([max(q[0], 0),max(q[1], 0),max(q[2], 0)]) + min(max(q[0],q[1],q[2]), 0); 387 | } 388 | 389 | function dirFromAngle(ax, ay){ 390 | let dir = [0,0,1]; 391 | dir = rotX(dir, -ay); 392 | dir = rotY(dir, ax); 393 | 394 | return dir; 395 | } 396 | 397 | function march(df, p, dir){ 398 | let eps = 0.01; 399 | let range = 10000; 400 | let totDist = 0; 401 | 402 | let dist = df(p); 403 | while(dist > eps && totDist < range){ 404 | p = plus(p, times(dir, dist)); 405 | totDist += dist; 406 | dist = df(p); 407 | } 408 | 409 | if(dist < eps){ 410 | return p; 411 | } else { 412 | return false; 413 | } 414 | } -------------------------------------------------------------------------------- /jackrabbit (Controller, 2 player)/player.js: -------------------------------------------------------------------------------- 1 | let mouseDown = []; 2 | let mousePressed = []; 3 | let keyDown = []; 4 | let keyPressed = []; 5 | /* 6 | onmousemove = (e) => { 7 | let sens = [1/900, 1/900]; 8 | player.angle[0] += e.movementX * sens[0]; 9 | player.angle[1] -= e.movementY * sens[1]; 10 | 11 | if(player.angle[1] >= Math.PI/2){ 12 | player.angle[1] = Math.PI/2; 13 | } 14 | if(player.angle[1] <= -Math.PI/2){ 15 | player.angle[1] = -Math.PI/2; 16 | } 17 | } 18 | 19 | onmousedown = (e) => { 20 | mouseDown[e.button] = true; 21 | mousePressed[e.button] = true; 22 | } 23 | 24 | onmouseup = (e) => { 25 | mouseDown[e.button] = false; 26 | } 27 | 28 | onkeydown = (e) => { 29 | keyDown[e.key.toLowerCase()] = true; 30 | keyPressed[e.key.toLowerCase()] = true; 31 | } 32 | 33 | onkeyup = (e) => { 34 | keyDown[e.key.toLowerCase()] = false; 35 | } 36 | */ 37 | let p1LeftStick = [0, 0]; 38 | let p2LeftStick = [0, 0]; 39 | let p1RTrigger = false; 40 | let p1LTrigger = false; 41 | 42 | let p2RTrigger = false; 43 | let p2LTrigger = false; 44 | 45 | function doInputs(){ 46 | let gamepads = navigator.getGamepads(); 47 | 48 | let pads = []; 49 | for(let i of gamepads){ 50 | if(i){ 51 | pads.push(i); 52 | } 53 | } 54 | 55 | let sens = [0.04, 0.04]; 56 | 57 | //player 1 58 | if(Math.hypot(pads[0].axes[2],pads[0].axes[3]) >= .1){ 59 | player.angle[0] += sens[0] * pads[0].axes[2] * dt/(1/70); 60 | player.angle[1] += sens[1] * -pads[0].axes[3] * dt/(1/70); 61 | } 62 | 63 | if(player.angle[1] >= Math.PI/2){ 64 | player.angle[1] = Math.PI/2; 65 | } 66 | if(player.angle[1] <= -Math.PI/2){ 67 | player.angle[1] = -Math.PI/2; 68 | } 69 | 70 | p1LeftStick = [pads[0].axes[0], -pads[0].axes[1]]; 71 | 72 | if(Math.hypot(pads[0].axes[0], pads[0].axes[1]) <= 0.1){ 73 | p1LeftStick = [0,0]; 74 | } 75 | 76 | if(pads[0].buttons[6].value > 0.5){ 77 | p1LTrigger = true; 78 | } else { 79 | p1LTrigger = false; 80 | } 81 | 82 | if(pads[0].buttons[7].value > 0.5){ 83 | p1RTrigger = true; 84 | } else { 85 | p1RTrigger = false; 86 | } 87 | 88 | //player 2 89 | 90 | if(Math.hypot(pads[1].axes[2],pads[1].axes[3]) >= .1){ 91 | player2.angle[0] += sens[0] * pads[1].axes[2] * dt/(1/70); 92 | player2.angle[1] += sens[1] * -pads[1].axes[3] * dt/(1/70); 93 | } 94 | 95 | if(player2.angle[1] >= Math.PI/2){ 96 | player2.angle[1] = Math.PI/2; 97 | } 98 | if(player2.angle[1] <= -Math.PI/2){ 99 | player2.angle[1] = -Math.PI/2; 100 | } 101 | 102 | p2LeftStick = [pads[1].axes[0], -pads[1].axes[1]]; 103 | 104 | if(Math.hypot(pads[1].axes[0], pads[1].axes[1]) <= 0.1){ 105 | p2LeftStick = [0,0]; 106 | } 107 | 108 | if(pads[1].buttons[6].value > 0.5){ 109 | p2LTrigger = true; 110 | } else { 111 | p2LTrigger = false; 112 | } 113 | 114 | if(pads[1].buttons[7].value > 0.5){ 115 | p2RTrigger = true; 116 | } else { 117 | p2RTrigger = false; 118 | } 119 | } 120 | 121 | function Player(id){ 122 | this.id = id; 123 | this.pos = [0,1.5,0]; 124 | 125 | this.camPos = [0,0,0]; 126 | 127 | this.angle = [0,0]; 128 | 129 | this.bodyAngle = [0,0]; 130 | 131 | this.gravity = 50; 132 | this.jumpVel = 15; 133 | this.terminalYVel = 30; 134 | this.speed = 7.5; 135 | 136 | this.velocity = [0,0,0]; 137 | this.jumpSpeed = 50; 138 | this.xFriction = 0.5; 139 | 140 | this.coyoteTime = 0.1; 141 | 142 | this.body2 = 0.5; //radius of body collision 143 | 144 | this.kickState = false; 145 | this.kickPos = undefined; 146 | this.kickPower = 50; //going to make kick more powerful w/ longer hold? idk controls but power should be a control 147 | 148 | 149 | 150 | this.update = () => { 151 | this.kick(); 152 | this.jump(); 153 | this.move(); 154 | 155 | this.legAnimator.update(); 156 | this.updateUniforms(); 157 | } 158 | 159 | this.jump = () => { 160 | if(this.id == 1){ 161 | if(p1LTrigger && this.coyoteTime > 0){ 162 | this.coyoteTime = -1; 163 | let upOffset = [0, 0.5, 0]; 164 | let dir = dirFromAngle(...this.angle); 165 | 166 | dir = normalize(plus(dir, upOffset)); 167 | dir[0] /= 2; 168 | dir[2] /= 2; 169 | this.velocity = times(dir, this.jumpSpeed); 170 | } 171 | } else { 172 | if(p2LTrigger && this.coyoteTime > 0){ 173 | this.coyoteTime = -1; 174 | let upOffset = [0, 0.5, 0]; 175 | let dir = dirFromAngle(...this.angle); 176 | 177 | dir = normalize(plus(dir, upOffset)); 178 | dir[0] /= 2; 179 | dir[2] /= 2; 180 | this.velocity = times(dir, this.jumpSpeed); 181 | } 182 | } 183 | } 184 | 185 | this.kick = () => { 186 | let kickRange = 7; 187 | if(this.id == 1){ 188 | if(p1RTrigger && ball.de(this.pos) < kickRange){ 189 | this.kickState = true; 190 | dt /= 10; 191 | let dir = dirFromAngle(...this.angle); 192 | let p = this.camPos; 193 | let marchRes = march(ball.de, p, dir); 194 | if(marchRes){ 195 | this.kickPos = marchRes; 196 | } else { 197 | this.kickPos = undefined; 198 | } 199 | 200 | } else if(this.kickState){ 201 | this.kickState = false; 202 | if(this.kickPos != undefined){ 203 | let upOffset = [0, -1, 0]; 204 | let kickDir = normalize(plus(ball.pos, times(plus(this.kickPos, upOffset), -1))); 205 | ball.velocity = times(kickDir, this.kickPower); 206 | 207 | ball.rotVel = -Math.hypot(ball.velocity[0], ball.velocity[2])/ball.size; 208 | ball.rotAxis = (cross(normalize([ball.velocity[0], 0, ball.velocity[2]]), [0, 1, 0])); 209 | } 210 | } 211 | } else { 212 | if(p2RTrigger && ball.de(this.pos) < kickRange){ 213 | this.kickState = true; 214 | dt /= 10; 215 | let dir = dirFromAngle(...this.angle); 216 | let p = this.camPos; 217 | let marchRes = march(ball.de, p, dir); 218 | if(marchRes){ 219 | this.kickPos = marchRes; 220 | } else { 221 | this.kickPos = undefined; 222 | } 223 | 224 | } else if(this.kickState){ 225 | this.kickState = false; 226 | if(this.kickPos != undefined){ 227 | let upOffset = [0, -1, 0]; 228 | let kickDir = normalize(plus(ball.pos, times(plus(this.kickPos, upOffset), -1))); 229 | ball.velocity = times(kickDir, this.kickPower); 230 | 231 | ball.rotVel = -Math.hypot(ball.velocity[0], ball.velocity[2])/ball.size; 232 | ball.rotAxis = (cross(normalize([ball.velocity[0], 0, ball.velocity[2]]), [0, 1, 0])); 233 | } 234 | } 235 | } 236 | } 237 | 238 | this.move = () => { 239 | let vel = [0,0,0]; 240 | 241 | if(keyDown["w"]){ 242 | vel[2] += cos(this.angle[0]); 243 | vel[0] += sin(this.angle[0]); 244 | } 245 | if(keyDown["s"]){ 246 | vel[2] -= cos(this.angle[0]); 247 | vel[0] -= sin(this.angle[0]); 248 | } 249 | if(keyDown["a"]){ 250 | vel[2] += sin(this.angle[0]); 251 | vel[0] -= cos(this.angle[0]); 252 | } 253 | if(keyDown["d"]){ 254 | vel[2] -= sin(this.angle[0]); 255 | vel[0] += cos(this.angle[0]); 256 | } 257 | 258 | if(this.id == 1){ 259 | vel = [p1LeftStick[0], 0, p1LeftStick[1]]; 260 | 261 | vel = rotY(vel, this.angle[0]); 262 | } else { 263 | vel = [p2LeftStick[0], 0, p2LeftStick[1]]; 264 | 265 | vel = rotY(vel, this.angle[0]); 266 | } 267 | 268 | if(len(vel) > 0){ 269 | this.bodyAngle[0] = aLerp(this.bodyAngle[0], Math.atan2(vel[0], vel[2]), 0.1 * (dt/(1/120))); 270 | if(this.id == 1){ 271 | renderer.setUni("playerAngle", [this.bodyAngle[0], 0]); 272 | } else { 273 | renderer.setUni("playerAngle2", [this.bodyAngle[0], 0]); 274 | } 275 | } 276 | 277 | if(!this.onGround()){ 278 | if(this.velocity[1] > 10){ 279 | this.legAnimator.setState(2, 0.1); 280 | } else { 281 | this.legAnimator.setState(3, 1); 282 | } 283 | } else { 284 | if(len(vel) > 0){ 285 | this.legAnimator.setState(0, 0.1); 286 | } else { 287 | this.legAnimator.setState(1, 0.2); 288 | } 289 | } 290 | 291 | 292 | if(len(vel) == 0){ 293 | vel = [0, 0, 0]; 294 | } else { 295 | vel = times(vel, this.speed*dt/len(vel)); 296 | } 297 | 298 | this.coyoteTime -= dt; 299 | 300 | if(this.onGround()){ 301 | this.coyoteTime = 0.2; 302 | this.velocity[0] *= 0; 303 | this.velocity[2] *= 0; 304 | } 305 | 306 | if(keyPressed[" "] && this.coyoteTime > 0){ 307 | this.velocity[1] = this.jumpVel; 308 | this.coyoteTime = -1; 309 | } 310 | 311 | this.velocity[1] -= this.gravity*dt; 312 | vel = plus(times(this.velocity, dt), vel); 313 | 314 | this.pos = plus(vel, this.pos); 315 | 316 | while(de(this.pos) < this.body2){ 317 | let norm = deNormal(this.pos); 318 | this.pos = plus(this.pos, times(norm,-(de(this.pos) - this.body2))); 319 | this.velocity = plus(this.velocity, times(norm,-dot(this.velocity, norm))); 320 | } 321 | } 322 | 323 | this.onGround = () => { 324 | return de(plus(this.pos, [0,-this.body2,0])) < 0.1; 325 | } 326 | 327 | this.updateUniforms = () => { 328 | if(this.id == 1){ 329 | renderer.setUni("playerPos", this.pos); 330 | renderer.setUni("camAngle", this.angle); 331 | } else { 332 | renderer.setUni("playerPos2", this.pos); 333 | renderer.setUni("camAngle2", this.angle); 334 | } 335 | 336 | let camDir = [0, 0, -5]; 337 | 338 | camDir = rotX(camDir, -this.angle[1]); 339 | 340 | camDir = rotY(camDir, this.angle[0]); 341 | 342 | let camPos = plus(plus(this.pos, [0,1,0]), camDir); 343 | 344 | let iterations = 1000; 345 | 346 | while(de(camPos) < 0.5 && iterations > 0){ 347 | iterations--; 348 | camPos = plus(camPos, times(camDir, -0.005/5)); 349 | } 350 | if(this.id == 1){ 351 | renderer.setUni("camPos", camPos); 352 | } else { 353 | renderer.setUni("camPos2", camPos); 354 | } 355 | this.camPos = camPos; 356 | } 357 | 358 | this.createAnimators = () => { 359 | let legUnis = []; 360 | if(this.id == 1){ 361 | legUnis = [ 362 | "uhip1", "ujr1", "ujr2", "ujr3", "uhip2", "ujl1", "ujl2", "ujl3", "uHeadPos", "uChestPos", "uBodyAngle" 363 | ]; 364 | } else { 365 | legUnis = [ 366 | "uhip1p2", "ujr1p2", "ujr2p2", "ujr3p2", "uhip2p2", "ujl1p2", "ujl2p2", "ujl3p2", "uHeadPosp2", "uChestPosp2", "uBodyAnglep2" 367 | ]; 368 | } 369 | 370 | let legUniValues = [ 371 | [ 372 | [.1,-.1,-.12], 373 | [0.15, -0.26, 0.05], 374 | [0.13, -0.35, -0.15], 375 | [0.13, -0.46, 0], 376 | 377 | [-.1,-.1,-.12], 378 | [-0.15, -0.26, 0.05], 379 | [-0.13, -0.35, -0.15], 380 | [-0.13, -0.46, 0], 381 | [0,0,0], 382 | [0,0,0], 383 | [0,0,0], 384 | 1.2 385 | ], 386 | 387 | //left leg back 388 | [ 389 | [.1,-.1,-.12], 390 | [0.15, -0.2, 0.15], 391 | [0.13, -0.35, -0.], 392 | [0.13, -0.46, 0.15], 393 | 394 | [-.1,-.1,-.12], 395 | [-0.15, -0.28, -0.05], 396 | [-0.13, -0.3, -0.2], 397 | [-0.13, -0.46, -0.15], 398 | [0,0,0], 399 | [0,0,0], 400 | [0,-0.4,0], 401 | 1.2 402 | ], 403 | 404 | //left leg up 405 | [ 406 | [.1,-.1,-.12], 407 | [0.15, -0.26, 0.05], 408 | [0.13, -0.35, -0.15], 409 | [0.13, -0.46, 0], 410 | 411 | [-.1,-.1,-.12], 412 | [-0.15, -0.18, 0.05], 413 | [-0.13, -0.25, -0.15], 414 | [-0.13, -0.35, 0], 415 | [0,0,0], 416 | [0,0,0], 417 | [0,-0.35,0], 418 | 1.2 419 | ], 420 | 421 | //left leg front 422 | [ 423 | [.1,-.1,-.12], 424 | [0.15, -0.28, -0.05], 425 | [0.13, -0.3, -0.2], 426 | [0.13, -0.46, -0.15], 427 | 428 | [-.1,-.1,-.12], 429 | [-0.15, -0.2, 0.15], 430 | [-0.13, -0.35, -0.], 431 | [-0.13, -0.46, 0.15], 432 | [0,0,0], 433 | [0,0,0], 434 | [0,-0.3,0], 435 | 1.2 436 | ], 437 | 438 | //left leg down 439 | [ 440 | [.1,-.1,-.12], 441 | [0.15, -0.18, 0.05], 442 | [0.13, -0.25, -0.15], 443 | [0.13, -0.35, 0], 444 | 445 | [-.1,-.1,-.12], 446 | [-0.15, -0.26, 0.05], 447 | [-0.13, -0.35, -0.15], 448 | [-0.13, -0.46, 0], 449 | [0,0,0], 450 | [0,0,0], 451 | [0,-0.35,0], 452 | 1.2 453 | ], 454 | //both legs up 1 455 | [ 456 | [.1,-.1,-.12], 457 | [0.15, -0.18, 0.05], 458 | [0.13, -0.25, -0.15], 459 | [0.13, -0.35, 0], 460 | 461 | [-.1,-.1,-.12], 462 | [-0.15, -0.18, 0.05], 463 | [-0.13, -0.25, -0.15], 464 | [-0.13, -0.35, 0], 465 | [0,0,0], 466 | [0,0,0], 467 | [0,-0.2,0], 468 | 1.2 469 | ], 470 | //both legs up 2 471 | [ 472 | [.1,-.1,-.12], 473 | [0.15, -0.13, 0.05], 474 | [0.13, -0.2, -0.15], 475 | [0.13, -0.3, 0], 476 | 477 | [-.1,-.1,-.12], 478 | [-0.15, -0.13, 0.05], 479 | [-0.13, -0.2, -0.15], 480 | [-0.13, -0.3, 0], 481 | [0,0,0], 482 | [0,0,0], 483 | [0,-0.2,0], 484 | 1.2 485 | ] 486 | ]; 487 | 488 | for(let i in legUnis){ 489 | renderer.addUniform(legUnis[i], "vec3", legUniValues[0][i]); 490 | } 491 | if(this.id == 1){ 492 | renderer.addUniform("uLift", "float", 1.2); 493 | this.legAnimator = new Animator([...legUnis, "uLift"], sinLerp); 494 | } else { 495 | renderer.addUniform("uLiftp2", "float", 1.2); 496 | this.legAnimator = new Animator([...legUnis, "uLiftp2"], sinLerp); 497 | } 498 | 499 | //this.legAnimator.addKeyFrame(legUniValues[0], 0); 500 | let stepTime = 0.3; 501 | 502 | this.legAnimator.addKeyFrame(legUniValues[1], 0., 0); 503 | this.legAnimator.addKeyFrame(legUniValues[2], stepTime/4, 0); 504 | this.legAnimator.addKeyFrame(legUniValues[3], 2*stepTime/4, 0); 505 | this.legAnimator.addKeyFrame(legUniValues[4], 3*stepTime/4, 0); 506 | this.legAnimator.addKeyFrame(legUniValues[1], stepTime, 0); 507 | this.legAnimator.addKeyFrame(legUniValues[0], stepTime, 1); 508 | this.legAnimator.addKeyFrame(legUniValues[5], 0., 2); 509 | this.legAnimator.addKeyFrame(legUniValues[6], 0., 3); 510 | //this.legAnimator.setState(0, -1); 511 | 512 | 513 | //this.legAnimator.addKeyFrame(legUniValues[0], 1.2); 514 | } 515 | 516 | this.createAnimators(); 517 | } 518 | 519 | let player = new Player(1); 520 | let player2 = new Player(2); 521 | 522 | player.pos = [0, 5, 15]; 523 | player.angle = [Math.PI, 0]; 524 | player.bodyAngle = [Math.PI, 0]; 525 | 526 | player2.pos = [0, 5, -15]; 527 | player2.angle = [0, 0]; 528 | player2.bodyAngle = [0,0]; 529 | -------------------------------------------------------------------------------- /jackrabbit (mouse and keyboard, 1 player)/graphics.js: -------------------------------------------------------------------------------- 1 | let renderer = new Renderer( 2 | 3 | //de 4 | ` 5 | float rings(vec3 p){ 6 | float rad = 3.; 7 | float inRad = 3.; 8 | float ringThickness = 0.3; 9 | vec3 r1P = p; 10 | r1P = twist(r1P, 0.3); 11 | 12 | float ring1 = sdTorus(r1P, vec2(rad, ringThickness)); 13 | 14 | vec3 r2P = p; 15 | r2P = rotY(r2P, 3.141/3.); 16 | r2P = twist(r2P, 0.3); 17 | 18 | float ring2 = sdTorus(r2P, vec2(rad, ringThickness)); 19 | 20 | vec3 r3P = p; 21 | r3P = rotY(r3P, 3.141*2./3.); 22 | r3P = twist(r3P, 0.3); 23 | 24 | float ring3 = sdTorus(r3P, vec2(rad, ringThickness)); 25 | 26 | ring1 = min(ring1, ring2); 27 | 28 | ring1 = min(ring1, ring3); 29 | 30 | return ring1; 31 | } 32 | 33 | float ball(vec3 p){ 34 | if(length(p-ballPos) > 3.5){ 35 | return sdSphere(p-ballPos, 3.); 36 | } 37 | p -= ballPos; 38 | p = ballRotMat*p; 39 | float rad = 3.; 40 | float inRad = 3.; 41 | 42 | float innerSphere = sdSphere(p, inRad); 43 | 44 | 45 | float rings = rings(p); 46 | 47 | return max(innerSphere, -rings); 48 | } 49 | 50 | float ball2(vec3 p){ 51 | return sdSphere(p-ballPos,3.); 52 | } 53 | 54 | float playerFace(vec3 p2){ 55 | p2 -= uHeadPos; 56 | float head = sdSphere(p2 - vec3(0., 0.4, 0.), 0.2); 57 | float nose = sdSphere(p2 - vec3(0., 0.37, 0.22), 0.1); 58 | float ear1 = min( 59 | sdCapsule(p2, vec3(0.17, 0.45, -0.1), 1.1*vec3(0.15, 0.56, -0.4), 0.03), 60 | sdCapsule(p2, vec3(0.12, 0.5, -0.1), 1.1*vec3(0.15, 0.56, -0.4), 0.03) 61 | ); 62 | float ear2 = min( 63 | sdCapsule(p2, vec3(-0.17, 0.45, -0.1), 1.1*vec3(-0.15, 0.56, -0.4), 0.03), 64 | sdCapsule(p2, vec3(-0.12, 0.5, -0.1), 1.1*vec3(-0.15, 0.56, -0.4), 0.03) 65 | ); 66 | ear1 = min(ear1, ear2); 67 | 68 | float cheek1 = sdCapsule(p2, vec3(0.17, 0.36, -0.), vec3(0.07, 0.32, 0.17), 0.02); 69 | float cheek2 = sdCapsule(p2, vec3(-0.17, 0.36, -0.), vec3(-0.07, 0.32, 0.17), 0.02); 70 | cheek1 = min(cheek1, cheek2); 71 | 72 | float socket1 = sdSphere(p2 - vec3(0.15, 0.45, 0.08), 0.07); 73 | float socket2 = sdSphere(p2 - vec3(-0.15, 0.45, 0.08), 0.07); 74 | socket1 = min(socket1, socket2); 75 | 76 | float noseBone = sdCapsule(p2, vec3(0.035, 0.43, 0.27), vec3(-0.035, 0.43, 0.27), 0.03); 77 | 78 | float d = smin(head, nose, 0.1); 79 | d = smin(d, ear1, 0.1); 80 | 81 | 82 | d = smin(d, cheek1, 0.05); 83 | 84 | d = smin(d, noseBone, 0.05); 85 | 86 | d = max(d, -socket1); 87 | return d; 88 | } 89 | 90 | float playerLegs(vec3 p){ 91 | /*vec3 hip1 = vec3(0.1, -0.1, -0.12); //hip right 92 | vec3 jr1 = vec3(0.15, -0.26, 0.05); //joint right 1, top knee 93 | vec3 jr2 = vec3(0.13, -0.35, -0.15); //joint right 2, ankle joint 94 | vec3 jr3 = vec3(0.13, -0.46, 0.); //joint right 3, foot point 95 | 96 | vec3 hip2 = vec3(-0.1, -0.1, -0.12); //hip right 97 | vec3 jl1 = vec3(-0.15, -0.26, 0.05); //joint right 1, top knee 98 | vec3 jl2 = vec3(-0.13, -0.35, -0.15); //joint right 2, ankle joint 99 | vec3 jl3 = vec3(-0.13, -0.46, 0.); //joint right 3, foot point*/ 100 | 101 | vec3 hip1 = uhip1; //hip right 102 | vec3 jr1 = ujr1; //joint right 1, top knee 103 | vec3 jr2 = ujr2; //joint right 2, ankle joint 104 | vec3 jr3 = ujr3; //joint right 3, foot point 105 | 106 | vec3 hip2 = uhip2; //hip right 107 | vec3 jl1 = ujl1; //joint right 1, top knee 108 | vec3 jl2 = ujl2; //joint right 2, ankle joint 109 | vec3 jl3 = ujl3; //joint right 3, foot point 110 | 111 | float thighGap = 0.05 / 2.; 112 | 113 | float thigh1 = min( 114 | sdCapsule(p-vec3(0., thighGap, 0.), hip1, jr1, 0.015), 115 | sdCapsule(p-vec3(0., -thighGap, 0.), hip1, jr1, 0.015) 116 | ); 117 | float shin1 = sdCapsule(p, jr1, jr2, 0.025); 118 | float ankle1 = sdCapsule(p, jr2, jr3, 0.025); 119 | 120 | float thigh2 = min( 121 | sdCapsule(p-vec3(0., thighGap, 0.), hip2, jl1, 0.015), 122 | sdCapsule(p-vec3(0., -thighGap, 0.), hip2, jl1, 0.015) 123 | ); 124 | float shin2 = sdCapsule(p, jl1, jl2, 0.025); 125 | float ankle2 = sdCapsule(p, jl2, jl3, 0.025); 126 | 127 | thigh1 = min(thigh1, shin1); 128 | thigh1 = min(thigh1, ankle1); 129 | thigh1 = min(thigh1, thigh2); 130 | thigh1 = min(thigh1, shin2); 131 | thigh1 = min(thigh1, ankle2); 132 | 133 | return thigh1; 134 | } 135 | 136 | float playerBody(vec3 p){ 137 | 138 | float rCone = sdRoundCone(p, vec3(0., 0.1, 0.) + uChestPos, vec3(0., -0.1, -0.12), 0.18, 0.1); 139 | float bottom = p.y - (-0.1); 140 | float d = max(rCone, -bottom); 141 | d = rCone; 142 | return d; 143 | } 144 | 145 | float playerEyes(vec3 p){ 146 | p -= uHeadPos; 147 | float eye1 = sdSphere(p - vec3(0.15, 0.45, 0.08), 0.05); 148 | float eye2 = sdSphere(p - vec3(-0.15, 0.45, 0.08), 0.05); 149 | eye1 = min(eye1, eye2); 150 | 151 | return eye1; 152 | } 153 | float playerJacket(vec3 p, float face){ 154 | vec3 jacketCenter = vec3(0., -0.1, 0.); 155 | p -= jacketCenter; 156 | float lift = uLift; 157 | vec3 p2 = bend(p.zyx, lift); 158 | p2 = p2.zyx; 159 | p2 = bend(p2, lift); 160 | vec3 p1 = p2/vec3(1.,12.,1.); 161 | float jacket = sdTorus(p1, vec2(.24, 0.04)); 162 | float cutRad = 1.; 163 | float jacketIntersection = sdSphere(p - cutRad*normalize(vec3(0., -1.,1.)), cutRad); 164 | 165 | jacketIntersection = min( 166 | jacketIntersection, 167 | sdSphere(p-vec3(0., 0.15, 0.2), 0.2) 168 | ); 169 | 170 | jacketIntersection = min( 171 | jacketIntersection, 172 | sdSphere(abs(p)-vec3(2., -0.2, 0.), 1.75) 173 | ); 174 | 175 | jacket = max(jacket, -jacketIntersection); 176 | 177 | jacket = max(jacket, -sdSphere(p - vec3(0., 0.4, 0.) + jacketCenter, 0.2)); 178 | 179 | 180 | 181 | float d = max(jacket, -face); 182 | 183 | return d; 184 | } 185 | 186 | float player(vec3 p){ 187 | vec3 p2 = p-playerPos; 188 | 189 | if(length(p-playerPos) > 1.2){ 190 | return sdSphere(p2, 1.); 191 | } 192 | p2 = rotY(p2, -playerAngle.x); 193 | 194 | vec3 p3 = rotX(p2, uBodyAngle.y); 195 | 196 | float face = playerFace(p3); 197 | float body = playerBody(p3); 198 | float eyes = playerEyes(p3); 199 | float legs = playerLegs(p2); 200 | float jacket = playerJacket(p3, face); 201 | 202 | float d = min(face, body); 203 | d = min(d, eyes); 204 | d = min(d, legs); 205 | d = min(d, jacket); 206 | 207 | return d; 208 | } 209 | 210 | float groundBone(vec3 p){ 211 | float d = p.y; 212 | d = max(d, -sdSphere(p-vec3(0.,10.,0.), 12.5)); 213 | return d; 214 | } 215 | 216 | float ground(vec3 p){ 217 | float base = p.y; 218 | float tiles = groundBone(p); 219 | float d = min(base, tiles); 220 | return base; 221 | } 222 | 223 | float goals(vec3 p){ 224 | vec3 goalSize = vec3(17.5, 20., 10.); 225 | return min(sdBox(p - vec3(0.,0.,50.), goalSize), sdBox(p - vec3(0.,0.,-50.), goalSize)); 226 | } 227 | 228 | float walls(vec3 p){ 229 | float walls = -sdBox(p, vec3(30., 100., 50.)); 230 | float goals = goals(p); 231 | walls = max(walls, -goals); 232 | return walls; 233 | } 234 | 235 | float bloomDe(vec3 p){ 236 | return ball2(p); 237 | } 238 | 239 | float de(vec3 p){ 240 | float d = 100000.; 241 | float floor = ground(p); 242 | float walls = walls(p); 243 | float ball = ball(p); 244 | float player = player(p); 245 | 246 | d = min(floor, walls); 247 | d = min(d, ball); 248 | d = min(d, player); 249 | return d; 250 | } 251 | `, 252 | 253 | 254 | 255 | //color 256 | ` 257 | 258 | vec3 col = vec3(0.,0.,0.); 259 | if(dist <= MIN_DIST){ 260 | vec3 norm = grad(p); 261 | 262 | col = norm; 263 | if(length(p - ballPos) <= 3.005){ 264 | vec3 p2 = p-ballPos; 265 | p2 = ballRotMat*p2; 266 | 267 | 268 | col = vec3(0.,0.2,.2) + vec3(vec3(clamp(dot(normalize(vec3(-0.2, .4, -0.5)), norm), 0., 1.))); 269 | 270 | if(length(p2) > 3.){ 271 | col = vec3(0.1); 272 | } 273 | 274 | float rDist = rings(p2); 275 | if(rDist > 0.){ 276 | col += 1./(1.+10.*rDist); 277 | } 278 | 279 | if(length(p2) < 3.){ 280 | col = vec3(1.); 281 | } 282 | 283 | col += 0.2*vec3(clamp(dot(normalize(vec3(-0.2, .4, -0.5)), norm), 0., 1.)); 284 | } 285 | 286 | if(player(p) < 0.005){ 287 | vec3 p2 = p-playerPos; 288 | p2 = rotY(p2, -playerAngle.x); 289 | vec3 p3 = rotX(p2, uBodyAngle.y); 290 | 291 | col = vec3(abs(norm)); 292 | 293 | if(playerFace(p3) <= 0.005){ 294 | vec3 col1 = 2.*vec3(0.1,0.,0.2); 295 | 296 | vec3 faceNorm = norm + 0.1*noise2Norm(3.*p3); 297 | 298 | col = vec3(0.); 299 | col += col1*clamp(dot(norm, normalize(vec3(1., 1., 1.))), 0., 1.); 300 | col += col1*clamp(dot(norm, normalize(vec3(-.7, .8, -.5))), 0., 1.); 301 | 302 | if(p3.x > 0.){ 303 | col = mix(col, stars(dir)+vec3(0.,0.3,0.3), abs(noise(10.*p3))); 304 | } 305 | 306 | float eyeDist = playerEyes(p3); 307 | 308 | col += (1./(1.+40.*eyeDist)); 309 | } 310 | 311 | if(playerEyes(p3) <= 0.005){ 312 | col = vec3(0.8); 313 | } 314 | 315 | else if(playerBody(p3) <= 0.005){ 316 | float sternumWidth = 0.02; 317 | float ribGap = 0.04; 318 | float ribSize = 0.02; 319 | vec3 bodyNorm = norm; 320 | 321 | col = stars(dir) + noise(2.*dir)*vec3(0.1,0.,0.2); 322 | if(abs(p3.x) < sternumWidth){ 323 | col = vec3(.8); 324 | col = 4.*vec3(0.1,0.,0.2); 325 | col -= (length(p2.x)/(3.*sternumWidth)); 326 | } 327 | float ribNum = mod(p3.y+abs(p3.x)/5., ribGap+ribSize); 328 | if(ribNum < ribSize){ 329 | col = vec3(1.); 330 | col = 4.*vec3(0.1,0.,0.2); 331 | col -= (1.-(ribNum/ribSize)); 332 | } 333 | 334 | 335 | //col *= clamp(dot(norm, normalize(vec3(1.))), 0., 1.); 336 | } 337 | 338 | else if(playerLegs(p2) <= 0.005){ 339 | vec3 col1 = 4. * vec3(0.1, 0., 0.2); 340 | col = vec3(0.); 341 | col += col1*clamp(dot(norm, normalize(vec3(1.))), 0., 1.); 342 | col += col1*clamp(dot(norm, normalize(vec3(-0.7, 0.5, -0.6))), 0., 1.); 343 | } 344 | 345 | else if(playerJacket(p3, playerFace(p3)) <= 0.005){ 346 | vec3 col1 = vec3(0.1, 0.1, 0.2); 347 | vec3 p4 = p3 / vec3(1., 12., 1.); 348 | vec3 jacketNorm = norm + 0.2*noise2Norm(3.*p4); 349 | col = vec3(0.); 350 | col += col1*clamp(dot(norm, normalize(vec3(1.))), 0., 1.); 351 | col += col1*clamp(dot(norm, normalize(vec3(-0.7,0.9,-0.6))), 0., 1.); 352 | if(p3.x > 0. && false){ 353 | col = mix(col, stars(dir)+vec3(0.,0.3,0.3), 1.-abs(noise(4.*p3))); 354 | } 355 | } 356 | 357 | //col += .5*dot(norm, vec3(1., 1., 1.)); 358 | } 359 | 360 | 361 | else if(ground(p) <= 0.002){ 362 | col = vec3(0.1,0.1,0.1); 363 | float noiseGood = noise(p*50.)/8. + noise(p*25.)/4. + noise(p*12.5)/2.; 364 | float pat = pat2(p); 365 | float eps = 0.001/2.; 366 | col += pat*vec3(0.9,1.,1.); 367 | vec3 patNorm = normalize(vec3( 368 | (pat2(p - vec3(eps, 0., 0.)) - pat2(p + vec3(eps, 0., 0.)))/(2.*eps), 369 | 1., 370 | (pat2(p - vec3(0., 0., eps)) - pat2(p + vec3(0., 0., eps)))/(2.*eps) 371 | )); 372 | vec3 patLightDir = normalize(vec3(1.,1.,1.)); 373 | vec3 patLight2Dir = normalize(vec3(-0.7, .2, -0.3)); 374 | 375 | float distNum = (5./(length(p-playerPos + vec3(0., 2., 0.))*length(p-playerPos + vec3(0., 2., 0.)))); 376 | distNum = pow(1.1, -length(p-playerPos + vec3(0., 2., 0.)))/1.1; 377 | 378 | float patLight = clamp(dot(patNorm, patLightDir)*distNum + 0.5*(1.-distNum), 0., 1.); 379 | patLight = clamp(patLight, 0., 1.); 380 | 381 | patLight = clamp(patLight, 0., 1.); 382 | 383 | col = vec3(.1)*(0.6+patLight/2.); 384 | col += pat2(p)/7.; 385 | //col += vec3(0.8,1.,1.) * pat2(p)*abs(sin(t)); 386 | 387 | col += pow(clamp(dot(normalize(p-camPos), reflect(normalize(vec3(0.,15.,0.)-p), patNorm)), 0., 1.), 1.)/4.; 388 | 389 | 390 | if(pat3(p) == 1. && false){ 391 | col = vec3(0.); 392 | col += pow(clamp(dot(normalize(p-camPos), reflect(patLightDir, patNorm)), 0., 1.), 32.); 393 | } 394 | 395 | col += (1./(1.+4.*walls(p))); 396 | col += clamp((.75/(1.+0.5*(ball2(p)*ball2(p)))) * dot(patNorm, normalize(ballPos-p)), 0., 1.); 397 | } 398 | 399 | else if(walls(p) <= 0.005){ 400 | col = vec3(1.,0.,1.) + dot(norm, normalize(vec3(1.))); 401 | 402 | 403 | vec3 dustCol = vec3(0.1, 0., 0.2); 404 | if(dir.z < 0.){ 405 | dustCol = mix(dustCol, vec3(0.2,0.,0.), abs(dir.z)); 406 | } else { 407 | dustCol = mix(dustCol, vec3(0.,0.2,0.2), abs(dir.z)); 408 | } 409 | col = stars(dir) + dustCol*noise(dir*1.5); 410 | 411 | 412 | if(abs(norm.x) > 0.7){ 413 | col += pat2(p.yxz)*(1./(p.y+1.)); 414 | } 415 | if(abs(norm.z) > 0.7){ 416 | col += pat2(p.xzy)*(1./(p.y+1.)); 417 | } 418 | 419 | float goalDist = goals(p); 420 | if(goalDist > 0.){ 421 | goalDist -= noise(p+vec3(t, cos(t), sin(t)))+noise(2.*p+vec3(t, cos(t), sin(t)))/2.; 422 | } 423 | 424 | vec3 goalCol = vec3(0., .8, .8); 425 | if(p.z < 0.){ 426 | goalCol = vec3(.7, 0., 0.); 427 | } 428 | 429 | goalCol += (noise(2.*p+vec3(t, cos(t), sin(t)))+noise(4.*p+vec3(t, cos(t), sin(t)))/2.)/5.; 430 | 431 | if(goalDist < 0.005){ 432 | col = vec3(1.,0.,0.); 433 | col = stars(dir) + dustCol*noise(dir*1.5); 434 | } 435 | if(goalDist > 0.005 && goalDist <= 1.){ 436 | col = goalCol; 437 | } 438 | if(goalDist >= 1. && goalDist <= 1.5){ 439 | col = mix(goalCol, col, (goalDist-1.)/0.5); 440 | } 441 | } 442 | 443 | if(bloomDe(p) > 0.02){ 444 | col += .5/(3.*bloomDist*bloomDist+1.); 445 | } 446 | 447 | /*if(pos.x > sin(t)){ 448 | col = abs(norm); 449 | }*/ 450 | 451 | } else { 452 | color = vec4(0.,0.,0.,1.); 453 | } 454 | 455 | color = vec4(col, 1.); 456 | 457 | color = pow(color, vec4(1.)); 458 | `, 459 | 460 | 461 | 462 | 463 | //functions for color 464 | ` 465 | float pattern(vec2 p, float t, float o){ 466 | p /= 1.5; 467 | 468 | float sum = 0.; 469 | 470 | for(float i = 0.; i < o; i++){ 471 | p = fract(1.5*p)-.5; 472 | float d = sin(10.*length(p) + t); 473 | d = .1/d; 474 | sum += d; 475 | } 476 | 477 | return clamp(sum, 0., 1.); 478 | } 479 | 480 | float pat2(vec3 p){ 481 | float noise1 = noise(p/10.)/2. + noise(p)/2. + noise(p*2.)/4. + noise(p*4.)/4. + noise(p*8.)/4. + noise(p*16.)/4.+noise(p*32.)/8.+noise(p*64.)/16.+noise(p*128.)/32.; 482 | 483 | //return 1.-pattern(p.xz/200., 72./20., 12.-length((playerPos.xz-p.xz))/(140./15.)) + noise(p)/1000.; 484 | //return 1.-pattern(p.xz/200., 72./20., 12.) + noise(p)/1000.; 485 | return pattern(p.xz/200., 45./20., 12.) + noise(2.*p)/200. + noise1/10.; 486 | //return pattern(p.xz/200., t/20., 12.) + noise(p)/1000.; 487 | 488 | } 489 | 490 | float pat3(vec3 p){ 491 | return pattern(p.xz/200., 72./20., 12.); 492 | } 493 | 494 | float noise2(vec3 p){ 495 | return noise(p/10.)/2. + noise(p)/2. + noise(p*2.)/4. + noise(p*4.)/4. + noise(p*8.)/4. + noise(p*16.)/4.+noise(p*32.)/8.+noise(p*64.)/16.+noise(p*128.)/32.; 496 | } 497 | 498 | vec3 noise2Norm(vec3 p){ 499 | float eps = 0.01; 500 | return normalize(vec3( 501 | noise2(p + vec3(eps, 0., 0.)) - noise2(p + vec3(-eps, 0., 0.)), 502 | noise2(p + vec3(0., eps, 0.)) - noise2(p + vec3(0., -eps, 0.)), 503 | noise2(p + vec3(0., 0., eps)) - noise2(p + vec3(0., 0., -eps)) 504 | )); 505 | } 506 | 507 | `, 508 | 509 | //uniforms 510 | ` 511 | uniform vec3 uhip1;// = vec3(0.1, -0.1, -0.12); //hip right 512 | uniform vec3 ujr1;// = vec3(0.15, -0.26, 0.05); //joint right 1, top knee 513 | uniform vec3 ujr2;// = vec3(0.13, -0.35, -0.15); //joint right 2, ankle joint 514 | uniform vec3 ujr3;// = vec3(0.13, -0.46, 0.); //joint right 3, foot point 515 | 516 | uniform vec3 uhip2;// = vec3(-0.1, -0.1, -0.12); //hip right 517 | uniform vec3 ujl1;// = vec3(-0.15, -0.26, 0.05); //joint right 1, top knee 518 | uniform vec3 ujl2;// = vec3(-0.13, -0.35, -0.15); //joint right 2, ankle joint 519 | uniform vec3 ujl3;// = vec3(-0.13, -0.46, 0.); //joint right 3, foot point 520 | 521 | uniform vec3 uChestPos; 522 | uniform vec3 uHeadPos; 523 | uniform float uLift; 524 | uniform vec3 uBodyAngle; 525 | ` 526 | ); 527 | 528 | //vec3 goalSize = vec3(17.5, 20., 10.); 529 | function de(p){ 530 | let d = Infinity; 531 | let floor = p[1]; 532 | let walls = -sdBox3(p, [30, 100, 50]); 533 | let goalSize = [17.5, 20, 10]; 534 | let goals = min( 535 | sdBox3(plus(p, [0, 0, -50]), goalSize), 536 | sdBox3(plus(p, [0, 0, 50]), goalSize) 537 | ); 538 | walls = max(walls, -goals); 539 | 540 | d = min(floor, walls); 541 | 542 | 543 | return d; 544 | } -------------------------------------------------------------------------------- /jackrabbit (Controller, 2 player)/graphics.js: -------------------------------------------------------------------------------- 1 | let renderer = new Renderer( 2 | 3 | //de 4 | ` 5 | float rings(vec3 p){ 6 | float rad = 3.; 7 | float inRad = 3.; 8 | float ringThickness = 0.3; 9 | vec3 r1P = p; 10 | r1P = twist(r1P, 0.3); 11 | 12 | float ring1 = sdTorus(r1P, vec2(rad, ringThickness)); 13 | 14 | vec3 r2P = p; 15 | r2P = rotY(r2P, 3.141/3.); 16 | r2P = twist(r2P, 0.3); 17 | 18 | float ring2 = sdTorus(r2P, vec2(rad, ringThickness)); 19 | 20 | vec3 r3P = p; 21 | r3P = rotY(r3P, 3.141*2./3.); 22 | r3P = twist(r3P, 0.3); 23 | 24 | float ring3 = sdTorus(r3P, vec2(rad, ringThickness)); 25 | 26 | ring1 = min(ring1, ring2); 27 | 28 | ring1 = min(ring1, ring3); 29 | 30 | return ring1; 31 | } 32 | 33 | float ball(vec3 p){ 34 | if(length(p-ballPos) > 3.5){ 35 | return sdSphere(p-ballPos, 3.); 36 | } 37 | p -= ballPos; 38 | p = ballRotMat*p; 39 | float rad = 3.; 40 | float inRad = 3.; 41 | 42 | float innerSphere = sdSphere(p, inRad); 43 | 44 | 45 | float rings = rings(p); 46 | 47 | return max(innerSphere, -rings); 48 | } 49 | 50 | float ball2(vec3 p){ 51 | return sdSphere(p-ballPos,3.); 52 | } 53 | 54 | float playerFace(vec3 p2){ 55 | p2 -= uHeadPos; 56 | float head = sdSphere(p2 - vec3(0., 0.4, 0.), 0.2); 57 | float nose = sdSphere(p2 - vec3(0., 0.37, 0.22), 0.1); 58 | float ear1 = min( 59 | sdCapsule(p2, vec3(0.17, 0.45, -0.1), 1.1*vec3(0.15, 0.56, -0.4), 0.03), 60 | sdCapsule(p2, vec3(0.12, 0.5, -0.1), 1.1*vec3(0.15, 0.56, -0.4), 0.03) 61 | ); 62 | float ear2 = min( 63 | sdCapsule(p2, vec3(-0.17, 0.45, -0.1), 1.1*vec3(-0.15, 0.56, -0.4), 0.03), 64 | sdCapsule(p2, vec3(-0.12, 0.5, -0.1), 1.1*vec3(-0.15, 0.56, -0.4), 0.03) 65 | ); 66 | ear1 = min(ear1, ear2); 67 | 68 | float cheek1 = sdCapsule(p2, vec3(0.17, 0.36, -0.), vec3(0.07, 0.32, 0.17), 0.02); 69 | float cheek2 = sdCapsule(p2, vec3(-0.17, 0.36, -0.), vec3(-0.07, 0.32, 0.17), 0.02); 70 | cheek1 = min(cheek1, cheek2); 71 | 72 | float socket1 = sdSphere(p2 - vec3(0.15, 0.45, 0.08), 0.07); 73 | float socket2 = sdSphere(p2 - vec3(-0.15, 0.45, 0.08), 0.07); 74 | socket1 = min(socket1, socket2); 75 | 76 | float noseBone = sdCapsule(p2, vec3(0.035, 0.43, 0.27), vec3(-0.035, 0.43, 0.27), 0.03); 77 | 78 | float d = smin(head, nose, 0.1); 79 | d = smin(d, ear1, 0.1); 80 | 81 | 82 | d = smin(d, cheek1, 0.05); 83 | 84 | d = smin(d, noseBone, 0.05); 85 | 86 | d = max(d, -socket1); 87 | return d; 88 | } 89 | 90 | float playerLegs(vec3 p){ 91 | /*vec3 hip1 = vec3(0.1, -0.1, -0.12); //hip right 92 | vec3 jr1 = vec3(0.15, -0.26, 0.05); //joint right 1, top knee 93 | vec3 jr2 = vec3(0.13, -0.35, -0.15); //joint right 2, ankle joint 94 | vec3 jr3 = vec3(0.13, -0.46, 0.); //joint right 3, foot point 95 | 96 | vec3 hip2 = vec3(-0.1, -0.1, -0.12); //hip right 97 | vec3 jl1 = vec3(-0.15, -0.26, 0.05); //joint right 1, top knee 98 | vec3 jl2 = vec3(-0.13, -0.35, -0.15); //joint right 2, ankle joint 99 | vec3 jl3 = vec3(-0.13, -0.46, 0.); //joint right 3, foot point*/ 100 | 101 | vec3 hip1 = uhip1; //hip right 102 | vec3 jr1 = ujr1; //joint right 1, top knee 103 | vec3 jr2 = ujr2; //joint right 2, ankle joint 104 | vec3 jr3 = ujr3; //joint right 3, foot point 105 | 106 | vec3 hip2 = uhip2; //hip right 107 | vec3 jl1 = ujl1; //joint right 1, top knee 108 | vec3 jl2 = ujl2; //joint right 2, ankle joint 109 | vec3 jl3 = ujl3; //joint right 3, foot point 110 | 111 | float thighGap = 0.05 / 2.; 112 | 113 | float thigh1 = min( 114 | sdCapsule(p-vec3(0., thighGap, 0.), hip1, jr1, 0.015), 115 | sdCapsule(p-vec3(0., -thighGap, 0.), hip1, jr1, 0.015) 116 | ); 117 | float shin1 = sdCapsule(p, jr1, jr2, 0.025); 118 | float ankle1 = sdCapsule(p, jr2, jr3, 0.025); 119 | 120 | float thigh2 = min( 121 | sdCapsule(p-vec3(0., thighGap, 0.), hip2, jl1, 0.015), 122 | sdCapsule(p-vec3(0., -thighGap, 0.), hip2, jl1, 0.015) 123 | ); 124 | float shin2 = sdCapsule(p, jl1, jl2, 0.025); 125 | float ankle2 = sdCapsule(p, jl2, jl3, 0.025); 126 | 127 | thigh1 = min(thigh1, shin1); 128 | thigh1 = min(thigh1, ankle1); 129 | thigh1 = min(thigh1, thigh2); 130 | thigh1 = min(thigh1, shin2); 131 | thigh1 = min(thigh1, ankle2); 132 | 133 | return thigh1; 134 | } 135 | 136 | float playerBody(vec3 p){ 137 | 138 | float rCone = sdRoundCone(p, vec3(0., 0.1, 0.) + uChestPos, vec3(0., -0.1, -0.12), 0.18, 0.1); 139 | float bottom = p.y - (-0.1); 140 | float d = max(rCone, -bottom); 141 | d = rCone; 142 | return d; 143 | } 144 | 145 | float playerEyes(vec3 p){ 146 | p -= uHeadPos; 147 | float eye1 = sdSphere(p - vec3(0.15, 0.45, 0.08), 0.05); 148 | float eye2 = sdSphere(p - vec3(-0.15, 0.45, 0.08), 0.05); 149 | eye1 = min(eye1, eye2); 150 | 151 | return eye1; 152 | } 153 | float playerJacket(vec3 p, float face){ 154 | vec3 jacketCenter = vec3(0., -0.1, 0.); 155 | p -= jacketCenter; 156 | float lift = uLift; 157 | vec3 p2 = bend(p.zyx, lift); 158 | p2 = p2.zyx; 159 | p2 = bend(p2, lift); 160 | vec3 p1 = p2/vec3(1.,12.,1.); 161 | float jacket = sdTorus(p1, vec2(.24, 0.04)); 162 | float cutRad = 1.; 163 | float jacketIntersection = sdSphere(p - cutRad*normalize(vec3(0., -1.,1.)), cutRad); 164 | 165 | jacketIntersection = min( 166 | jacketIntersection, 167 | sdSphere(p-vec3(0., 0.15, 0.2), 0.2) 168 | ); 169 | 170 | jacketIntersection = min( 171 | jacketIntersection, 172 | sdSphere(abs(p)-vec3(2., -0.2, 0.), 1.75) 173 | ); 174 | 175 | jacket = max(jacket, -jacketIntersection); 176 | 177 | jacket = max(jacket, -sdSphere(p - vec3(0., 0.4, 0.) + jacketCenter, 0.2)); 178 | 179 | 180 | 181 | float d = max(jacket, -face); 182 | 183 | return d; 184 | } 185 | 186 | float player(vec3 p){ 187 | vec3 p2 = p-playerPos; 188 | 189 | if(length(p-playerPos) > 1.2){ 190 | return sdSphere(p2, 1.); 191 | } 192 | p2 = rotY(p2, -playerAngle.x); 193 | 194 | vec3 p3 = rotX(p2, uBodyAngle.y); 195 | 196 | float face = playerFace(p3); 197 | float body = playerBody(p3); 198 | float eyes = playerEyes(p3); 199 | float legs = playerLegs(p2); 200 | float jacket = playerJacket(p3, face); 201 | 202 | float d = min(face, body); 203 | d = min(d, eyes); 204 | d = min(d, legs); 205 | d = min(d, jacket); 206 | 207 | return d; 208 | } 209 | 210 | float playerFace2(vec3 p2){ 211 | p2 -= uHeadPosp2; 212 | float head = sdSphere(p2 - vec3(0., 0.4, 0.), 0.2); 213 | float nose = sdSphere(p2 - vec3(0., 0.37, 0.22), 0.1); 214 | float ear1 = min( 215 | sdCapsule(p2, vec3(0.17, 0.45, -0.1), 1.1*vec3(0.15, 0.56, -0.4), 0.03), 216 | sdCapsule(p2, vec3(0.12, 0.5, -0.1), 1.1*vec3(0.15, 0.56, -0.4), 0.03) 217 | ); 218 | float ear2 = min( 219 | sdCapsule(p2, vec3(-0.17, 0.45, -0.1), 1.1*vec3(-0.15, 0.56, -0.4), 0.03), 220 | sdCapsule(p2, vec3(-0.12, 0.5, -0.1), 1.1*vec3(-0.15, 0.56, -0.4), 0.03) 221 | ); 222 | ear1 = min(ear1, ear2); 223 | 224 | float cheek1 = sdCapsule(p2, vec3(0.17, 0.36, -0.), vec3(0.07, 0.32, 0.17), 0.02); 225 | float cheek2 = sdCapsule(p2, vec3(-0.17, 0.36, -0.), vec3(-0.07, 0.32, 0.17), 0.02); 226 | cheek1 = min(cheek1, cheek2); 227 | 228 | float socket1 = sdSphere(p2 - vec3(0.15, 0.45, 0.08), 0.07); 229 | float socket2 = sdSphere(p2 - vec3(-0.15, 0.45, 0.08), 0.07); 230 | socket1 = min(socket1, socket2); 231 | 232 | float noseBone = sdCapsule(p2, vec3(0.035, 0.43, 0.27), vec3(-0.035, 0.43, 0.27), 0.03); 233 | 234 | float d = smin(head, nose, 0.1); 235 | d = smin(d, ear1, 0.1); 236 | 237 | 238 | d = smin(d, cheek1, 0.05); 239 | 240 | d = smin(d, noseBone, 0.05); 241 | 242 | d = max(d, -socket1); 243 | return d; 244 | } 245 | 246 | float playerLegs2(vec3 p){ 247 | /*vec3 hip1 = vec3(0.1, -0.1, -0.12); //hip right 248 | vec3 jr1 = vec3(0.15, -0.26, 0.05); //joint right 1, top knee 249 | vec3 jr2 = vec3(0.13, -0.35, -0.15); //joint right 2, ankle joint 250 | vec3 jr3 = vec3(0.13, -0.46, 0.); //joint right 3, foot point 251 | 252 | vec3 hip2 = vec3(-0.1, -0.1, -0.12); //hip right 253 | vec3 jl1 = vec3(-0.15, -0.26, 0.05); //joint right 1, top knee 254 | vec3 jl2 = vec3(-0.13, -0.35, -0.15); //joint right 2, ankle joint 255 | vec3 jl3 = vec3(-0.13, -0.46, 0.); //joint right 3, foot point*/ 256 | 257 | vec3 hip1 = uhip1p2; //hip right 258 | vec3 jr1 = ujr1p2; //joint right 1, top knee 259 | vec3 jr2 = ujr2p2; //joint right 2, ankle joint 260 | vec3 jr3 = ujr3p2; //joint right 3, foot point 261 | 262 | vec3 hip2 = uhip2p2; //hip right 263 | vec3 jl1 = ujl1p2; //joint right 1, top knee 264 | vec3 jl2 = ujl2p2; //joint right 2, ankle joint 265 | vec3 jl3 = ujl3p2; //joint right 3, foot point 266 | 267 | float thighGap = 0.05 / 2.; 268 | 269 | float thigh1 = min( 270 | sdCapsule(p-vec3(0., thighGap, 0.), hip1, jr1, 0.015), 271 | sdCapsule(p-vec3(0., -thighGap, 0.), hip1, jr1, 0.015) 272 | ); 273 | float shin1 = sdCapsule(p, jr1, jr2, 0.025); 274 | float ankle1 = sdCapsule(p, jr2, jr3, 0.025); 275 | 276 | float thigh2 = min( 277 | sdCapsule(p-vec3(0., thighGap, 0.), hip2, jl1, 0.015), 278 | sdCapsule(p-vec3(0., -thighGap, 0.), hip2, jl1, 0.015) 279 | ); 280 | float shin2 = sdCapsule(p, jl1, jl2, 0.025); 281 | float ankle2 = sdCapsule(p, jl2, jl3, 0.025); 282 | 283 | thigh1 = min(thigh1, shin1); 284 | thigh1 = min(thigh1, ankle1); 285 | thigh1 = min(thigh1, thigh2); 286 | thigh1 = min(thigh1, shin2); 287 | thigh1 = min(thigh1, ankle2); 288 | 289 | return thigh1; 290 | } 291 | 292 | float playerBody2(vec3 p){ 293 | 294 | float rCone = sdRoundCone(p, vec3(0., 0.1, 0.) + uChestPosp2, vec3(0., -0.1, -0.12), 0.18, 0.1); 295 | float bottom = p.y - (-0.1); 296 | float d = max(rCone, -bottom); 297 | d = rCone; 298 | return d; 299 | } 300 | 301 | float playerEyes2(vec3 p){ 302 | p -= uHeadPosp2; 303 | float eye1 = sdSphere(p - vec3(0.15, 0.45, 0.08), 0.05); 304 | float eye2 = sdSphere(p - vec3(-0.15, 0.45, 0.08), 0.05); 305 | eye1 = min(eye1, eye2); 306 | 307 | return eye1; 308 | } 309 | float playerJacket2(vec3 p, float face){ 310 | vec3 jacketCenter = vec3(0., -0.1, 0.); 311 | p -= jacketCenter; 312 | float lift = uLift; 313 | vec3 p2 = bend(p.zyx, lift); 314 | p2 = p2.zyx; 315 | p2 = bend(p2, lift); 316 | vec3 p1 = p2/vec3(1.,12.,1.); 317 | float jacket = sdTorus(p1, vec2(.24, 0.04)); 318 | float cutRad = 1.; 319 | float jacketIntersection = sdSphere(p - cutRad*normalize(vec3(0., -1.,1.)), cutRad); 320 | 321 | jacketIntersection = min( 322 | jacketIntersection, 323 | sdSphere(p-vec3(0., 0.15, 0.2), 0.2) 324 | ); 325 | 326 | jacketIntersection = min( 327 | jacketIntersection, 328 | sdSphere(abs(p)-vec3(2., -0.2, 0.), 1.75) 329 | ); 330 | 331 | jacket = max(jacket, -jacketIntersection); 332 | 333 | jacket = max(jacket, -sdSphere(p - vec3(0., 0.4, 0.) + jacketCenter, 0.2)); 334 | 335 | 336 | 337 | float d = max(jacket, -face); 338 | 339 | return d; 340 | } 341 | 342 | float player2(vec3 p){ 343 | vec3 p2 = p-playerPos2; 344 | 345 | if(length(p-playerPos2) > 1.2){ 346 | return sdSphere(p2, 1.); 347 | } 348 | p2 = rotY(p2, -playerAngle2.x); 349 | 350 | vec3 p3 = rotX(p2, uBodyAnglep2.y); 351 | 352 | float face = playerFace2(p3); 353 | float body = playerBody2(p3); 354 | float eyes = playerEyes2(p3); 355 | float legs = playerLegs2(p2); 356 | float jacket = playerJacket2(p3, face); 357 | 358 | float d = min(face, body); 359 | d = min(d, eyes); 360 | d = min(d, legs); 361 | d = min(d, jacket); 362 | 363 | return d; 364 | } 365 | 366 | float groundBone(vec3 p){ 367 | float d = p.y; 368 | d = max(d, -sdSphere(p-vec3(0.,10.,0.), 12.5)); 369 | return d; 370 | } 371 | 372 | float ground(vec3 p){ 373 | float base = p.y; 374 | float tiles = groundBone(p); 375 | float d = min(base, tiles); 376 | return base; 377 | } 378 | 379 | float goals(vec3 p){ 380 | vec3 goalSize = vec3(17.5, 20., 10.); 381 | return min(sdBox(p - vec3(0.,0.,50.), goalSize), sdBox(p - vec3(0.,0.,-50.), goalSize)); 382 | } 383 | 384 | float walls(vec3 p){ 385 | float walls = -sdBox(p, vec3(30., 100., 50.)); 386 | float goals = goals(p); 387 | walls = max(walls, -goals); 388 | return walls; 389 | } 390 | 391 | float bloomDe(vec3 p){ 392 | return ball2(p); 393 | } 394 | 395 | float de(vec3 p){ 396 | float d = 100000.; 397 | float floor = ground(p); 398 | float walls = walls(p); 399 | float ball = ball(p); 400 | float player = player(p); 401 | float player2 = player2(p); 402 | 403 | d = min(floor, walls); 404 | d = min(d, ball); 405 | d = min(d, player); 406 | d = min(d, player2); 407 | return d; 408 | } 409 | `, 410 | 411 | 412 | 413 | //color 414 | ` 415 | 416 | vec3 col = vec3(0.,0.,0.); 417 | if(dist <= MIN_DIST){ 418 | vec3 norm = grad(p); 419 | 420 | col = norm; 421 | if(length(p - ballPos) <= 3.005){ 422 | vec3 p2 = p-ballPos; 423 | p2 = ballRotMat*p2; 424 | 425 | 426 | col = vec3(0.,0.2,.2) + vec3(vec3(clamp(dot(normalize(vec3(-0.2, .4, -0.5)), norm), 0., 1.))); 427 | 428 | if(length(p2) > 3.){ 429 | col = vec3(0.1); 430 | } 431 | 432 | float rDist = rings(p2); 433 | if(rDist > 0.){ 434 | col += 1./(1.+10.*rDist); 435 | } 436 | 437 | if(length(p2) < 3.){ 438 | col = vec3(1.); 439 | } 440 | 441 | col += 0.2*vec3(clamp(dot(normalize(vec3(-0.2, .4, -0.5)), norm), 0., 1.)); 442 | } 443 | 444 | if(player(p) < 0.005){ 445 | vec3 p2 = p-playerPos; 446 | p2 = rotY(p2, -playerAngle.x); 447 | vec3 p3 = rotX(p2, uBodyAngle.y); 448 | 449 | col = vec3(abs(norm)); 450 | 451 | if(playerFace(p3) <= 0.005){ 452 | vec3 col1 = 2.*vec3(0.1,0.,0.2); 453 | 454 | vec3 faceNorm = norm + 0.1*noise2Norm(3.*p3); 455 | 456 | col = vec3(0.); 457 | col += col1*clamp(dot(norm, normalize(vec3(1., 1., 1.))), 0., 1.); 458 | col += col1*clamp(dot(norm, normalize(vec3(-.7, .8, -.5))), 0., 1.); 459 | 460 | if(p3.x > 0.){ 461 | col = mix(col, stars(dir)+vec3(0.,0.3,0.3), abs(noise(10.*p3))); 462 | } 463 | 464 | float eyeDist = playerEyes(p3); 465 | 466 | col += (1./(1.+40.*eyeDist)); 467 | } 468 | 469 | if(playerEyes(p3) <= 0.005){ 470 | col = vec3(0.8); 471 | } 472 | 473 | else if(playerBody(p3) <= 0.005){ 474 | float sternumWidth = 0.02; 475 | float ribGap = 0.04; 476 | float ribSize = 0.02; 477 | vec3 bodyNorm = norm; 478 | 479 | col = stars(dir) + noise(2.*dir)*vec3(0.1,0.,0.2); 480 | if(abs(p3.x) < sternumWidth){ 481 | col = vec3(.8); 482 | col = 4.*vec3(0.1,0.,0.2); 483 | col -= (length(p2.x)/(3.*sternumWidth)); 484 | } 485 | float ribNum = mod(p3.y+abs(p3.x)/5., ribGap+ribSize); 486 | if(ribNum < ribSize){ 487 | col = vec3(1.); 488 | col = 4.*vec3(0.1,0.,0.2); 489 | col -= (1.-(ribNum/ribSize)); 490 | } 491 | 492 | 493 | //col *= clamp(dot(norm, normalize(vec3(1.))), 0., 1.); 494 | } 495 | 496 | else if(playerLegs(p2) <= 0.005){ 497 | vec3 col1 = 4. * vec3(0.1, 0., 0.2); 498 | col = vec3(0.); 499 | col += col1*clamp(dot(norm, normalize(vec3(1.))), 0., 1.); 500 | col += col1*clamp(dot(norm, normalize(vec3(-0.7, 0.5, -0.6))), 0., 1.); 501 | } 502 | 503 | else if(playerJacket(p3, playerFace(p3)) <= 0.005){ 504 | vec3 col1 = vec3(0.1, 0.1, 0.2); 505 | vec3 p4 = p3 / vec3(1., 12., 1.); 506 | vec3 jacketNorm = norm + 0.2*noise2Norm(3.*p4); 507 | col = vec3(0.); 508 | col += col1*clamp(dot(norm, normalize(vec3(1.))), 0., 1.); 509 | col += col1*clamp(dot(norm, normalize(vec3(-0.7,0.9,-0.6))), 0., 1.); 510 | if(p3.x > 0. && false){ 511 | col = mix(col, stars(dir)+vec3(0.,0.3,0.3), 1.-abs(noise(4.*p3))); 512 | } 513 | } 514 | 515 | //col += .5*dot(norm, vec3(1., 1., 1.)); 516 | } 517 | else if(player2(p) < 0.005){ 518 | vec3 p2 = p-playerPos2; 519 | p2 = rotY(p2, -playerAngle2.x); 520 | vec3 p3 = rotX(p2, uBodyAnglep2.y); 521 | 522 | col = vec3(abs(norm)); 523 | 524 | if(playerFace2(p3) <= 0.005){ 525 | vec3 col1 = 2.*vec3(0.1,0.,0.1); 526 | 527 | vec3 faceNorm = norm + 0.1*noise2Norm(3.*p3); 528 | 529 | col = vec3(0.); 530 | col += col1*clamp(dot(norm, normalize(vec3(1., 1., 1.))), 0., 1.); 531 | col += col1*clamp(dot(norm, normalize(vec3(-.7, .8, -.5))), 0., 1.); 532 | 533 | if(p3.x > 0.){ 534 | col = mix(col, stars(dir)+vec3(0.3,0.,0.), abs(noise(10.*p3))); 535 | } 536 | 537 | float eyeDist = playerEyes(p3); 538 | 539 | col += (1./(1.+40.*eyeDist)); 540 | } 541 | 542 | if(playerEyes2(p3) <= 0.005){ 543 | col = vec3(0.8); 544 | } 545 | 546 | else if(playerBody2(p3) <= 0.005){ 547 | float sternumWidth = 0.02; 548 | float ribGap = 0.04; 549 | float ribSize = 0.02; 550 | vec3 bodyNorm = norm; 551 | 552 | col = stars(dir) + noise(2.*dir)*vec3(0.1,0.,0.1); 553 | if(abs(p3.x) < sternumWidth){ 554 | col = vec3(.8); 555 | col = 4.*vec3(0.1,0.,0.1); 556 | col -= (length(p2.x)/(3.*sternumWidth)); 557 | } 558 | float ribNum = mod(p3.y+abs(p3.x)/5., ribGap+ribSize); 559 | if(ribNum < ribSize){ 560 | col = vec3(1.); 561 | col = 4.*vec3(0.1,0.,0.1); 562 | col -= (1.-(ribNum/ribSize)); 563 | } 564 | 565 | 566 | //col *= clamp(dot(norm, normalize(vec3(1.))), 0., 1.); 567 | } 568 | 569 | else if(playerLegs2(p2) <= 0.005){ 570 | vec3 col1 = 4. * vec3(0.1, 0., 0.1); 571 | col = vec3(0.); 572 | col += col1*clamp(dot(norm, normalize(vec3(1.))), 0., 1.); 573 | col += col1*clamp(dot(norm, normalize(vec3(-0.7, 0.5, -0.6))), 0., 1.); 574 | } 575 | 576 | else if(playerJacket2(p3, playerFace2(p3)) <= 0.005){ 577 | vec3 col1 = vec3(0.2, 0.1, 0.1); 578 | vec3 p4 = p3 / vec3(1., 12., 1.); 579 | vec3 jacketNorm = norm + 0.2*noise2Norm(3.*p4); 580 | col = vec3(0.); 581 | col += col1*clamp(dot(norm, normalize(vec3(1.))), 0., 1.); 582 | col += col1*clamp(dot(norm, normalize(vec3(-0.7,0.9,-0.6))), 0., 1.); 583 | if(p3.x > 0. && false){ 584 | col = mix(col, stars(dir)+vec3(0.,0.3,0.3), 1.-abs(noise(4.*p3))); 585 | } 586 | } 587 | 588 | //col += .5*dot(norm, vec3(1., 1., 1.)); 589 | } 590 | 591 | else if(ground(p) <= 0.002){ 592 | col = vec3(0.1,0.1,0.1); 593 | float noiseGood = noise(p*50.)/8. + noise(p*25.)/4. + noise(p*12.5)/2.; 594 | float pat = pat2(p); 595 | float eps = 0.001/2.; 596 | col += pat*vec3(0.9,1.,1.); 597 | vec3 patNorm = normalize(vec3( 598 | (pat2(p - vec3(eps, 0., 0.)) - pat2(p + vec3(eps, 0., 0.)))/(2.*eps), 599 | 1., 600 | (pat2(p - vec3(0., 0., eps)) - pat2(p + vec3(0., 0., eps)))/(2.*eps) 601 | )); 602 | vec3 patLightDir = normalize(vec3(1.,1.,1.)); 603 | vec3 patLight2Dir = normalize(vec3(-0.7, .2, -0.3)); 604 | 605 | float distNum = (5./(length(p-playerPos + vec3(0., 2., 0.))*length(p-playerPos + vec3(0., 2., 0.)))); 606 | distNum = pow(1.1, -length(p-playerPos + vec3(0., 2., 0.)))/1.1; 607 | 608 | float patLight = clamp(dot(patNorm, patLightDir)*distNum + 0.5*(1.-distNum), 0., 1.); 609 | patLight = clamp(patLight, 0., 1.); 610 | 611 | patLight = clamp(patLight, 0., 1.); 612 | 613 | col = vec3(.1)*(0.6+patLight/2.); 614 | col += pat2(p)/7.; 615 | //col += vec3(0.8,1.,1.) * pat2(p)*abs(sin(t)); 616 | 617 | col += pow(clamp(dot(normalize(p-camPos), reflect(normalize(vec3(0.,15.,0.)-p), patNorm)), 0., 1.), 1.)/4.; 618 | 619 | 620 | if(pat3(p) == 1. && false){ 621 | col = vec3(0.); 622 | col += pow(clamp(dot(normalize(p-camPos), reflect(patLightDir, patNorm)), 0., 1.), 32.); 623 | } 624 | 625 | col += (1./(1.+4.*walls(p))); 626 | col += clamp((.75/(1.+0.5*(ball2(p)*ball2(p)))) * dot(patNorm, normalize(ballPos-p)), 0., 1.); 627 | } 628 | 629 | else if(walls(p) <= 0.005){ 630 | col = vec3(1.,0.,1.) + dot(norm, normalize(vec3(1.))); 631 | 632 | 633 | vec3 dustCol = vec3(0.1, 0., 0.2); 634 | if(dir.z < 0.){ 635 | dustCol = mix(dustCol, vec3(0.2,0.,0.), abs(dir.z)); 636 | } else { 637 | dustCol = mix(dustCol, vec3(0.,0.2,0.2), abs(dir.z)); 638 | } 639 | col = stars(dir) + dustCol*noise(dir*1.5); 640 | 641 | 642 | if(abs(norm.x) > 0.7){ 643 | col += pat2(p.yxz)*(1./(p.y+1.)); 644 | } 645 | if(abs(norm.z) > 0.7){ 646 | col += pat2(p.xzy)*(1./(p.y+1.)); 647 | } 648 | 649 | float goalDist = goals(p); 650 | if(goalDist > 0.){ 651 | goalDist -= noise(p+vec3(t, cos(t), sin(t)))+noise(2.*p+vec3(t, cos(t), sin(t)))/2.; 652 | } 653 | 654 | vec3 goalCol = vec3(0., .8, .8); 655 | if(p.z < 0.){ 656 | goalCol = vec3(.7, 0., 0.); 657 | } 658 | 659 | goalCol += (noise(2.*p+vec3(t, cos(t), sin(t)))+noise(4.*p+vec3(t, cos(t), sin(t)))/2.)/5.; 660 | 661 | if(goalDist < 0.005){ 662 | col = vec3(1.,0.,0.); 663 | col = stars(dir) + dustCol*noise(dir*1.5); 664 | } 665 | if(goalDist > 0.005 && goalDist <= 1.){ 666 | col = goalCol; 667 | } 668 | if(goalDist >= 1. && goalDist <= 1.5){ 669 | col = mix(goalCol, col, (goalDist-1.)/0.5); 670 | } 671 | } 672 | 673 | if(bloomDe(p) > 0.02){ 674 | col += .5/(3.*bloomDist*bloomDist+1.); 675 | } 676 | 677 | } else { 678 | color = vec4(0.,0.,0.,1.); 679 | } 680 | 681 | color = vec4(col, 1.); 682 | 683 | color = pow(color, vec4(1.)); 684 | `, 685 | 686 | 687 | 688 | 689 | //functions for color 690 | ` 691 | float pattern(vec2 p, float t, float o){ 692 | p /= 1.5; 693 | 694 | float sum = 0.; 695 | 696 | for(float i = 0.; i < o; i++){ 697 | p = fract(1.5*p)-.5; 698 | float d = sin(10.*length(p) + t); 699 | d = .1/d; 700 | sum += d; 701 | } 702 | 703 | return clamp(sum, 0., 1.); 704 | } 705 | 706 | float pat2(vec3 p){ 707 | float noise1 = noise(p/10.)/2. + noise(p)/2. + noise(p*2.)/4. + noise(p*4.)/4. + noise(p*8.)/4. + noise(p*16.)/4.+noise(p*32.)/8.+noise(p*64.)/16.+noise(p*128.)/32.; 708 | 709 | //return 1.-pattern(p.xz/200., 72./20., 12.-length((playerPos.xz-p.xz))/(140./15.)) + noise(p)/1000.; 710 | //return 1.-pattern(p.xz/200., 72./20., 12.) + noise(p)/1000.; 711 | return pattern(p.xz/200., 45./20., 12.) + noise(2.*p)/200. + noise1/10.; 712 | //return pattern(p.xz/200., t/20., 12.) + noise(p)/1000.; 713 | 714 | } 715 | 716 | float pat3(vec3 p){ 717 | return pattern(p.xz/200., 72./20., 12.); 718 | } 719 | 720 | float noise2(vec3 p){ 721 | return noise(p/10.)/2. + noise(p)/2. + noise(p*2.)/4. + noise(p*4.)/4. + noise(p*8.)/4. + noise(p*16.)/4.+noise(p*32.)/8.+noise(p*64.)/16.+noise(p*128.)/32.; 722 | } 723 | 724 | vec3 noise2Norm(vec3 p){ 725 | float eps = 0.01; 726 | return normalize(vec3( 727 | noise2(p + vec3(eps, 0., 0.)) - noise2(p + vec3(-eps, 0., 0.)), 728 | noise2(p + vec3(0., eps, 0.)) - noise2(p + vec3(0., -eps, 0.)), 729 | noise2(p + vec3(0., 0., eps)) - noise2(p + vec3(0., 0., -eps)) 730 | )); 731 | } 732 | 733 | `, 734 | 735 | //uniforms 736 | ` 737 | uniform vec3 uhip1;// = vec3(0.1, -0.1, -0.12); //hip right 738 | uniform vec3 ujr1;// = vec3(0.15, -0.26, 0.05); //joint right 1, top knee 739 | uniform vec3 ujr2;// = vec3(0.13, -0.35, -0.15); //joint right 2, ankle joint 740 | uniform vec3 ujr3;// = vec3(0.13, -0.46, 0.); //joint right 3, foot point 741 | 742 | uniform vec3 uhip2;// = vec3(-0.1, -0.1, -0.12); //hip right 743 | uniform vec3 ujl1;// = vec3(-0.15, -0.26, 0.05); //joint right 1, top knee 744 | uniform vec3 ujl2;// = vec3(-0.13, -0.35, -0.15); //joint right 2, ankle joint 745 | uniform vec3 ujl3;// = vec3(-0.13, -0.46, 0.); //joint right 3, foot point 746 | 747 | uniform vec3 uChestPos; 748 | uniform vec3 uHeadPos; 749 | uniform float uLift; 750 | uniform vec3 uBodyAngle; 751 | 752 | uniform vec3 uhip1p2;// = vec3(0.1, -0.1, -0.12); //hip right 753 | uniform vec3 ujr1p2;// = vec3(0.15, -0.26, 0.05); //joint right 1, top knee 754 | uniform vec3 ujr2p2;// = vec3(0.13, -0.35, -0.15); //joint right 2, ankle joint 755 | uniform vec3 ujr3p2;// = vec3(0.13, -0.46, 0.); //joint right 3, foot point 756 | 757 | uniform vec3 uhip2p2;// = vec3(-0.1, -0.1, -0.12); //hip right 758 | uniform vec3 ujl1p2;// = vec3(-0.15, -0.26, 0.05); //joint right 1, top knee 759 | uniform vec3 ujl2p2;// = vec3(-0.13, -0.35, -0.15); //joint right 2, ankle joint 760 | uniform vec3 ujl3p2;// = vec3(-0.13, -0.46, 0.); //joint right 3, foot point 761 | 762 | uniform vec3 uChestPosp2; 763 | uniform vec3 uHeadPosp2; 764 | uniform float uLiftp2; 765 | uniform vec3 uBodyAnglep2; 766 | ` 767 | ); 768 | 769 | //vec3 goalSize = vec3(17.5, 20., 10.); 770 | function de(p){ 771 | let d = Infinity; 772 | let floor = p[1]; 773 | let walls = -sdBox3(p, [30, 100, 50]); 774 | let goalSize = [17.5, 20, 10]; 775 | let goals = min( 776 | sdBox3(plus(p, [0, 0, -50]), goalSize), 777 | sdBox3(plus(p, [0, 0, 50]), goalSize) 778 | ); 779 | walls = max(walls, -goals); 780 | 781 | d = min(floor, walls); 782 | 783 | 784 | return d; 785 | } --------------------------------------------------------------------------------