4230-hw-1/ChaosGame/ChaosGame.js
2022-06-23 15:54:01 -05:00

132 lines
3.5 KiB
JavaScript

// HelloPoint2.js (c) 2012 matsuda, 2022 Jonathon Doran
"use strict";
// Vertex shader program
const vertex_shader = `
attribute vec4 a_Position; // attribute variables are assigned by the main program
void main()
{
gl_Position = a_Position;
gl_PointSize = 1.0;
} `;
// Fragment shader program
const fragment_shader = `
void main()
{
gl_FragColor = vec4(0.2, 0.8, 1.0, 1.0); // Set the point color to a nice cyan
} `;
//
// Chaos Game
//
// Classes
// vec2: 2D vectors
class vec2 {
constructor(x = 0, y = 0) {
this.x = x;
this.y = y;
}
add(rhs) {
if (rhs)
return new vec2(this.x + rhs.x, this.y + rhs.y);
return null;
}
sub(rhs) {
if (rhs)
return new vec2(this.x - rhs.x, this.y - rhs.y);
return null;
}
copy() {
return new vec2(this.x, this.y);
}
move_halfway(rhs) {
// Calculate the vector direction to move in, and change in that direction.
this.x += (rhs.x - this.x) / 2;
this.y += (rhs.y - this.y) / 2;
}
}
// triangle2 class: Holds 3 vertices, represented as vectors from the origin
class triangle2 {
// constructor: Make a new triangle
constructor({ v0 = null, v1 = null, v2 = null, type = "scalene", radius = 0, center = {x: 0, y: 0}} = {}) {
this.v = [, ,]
this.v[0] = v0;
this.v[1] = v1;
this.v[2] = v2;
if (type === "equilateral") {
this.make_equilateral(radius, center);
}
}
// make_equilateral: construct an equilateral triangle
// @param radius: Distance from center of triangle to vertices
make_equilateral(radius, center = {x: 0, y: 0}) {
// compute the math constants
const r_sin_120 = Math.sin(Math.PI / 3) * radius;
const r_cos_120 = 0.5 * radius;
// Equilateral triangle centered on origin
this.v[0] = new vec2(-r_sin_120, -r_cos_120).add(center);
this.v[1] = new vec2(0, radius).add(center);
this.v[2] = new vec2(r_sin_120, -r_cos_120).add(center);
}
get_vertex(index) { return this.v[index]; }
get_rand_vertex() { return this.v[Math.floor(Math.random() * 3)]; }
}
// function draw_point: draw a point
function draw_point(gl, a_Position, p) {
// Pass vertex position to attribute variable
gl.vertexAttrib3f(a_Position, p.x, p.y, 0.0);
// Draw
gl.drawArrays(gl.POINTS, 0, 1);
}
function main() {
// Retrieve <canvas> element
var canvas = document.getElementById('webgl');
// Get the rendering context for WebGL
var gl = getWebGLContext(canvas);
if (!gl) {
console.log('Failed to get the rendering context for WebGL');
return;
}
// Initialize shaders
if (!initShaders(gl, vertex_shader, fragment_shader)) {
console.log('Failed to intialize shaders.');
return;
}
// Get the storage location of a_Position
var a_Position = gl.getAttribLocation(gl.program, 'a_Position');
if (a_Position < 0) {
console.log('Failed to get the storage location of a_Position');
return;
}
// Specify the color for clearing canvas as black, and clear canvas
gl.clearColor(0.0, 0.0, 0.0, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT);
// make an equilateral triangle of radius 0.8, centered in the clip space
const radius = 0.8;
var triangle = new triangle2({type: "equilateral", radius: radius, center: {x: 0, y: -radius/4}});
// initialize point p to a copy of one of the vectors
var i, p = triangle.get_vertex(0)?.copy();
// loop for ten thousand years
for (i = 0; i < 50000; i++) {
// get a random vertex
var random_vertex = triangle.get_rand_vertex();
// move to the midpoint
p.move_halfway(random_vertex);
// draw point
draw_point(gl, a_Position, p);
}
}