This JavaScript program demonstrates the default viewing space for a WebGL program. The default viewing space is a the 2 by 2 by 2 cube from -1 to 1 in the x, y, and z dimensions.
<!DOCTYPE html> <html> <head> <title>XoaX.net's WebGL</title> <script id="idModelVertexShader" type="c"> attribute vec4 av4Vertex; attribute vec4 av4Color; varying vec4 vv4Color; void main() { gl_Position = av4Vertex; vv4Color = av4Color; } </script> <script id="idModelFragmantShader" type="c"> precision mediump float; varying vec4 vv4Color; void main() { gl_FragColor = vv4Color; } </script> <script id="idViewVertexShader" type="c"> attribute vec4 av4Vertex; attribute vec4 av4Color; varying vec4 vv4Color; void main() { gl_Position = av4Vertex; vv4Color = av4Color; } </script> <script id="idViewFragmantShader" type="c"> precision mediump float; varying vec4 vv4Color; void main() { gl_FragColor = vv4Color; } </script> <script type="text/javascript"> var gqModelWebGL = null; var gqViewWebGL = 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() { gfaVertices = new Float32Array([ // Put the vertices for the diamond first, then the cube vertices 0.0, 0.85, 0.0, 1.0, 0.85, 0.0, 0.85, 1.0, -0.85, 0.0, -0.85, 1.0, 0.0, -0.85, 0.0, 1.0, // These must be drawn back to front to render it correctly with the alpha blending -1.0, 1.0, 1.0, 1.0, -1.0, 1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, -1.0, -1.0, -1.0, 1.0, // x = -1 1.0, -1.0, 1.0, 1.0, 1.0, -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, -1.0, -1.0, -1.0, 1.0, // y = -1 1.0, 1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, -1.0, 1.0, -1.0, 1.0, -1.0, -1.0, -1.0, 1.0, // z = -1 1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, // x = 1 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, -1.0, 1.0, 1.0, 1.0, -1.0, 1.0, -1.0, 1.0, // y = 1 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0 // z = 1 ]); gqModelWebGL = new CInstanceWebGL("idModelCanvas", "idModelVertexShader", "idModelFragmantShader", 4); gqViewWebGL = new CInstanceWebGL("idViewCanvas", "idViewVertexShader", "idViewFragmantShader", 7*4); CreateProgramAndContext(gqModelWebGL); CreateProgramAndContext(gqViewWebGL); CreateBuffers(gqModelWebGL); CreateBuffers(gqViewWebGL); // Begin the animation loop. const kiIntervalId = setInterval(Render, 20); } function Render() { RenderModel(gqModelWebGL); RenderModel(gqViewWebGL); } var gfAngle = 0.0; function RenderModel(qInstanceWebGL) { var qGL = qInstanceWebGL.mqGL; var faVert = qInstanceWebGL.mfaTransformedVertices; var faClr = qInstanceWebGL.mfaVertexColors; // Create the rotation matrix var faRotationMatrix = CreateARotationAroundYMatrix(gfAngle); // Transform the first four vertices by the rotation: 4 vertices with 4 coordinates // First copy the vertices before the transformation for (var i = 0; i < 16; ++i) { faVert[i] = gfaVertices[i]; } // Transform each diamond vertex for (var i = 0; i < 4; ++i) { MultiplyMatrixVertex(faRotationMatrix, faVert, 4*i); // Set the colors too faClr[4*i] = .25; faClr[4*i + 1] = .4 + Math.min(Math.max(Math.sin(faVert[4*i + 2]), -.4), .4); faClr[4*i + 2] = .25; faClr[4*i + 3] = 1.0; } gfAngle += .01; gfAngle = ((gfAngle >= 2.0*Math.PI) ? (gfAngle - 2.0*Math.PI) : gfAngle); if (qInstanceWebGL === gqViewWebGL) { var faLookAtMatrix = CreateLookAtMatrix([1, 3, 2],[0, 0, 0],[0, 1, 0]); // Create the orthographic matrix var faOrthoMatrix = CreateOrthographicMatrix(-2.0, 2.0, -2.0, 2.0, 2.0, -2.0); MultiplyMatrices(faOrthoMatrix, faLookAtMatrix); // Add the extra colors for the view cube 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 = 16 + 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; } } for (var i = 0; i < 28; ++i) { MultiplyMatrixVertex(faOrthoMatrix, faVert, 4*i); } } // We need to create the buffers afterward CreateBuffers(qInstanceWebGL); qGL.clearColor(0.0, 0.0, 0.0, 1.0); if (qInstanceWebGL !== gqViewWebGL) { qGL.clear(qGL.COLOR_BUFFER_BIT); qGL.drawArrays(qGL.TRIANGLE_STRIP, 0, 4); } else { 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); qGL.drawArrays(qGL.TRIANGLE_STRIP, 0, 4); // The six sides qGL.drawArrays(qGL.TRIANGLE_STRIP, 4, 4); qGL.drawArrays(qGL.TRIANGLE_STRIP, 8, 4); qGL.drawArrays(qGL.TRIANGLE_STRIP, 12, 4); qGL.drawArrays(qGL.TRIANGLE_STRIP, 16, 4); qGL.drawArrays(qGL.TRIANGLE_STRIP, 20, 4); qGL.drawArrays(qGL.TRIANGLE_STRIP, 24, 4); } } function CreateARotationAroundYMatrix(fRotateRadians) { var fSin = Math.sin(fRotateRadians); var fCos = Math.cos(fRotateRadians); var faMatrix = new Float32Array([ fCos, 0.0, -fSin, 0.0, 0.0, 1.0, 0.0, 0.0, fSin, 0.0, fCos, 0.0, 0.0, 0.0, 0.0, 1.0]); return faMatrix; } // 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 CreateOrthographicMatrix(fLeft, fRight, fBottom, fTop, fNear, fFar) { if (fLeft >= fRight || fBottom >= fTop || fFar >= fNear) { throw 'Improper Orthographic Projection Matrix'; } fDx = fRight - fLeft; fDy = fTop - fBottom; fDz = fNear - fFar; var faMatrix = new Float32Array([ 2.0/fDx, 0.0, 0.0, 0.0, 0.0, 2.0/fDy, 0.0, 0.0, 0.0, 0.0, 2.0/fDz, 0.0, -(fLeft + fRight)/fDx, -(fBottom + fTop)/fDy, -(fNear + fFar)/fDz, 1.0]); return faMatrix; } function MultiplyMatrices(faaM, faaA) { // M = M*A, Note M != A var faRow = [0,0,0,0]; for (iRow = 0; iRow < 4; ++iRow) { // Copy the current row for(iCol = 0; iCol < 4; ++iCol) { faRow[iCol] = faaM[iRow + 4*iCol]; } for(iCol = 0; iCol < 4; ++iCol) { faaM[iRow + 4*iCol] = 0.0; for (k = 0; k < 4; ++k) { faaM[iRow + 4*iCol] += faRow[k]*faaA[4*iCol + k]; } } } } 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="idModelCanvas" width="400", height="400" style="border:1px solid lightgray"></canvas> <canvas id="idViewCanvas" width="400", height="400" style="border:1px solid lightgray"></canvas> </body> </html>
© 20072024 XoaX.net LLC. All rights reserved.