WebGL JavaScript

Viewing the Default Orientation

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.

ViewingTheDefaultOrientation.html

<!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>
 

Output

 
 

© 2007–2024 XoaX.net LLC. All rights reserved.