//script.js
const canvas = document.getElementById('glCanvas');
const gl = canvas.getContext('webgl');
// Check if WebGL is available
if (!gl) {
console.error('WebGL not supported');
throw new Error('WebGL not supported');
}
// Vertex shader source code
const vertexShaderSource = `
attribute vec4 a_position;
attribute vec4 a_color;
uniform mat4 u_matrix;
varying vec4 v_color;
void main() {
gl_Position = u_matrix * a_position;
v_color = a_color;
}
`;
// Fragment shader source code
const fragmentShaderSource = `
precision mediump float;
varying vec4 v_color;
void main() {
gl_FragColor = v_color;
}
`;
// Function to create shaders
function createShader(gl, type, source) {
const shader = gl.createShader(type);
gl.shaderSource(shader, source);
gl.compileShader(shader);
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
console.error('Error compiling shader:', gl.getShaderInfoLog(shader));
gl.deleteShader(shader);
return null;
}
return shader;
}
// Create vertex and fragment shaders
const vertexShader = createShader(gl, gl.VERTEX_SHADER, vertexShaderSource);
const fragmentShader = createShader(gl, gl.FRAGMENT_SHADER, fragmentShaderSource);
// Create the shader program
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)) {
console.error('Error linking program:', gl.getProgramInfoLog(program));
gl.deleteProgram(program);
return null;
}
return program;
}
const program = createProgram(gl, vertexShader, fragmentShader);
gl.useProgram(program);
// Define the cube vertices and colors
const positions = new Float32Array([
// Front face
-0.5, -0.5, 0.5,
0.5, -0.5, 0.5,
0.5, 0.5, 0.5,
-0.5, 0.5, 0.5,
// Back face
-0.5, -0.5, -0.5,
-0.5, 0.5, -0.5,
0.5, 0.5, -0.5,
0.5, -0.5, -0.5,
// Top face
-0.5, 0.5, -0.5,
-0.5, 0.5, 0.5,
0.5, 0.5, 0.5,
0.5, 0.5, -0.5,
// Bottom face
-0.5, -0.5, -0.5,
0.5, -0.5, -0.5,
0.5, -0.5, 0.5,
-0.5, -0.5, 0.5,
// Right face
0.5, -0.5, -0.5,
0.5, 0.5, -0.5,
0.5, 0.5, 0.5,
0.5, -0.5, 0.5,
// Left face
-0.5, -0.5, -0.5,
-0.5, -0.5, 0.5,
-0.5, 0.5, 0.5,
-0.5, 0.5, -0.5,
]);
const colors = new Float32Array([
// Front face colors
1, 0, 0, 1,
1, 0, 0, 1,
1, 0, 0, 1,
1, 0, 0, 1,
// Back face colors
0, 1, 0, 1,
0, 1, 0, 1,
0, 1, 0, 1,
0, 1, 0, 1,
// Top face colors
0, 0, 1, 1,
0, 0, 1, 1,
0, 0, 1, 1,
0, 0, 1, 1,
// Bottom face colors
1, 1, 0, 1,
1, 1, 0, 1,
1, 1, 0, 1,
1, 1, 0, 1,
// Right face colors
1, 0, 1, 1,
1, 0, 1, 1,
1, 0, 1, 1,
1, 0, 1, 1,
// Left face colors
0, 1, 1, 1,
0, 1, 1, 1,
0, 1, 1, 1,
0, 1, 1, 1,
]);
const indices = new Uint16Array([
0, 1, 2, 0, 2, 3, // Front face
4, 5, 6, 4, 6, 7, // Back face
8, 9, 10, 8, 10, 11, // Top face
12, 13, 14, 12, 14, 15, // Bottom face
16, 17, 18, 16, 18, 19, // Right face
20, 21, 22, 20, 22, 23, // Left face
]);
// Position buffer
const positionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
gl.bufferData(gl.ARRAY_BUFFER, positions, gl.STATIC_DRAW);
// Color buffer
const colorBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
gl.bufferData(gl.ARRAY_BUFFER, colors, gl.STATIC_DRAW);
// Index buffer
const indexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);
// Enable the position attribute
const positionAttributeLocation = gl.getAttribLocation(program, 'a_position');
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
gl.vertexAttribPointer(positionAttributeLocation, 3, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(positionAttributeLocation);
// Enable the color attribute
const colorAttributeLocation = gl.getAttribLocation(program, 'a_color');
gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
gl.vertexAttribPointer(colorAttributeLocation, 4, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(colorAttributeLocation);
// Get the uniform location
const matrixLocation = gl.getUniformLocation(program, 'u_matrix');
// Create matrices for transformation
let rotation = 0;
function drawScene() {
rotation += 0.01;
// Create perspective matrix
const aspect = canvas.width / canvas.height;
const projectionMatrix = mat4.perspective([], Math.PI / 4, aspect, 0.1, 10.0);
// Create view matrix
const viewMatrix = mat4.lookAt([], [0, 0, -4], [0, 0, 0], [0, 1, 0]);
// Create model matrix (rotation)
const modelMatrix = mat4.create();
mat4.rotate(modelMatrix, modelMatrix, rotation, [1, 1, 0]); // Rotate around the diagonal axis
// Combine the matrices
const modelViewMatrix = mat4.multiply([], viewMatrix, modelMatrix);
const finalMatrix = mat4.multiply([], projectionMatrix, modelViewMatrix);
// Set the matrix uniform
gl.uniformMatrix4fv(matrixLocation, false, finalMatrix);
// Clear the canvas
gl.clearColor(0, 0, 0, 1); // Clear to black
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
// Enable depth testing
gl.enable(gl.DEPTH_TEST);
// Draw the cube
gl.drawElements(gl.TRIANGLES, indices.length, gl.UNSIGNED_SHORT, 0);
// Request animation frame for continuous rendering
requestAnimationFrame(drawScene);
}
// Start drawing the scene
drawScene();