├── 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 | }
--------------------------------------------------------------------------------