This JavaScript program demonstrates how rotate various geometric primitives around the z-axis in WebGL.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<title>XoaX.net's Javascript</title>
<!-- Supply a transparent 1x1 favicon -->
<link rel="icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=">
<style>
#idCanvas {
border: 1px solid black;
width: 800px;
height: 600px
}
</style>
<script id="idVertexShader" type="c">
attribute vec4 av4VertexPosition;
attribute vec4 av4VertexColor;
varying vec4 vv4Color;
uniform mat4 um4Model;
uniform mat4 um4Projection;
void main() {
gl_Position = um4Projection*um4Model*av4VertexPosition;
vv4Color = av4VertexColor;
gl_PointSize = 25.0;
}
</script>
<script id="idFragmantShader" type="c">
precision mediump float;
varying vec4 vv4Color;
void main() {
gl_FragColor = vv4Color;
}
</script>
<script type="text/javascript" src="RotatePrimitivesAroundZ.js"></script>
</head>
<body onload="Initialize()">
<canvas id="idCanvas"></canvas>
</body>
</html>let gqGL = null; let gqProgram = null; let gqVertexBuffer = null; let gqColorBuffer = null; let gqVertexAttributeLoc = null; let gqColorAttributeLoc = null; let gqModelMatrixAttributeLoc = null; let gqProjMatrixAttributeLoc = null; // Animation controls let gdPrevMS = 0; let gdRotationAngle = 0; function Initialize() { const qCanvas = document.getElementById("idCanvas"); qCanvas.width = qCanvas.clientWidth; qCanvas.height = qCanvas.clientHeight; gqGL = qCanvas.getContext("webgl"); gqProgram = CreateProgram(gqGL); if (!gqGL.getProgramParameter(gqProgram, gqGL.LINK_STATUS)) { alert('The program failed to initialize', gqGL.getProgramInfoLog(gqProgram)); } gqVertexBuffer = CreateVertexBuffer(gqGL); gqColorBuffer = CreateColorBuffer(gqGL); gqVertexAttributeLoc = gqGL.getAttribLocation(gqProgram, "av4VertexPosition"); gqColorAttributeLoc = gqGL.getAttribLocation(gqProgram, "av4VertexColor"); gqModelMatrixAttributeLoc = gqGL.getUniformLocation(gqProgram, "um4Model"); gqProjMatrixAttributeLoc = gqGL.getUniformLocation(gqProgram, "um4Projection"); // Begin the rendering loop requestAnimationFrame(Render); } function CreateProgram(kqGL) { // Compile the vertex shader const ksVertexShaderCode = document.getElementById("idVertexShader").innerHTML; let qVertexShader = kqGL.createShader(kqGL.VERTEX_SHADER); kqGL.shaderSource(qVertexShader, ksVertexShaderCode); kqGL.compileShader(qVertexShader); // Compile the fragment shader const ksFragmentShaderCode = document.getElementById("idFragmantShader").innerHTML; let qFragmentShader = kqGL.createShader(kqGL.FRAGMENT_SHADER); kqGL.shaderSource(qFragmentShader, ksFragmentShaderCode); kqGL.compileShader(qFragmentShader); // Compile and link the program let qProgram = kqGL.createProgram(); kqGL.attachShader(qProgram, qVertexShader); kqGL.attachShader(qProgram, qFragmentShader); kqGL.linkProgram(qProgram); if (!kqGL.getProgramParameter(qProgram, kqGL.LINK_STATUS)) { alert('The program failed to initialize', kqGL.getProgramInfoLog(qProgram)); } return qProgram; } function CreateVertexBuffer(kqGL) { const kqVertexBuffer = kqGL.createBuffer(); // Set this as the current buffer kqGL.bindBuffer(kqGL.ARRAY_BUFFER, kqVertexBuffer); // The vertices form a reversed z. The first three are in counter-clockwise order const kfaVertices = new Float32Array([1.0, 1.0, -1.0, 1.0, 1.0, -1.0, -1.0, -1.0]); kqGL.bufferData(kqGL.ARRAY_BUFFER, kfaVertices, kqGL.STATIC_DRAW); return kqVertexBuffer; } function CreateColorBuffer(kqGL) { const kqColorBuffer = kqGL.createBuffer(); kqGL.bindBuffer(kqGL.ARRAY_BUFFER, kqColorBuffer); // Four RGBA colors const kfaColors = new Float32Array([1.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0]); kqGL.bufferData(kqGL.ARRAY_BUFFER, kfaColors, kqGL.STATIC_DRAW); return kqColorBuffer; } function SetVertexAttribute(kqGL) { const kiCoordinatesPerVector = 2; const kiType = kqGL.FLOAT; const kbNormalizeVectors = false; const kiStride = 0; // Byte offset between successive values const kiInitialOffset = 0; // Byte offset for first value kqGL.bindBuffer(kqGL.ARRAY_BUFFER, gqVertexBuffer); kqGL.vertexAttribPointer(gqVertexAttributeLoc, kiCoordinatesPerVector, kiType, kbNormalizeVectors, kiStride, kiInitialOffset); kqGL.enableVertexAttribArray(gqVertexAttributeLoc); } function SetColorAttribute(kqGL) { const kiCoordinatesPerVector = 4; const kiType = kqGL.FLOAT; const kbNormalizeVectors = false; const kiStride = 0; // Byte offset between successive values const kiInitialOffset = 0; // Byte offset for first value kqGL.bindBuffer(kqGL.ARRAY_BUFFER, gqColorBuffer); kqGL.vertexAttribPointer(gqColorAttributeLoc, kiCoordinatesPerVector, kiType, kbNormalizeVectors, kiStride, kiInitialOffset); kqGL.enableVertexAttribArray(gqColorAttributeLoc); } function Render(dCurrMS) { let dDiffMS = dCurrMS - gdPrevMS; gdRotationAngle += dDiffMS*(Math.PI/5000); gdRotationAngle = gdRotationAngle - 2.0*Math.PI*Math.floor(gdRotationAngle/(2.0*Math.PI)); gdPrevMS = dCurrMS; Draw(gqGL); requestAnimationFrame(Render); } function Draw(kqGL) { // Set up kqGL.clearColor(0.5, 0.5, 0.5, 1.0); kqGL.clearDepth(1.0); kqGL.enable(kqGL.DEPTH_TEST); kqGL.depthFunc(kqGL.LEQUAL); kqGL.clear(kqGL.COLOR_BUFFER_BIT | kqGL.DEPTH_BUFFER_BIT); let dSin = Math.sin(gdRotationAngle); let dCos = Math.cos(gdRotationAngle); // A rotation around the origin followed by a translation - matrix // The bottom row: indices 12, 13, 14 define translation. // Consider that multiplication looks like a row times the matrix vM, when we write Mv. let faM = new Float32Array(16); faM[0] = dCos; faM[1] = dSin; faM[2] = 0.0; faM[3] = 0.0; faM[4] = -dSin; faM[5] = dCos; faM[6] = 0.0; faM[7] = 0.0; faM[8] = 0.0; faM[9] = 0.0; faM[10] = 1.0; faM[11] = 0.0; faM[12] = 0.0; faM[13] = 0.0; faM[14] = -4.0; faM[15] = 1.0; const kdFieldOfView = Math.PI/4.0; const kdAspect = kqGL.canvas.clientWidth/kqGL.canvas.clientHeight; const kdNearPlane = .1; const kdFarPlane = 10.0; let faProj = GetPerspectiveProjection(kdFieldOfView, kdAspect, kdNearPlane, kdFarPlane); SetVertexAttribute(kqGL); SetColorAttribute(kqGL); kqGL.useProgram(gqProgram); const kbUseTranspose = false; kqGL.uniformMatrix4fv(gqModelMatrixAttributeLoc, kbUseTranspose, faM); kqGL.uniformMatrix4fv(gqProjMatrixAttributeLoc, kbUseTranspose, faProj); // Use indices to render line segments between each pair of points. var ui8aIndices = new Uint8Array([0,1, 0,2, 0,3, 1,2, 1,3, 2,3]); var qIndexBuffer = kqGL.createBuffer(); kqGL.bindBuffer(kqGL.ELEMENT_ARRAY_BUFFER, qIndexBuffer); kqGL.bufferData(kqGL.ELEMENT_ARRAY_BUFFER, ui8aIndices, kqGL.STATIC_DRAW); kqGL.drawElements(kqGL.LINES, 12, kqGL.UNSIGNED_BYTE, 0); const kiOffset = 0; const kiVertices = 4; // Uncomment to see various primitives rendered. Rendering is in array order. kqGL.drawArrays(kqGL.POINTS, kiOffset, kiVertices); //kqGL.drawArrays(kqGL.TRIANGLE_STRIP, kiOffset, kiVertices); //kqGL.drawArrays(kqGL.LINE_STRIP, kiOffset, kiVertices); //kqGL.drawArrays(kqGL.LINE_LOOP, kiOffset, kiVertices); //kqGL.drawArrays(kqGL.LINES, kiOffset, kiVertices); //kqGL.drawArrays(kqGL.TRIANGLES, kiOffset, kiVertices); //kqGL.drawArrays(kqGL.TRIANGLE_FAN, kiOffset, kiVertices); } function GetPerspectiveProjection(dFOV, dAspect, dNear, dFar) { let faM = new Float32Array(16); let dF = 1.0/Math.tan(dFOV/2.0); let dNF = 1/(dNear-dFar); faM[0] = dF/dAspect; faM[1] = 0.0; faM[2] = 0.0; faM[3] = 0.0; faM[4] = 0.0; faM[5] = dF; faM[6] = 0.0; faM[7] = 0.0; faM[8] = 0.0; faM[9] = 0.0; faM[10] = (dNear+dFar)*dNF; faM[11] = -1.0; faM[12] = 0.0; faM[13] = 0.0; faM[14] = 2.0*dNear*dFar*dNF; faM[15] = 0.0; return faM; }
© 20072026 XoaX.net LLC. All rights reserved.