mirror of
https://github.com/SamEyeBam/animate.git
synced 2026-02-04 09:20:25 +00:00
V1.1
Giant refactor. added layers. ui overhaul. added save/load and we now got presets
This commit is contained in:
37
Tests/webGl/New/index.html
Normal file
37
Tests/webGl/New/index.html
Normal file
@@ -0,0 +1,37 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>WebGL Template</title>
|
||||
<style>
|
||||
/* Set canvas to occupy the full width and height of the window */
|
||||
canvas {
|
||||
display: block;
|
||||
width: 800px;
|
||||
height: 800px;
|
||||
margin: 0 560px;
|
||||
padding: 0;
|
||||
|
||||
}
|
||||
|
||||
.canvas2d {
|
||||
position: absolute !important;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
}
|
||||
body{
|
||||
margin:0
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<canvas id="canvas"></canvas>
|
||||
<canvas id="canvas2d" class="canvas2d"></canvas>
|
||||
<script src="index.js">
|
||||
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
194
Tests/webGl/New/index.js
Normal file
194
Tests/webGl/New/index.js
Normal file
@@ -0,0 +1,194 @@
|
||||
// Get the canvas element and create a WebGL context
|
||||
const canvas = document.getElementById('canvas');
|
||||
const canvas2d = document.getElementById('canvas2d');
|
||||
const gl = canvas.getContext('webgl') || canvas.getContext('experimental-webgl');
|
||||
let ctx = canvas2d.getContext("2d");
|
||||
ctx.canvas.width = 800;
|
||||
ctx.canvas.height = 800;
|
||||
|
||||
// Check if WebGL is available
|
||||
if (!gl) {
|
||||
alert('WebGL not supported in your browser.');
|
||||
} else {
|
||||
// Set the canvas size and WebGL viewport
|
||||
canvas.width = 800;
|
||||
canvas.height = 800;
|
||||
let centerX = ctx.canvas.width / 2;
|
||||
let centerY = ctx.canvas.height / 2;
|
||||
gl.viewport(0, 0, canvas.width, canvas.height);
|
||||
|
||||
// Define the vertex shader source code
|
||||
const glsl = x => x;
|
||||
const vertexShaderSource = glsl`
|
||||
attribute vec2 position;
|
||||
uniform float u_rotation;
|
||||
uniform vec2 u_pos;
|
||||
void main() {
|
||||
float centerX = 0.0;
|
||||
float centerY = 0.0;
|
||||
float xPos = position.x;
|
||||
float yPos = position.y;
|
||||
float x = xPos * cos(u_rotation) - yPos * sin(u_rotation);
|
||||
float y = yPos * cos(u_rotation) + xPos * sin(u_rotation);
|
||||
gl_Position = vec4(x+u_pos.x , y+u_pos.y , 0, 1);
|
||||
}
|
||||
`;
|
||||
|
||||
// Define the fragment shader source code
|
||||
const fragmentShaderSource = `
|
||||
precision mediump float;
|
||||
uniform vec4 fColor;
|
||||
void main() {
|
||||
gl_FragColor = fColor;
|
||||
}
|
||||
`;
|
||||
|
||||
// Create and compile the vertex and fragment shaders
|
||||
const vertexShader = createShader(gl, gl.VERTEX_SHADER, vertexShaderSource);
|
||||
const fragmentShader = createShader(gl, gl.FRAGMENT_SHADER, fragmentShaderSource);
|
||||
|
||||
// Create a program, attach the shaders, and link the program
|
||||
const program = createProgram(gl, vertexShader, fragmentShader);
|
||||
|
||||
// Get the attribute and uniform locations
|
||||
const positionAttributeLocation = gl.getAttribLocation(program, 'position');
|
||||
const positionLocalAttributeLocation = gl.getUniformLocation(program, 'u_pos');
|
||||
const rotationUniformLocation = gl.getUniformLocation(program, 'u_rotation');
|
||||
const fColorLocation = gl.getUniformLocation(program, "fColor");
|
||||
|
||||
// Create a buffer to store vertex positions
|
||||
const positionBuffer = gl.createBuffer();
|
||||
|
||||
function polyPoints(sides) {
|
||||
let pointsArr = [];
|
||||
let width = 1;
|
||||
let rotation = 0
|
||||
pointsArr.push(width * Math.cos((rotation * Math.PI) / 180));
|
||||
pointsArr.push(width * Math.sin((rotation * Math.PI) / 180))
|
||||
for (let i = 0; i < sides; i++) {
|
||||
pointsArr.push(width * Math.cos((i * 2 * Math.PI) / sides + (rotation * Math.PI) / 180))
|
||||
pointsArr.push(width * Math.sin((i * 2 * Math.PI) / sides + (rotation * Math.PI) / 180))
|
||||
}
|
||||
return pointsArr
|
||||
}
|
||||
|
||||
|
||||
function rad(degrees) {
|
||||
var pi = Math.PI;
|
||||
return degrees * (pi / 180);
|
||||
}
|
||||
|
||||
// Function to create and compile a shader
|
||||
function createShader(gl, type, source) {
|
||||
const shader = gl.createShader(type);
|
||||
gl.shaderSource(shader, source);
|
||||
gl.compileShader(shader);
|
||||
if (gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
|
||||
return shader;
|
||||
}
|
||||
console.error(gl.getShaderInfoLog(shader));
|
||||
gl.deleteShader(shader);
|
||||
}
|
||||
|
||||
// Function to create a program and link shaders
|
||||
function createProgram(gl, vertexShader, fragmentShader) {
|
||||
const program = gl.createProgram();
|
||||
gl.attachShader(program, vertexShader);
|
||||
gl.attachShader(program, fragmentShader);
|
||||
gl.linkProgram(program);
|
||||
if (gl.getProgramParameter(program, gl.LINK_STATUS)) {
|
||||
return program;
|
||||
}
|
||||
console.error(gl.getProgramInfoLog(program));
|
||||
gl.deleteProgram(program);
|
||||
}
|
||||
// Function to draw the scene
|
||||
let prevTime = 0
|
||||
function drawScene(time) {
|
||||
// Convert time to seconds
|
||||
// console.log(time - prevTime)
|
||||
prevTime = time
|
||||
time *= 0.001;
|
||||
|
||||
// Clear the canvas with a black background
|
||||
gl.clearColor(0, 0, 0, 1);
|
||||
gl.clear(gl.COLOR_BUFFER_BIT);
|
||||
|
||||
// Use the shader program
|
||||
gl.useProgram(program);
|
||||
|
||||
// Enable the position attribute
|
||||
gl.enableVertexAttribArray(positionAttributeLocation);
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
|
||||
gl.vertexAttribPointer(positionAttributeLocation, 2, gl.FLOAT, false, 0, 0);
|
||||
// Create a buffer to store vertex positions
|
||||
let blue = [0.17, 0.49, 0.85] //blue
|
||||
let green = [0.17, 0.85, 0.46] //green
|
||||
let pink = [0.96, 0.24, 0.86] //green
|
||||
|
||||
render_clear();
|
||||
for (let i = 0; i < 10000; i++) {
|
||||
DrawPolygon(4, 400, (0+time)*i*0.1, "Crimson")
|
||||
// drawPoly(4, time * i * 0.001, blue, 0, 0)
|
||||
}
|
||||
|
||||
Draw_center()
|
||||
drawCircle()
|
||||
// console.log(time)
|
||||
// Request the next frame to be drawn
|
||||
requestAnimationFrame(drawScene);
|
||||
}
|
||||
|
||||
const positions1 = polyPoints(4)
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
|
||||
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions1), gl.STATIC_DRAW);
|
||||
function drawPoly(sides, speed, colour, x, y) {
|
||||
gl.uniform1f(rotationUniformLocation, speed);
|
||||
gl.uniform4f(fColorLocation, colour[0], colour[1], colour[2], 1);
|
||||
gl.uniform2f(positionLocalAttributeLocation, x, y);
|
||||
|
||||
gl.drawArrays(gl.LINE_LOOP, 0, positions1.length / 2);
|
||||
}
|
||||
|
||||
// Start rendering the scene
|
||||
requestAnimationFrame(drawScene);
|
||||
function Draw_center() {
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(centerX - 400, centerY);
|
||||
ctx.lineTo(centerX + 400, centerY);
|
||||
ctx.moveTo(centerX, centerY - 400);
|
||||
ctx.lineTo(centerX, centerY + 400);
|
||||
ctx.strokeStyle = "green";
|
||||
ctx.stroke();
|
||||
// console.log("drawn center")
|
||||
}
|
||||
function drawCircle() {
|
||||
ctx.beginPath();
|
||||
ctx.arc(centerX, centerY, 400, 0, 2 * Math.PI, false);
|
||||
ctx.strokeStyle = "green";
|
||||
ctx.stroke();
|
||||
}
|
||||
function DrawPolygon(sides, width, rotation, colour) {
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(
|
||||
centerX + width * Math.cos((rotation * Math.PI) / 180),
|
||||
centerY + width * Math.sin((rotation * Math.PI) / 180)
|
||||
);
|
||||
|
||||
for (var i = 1; i <= sides; i += 1) {
|
||||
ctx.lineTo(
|
||||
centerX + width * Math.cos((i * 2 * Math.PI) / sides + (rotation * Math.PI) / 180),
|
||||
centerY + width * Math.sin((i * 2 * Math.PI) / sides + (rotation * Math.PI) / 180)
|
||||
);
|
||||
}
|
||||
|
||||
ctx.strokeStyle = colour;
|
||||
ctx.lineWidth = 1;
|
||||
ctx.stroke();
|
||||
}
|
||||
function render_clear() {
|
||||
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
|
||||
ctx.fillStyle = "rgb(0,0,0,0)";
|
||||
ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);
|
||||
}
|
||||
}
|
||||
112
Tests/webGl/circle fractal/css/styles.css
Normal file
112
Tests/webGl/circle fractal/css/styles.css
Normal file
@@ -0,0 +1,112 @@
|
||||
body {
|
||||
-webkit-box-sizing: border-box;
|
||||
/* Safari/Chrome, other WebKit */
|
||||
-moz-box-sizing: border-box;
|
||||
/* Firefox, other Gecko */
|
||||
box-sizing: border-box;
|
||||
/* Opera/IE 8+ */
|
||||
height: 100%
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
canvas {
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
#toolbar {
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
height: 100%;
|
||||
|
||||
position: absolute;
|
||||
padding: 0px 20px 0px 20px;
|
||||
width: 500px;
|
||||
height: 100vh;
|
||||
overflow-y: scroll;
|
||||
background-color: rgb(189, 189, 189);
|
||||
}
|
||||
|
||||
#custom {
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
height: 100%;
|
||||
|
||||
/* position: absolute; */
|
||||
padding: 0px 20px 0px 20px;
|
||||
/* width: 500px; */
|
||||
/* height: 100vh; */
|
||||
background-color: rgb(189, 189, 189);
|
||||
}
|
||||
|
||||
.button {
|
||||
display: block;
|
||||
position: absolute;
|
||||
right: 20px;
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
|
||||
.controls {
|
||||
display: flex;
|
||||
margin: 8px 0px;
|
||||
}
|
||||
|
||||
.controlFrameButton {
|
||||
width: 8%;
|
||||
}
|
||||
.controlPauseButton {
|
||||
width: 80%;
|
||||
margin: auto;
|
||||
}
|
||||
/* <!-- HTML !-->
|
||||
<button class="button-8" role="button">Button 8</button> */
|
||||
|
||||
/* CSS */
|
||||
.button-8 {
|
||||
background-color: #e1ecf4;
|
||||
border-radius: 3px;
|
||||
border: 1px solid #7aa7c7;
|
||||
box-shadow: rgba(255, 255, 255, .7) 0 1px 0 0 inset;
|
||||
box-sizing: border-box;
|
||||
color: #1f3f55;
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
/* font-family: -apple-system,system-ui,"Segoe UI","Liberation Sans",sans-serif; */
|
||||
font-size: 13px;
|
||||
font-weight: 400;
|
||||
line-height: 1.15385;
|
||||
/* margin: 0; */
|
||||
outline: none;
|
||||
padding: 8px .8em;
|
||||
position: relative;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
user-select: none;
|
||||
-webkit-user-select: none;
|
||||
touch-action: manipulation;
|
||||
vertical-align: baseline;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.button-8:hover,
|
||||
.button-8:focus {
|
||||
background-color: #b3d3ea;
|
||||
color: #2c5777;
|
||||
}
|
||||
|
||||
.button-8:focus {
|
||||
box-shadow: 0 0 0 4px rgba(0, 149, 255, .15);
|
||||
}
|
||||
|
||||
.button-8:active {
|
||||
background-color: #a0c7e4;
|
||||
box-shadow: none;
|
||||
color: #2c5777;
|
||||
}
|
||||
|
||||
.buttonReset{
|
||||
background-color: #f4e1e1;
|
||||
}
|
||||
58
Tests/webGl/circle fractal/index.html
Normal file
58
Tests/webGl/circle fractal/index.html
Normal file
@@ -0,0 +1,58 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<!-- ahhh -->
|
||||
|
||||
<head>
|
||||
<title>Document</title>
|
||||
<link rel="stylesheet" href="./css/styles.css">
|
||||
</head>
|
||||
|
||||
<body style="margin:0;">
|
||||
<canvas id="canvas" style="display: block;box-sizing: border-box;"></canvas>
|
||||
<div id="toolbar">
|
||||
<br>
|
||||
<select id="shape-selector">
|
||||
<option value="EyePrototype">EyePrototype</option>
|
||||
<option value="Nodal_expanding">Nodal_expanding</option>
|
||||
<option value="MaryFace">MaryFace</option>
|
||||
<option value="CircleExpand">CircleExpand</option>
|
||||
<option value="PolyTwistColourWidth">PolyTwistColourWidth</option>
|
||||
<option value="FloralPhyllo">FloralPhyllo</option>
|
||||
<option value="FloralPhyllo_Accident">FloralPhyllo_Accident</option>
|
||||
<option value="Spiral1">Spiral1</option>
|
||||
<option value="FloralAccident">FloralAccident</option>
|
||||
<option value="Phyllotaxis">Phyllotaxis</option>
|
||||
<option value="SquareTwist_angle">SquareTwist_angle</option>
|
||||
</select>
|
||||
<div id="custom"></div>
|
||||
<br>
|
||||
<p>Controls:</p>
|
||||
<p>
|
||||
Press "Space" to pause and start the animation
|
||||
</p>
|
||||
<p>
|
||||
Press "P" to show/hide the control panel
|
||||
</p>
|
||||
<br>
|
||||
<p>Speed</p>
|
||||
<input type="text" id="inputDegPerSec" value="10" onchange="ChangeDegPerSec(this.value)">
|
||||
<br>
|
||||
<p>Controls</p>
|
||||
<div class="controls">
|
||||
<button class="controlFrameButton button-8" onclick="BackwardFrame()"><</button>
|
||||
<button class="controlPauseButton button-8" id="pauseButton" onclick="TogglePause()">Play</button>
|
||||
<button class="controlFrameButton button-8" onclick="ForwardFrame()">></button>
|
||||
</div>
|
||||
<button class="buttonReset button-8" id="resetButton" onclick="Reset()">Reset Rotation</button>
|
||||
</div>
|
||||
<div>
|
||||
<button onclick="manualToggleSettings()" class="button">Show/hide</button>
|
||||
</div>
|
||||
</body>
|
||||
<script src="./js/helper.js" type="text/javascript"></script>
|
||||
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
|
||||
<script src="./js/math.js" type="text/javascript"></script>
|
||||
<script src="./js/objects.js" type="text/javascript"></script>
|
||||
<script src="./js/index.js"></script>
|
||||
|
||||
</html>
|
||||
274
Tests/webGl/circle fractal/js/helper.js
Normal file
274
Tests/webGl/circle fractal/js/helper.js
Normal file
@@ -0,0 +1,274 @@
|
||||
async function fetchConfig(className) {
|
||||
// const config = await $.getJSON("config.json");
|
||||
const config = {
|
||||
|
||||
EyePrototype: [
|
||||
{ type: "range", min: -20, max: 20, defaultValue: 0, property: "Val1" },
|
||||
// { type: "color", defaultValue: "#00fffb", property: "colourPupil" },
|
||||
],
|
||||
};
|
||||
return config[className];
|
||||
}
|
||||
|
||||
function addControl(item, instance) {
|
||||
console.log(item);
|
||||
let parentDiv = document.getElementById("custom");
|
||||
|
||||
let title = document.createElement("p");
|
||||
title.innerText = item.property + ": " + item.defaultValue;
|
||||
title.id = "elText" + item.property;
|
||||
|
||||
let control = document.createElement("input");
|
||||
control.type = item.type;
|
||||
|
||||
if (item.type === "range") {
|
||||
control.min = item.min;
|
||||
control.max = item.max;
|
||||
}
|
||||
|
||||
control.value = item.defaultValue;
|
||||
control.className = "control";
|
||||
control.id = "el" + item.property;
|
||||
|
||||
const listener = (event) => {
|
||||
const newValue = event.target.value;
|
||||
instance[item.property] =
|
||||
item.type === "range" ? parseInt(newValue, 10) : newValue;
|
||||
|
||||
title.innerText = item.property + ": " + newValue;
|
||||
};
|
||||
|
||||
control.addEventListener("input", listener);
|
||||
|
||||
parentDiv.appendChild(title);
|
||||
parentDiv.appendChild(control);
|
||||
|
||||
return { element: control, listener };
|
||||
}
|
||||
|
||||
function drawEyelid(width, x1, y1, colour) {
|
||||
x1 -= centerX;
|
||||
y1 -= centerY;
|
||||
|
||||
const angle = Math.atan2(y1, x1);
|
||||
const cosAngle = Math.cos(angle);
|
||||
const sinAngle = Math.sin(angle);
|
||||
|
||||
const x2 = cosAngle * width;
|
||||
const y2 = sinAngle * width;
|
||||
|
||||
const x3Old = width / 2;
|
||||
const y3Old = width / 2;
|
||||
const x4Old = width / 2;
|
||||
const y4Old = -width / 2;
|
||||
|
||||
const x3 = x3Old * cosAngle - y3Old * sinAngle;
|
||||
const y3 = x3Old * sinAngle + y3Old * cosAngle;
|
||||
const x4 = x4Old * cosAngle - y4Old * sinAngle;
|
||||
const y4 = x4Old * sinAngle + y4Old * cosAngle;
|
||||
|
||||
x1 += centerX;
|
||||
y1 += centerY;
|
||||
const x2Final = x2 + x1;
|
||||
const y2Final = y2 + y1;
|
||||
const x3Final = x3 + x1;
|
||||
const y3Final = y3 + y1;
|
||||
const x4Final = x4 + x1;
|
||||
const y4Final = y4 + y1;
|
||||
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(x1, y1);
|
||||
ctx.quadraticCurveTo(x3Final, y3Final, x2Final, y2Final);
|
||||
|
||||
ctx.moveTo(x1, y1);
|
||||
ctx.quadraticCurveTo(x4Final, y4Final, x2Final, y2Final);
|
||||
ctx.fillStyle = colour;
|
||||
ctx.fill();
|
||||
|
||||
ctx.lineWidth = 2;
|
||||
ctx.strokeStyle = "black";
|
||||
ctx.stroke();
|
||||
}
|
||||
|
||||
function drawEyelidAccident(x1, y1) {
|
||||
let leafWidth = 120;
|
||||
let leafHeight = 60;
|
||||
x1 -= centerX;
|
||||
y1 -= centerY;
|
||||
let angle = Math.atan(y1 / x1);
|
||||
// if(angle >=Math.PI){
|
||||
// angle -=Math.PI
|
||||
// console.log("greater called")
|
||||
// }
|
||||
angle = Math.abs(angle);
|
||||
let x2Old = 0 + leafWidth;
|
||||
let y2Old = 0;
|
||||
|
||||
let x3Old = 0 + leafWidth / 2;
|
||||
let y3Old = 0 + leafHeight / 2;
|
||||
|
||||
let x4Old = 0 + leafWidth / 2;
|
||||
let y4Old = 0 - leafHeight / 2;
|
||||
|
||||
let x2 = x2Old * Math.cos(angle) - y2Old * Math.sin(angle);
|
||||
let y2 = x2Old * Math.sin(angle) + y2Old * Math.cos(angle);
|
||||
|
||||
let x3 = x3Old * Math.cos(angle) - y3Old * Math.sin(angle);
|
||||
let y3 = x3Old * Math.sin(angle) + y3Old * Math.cos(angle);
|
||||
|
||||
let x4 = x4Old * Math.cos(angle) - y4Old * Math.sin(angle);
|
||||
let y4 = x4Old * Math.sin(angle) + y4Old * Math.cos(angle);
|
||||
|
||||
let oldx1 = x1;
|
||||
let oldy1 = y1;
|
||||
|
||||
x1 += centerX; // +x2/2
|
||||
y1 += centerY; // +x2/2
|
||||
x2 += x1;
|
||||
y2 += y1;
|
||||
x3 += x1;
|
||||
y3 += y1;
|
||||
x4 += x1;
|
||||
y4 += y1;
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(x1, y1);
|
||||
ctx.quadraticCurveTo(x3, y3, x2, y2);
|
||||
|
||||
ctx.moveTo(x1, y1);
|
||||
ctx.quadraticCurveTo(x4, y4, x2, y2);
|
||||
ctx.fillStyle = "black";
|
||||
ctx.fill();
|
||||
|
||||
ctx.lineWidth = 1;
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(x1, y1);
|
||||
ctx.quadraticCurveTo(x3, y3, x2, y2);
|
||||
|
||||
ctx.moveTo(x1, y1);
|
||||
ctx.quadraticCurveTo(x4, y4, x2, y2);
|
||||
ctx.strokeStyle = "orange";
|
||||
ctx.stroke();
|
||||
}
|
||||
|
||||
function DrawPolygon(sides, width, rotation, colour, line_width) {
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(
|
||||
centerX + width * Math.cos((rotation * Math.PI) / 180),
|
||||
centerY + width * Math.sin((rotation * Math.PI) / 180)
|
||||
);
|
||||
|
||||
for (var i = 1; i <= sides; i += 1) {
|
||||
ctx.lineTo(
|
||||
centerX +
|
||||
width *
|
||||
Math.cos((i * 2 * Math.PI) / sides + (rotation * Math.PI) / 180),
|
||||
centerY +
|
||||
width * Math.sin((i * 2 * Math.PI) / sides + (rotation * Math.PI) / 180)
|
||||
);
|
||||
}
|
||||
ctx.strokeStyle = colour;
|
||||
ctx.lineWidth = line_width;
|
||||
ctx.stroke();
|
||||
}
|
||||
|
||||
function rad(degrees) {
|
||||
return (degrees * Math.PI) / 180;
|
||||
}
|
||||
|
||||
function colourToText(colour) {
|
||||
return "rgb(" + colour[0] + "," + colour[1] + "," + colour[2] + ")";
|
||||
}
|
||||
|
||||
|
||||
function waveNormal(x, max) {
|
||||
let val = Math.sin((x / max) * Math.PI * 2 - max * (Math.PI / (max * 2))) / 2 + 0.5
|
||||
return val
|
||||
}
|
||||
|
||||
function LerpHex(a, b, amount) {
|
||||
var ah = parseInt(a.replace(/#/g, ""), 16),
|
||||
ar = ah >> 16,
|
||||
ag = (ah >> 8) & 0xff,
|
||||
ab = ah & 0xff,
|
||||
bh = parseInt(b.replace(/#/g, ""), 16),
|
||||
br = bh >> 16,
|
||||
bg = (bh >> 8) & 0xff,
|
||||
bb = bh & 0xff,
|
||||
rr = ar + amount * (br - ar),
|
||||
rg = ag + amount * (bg - ag),
|
||||
rb = ab + amount * (bb - ab);
|
||||
|
||||
return (
|
||||
"#" + (((1 << 24) + (rr << 16) + (rg << 8) + rb) | 0).toString(16).slice(1)
|
||||
);
|
||||
}
|
||||
|
||||
function LerpRGB(a, b, t) {
|
||||
if (t < 0) {
|
||||
t *= -1;
|
||||
}
|
||||
var newColor = [0, 0, 0];
|
||||
newColor[0] = a[0] + (b[0] - a[0]) * t;
|
||||
newColor[1] = a[1] + (b[1] - a[1]) * t;
|
||||
newColor[2] = a[2] + (b[2] - a[2]) * t;
|
||||
return newColor;
|
||||
}
|
||||
|
||||
function lerpRGB(a, b, t) {
|
||||
const result = [0, 0, 0];
|
||||
for (let i = 0; i < 3; i++) {
|
||||
result[i] = (1 - t) * a[i] + t * b[i];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
function drawCenter(width) {
|
||||
console.log("center?")
|
||||
ctx.strokeStyle = "pink";
|
||||
ctx.lineWidth = 1
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(centerX - width, centerY);
|
||||
ctx.lineTo(centerX + width, centerY);
|
||||
ctx.closePath();
|
||||
ctx.stroke();
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(centerX, centerY - width);
|
||||
ctx.lineTo(centerX, centerY + width);
|
||||
ctx.closePath();
|
||||
ctx.stroke();
|
||||
}
|
||||
|
||||
function render_clear() {
|
||||
// ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
|
||||
// ctx.fillStyle = "black";
|
||||
// ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);
|
||||
}
|
||||
|
||||
function rotatePointTmp(x, y, centerXX, centerYY, rotation) {
|
||||
let xFromC = x - centerXX;
|
||||
let yFromC = y - centerYY;
|
||||
let d = (xFromC ** 2 + yFromC ** 2) ** 0.5
|
||||
// let orgAngle = Math.atan2(yFromC/xFromC)
|
||||
let orgAngle = Math.atan2(xFromC, yFromC)
|
||||
let tmp = Math.cos(rad(orgAngle - rotation)) * d
|
||||
// console.log(Math.cos((-90)*(Math.PI/180)))
|
||||
console.log(orgAngle)
|
||||
console.log(rad(rotation))
|
||||
console.log(Math.cos(orgAngle - rad(rotation)) * d)
|
||||
console.log(d)
|
||||
// console.log(d)
|
||||
let newPointX = Math.cos(orgAngle - rad(rotation+90)) * d + centerXX;
|
||||
let newPointY = Math.sin(orgAngle - rad(rotation+90)) * d + centerYY;
|
||||
return [newPointX, newPointY]
|
||||
}
|
||||
|
||||
function rotatePoint(x,y,rotation){
|
||||
let nCos = Math.cos(rad(rotation))
|
||||
// console.log(nCos*(180/Math.PI))
|
||||
// console.log(rad(rotation))
|
||||
let nSin = Math.sin(rad(rotation))
|
||||
let newX = x*nCos - y*nSin
|
||||
let newY = y*nCos + x*nSin
|
||||
return [newX,newY]
|
||||
}
|
||||
148
Tests/webGl/circle fractal/js/index.js
Normal file
148
Tests/webGl/circle fractal/js/index.js
Normal file
@@ -0,0 +1,148 @@
|
||||
//jshint esversion:8
|
||||
let c = document.getElementById("canvas");
|
||||
const gl = canvas.getContext('webgl');
|
||||
// canvas.width = 800;
|
||||
// canvas.height = 800;
|
||||
canvas.width = window.innerWidth;
|
||||
canvas.height = window.innerHeight;
|
||||
gl.viewport(0, 0, canvas.width, canvas.height);
|
||||
// let ctx = c.getContext("2d");
|
||||
// ctx.canvas.width = window.innerWidth;
|
||||
// ctx.canvas.height = window.innerHeight;
|
||||
// centerX = ctx.canvas.width / 2;
|
||||
// centerY = ctx.canvas.height / 2;
|
||||
|
||||
window.addEventListener('resize', function () {
|
||||
console.log('addEventListener - resize');
|
||||
canvas.width = window.innerWidth;
|
||||
canvas.height = window.innerHeight;
|
||||
gl.viewport(0, 0, canvas.width, canvas.height);
|
||||
}, true);
|
||||
|
||||
|
||||
let deg_per_sec = 10;
|
||||
let targetFps = 60;
|
||||
let frameDuration = 1000 / targetFps;
|
||||
|
||||
let rotation = 0; //was = j = angle
|
||||
let paused = true;
|
||||
render_clear();
|
||||
|
||||
let drawObj = null;
|
||||
function createInstance(className, args) {
|
||||
const classMap = {
|
||||
|
||||
EyePrototype: EyePrototype,
|
||||
// Add more class constructors here as needed
|
||||
};
|
||||
|
||||
if (classMap.hasOwnProperty(className)) {
|
||||
return new classMap[className](...args);
|
||||
} else {
|
||||
throw new Error(`Unknown class name: ${className}`);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
async function updateDrawObj() {
|
||||
const shapeSelector = document.getElementById("shape-selector");
|
||||
const selectedShape = shapeSelector.value;
|
||||
const config = await fetchConfig(selectedShape);
|
||||
if (drawObj) {
|
||||
drawObj.remove(); // Remove the previous instance
|
||||
}
|
||||
// Extract default values from the configuration
|
||||
const defaultValues = config
|
||||
// .filter((item) => item.type !== "color") // Exclude color inputs
|
||||
.map((item) => item.defaultValue);
|
||||
|
||||
drawObj = createInstance(selectedShape, defaultValues);
|
||||
|
||||
// drawObj = await createShapeWithRandomProperties(813311281, config1);
|
||||
console.log(drawObj)
|
||||
drawObj.initialise(config);
|
||||
}
|
||||
|
||||
updateDrawObj();
|
||||
|
||||
function render() {
|
||||
setTimeout(() => {
|
||||
requestAnimationFrame(() => {
|
||||
render_clear();
|
||||
if (drawObj) {
|
||||
drawObj.draw(rotation);
|
||||
}
|
||||
|
||||
if (!paused) {
|
||||
rotation += deg_per_sec / targetFps;
|
||||
}
|
||||
// drawCenter(300)
|
||||
});
|
||||
render();
|
||||
}, frameDuration);
|
||||
}
|
||||
|
||||
document
|
||||
.getElementById("shape-selector")
|
||||
.addEventListener("change", updateDrawObj);
|
||||
|
||||
let toolbarShowing = true;
|
||||
document.addEventListener("keydown", toggleSettings);
|
||||
|
||||
function manualToggleSettings() {
|
||||
console.log("hi")
|
||||
toolbarShowing = !toolbarShowing;
|
||||
let tb = document.getElementById("toolbar");
|
||||
if (toolbarShowing) {
|
||||
tb.style.display = "flex";
|
||||
} else {
|
||||
tb.style.display = "none";
|
||||
}
|
||||
}
|
||||
|
||||
function toggleSettings(e) {
|
||||
if (e.key == "p") {
|
||||
toolbarShowing = !toolbarShowing;
|
||||
}
|
||||
if (e.code === "Space") {
|
||||
paused = !paused;
|
||||
}
|
||||
|
||||
let tb = document.getElementById("toolbar");
|
||||
if (toolbarShowing) {
|
||||
tb.style.display = "flex";
|
||||
} else {
|
||||
tb.style.display = "none";
|
||||
}
|
||||
}
|
||||
|
||||
function TogglePause() {
|
||||
let pb = document.getElementById("pauseButton");
|
||||
paused = !paused;
|
||||
|
||||
if (paused) {
|
||||
pb.textContent = "Play";
|
||||
} else {
|
||||
pb.textContent = "Pause";
|
||||
}
|
||||
}
|
||||
function Reset() {
|
||||
rotation = 0; //was = j = angle
|
||||
currentFrame = 0;
|
||||
}
|
||||
|
||||
function ForwardFrame() {
|
||||
rotation += deg_per_sec / fps; // was = j = innerRotation, now = rotation
|
||||
currentFrame += 1; // was = i
|
||||
}
|
||||
function BackwardFrame() {
|
||||
rotation -= deg_per_sec / fps; // was = j = innerRotation, now = rotation
|
||||
currentFrame -= 1; // was = i
|
||||
}
|
||||
|
||||
function ChangeDegPerSec(newValue) {
|
||||
deg_per_sec = newValue;
|
||||
}
|
||||
|
||||
window.onload = render;
|
||||
77
Tests/webGl/circle fractal/js/math.js
Normal file
77
Tests/webGl/circle fractal/js/math.js
Normal file
@@ -0,0 +1,77 @@
|
||||
function rotateMatrix2d(p, angle) {
|
||||
// cos0 sin0
|
||||
// -sin0 cos0
|
||||
const angleD = rad(angle);
|
||||
const r = [
|
||||
[Math.cos(angleD), Math.sin(angleD)],
|
||||
[-Math.sin(angleD), Math.cos(angleD)],
|
||||
];
|
||||
const newPoint = [
|
||||
p[0] * r[0][0] + p[1] * r[0][1],
|
||||
p[0] * r[1][0] + p[1] * r[1][1],
|
||||
];
|
||||
return newPoint;
|
||||
}
|
||||
|
||||
function rotateMatrix3dX(p, angle) {
|
||||
// cos0 sin0
|
||||
// -sin0 cos0
|
||||
const angleD = rad(angle);
|
||||
const r = [
|
||||
[1, 0, 0],
|
||||
[0, Math.cos(angleD), -Math.sin(angleD)],
|
||||
[0, Math.sin(angleD), Math.cos(angleD)],
|
||||
];
|
||||
const newPoint = [
|
||||
p[0] * r[0][0] + p[1] * r[0][1] + p[2] * r[0][2],
|
||||
p[0] * r[1][0] + p[1] * r[1][1] + p[2] * r[1][2],
|
||||
p[0] * r[2][0] + p[1] * r[2][1] + p[2] * r[2][2],
|
||||
];
|
||||
return newPoint;
|
||||
}
|
||||
|
||||
function rotateMatrix3dY(p, angle) {
|
||||
// cos0 sin0
|
||||
// -sin0 cos0
|
||||
const angleD = rad(angle);
|
||||
const r = [
|
||||
[Math.cos(angleD), 0, Math.sin(angleD)],
|
||||
[0, 1, 0],
|
||||
[-Math.sin(angleD), 0, Math.cos(angleD)],
|
||||
];
|
||||
const newPoint = [
|
||||
p[0] * r[0][0] + p[1] * r[0][1] + p[2] * r[0][2],
|
||||
p[0] * r[1][0] + p[1] * r[1][1] + p[2] * r[1][2],
|
||||
p[0] * r[2][0] + p[1] * r[2][1] + p[2] * r[2][2],
|
||||
];
|
||||
return newPoint;
|
||||
}
|
||||
function rotateMatrix3dZ(p, angle) {
|
||||
// cos0 sin0
|
||||
// -sin0 cos0
|
||||
const angleD = rad(angle);
|
||||
const r = [
|
||||
[Math.cos(angleD), -Math.sin(angleD), 0],
|
||||
[Math.sin(angleD), Math.cos(angleD), 0],
|
||||
[0, 0, 1],
|
||||
];
|
||||
const newPoint = [
|
||||
p[0] * r[0][0] + p[1] * r[0][1] + p[2] * r[0][2],
|
||||
p[0] * r[1][0] + p[1] * r[1][1] + p[2] * r[1][2],
|
||||
p[0] * r[2][0] + p[1] * r[2][1] + p[2] * r[2][2],
|
||||
];
|
||||
return newPoint;
|
||||
}
|
||||
|
||||
function projectionOrth(v) {
|
||||
const p = [
|
||||
[1, 0, 0],
|
||||
[0, 1, 0],
|
||||
];
|
||||
|
||||
const nPoint = [
|
||||
p[0][0] * v[0] + p[0][1] * v[1] + p[0][2] * v[2],
|
||||
p[1][0] * v[0] + p[1][1] * v[1] + p[1][2] * v[2],
|
||||
];
|
||||
return nPoint;
|
||||
}
|
||||
153
Tests/webGl/circle fractal/js/objects.js
Normal file
153
Tests/webGl/circle fractal/js/objects.js
Normal file
@@ -0,0 +1,153 @@
|
||||
class BaseShape {
|
||||
constructor() {
|
||||
this.controls = []; // Keep track of created elements and event listeners
|
||||
this.speedMultiplier = 100;
|
||||
}
|
||||
|
||||
initialise(config) {
|
||||
for (let item of config) {
|
||||
const { element, listener } = addControl(item, this);
|
||||
this.controls.push({ element, listener });
|
||||
}
|
||||
|
||||
const { element, listener } = addControl({ type: "range", min: 1, max: 500, defaultValue: 100, property: "speedMultiplier", }, this);
|
||||
this.controls.push({ element, listener });
|
||||
}
|
||||
|
||||
remove() {
|
||||
this.controls.forEach(({ element, listener }) => {
|
||||
if (element && listener) {
|
||||
element.removeEventListener("input", listener);
|
||||
}
|
||||
if (element && element.parentElement) {
|
||||
element.parentElement.removeChild(element);
|
||||
const titleElement = document.getElementById("elText" + element.id.slice(2));
|
||||
titleElement.parentElement.removeChild(titleElement);
|
||||
}
|
||||
});
|
||||
this.controls = [];
|
||||
}
|
||||
|
||||
draw() {
|
||||
throw new Error("Draw function not implemented");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class EyePrototype extends BaseShape {
|
||||
constructor(Val1) {
|
||||
super();
|
||||
this.Val1 = Val1;
|
||||
this.iVal1Location = "";
|
||||
this.iResolutionLocation = ""//gl.getUniformLocation(this.program, 'iResolution');
|
||||
this.program = gl.createProgram();
|
||||
}
|
||||
initialise(config) {
|
||||
for (let item of config) {
|
||||
const { element, listener } = addControl(item, this);
|
||||
this.controls.push({ element, listener });
|
||||
}
|
||||
|
||||
const { element, listener } = addControl({ type: "range", min: 1, max: 500, defaultValue: 100, property: "speedMultiplier", }, this);
|
||||
this.controls.push({ element, listener });
|
||||
|
||||
const vertexShaderSource = `
|
||||
attribute vec2 position;
|
||||
void main() {
|
||||
gl_Position = vec4(position, 0.0, 1.0);
|
||||
}
|
||||
`;
|
||||
|
||||
// Create fragment shader using the code you wrote
|
||||
const fragmentShaderSource = `
|
||||
precision mediump float;
|
||||
uniform vec2 iResolution;
|
||||
uniform float iTime;
|
||||
uniform float iVal1;
|
||||
|
||||
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
|
||||
vec2 uv = (fragCoord * 2.0 - iResolution.xy) / iResolution.y;
|
||||
vec2 uv0 = uv;
|
||||
vec3 colour = vec3(1.0, 1.5, 2.0);
|
||||
vec3 colour2 = vec3(0.2, 0.2, 1.0);
|
||||
float pi = 3.1415926;
|
||||
float val1Div = iVal1/10.0;
|
||||
|
||||
|
||||
for (float i = 0.0; i < 2.0; i++) {
|
||||
uv = fract(uv * val1Div) - 0.5;
|
||||
float distance = length(uv);
|
||||
|
||||
distance = sin(distance * pi * 5.0 - iTime) / (pi * 5.0);
|
||||
distance = abs(distance);
|
||||
distance = 0.02 / distance;
|
||||
|
||||
colour = mix(colour, colour2, length(uv));
|
||||
|
||||
colour *= distance;
|
||||
}
|
||||
|
||||
float distance = length(uv0);
|
||||
distance = sin(distance * pi * 5.0 - iTime) / (pi * 5.0);
|
||||
distance = abs(distance);
|
||||
distance = 0.02 / distance;
|
||||
|
||||
colour = mix(colour, colour2, length(uv0));
|
||||
colour *= distance;
|
||||
|
||||
fragColor = vec4(colour, 1.0);
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec2 fragCoord = gl_FragCoord.xy;
|
||||
vec2 iResolution = vec2(${canvas.width.toFixed(1)}, ${canvas.height.toFixed(1)});
|
||||
|
||||
float iTime = ${performance.now().toFixed(3)} / 1000.0;
|
||||
vec4 fragColor;
|
||||
mainImage(fragColor, fragCoord);
|
||||
gl_FragColor = fragColor;
|
||||
}
|
||||
`;
|
||||
|
||||
// Compile and link shaders
|
||||
const vertexShader = gl.createShader(gl.VERTEX_SHADER);
|
||||
gl.shaderSource(vertexShader, vertexShaderSource);
|
||||
gl.compileShader(vertexShader);
|
||||
|
||||
const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
|
||||
gl.shaderSource(fragmentShader, fragmentShaderSource);
|
||||
gl.compileShader(fragmentShader);
|
||||
|
||||
// const this.program = gl.createProgram();
|
||||
gl.attachShader(this.program, vertexShader);
|
||||
gl.attachShader(this.program, fragmentShader);
|
||||
gl.linkProgram(this.program);
|
||||
gl.useProgram(this.program);
|
||||
|
||||
// Create vertex buffer
|
||||
const positionBuffer = gl.createBuffer();
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
|
||||
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1, -1, 1, -1, -1, 1, 1, 1]), gl.STATIC_DRAW);
|
||||
const positionAttributeLocation = gl.getAttribLocation(this.program, 'position');
|
||||
gl.enableVertexAttribArray(positionAttributeLocation);
|
||||
gl.vertexAttribPointer(positionAttributeLocation, 2, gl.FLOAT, false, 0, 0);
|
||||
|
||||
// Set uniforms
|
||||
this.iResolutionLocation = gl.getUniformLocation(this.program, 'iResolution');
|
||||
this.iVal1Location = gl.getUniformLocation(this.program, 'iVal1');
|
||||
|
||||
}
|
||||
|
||||
draw(rotation) {
|
||||
|
||||
gl.uniform2f(this.iResolutionLocation, canvas.width, canvas.height);
|
||||
gl.uniform1f(gl.getUniformLocation(this.program, 'iTime'), performance.now() / 1000.0);
|
||||
gl.uniform1f(this.iVal1Location, this.Val1);
|
||||
|
||||
|
||||
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
|
||||
// requestAnimationFrame(render);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
21
Tests/webGl/first test/index.html
Normal file
21
Tests/webGl/first test/index.html
Normal file
@@ -0,0 +1,21 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>WebGL Centered Square</title>
|
||||
<style>
|
||||
body {
|
||||
margin: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
canvas {
|
||||
display: block;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<canvas id="canvas"></canvas>
|
||||
<script src="main.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
98
Tests/webGl/first test/main.js
Normal file
98
Tests/webGl/first test/main.js
Normal file
@@ -0,0 +1,98 @@
|
||||
const canvas = document.getElementById('canvas');
|
||||
const gl = canvas.getContext('webgl');
|
||||
|
||||
if (!gl) {
|
||||
alert('WebGL is not supported in your browser.');
|
||||
}
|
||||
|
||||
function resizeCanvas() {
|
||||
canvas.width = window.innerWidth;
|
||||
canvas.height = window.innerHeight;
|
||||
gl.viewport(0, 0, canvas.width, canvas.height);
|
||||
}
|
||||
|
||||
window.addEventListener('resize', resizeCanvas);
|
||||
resizeCanvas();
|
||||
|
||||
const vertices = [
|
||||
-0.5, -0.5,
|
||||
0.5, -0.5,
|
||||
0.5, 0.5,
|
||||
-0.5, 0.5,
|
||||
];
|
||||
|
||||
const vertexBuffer = gl.createBuffer();
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
|
||||
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
|
||||
|
||||
const vertexShaderSource = `
|
||||
attribute vec2 a_position;
|
||||
|
||||
uniform vec2 u_resolution;
|
||||
uniform vec2 u_translation;
|
||||
uniform vec2 u_scale;
|
||||
|
||||
void main() {
|
||||
vec2 scaledPosition = a_position * u_scale;
|
||||
vec2 position = scaledPosition + u_translation;
|
||||
|
||||
vec2 zeroToOne = position / u_resolution;
|
||||
vec2 zeroToTwo = zeroToOne * 2.0;
|
||||
vec2 clipSpace = zeroToTwo - 1.0;
|
||||
|
||||
gl_Position = vec4(clipSpace * vec2(1, -1), 0, 1);
|
||||
}
|
||||
`;
|
||||
|
||||
const vertexShader = gl.createShader(gl.VERTEX_SHADER);
|
||||
gl.shaderSource(vertexShader, vertexShaderSource);
|
||||
gl.compileShader(vertexShader);
|
||||
|
||||
const fragmentShaderSource = `
|
||||
precision mediump float;
|
||||
|
||||
void main() {
|
||||
gl_FragColor = vec4(1, 0, 0, 1);
|
||||
}
|
||||
`;
|
||||
|
||||
const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
|
||||
gl.shaderSource(fragmentShader, fragmentShaderSource);
|
||||
gl.compileShader(fragmentShader);
|
||||
|
||||
const program = gl.createProgram();
|
||||
gl.attachShader(program, vertexShader);
|
||||
gl.attachShader(program, fragmentShader);
|
||||
gl.linkProgram(program);
|
||||
gl.useProgram(program);
|
||||
|
||||
const positionAttributeLocation = gl.getAttribLocation(program, 'a_position');
|
||||
gl.enableVertexAttribArray(positionAttributeLocation);
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
|
||||
gl.vertexAttribPointer(positionAttributeLocation, 2, gl.FLOAT, false, 0, 0);
|
||||
|
||||
const resolutionUniformLocation = gl.getUniformLocation(program, 'u_resolution');
|
||||
const translationUniformLocation = gl.getUniformLocation(program, 'u_translation');
|
||||
const scaleUniformLocation = gl.getUniformLocation(program, 'u_scale');
|
||||
|
||||
function drawScene() {
|
||||
gl.clearColor(0, 0, 0, 1);
|
||||
gl.clear(gl.COLOR_BUFFER_BIT);
|
||||
|
||||
gl.uniform2f(resolutionUniformLocation, canvas.width, canvas.height);
|
||||
|
||||
const squareWidth = 50;
|
||||
const squareHeight = 50;
|
||||
const xCenter = (canvas.width - squareWidth) / 2;
|
||||
const yCenter = (canvas.height - squareHeight) / 2;
|
||||
gl.uniform2f(translationUniformLocation, xCenter, yCenter);
|
||||
|
||||
gl.uniform2f(scaleUniformLocation, squareWidth, squareHeight);
|
||||
|
||||
gl.drawArrays(gl.TRIANGLE_FAN, 0, 4);
|
||||
|
||||
requestAnimationFrame(drawScene);
|
||||
}
|
||||
|
||||
drawScene();
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Tests/webGl/my-threejs-test/.parcel-cache/data.mdb
Normal file
BIN
Tests/webGl/my-threejs-test/.parcel-cache/data.mdb
Normal file
Binary file not shown.
BIN
Tests/webGl/my-threejs-test/.parcel-cache/lock.mdb
Normal file
BIN
Tests/webGl/my-threejs-test/.parcel-cache/lock.mdb
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
32322
Tests/webGl/my-threejs-test/dist/index.975ef6c8.js
vendored
Normal file
32322
Tests/webGl/my-threejs-test/dist/index.975ef6c8.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
Tests/webGl/my-threejs-test/dist/index.975ef6c8.js.map
vendored
Normal file
1
Tests/webGl/my-threejs-test/dist/index.975ef6c8.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
22
Tests/webGl/my-threejs-test/dist/index.html
vendored
Normal file
22
Tests/webGl/my-threejs-test/dist/index.html
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Phyllotaxis Animation with Three.js and ShaderMaterial</title>
|
||||
<style>body {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
canvas {
|
||||
display: block;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script> -->
|
||||
<script src="/index.975ef6c8.js" defer=""></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
23
Tests/webGl/my-threejs-test/index.html
Normal file
23
Tests/webGl/my-threejs-test/index.html
Normal file
@@ -0,0 +1,23 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Phyllotaxis Animation with Three.js and ShaderMaterial</title>
|
||||
<style>
|
||||
body {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
canvas {
|
||||
display: block;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script> -->
|
||||
<script src="./src/index.js" type="module"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
3714
Tests/webGl/my-threejs-test/package-lock.json
generated
Normal file
3714
Tests/webGl/my-threejs-test/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
21
Tests/webGl/my-threejs-test/package.json
Normal file
21
Tests/webGl/my-threejs-test/package.json
Normal file
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"name": "my-threejs-test",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"start": "parcel index.html",
|
||||
"build": "parcel build index.html"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"devDependencies": {
|
||||
"parcel": "^2.12.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@parcel/transformer-glsl": "^2.12.0",
|
||||
"postprocessing": "^6.35.3",
|
||||
"three": "^0.163.0"
|
||||
}
|
||||
}
|
||||
19
Tests/webGl/my-threejs-test/shaders/fragment.glsl
Normal file
19
Tests/webGl/my-threejs-test/shaders/fragment.glsl
Normal file
@@ -0,0 +1,19 @@
|
||||
varying vec3 vColor;
|
||||
|
||||
void main() {
|
||||
float distance = length(gl_PointCoord - vec2(0.5, 0.5));
|
||||
float radius = 0.5; // The radius of the circle, where 0.5 is the edge of the point sprite
|
||||
float intensity = 0.5; // Gaussian for smooth intensity increase
|
||||
// float intensity = exp(-pow(distance * 3.0, 2.0)); // Gaussian for smooth intensity increase
|
||||
|
||||
// If the distance is greater than the radius, discard the fragment (make it transparent)
|
||||
if (distance > radius) {
|
||||
discard;
|
||||
}
|
||||
|
||||
// Use the intensity to modulate the color within the circle
|
||||
vec3 brightColor = vColor * intensity;
|
||||
brightColor = clamp(brightColor, 0.0, 2.5);
|
||||
|
||||
gl_FragColor = vec4(brightColor, 1.0); // Full alpha within the circle
|
||||
}
|
||||
33
Tests/webGl/my-threejs-test/shaders/vertex.glsl
Normal file
33
Tests/webGl/my-threejs-test/shaders/vertex.glsl
Normal file
@@ -0,0 +1,33 @@
|
||||
uniform float time;
|
||||
uniform vec3 color1;
|
||||
uniform vec3 color2;
|
||||
varying vec3 vColor;
|
||||
|
||||
const float PI = 3.1415926535897932384626433832795;
|
||||
const float goldenAngle = PI * (3.0 - sqrt(5.0));
|
||||
|
||||
void main() {
|
||||
// Calculate the normalized distance from center
|
||||
float index = float(gl_VertexID);
|
||||
float radiuss = sqrt(index) * 5.0;
|
||||
float normalizedRadius = radiuss / 200.0; // Adjust this divisor based on your pattern's size
|
||||
|
||||
// Calculate the angle for each point based on its index
|
||||
float angle = index * (goldenAngle + time * 0.001);
|
||||
if (mod(index,2.0) != 0.0){
|
||||
angle *=-1.0;
|
||||
}
|
||||
|
||||
// Color changes over time - Adding a slow wave effect based on the distance from center
|
||||
float colorTime = time * -2.1; // Slow down the color change over time
|
||||
float colorWave = sin(normalizedRadius * PI * 2.0 + colorTime); // Wave based on distance and time
|
||||
float colorMixFactor = colorWave * 0.5 + 0.5; // Normalize the wave between 0 and 1
|
||||
|
||||
vColor = mix(color1, color2, colorMixFactor); // Mix the colors based on the computed factor
|
||||
|
||||
// Calculate the animated position
|
||||
vec3 animatedPosition = vec3(radiuss * cos(angle), radiuss * sin(angle), 0.0);
|
||||
|
||||
gl_Position = projectionMatrix * modelViewMatrix * vec4(animatedPosition, 1.0);
|
||||
gl_PointSize = 10.0;
|
||||
}
|
||||
110
Tests/webGl/my-threejs-test/src/index.js
Normal file
110
Tests/webGl/my-threejs-test/src/index.js
Normal file
@@ -0,0 +1,110 @@
|
||||
import * as THREE from 'three';
|
||||
import { EffectComposer } from 'three/examples/jsm/postprocessing/EffectComposer.js';
|
||||
import { RenderPass } from 'three/examples/jsm/postprocessing/RenderPass.js';
|
||||
import { UnrealBloomPass } from 'three/examples/jsm/postprocessing/UnrealBloomPass.js';
|
||||
|
||||
import vertexShader from '../shaders/vertex.glsl';
|
||||
import fragmentShader from '../shaders/fragment.glsl';
|
||||
|
||||
// Now you can use `vertexShader` and `fragmentShader` as strings in your Three.js material
|
||||
// Basic setup
|
||||
const scene = new THREE.Scene();
|
||||
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
|
||||
renderer = new THREE.WebGLRenderer({ alpha: true });
|
||||
renderer.setClearColor(0x000000, 0); // Transparent background color
|
||||
renderer.setSize(window.innerWidth, window.innerHeight);
|
||||
document.body.appendChild(renderer.domElement);
|
||||
// scene.add(renderer.domElement);
|
||||
|
||||
|
||||
// Phyllotaxis setup
|
||||
const pointsGeometry = new THREE.BufferGeometry();
|
||||
const n_points = 5000;
|
||||
const positions = new Float32Array(n_points * 3);
|
||||
const goldenAngle = Math.PI * (3 - Math.sqrt(5));
|
||||
// const goldenAngle = 0;
|
||||
|
||||
for (let i = 0; i < n_points; i++) {
|
||||
const angle = i * goldenAngle;
|
||||
const r = Math.sqrt(i) * 5;
|
||||
positions[i * 3] = r * Math.cos(angle); // x
|
||||
positions[i * 3 + 1] = r * Math.sin(angle); // y
|
||||
positions[i * 3 + 2] = 0; // z
|
||||
}
|
||||
|
||||
pointsGeometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
|
||||
|
||||
// ShaderMaterial
|
||||
const shaderMaterial = new THREE.ShaderMaterial({
|
||||
uniforms: {
|
||||
time: { value: 0.0 },
|
||||
color1: { value: new THREE.Color(0x2D81FC) }, // Blue
|
||||
color2: { value: new THREE.Color(0xFC0362) }, // Pink
|
||||
},
|
||||
vertexShader: vertexShader,
|
||||
fragmentShader: fragmentShader,
|
||||
transparent: true,
|
||||
blending: THREE.AdditiveBlending,
|
||||
});
|
||||
|
||||
const points = new THREE.Points(pointsGeometry, shaderMaterial);
|
||||
// Assign the points mesh to the bloom layer
|
||||
scene.add(points);
|
||||
points.layers.enable(1);
|
||||
|
||||
camera.position.z = 200;
|
||||
|
||||
// Compile the shader and catch any errors
|
||||
renderer.compile(scene, camera);
|
||||
|
||||
// Create layers
|
||||
const bloomLayer = new THREE.Layers();
|
||||
bloomLayer.set(1); // Setting the bloom layer to layer 1
|
||||
|
||||
// Set up the bloom pass
|
||||
const bloomPass = new UnrealBloomPass(new THREE.Vector2(window.innerWidth, window.innerHeight), 1.0, 0.4, 0.85);
|
||||
bloomPass.threshold = 0.1
|
||||
bloomPass.strength = 2.5
|
||||
bloomPass.radius = 0.55
|
||||
bloomPass.renderToScreen = true
|
||||
// Create a render scene pass
|
||||
const renderScene = new RenderPass(scene, camera);
|
||||
|
||||
// Set up the effect composer
|
||||
const composer = new EffectComposer(renderer);
|
||||
composer.setSize(window.innerWidth, window.innerHeight);
|
||||
composer.addPass(renderScene);
|
||||
composer.addPass(bloomPass);
|
||||
|
||||
renderer.outputEncoding = THREE.sRGBEncoding;
|
||||
renderer.toneMapping = THREE.ACESFilmicToneMapping;
|
||||
// renderer.toneMappingExposure = Math.pow( 0.9, 4.0 )
|
||||
renderer.toneMappingExposure = 1.0
|
||||
|
||||
|
||||
renderer.autoClear = false;
|
||||
points.layers.set(1);
|
||||
// Animation loop
|
||||
function animate() {
|
||||
requestAnimationFrame(animate);
|
||||
shaderMaterial.uniforms.time.value = performance.now() / 5000;
|
||||
|
||||
renderer.clear();
|
||||
|
||||
camera.layers.set(1);
|
||||
composer.render();
|
||||
|
||||
renderer.clearDepth();
|
||||
camera.layers.set(0);
|
||||
renderer.render(scene, camera);
|
||||
}
|
||||
|
||||
animate();
|
||||
|
||||
// Handle window resize
|
||||
window.addEventListener('resize', onWindowResize, false);
|
||||
function onWindowResize() {
|
||||
camera.aspect = window.innerWidth / window.innerHeight;
|
||||
camera.updateProjectionMatrix();
|
||||
renderer.setSize(window.innerWidth, window.innerHeight);
|
||||
}
|
||||
37
Tests/webGl/sams_webgl/index.html
Normal file
37
Tests/webGl/sams_webgl/index.html
Normal file
@@ -0,0 +1,37 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>WebGL Template</title>
|
||||
<style>
|
||||
/* Set canvas to occupy the full width and height of the window */
|
||||
canvas {
|
||||
display: block;
|
||||
width: 800px;
|
||||
height: 800px;
|
||||
margin: 0 560px;
|
||||
padding: 0;
|
||||
|
||||
}
|
||||
|
||||
.canvas2d {
|
||||
position: absolute !important;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
}
|
||||
body{
|
||||
margin:0
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<canvas id="canvas"></canvas>
|
||||
<canvas id="canvas2d" class="canvas2d"></canvas>
|
||||
<script src="index.js">
|
||||
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
204
Tests/webGl/sams_webgl/index.js
Normal file
204
Tests/webGl/sams_webgl/index.js
Normal file
@@ -0,0 +1,204 @@
|
||||
// Get the canvas element and create a WebGL context
|
||||
const canvas = document.getElementById('canvas');
|
||||
const canvas2d = document.getElementById('canvas2d');
|
||||
const gl = canvas.getContext('webgl') || canvas.getContext('experimental-webgl');
|
||||
let ctx = canvas2d.getContext("2d");
|
||||
ctx.canvas.width = 800;
|
||||
ctx.canvas.height = 800;
|
||||
|
||||
// Check if WebGL is available
|
||||
if (!gl) {
|
||||
alert('WebGL not supported in your browser.');
|
||||
} else {
|
||||
// Set the canvas size and WebGL viewport
|
||||
canvas.width = 800;
|
||||
canvas.height = 800;
|
||||
let centerX = ctx.canvas.width / 2;
|
||||
let centerY = ctx.canvas.height / 2;
|
||||
gl.viewport(0, 0, canvas.width, canvas.height);
|
||||
|
||||
// Define the vertex shader source code
|
||||
const vertexShaderSource = `
|
||||
vec3 hsv2rgb(vec3 c)
|
||||
{
|
||||
vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
|
||||
vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
|
||||
return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
|
||||
}
|
||||
|
||||
attribute vec2 position;
|
||||
uniform float u_rotation;
|
||||
uniform vec2 u_pos;
|
||||
|
||||
varying vec4 vColor;
|
||||
|
||||
void main() {
|
||||
vColor = vec4(hsv2rgb(vec3(u_rotation, 0.5+pow(position.y+0.4, 10.0), 1.0)), 1.0);
|
||||
|
||||
float centerX = 0.0;
|
||||
float centerY = 0.0;
|
||||
float xPos = position.x;
|
||||
float yPos = position.y;
|
||||
|
||||
float rot_cos = cos(u_rotation);
|
||||
float rot_sin = sin(u_rotation);
|
||||
|
||||
float x = xPos * rot_cos - yPos * rot_sin;
|
||||
float y = yPos * rot_cos + xPos * rot_sin;
|
||||
gl_Position = vec4(x+u_pos.x , y+u_pos.y , 0, 1);
|
||||
}
|
||||
`;
|
||||
|
||||
|
||||
// Define the fragment shader source code
|
||||
const fragmentShaderSource = `
|
||||
precision mediump float;
|
||||
varying vec4 vColor;
|
||||
uniform vec4 fColor;
|
||||
void main() {
|
||||
gl_FragColor = vColor;
|
||||
}
|
||||
`;
|
||||
|
||||
// Create and compile the vertex and fragment shaders
|
||||
const vertexShader = createShader(gl, gl.VERTEX_SHADER, vertexShaderSource);
|
||||
const fragmentShader = createShader(gl, gl.FRAGMENT_SHADER, fragmentShaderSource);
|
||||
|
||||
// Create a program, attach the shaders, and link the program
|
||||
const program = createProgram(gl, vertexShader, fragmentShader);
|
||||
|
||||
// Get the attribute and uniform locations
|
||||
const positionAttributeLocation = gl.getAttribLocation(program, 'position');
|
||||
// const positionAttributeLocation1 = gl.getAttribLocation(program, 'u_pos');
|
||||
const rotationUniformLocation = gl.getUniformLocation(program, 'u_rotation');
|
||||
const fColorLocation = gl.getUniformLocation(program, "fColor");
|
||||
|
||||
// Create a buffer to store vertex positions
|
||||
const positionBuffer = gl.createBuffer();
|
||||
|
||||
// Bind the buffer and send the vertex positions to the GPU
|
||||
|
||||
|
||||
function polyPoints(sides) {
|
||||
let pointsArr = [];
|
||||
let width = 1;
|
||||
let rotation = 0
|
||||
pointsArr.push(width * Math.cos((rotation * Math.PI) / 180));
|
||||
pointsArr.push(width * Math.sin((rotation * Math.PI) / 180))
|
||||
for (let i = 0; i < sides; i++) {
|
||||
pointsArr.push(width * Math.cos((i * 2 * Math.PI) / sides + (rotation * Math.PI) / 180))
|
||||
pointsArr.push(width * Math.sin((i * 2 * Math.PI) / sides + (rotation * Math.PI) / 180))
|
||||
}
|
||||
return pointsArr
|
||||
}
|
||||
|
||||
|
||||
function rad(degrees) {
|
||||
var pi = Math.PI;
|
||||
return degrees * (pi / 180);
|
||||
}
|
||||
|
||||
// Function to create and compile a shader
|
||||
function createShader(gl, type, source) {
|
||||
const shader = gl.createShader(type);
|
||||
gl.shaderSource(shader, source);
|
||||
gl.compileShader(shader);
|
||||
if (gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
|
||||
return shader;
|
||||
}
|
||||
console.error(gl.getShaderInfoLog(shader));
|
||||
gl.deleteShader(shader);
|
||||
}
|
||||
|
||||
// Function to create a program and link shaders
|
||||
function createProgram(gl, vertexShader, fragmentShader) {
|
||||
const program = gl.createProgram();
|
||||
gl.attachShader(program, vertexShader);
|
||||
gl.attachShader(program, fragmentShader);
|
||||
gl.linkProgram(program);
|
||||
if (gl.getProgramParameter(program, gl.LINK_STATUS)) {
|
||||
return program;
|
||||
}
|
||||
console.error(gl.getProgramInfoLog(program));
|
||||
gl.deleteProgram(program);
|
||||
}
|
||||
// Function to draw the scene
|
||||
let prevTime = 0
|
||||
function drawScene(time) {
|
||||
// Convert time to seconds
|
||||
// console.log(time - prevTime)
|
||||
prevTime = time
|
||||
time *= 0.001;
|
||||
|
||||
// Clear the canvas with a black background
|
||||
gl.clearColor(0, 0, 0, 1);
|
||||
gl.clear(gl.COLOR_BUFFER_BIT);
|
||||
|
||||
// Use the shader program
|
||||
gl.useProgram(program);
|
||||
|
||||
// Enable the position attribute
|
||||
|
||||
// Create a buffer to store vertex positions
|
||||
let blue = [0.17, 0.49, 0.85] //blue
|
||||
let green = [0.17, 0.85, 0.46] //green
|
||||
let pink = [0.96, 0.24, 0.86] //green
|
||||
|
||||
// drawPoly(3, time * 1, blue, 0, 0)
|
||||
// drawPoly(3, time * 0.8, pink, 0.35, 0.35)
|
||||
// drawPoly(5,time*0.6)
|
||||
// drawPoly(6,time*0.4)
|
||||
// drawPoly(7,time*0.2)
|
||||
//
|
||||
|
||||
// prepare the gl state for the draw (can be here as drawPoly gets called multiple times with the same state)
|
||||
// This could be improved by using a VAO to get the gpu to run over the for loop for you
|
||||
gl.enableVertexAttribArray(positionAttributeLocation);
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
|
||||
gl.vertexAttribPointer(positionAttributeLocation, 2, gl.FLOAT, false, 0, 0);
|
||||
|
||||
|
||||
for (let i = 0; i < 100; i++) {
|
||||
|
||||
drawPoly(4, time * i * 0.001, blue, 0, 0)
|
||||
}
|
||||
|
||||
|
||||
Draw_center()
|
||||
drawCircle()
|
||||
// console.log(time)
|
||||
// Request the next frame to be drawn
|
||||
requestAnimationFrame(drawScene);
|
||||
}
|
||||
|
||||
function drawPoly(sides, speed, colour, x, y) {
|
||||
gl.uniform1f(rotationUniformLocation, speed);
|
||||
gl.uniform4f(fColorLocation, colour[0], colour[1], colour[2], 1);
|
||||
gl.uniform2f(gl.getUniformLocation(program, 'u_pos'), x, y);
|
||||
const positions = polyPoints(sides)
|
||||
// const positionBuffer1 = gl.createBuffer();
|
||||
|
||||
// Assume the buffers are already bound
|
||||
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.DYNAMIC_DRAW);
|
||||
gl.drawArrays(gl.LINE_LOOP, 0, positions.length / 2);
|
||||
}
|
||||
|
||||
// Start rendering the scene
|
||||
requestAnimationFrame(drawScene);
|
||||
function Draw_center() {
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(centerX - 400, centerY);
|
||||
ctx.lineTo(centerX + 400, centerY);
|
||||
ctx.moveTo(centerX, centerY - 400);
|
||||
ctx.lineTo(centerX, centerY + 400);
|
||||
ctx.strokeStyle = "green";
|
||||
ctx.stroke();
|
||||
// console.log("drawn center")
|
||||
}
|
||||
function drawCircle() {
|
||||
ctx.beginPath();
|
||||
ctx.arc(centerX, centerY, 400, 0, 2 * Math.PI, false);
|
||||
ctx.strokeStyle = "green";
|
||||
ctx.stroke();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user