WebGL JavaScript

Draw a Wooden Cross

This JavaScript program demonstrates how to apply image textures to draw a wooden cross in a WebGL program.

WoodenCross.html

<!DOCTYPE html>
<html>
  <head>
    <title>XoaX.net's WebGL</title>

    <script  id="idVertexShader" type="c">
      // The attributes receives data from the buffers
      attribute vec2 afVertexCoordinates;
      uniform mat2 afScaleMatrix;
      uniform vec2 afTranslation;
      varying vec2 afTextureCoordinates;
      void main() {
        afTextureCoordinates = afScaleMatrix*(afVertexCoordinates + afTranslation);
        gl_Position = vec4(afVertexCoordinates, 0.0, 5.0);
      }
    </script>

    <script  id="idFragmantShader" type="c">
      precision mediump float;
      varying vec2 afTextureCoordinates;
      uniform sampler2D qUniformSampler;
      void main() {
        gl_FragColor = texture2D(qUniformSampler, afTextureCoordinates);
      }
    </script>

    <script type="text/javascript">
    function CreateTextures(qGL, qaImages) {
      var aqTextures = [];
      for (var i = 0; i < 3; ++i) {
        var qTexture = qGL.createTexture();
        qGL.bindTexture(qGL.TEXTURE_2D, qTexture);
        qGL.pixelStorei(qGL.UNPACK_FLIP_Y_WEBGL, true);

		// Set the parameters so we can render any size image.
		qGL.texParameteri(qGL.TEXTURE_2D, qGL.TEXTURE_WRAP_S, qGL.CLAMP_TO_EDGE);
		qGL.texParameteri(qGL.TEXTURE_2D, qGL.TEXTURE_WRAP_T, qGL.CLAMP_TO_EDGE);
		qGL.texParameteri(qGL.TEXTURE_2D, qGL.TEXTURE_MIN_FILTER, qGL.LINEAR);
		qGL.texParameteri(qGL.TEXTURE_2D, qGL.TEXTURE_MAG_FILTER, qGL.LINEAR);

		// Upload the image into the texture.
        qGL.texImage2D(qGL.TEXTURE_2D, 0, qGL.RGBA, qGL.RGBA, qGL.UNSIGNED_BYTE, qaImages[i]);
        aqTextures.push(qTexture);
      }
      return aqTextures;
    }

    function FinishRendering(qGL, qProgram, aqTextures) {
      // Clear the screen
	  qGL.clearColor(.5, 0.8, 0.5, 1);
	  qGL.clear(qGL.COLOR_BUFFER_BIT);

	  // Draw the textures
      var aiTextureIndices = [qGL.TEXTURE0, qGL.TEXTURE1, qGL.TEXTURE2];
      var aafScaleTrans = [[1.0/2.0, 1.0, 2.5, .5],[1.0, 1.0/7.0, .5, 4.5],[1.0/2.0, 1.0, -.5, .5]];
      for (var i = 0; i < 3; ++i) {
        // Create the scaling Matrix
        var afScaleMatrixCoord = new Float32Array([
          aafScaleTrans[i][0],   0.0,
          0.0,       aafScaleTrans[i][1]
        ]);
        var qScaleMatrix = qGL.getUniformLocation(qProgram, 'afScaleMatrix');
        qGL.uniformMatrix2fv(qScaleMatrix, false, afScaleMatrixCoord);

        // Create the translation
        var qTranslation = qGL.getUniformLocation(qProgram, 'afTranslation');
        qGL.uniform2f(qTranslation, aafScaleTrans[i][2], aafScaleTrans[i][3]);

        qGL.activeTexture(aiTextureIndices[i]);
        qGL.bindTexture(qGL.TEXTURE_2D, aqTextures[i]);

        var qUniformSampler = qGL.getUniformLocation(qProgram, 'qUniformSampler');
        qGL.uniform1i(qUniformSampler, i);

        var qAttrLoc = qGL.getAttribLocation(qProgram, "afVertexCoordinates");
        qGL.enableVertexAttribArray(qAttrLoc);
        qGL.vertexAttribPointer(qAttrLoc, 2, qGL.FLOAT, false, 0, 32*i);

        qGL.drawArrays(qGL.TRIANGLE_STRIP, 0, 4);
      }
    }

    function CreateNextImage(qGL, qProgram, aqImages, asFilenames, iIndex) {
      var qNewImage = new Image();
      qNewImage.onload = function() {
        aqImages.push(qNewImage);
        if (iIndex == 2) {
          var aqTextures = CreateTextures(qGL, aqImages);
          FinishRendering(qGL, qProgram, aqTextures);
        } else {
          CreateNextImage(qGL, qProgram, aqImages, asFilenames, iIndex + 1);
        }
      }
      qNewImage.src = asFilenames[iIndex];
    }

    function Draw(qGL, qProgram) {
      var asFilenames = ['LeftTexture.jpg', 'CenterTexture.jpg', 'RightTexture.jpg'];
      var aqImages = [];
      CreateNextImage(qGL, qProgram, aqImages, asFilenames, 0);
    }

    function Render() {
      // Get the WebGL Context
      var qCanvas = document.querySelector("#idCanvasWebGL");
      var qGL = qCanvas.getContext("webgl");

      // Compile the vertex shader
      var sVertexShaderCode = document.querySelector("#idVertexShader").text;
      var qVertexShader = qGL.createShader(qGL.VERTEX_SHADER);
      qGL.shaderSource(qVertexShader, sVertexShaderCode);
      qGL.compileShader(qVertexShader);

      // Compile the fragment shader
      var sFragmentShaderCode = document.querySelector("#idFragmantShader").text;
      var qFragmentShader = qGL.createShader(qGL.FRAGMENT_SHADER);
      qGL.shaderSource(qFragmentShader, sFragmentShaderCode);
      qGL.compileShader(qFragmentShader);

      // Compile and link the program
      var qProgram = qGL.createProgram();
      qGL.attachShader(qProgram, qVertexShader);
      qGL.attachShader(qProgram, qFragmentShader);
      qGL.linkProgram(qProgram);
      qGL.useProgram(qProgram);

      qGL.bindBuffer(qGL.ARRAY_BUFFER, qGL.createBuffer());
      qGL.bufferData(qGL.ARRAY_BUFFER, new Float32Array([
				-2.5, .5,
				-2.5, -.5,
				-.5, .5,
				-.5, -.5,

				-.5, -4.5,
				.5, -4.5,
				-.5, 2.5,
				.5, 2.5,

				2.5, -.5,
				2.5, .5,
				.5, -.5,
				.5, .5
      ]), qGL.STATIC_DRAW);

	  Draw(qGL, qProgram);
    }
    </script>
  </head>
  <body onload="Render()">
    <canvas id="idCanvasWebGL" width="512" height="512" style="border:1px solid red"></canvas>
  </body>
</html>
 

Output

 
 

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