This JavaScript program demonstrates the default viewing orientation for a WebGL program. The default orientation is looking down the z-axis with the z-axis coming out of the view plane, the y-axis pointing straight up, and the x-axis pointing to the right. To make the orientation more clear, we circle the view around the z-axis to make the z-axis visible. Alternatively, the z-axis would just be visible as a point.
<!DOCTYPE html>
<html>
<head>
<title>XoaX.net's WebGL</title>
<script id="idVertexShader" type="c">
attribute vec4 av4Vertex;
attribute vec4 av4Color;
varying vec4 vv4Color;
void main() {
gl_Position = av4Vertex;
vv4Color = av4Color;
}
</script>
<script id="idFragmantShader" type="c">
precision mediump float;
varying vec4 vv4Color;
void main() {
gl_FragColor = vv4Color;
}
</script>
<script type="text/javascript">
var gqWebGL = null;
function CreateProgramAndContext(qInstanceWebGL) {
// Get the WebGL Context
var qCanvas = document.querySelector("#"+qInstanceWebGL.msCanvasID);
qInstanceWebGL.mqGL = qCanvas.getContext("webgl");
var qGL = qInstanceWebGL.mqGL;
// Compile the vertex shader
var sVertexShaderCode = document.querySelector("#"+qInstanceWebGL.msVertexShaderID).text;
var qVertexShader = qGL.createShader(qGL.VERTEX_SHADER);
qGL.shaderSource(qVertexShader, sVertexShaderCode);
qGL.compileShader(qVertexShader);
// Compile the fragment shader
var sFragmentShaderCode = document.querySelector("#"+qInstanceWebGL.msFragmentShaderID).text;
var qFragmentShader = qGL.createShader(qGL.FRAGMENT_SHADER);
qGL.shaderSource(qFragmentShader, sFragmentShaderCode);
qGL.compileShader(qFragmentShader);
// Compile and link the program
qInstanceWebGL.mqProgram = qGL.createProgram();
qGL.attachShader(qInstanceWebGL.mqProgram, qVertexShader);
qGL.attachShader(qInstanceWebGL.mqProgram, qFragmentShader);
qGL.linkProgram(qInstanceWebGL.mqProgram);
qGL.useProgram(qInstanceWebGL.mqProgram);
}
function CreateBuffers(qInstanceWebGL) {
var qGL = qInstanceWebGL.mqGL;
var qVerticesBuffer = qGL.createBuffer();
qGL.bindBuffer(qGL.ARRAY_BUFFER, qVerticesBuffer);
qGL.bufferData(qGL.ARRAY_BUFFER, qInstanceWebGL.mfaTransformedVertices, qGL.STATIC_DRAW);
var qVertexLoc = qGL.getAttribLocation(qInstanceWebGL.mqProgram, 'av4Vertex');
qGL.vertexAttribPointer(qVertexLoc, 4, qGL.FLOAT, false, 0, 0);
qGL.enableVertexAttribArray(qVertexLoc);
var qColorsBuffer = qGL.createBuffer();
qGL.bindBuffer(qGL.ARRAY_BUFFER, qColorsBuffer);
qGL.bufferData(qGL.ARRAY_BUFFER, qInstanceWebGL.mfaVertexColors, qGL.STATIC_DRAW);
var qColors = qGL.getAttribLocation(qInstanceWebGL.mqProgram, 'av4Color');
qGL.vertexAttribPointer(qColors, 4, qGL.FLOAT, false, 0, 0);
qGL.enableVertexAttribArray(qColors);
}
var gfaVertices = null;
function Initialization() {
var dCS = .25; // The cube side size
gfaVertices = new Float32Array([
1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, // x-axis
1.0, 0.0, 0.0, 1.0, 0.95, 0.02, -0.02, 1.0, // x-axis arrowhead
1.0, 0.0, 0.0, 1.0, 0.95, -0.02, 0.02, 1.0, // x-axis arrowhead
0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, // y-axis
0.0, 1.0, 0.0, 1.0, 0.02, 0.95, -0.02, 1.0, // y-axis arrowhead
0.0, 1.0, 0.0, 1.0, -0.02, 0.95, 0.02, 1.0, // y-axis arrowhead
0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 1.0, // z-axis
0.0, 0.0, 1.0, 1.0, 0.02, -0.02, 0.95, 1.0, // z-axis arrowhead
0.0, 0.0, 1.0, 1.0, -0.02, 0.02, 0.95, 1.0, // z-axis arrowhead
// The cube around the origin.
// These sides must be drawn back to front to render it correctly with the alpha blending
-dCS, dCS, dCS, 1.0, -dCS, dCS, -dCS, 1.0, -dCS, -dCS, dCS, 1.0, -dCS, -dCS, -dCS, 1.0, // x = -dCS
dCS, -dCS, dCS, 1.0, dCS, -dCS, -dCS, 1.0, -dCS, -dCS, dCS, 1.0, -dCS, -dCS, -dCS, 1.0, // y = -dCS
dCS, dCS, -dCS, 1.0, dCS, -dCS, -dCS, 1.0, -dCS, dCS, -dCS, 1.0, -dCS, -dCS, -dCS, 1.0, // z = -dCS
dCS, dCS, dCS, 1.0, dCS, -dCS, dCS, 1.0, dCS, dCS, -dCS, 1.0, dCS, -dCS, -dCS, 1.0, // x = dCS
dCS, dCS, dCS, 1.0, dCS, dCS, -dCS, 1.0, -dCS, dCS, dCS, 1.0, -dCS, dCS, -dCS, 1.0, // y = dCS
dCS, dCS, dCS, 1.0, -dCS, dCS, dCS, 1.0, dCS, -dCS, dCS, 1.0, -dCS, -dCS, dCS, 1.0 // z = dCS
]);
gqWebGL = new CInstanceWebGL("idCanvas", "idVertexShader", "idFragmantShader", 42);
CreateProgramAndContext(gqWebGL);
CreateBuffers(gqWebGL);
// Begin the animation loop. This should use requestAnimationFrame instead
const kiIntervalId = setInterval(Render, 20);
}
function Render() {
RenderModel(gqWebGL);
}
var gfAngle = 0.0;
function RenderModel(qInstanceWebGL) {
// The view source will rotate around the z-axis
var dViewX = Math.sin(gfAngle);
var dViewY = Math.cos(gfAngle);
var faLookAtMatrix = CreateLookAtMatrix([.3*dViewX, .3*dViewY, .75],[0.0, 0.0, 0.0],[0, 1, 0]);
var faVert = qInstanceWebGL.mfaTransformedVertices;
var faClr = qInstanceWebGL.mfaVertexColors;
gfAngle = ((gfAngle + .02 >= 2.0*Math.PI) ? (gfAngle + .02 - 2.0*Math.PI) : gfAngle + .02);
// First copy the vertices before the transformation
for (var i = 0; i < (18+24)*4; ++i) {
faVert[i] = gfaVertices[i];
}
// Transform the axes and color them
for (var i = 0; i < 18; ++i) {
MultiplyMatrixVertex(faLookAtMatrix, faVert, 4*i);
// Set the colors too
faClr[4*i] = 0.25;
faClr[4*i + 1] = 0.25;
faClr[4*i + 2] = 0.25;
faClr[4*i + 3] = 1.0;
// Make the x-axis red, the y-axis green, and the z-axis blue
faClr[4*i + Math.floor(i/6)] = 1.0;
}
// Color the cube faces
for (var iFace = 0; iFace < 6; ++iFace) {
var fBrightness = 0.0;
if (iFace % 3 == 0) {
fBrightness = 1.0/7.0;
} else if (iFace % 3 == 2) {
fBrightness = 2.0/7.0;
} else {
fBrightness = 4.0/7.0;
}
var iBase = 18*4 + 16*iFace;
for (var iVertex = 0; iVertex < 4; ++iVertex) {
var iOffset = iBase + 4*iVertex;
faVert[iOffset] = gfaVertices[iOffset];
faVert[iOffset + 1] = gfaVertices[iOffset + 1];
faVert[iOffset + 2] = gfaVertices[iOffset + 2];
faVert[iOffset + 3] = gfaVertices[iOffset + 3];
faClr[iOffset] = fBrightness;
faClr[iOffset + 1] = fBrightness;
faClr[iOffset + 2] = fBrightness;
faClr[iOffset + 3] = .2;
}
}
// Transform the cube
for (var i = 18; i < 42; ++i) {
MultiplyMatrixVertex(faLookAtMatrix, faVert, 4*i);
}
// We need to create the buffers afterward
CreateBuffers(qInstanceWebGL);
var qGL = qInstanceWebGL.mqGL;
qGL.clearColor(0.0, 0.0, 0.0, 1.0);
qGL.enable(qGL.DEPTH_TEST);
qGL.clear(qGL.COLOR_BUFFER_BIT | qGL.DEPTH_BUFFER_BIT);
// Enable alpha blending
qGL.enable(qGL.BLEND);
// Set blending function
qGL.blendFunc(qGL.SRC_ALPHA, qGL.ONE_MINUS_SRC_ALPHA);
for (var i = 0; i < 9; ++i) {
qGL.drawArrays(qGL.LINES, i*2, 2);
}
// The six sides of the cube
daXOrder = (dViewX > 0.0) ? [18, 30] : [30, 18];
daYOrder = (dViewY > 0.0) ? [22, 34] : [34, 22];
qGL.drawArrays(qGL.TRIANGLE_STRIP, daXOrder[0], 4);
qGL.drawArrays(qGL.TRIANGLE_STRIP, daYOrder[0], 4);
qGL.drawArrays(qGL.TRIANGLE_STRIP, 26, 4);
qGL.drawArrays(qGL.TRIANGLE_STRIP, daXOrder[1], 4);
qGL.drawArrays(qGL.TRIANGLE_STRIP, daYOrder[1], 4);
qGL.drawArrays(qGL.TRIANGLE_STRIP, 38, 4);
}
// Multiply the four coordinate vertex in V at the start index
function MultiplyMatrixVertex(faM, faV, iStart) { // V = M*V
var faCopy = [0,0,0,0];
for (var i = 0; i < 4; ++i) {
faCopy[i] = faV[iStart + i];
}
for (iRow = 0; iRow < 4; ++iRow) {
faV[iStart + iRow] = faM[iRow]*faCopy[0] + faM[iRow + 4]*faCopy[1] + faM[iRow + 8]*faCopy[2] + faM[iRow + 12]*faCopy[3];
}
}
function Normalize(faV) {
var fL = Math.sqrt(faV[0]*faV[0] + faV[1]*faV[1] + faV[2]*faV[2]);
faV[0] /= fL; faV[1] /= fL; faV[2] /= fL;
}
function Dot(faV1, faV2) {
return (faV1[0]*faV2[0] + faV1[1]*faV2[1] + faV1[2]*faV2[2]);
}
function Cross(faV1, faV2) {
return [faV1[1]*faV2[2]-faV1[2]*faV2[1], faV1[2]*faV2[0]-faV1[0]*faV2[2], faV1[0]*faV2[1]-faV1[1]*faV2[0]];
}
function Difference(faV1, faV2) {
return [faV1[0]-faV2[0], faV1[1]-faV2[1], faV1[2]-faV2[2]];
}
function CreateLookAtMatrix(faEye, faObject, faUp) {
var faViewDirection = Difference(faObject, faEye);
Normalize(faViewDirection);
var faRight = Cross(faViewDirection, faUp);
Normalize(faRight);
var faStraightUp = Cross(faRight, faViewDirection);
var faMatrix = new Float32Array([
faRight[0], faStraightUp[0], faViewDirection[0], 0.0,
faRight[1], faStraightUp[1], faViewDirection[1], 0.0,
faRight[2], faStraightUp[2], faViewDirection[2], 0.0,
-Dot(faObject, faRight), -Dot(faObject, faStraightUp), -Dot(faObject, faViewDirection), 1.0]);
return faMatrix;
}
function CInstanceWebGL(sCanvasID, sVertexShaderID, sFragmentShaderID, iVertices) {
this.mqGL = null;
this.mqProgram = null;
this.msCanvasID = sCanvasID;
this.msVertexShaderID = sVertexShaderID;
this.msFragmentShaderID = sFragmentShaderID;
this.mfaTransformedVertices = new Float32Array(4*iVertices);
this.mfaVertexColors = new Float32Array(4*iVertices);
}
</script>
</head>
<body onload="Initialization();">
<canvas id="idCanvas" width="400", height="400" style="border:1px solid lightgray"></canvas>
</body>
</html>© 20072025 XoaX.net LLC. All rights reserved.