WebGL has opened a new era of 3D rendering of web pages, which allows 3D content to be rendered directly in canvas without the help of any plug-ins. Like the canvas 2D API, WebGL manipulates objects through scripts, so the steps are basically similar: prepare the working context, prepare the data, draw the object in canvas and render it. Unlike 2D, 3D involves more knowledge, such as world, light, texture, camera, matrix and other professional knowledge. WebGL has a good Chinese tutorial, which is the first link in the reference below, so I won’t show off my skills here. The following content is just a brief summary of what I learned.
Browser supportSince Microsoft has its own graphics development plan and has not supported WebGL, IE cannot run WebGL except for installing plugins. Other mainstream browsers such as Chrome, FireFox, Safari, Opera, etc., are all installed with the latest version. In addition to installing the latest browser, you must also ensure that the graphics card driver is also up-to-date.
After installing these, you can open the browser and enter the following URL to verify the browser's support for WebGL: http://webglreport.sourceforge.net/.
After installing the above browser normally, you can still not run WebGL, so you can forcefully enable WebGL support and try it. The method to enable it is as follows:
Chrome browser We need to add some startup parameters to Chrome. The following specific operation steps are taken as an example: find the shortcut to Chrome browser, right-click the shortcut, and select properties; in the target box, after the quotes after chrome.exe, add the following content: --enable-webgl-ignore-gpu-blacklist-allow-file-access-from-filesClick OK to close Chrome, and then use this shortcut to launch Chrome browser.
The meanings of several parameters are as follows:
--enable-webgl means to enable WebGL support;
--ignore-gpu-blacklist means to ignore the GPU blacklist, which means that some graphics card GPUs are not recommended to run WebGL because they are too old and other reasons. This parameter allows the browser to ignore this blacklist and force WebGL to run;
--allow-file-access-from-files means that you allow the loading of resources from locally. If you are not a WebGL developer and do not need to develop and debug WebGL, but just want to take a look at the WebGL demo, then you can not add this parameter.
Firefox browser Firefox users, please enter about:config in the browser's address bar, enter, and then search for webgl in the filter (filter), set webgl.force-enabled to true; set webgl.disabled to false; search for security.fileuri.strict_origin_policy in the filter (filter), set security.fileuri.strict_origin_policy to false; then close all Firefox windows currently open and restart Firefox.The first two settings are to force WebGL support, and the last security.fileuri.strict_origin_policy setting is to allow the loading of resources from the local area. If you are not a WebGL developer and do not need to develop and debug WebGL, but just want to take a look at the WebGL demo, then you can not set this item.
Safari browser Find Properties → Advanced in the menu, select Show Development Menu, then go to the Development Menu, and select Turn on WebGL. Development stepsThe following code is just a brief summary of the relevant concepts. It comes from the Chinese tutorial in the reference and involves a lot of knowledge in 3D. Interested students can directly jump to the Chinese tutorial in the practical reference to learn, which is much more detailed and accurate than what I explained here. Students who are joining in the fun can just take a look, without delving into the meaning of each line of code.
Preparation Needless to say, it is to add a canvas element to the page as a rendering container. For example:<bodyonload="start()">
<canvasid="glcanvas"width="640"height="480">
Yourbrowserdoesn'tappeartosupport theHTML5canvaselement.
</canvas>
</body>
Here is the time to officially start writing scripts. First, let’s take a look at the program entrance and overall structure:
functionstart(){
varcanvas=document.getElementById("glcanvas");
initGL(canvas);
initShaders();
initBuffers();
gl.clearColor(0.0,0.0,0.0,1.0);
gl.enable(gl.DEPTH_TEST);
drawScene();
}
Several methods here represent the drawing steps of a typical WebGL:
Step 1: Initialize the WebGL working environment - initGL The code for this method is as follows:vargl;
functioninitGL(canvas){
gl=null;
try{
//Trytograbthestandardcontext.Ifitfails,fallbacktoexperimental.
gl=canvas.getContext("webgl")||canvas.getContext("experimental-webgl");
}
catch(e){} //Ifwedon'thaveaGLcontext,giveupnow
if(!gl){
alert("UnabletoinitializeWebGL.Yourbrowsermaynotsupportit.");
}
}
This method is very simple, which is to obtain the WebGL drawing environment. You need to pass the parameter webgl to the canvas.getContext method. However, since the current WebGL standard has not been finalized, the parameters used in the experimental stage are experimental-webgl. Of course, it is also OK to call canvas.getContext(experimental-webgl). After the standards are set, you can modify another code.
Step 2: Initialize Shaders - initShaders The concept of shader Shader is relatively simple, to put it bluntly, it is the graphics card operation command. Constructing a 3D scene requires a lot of calculations of color, position and other information. If these calculations are performed by the software, the speed will be very slow. So if you let the graphics card calculate these operations, the speed is very fast; how to perform these calculations is specified by the shader. The shader code is written in a shader language called GLSL, and we won't talk about this language anymore.Shaders can be defined in html and used in code. Of course, it is the same for you to define a shader with a string in your program.
Let’s look at the definition first:
<scriptid="shader-fs"type="x-shader/x-fragment">
precisionmediumpfloat;
varyingvec4vColor;
voidmain(void){
gl_FragColor=vColor;
}
</script>
<scriptid="shader-vs"type="x-shader/x-vertex">
attributevec3aVertexPosition;
attributevec4aVertexColor;
uniformmat4uMVMatrix;
uniformmat4uPMatrix;
varyingvec4vColor;
voidmain(void){
gl_Position=uPMatrix*uMVMatrix*vec4(aVertexPosition, 1.0);
vColor=aVertexColor;
}
</script>
Here are two shaders: face shader and vertex shader.
Regarding these two shaders, it is necessary to explain here that the 3D models in computers are basically described by points combined with triangle faces. The vertex shader processes the data of these points, and the surface shader processes the data of points on the triangle faces through interpolation.
The vertex shader defined above defines the position and color calculation method of vertices; while the surface shader defines the color calculation method of interpolated points. In actual application scenarios, it will also involve processing light and other effects in shaders.
Define shaders, you can find them in the program and use them:
varshaderProgram;
functioninitShaders(){
varfragmentShader=getShader(gl,"shader-fs");
varvertexShader=getShader(gl,"shader-vs");
shaderProgram=gl.createProgram();
gl.attachShader(shaderProgram,vertexShader);
gl.attachShader(shaderProgram,fragmentShader);
gl.linkProgram(shaderProgram);
if(!gl.getProgramParameter(shaderProgram,gl.LINK_STATUS)){
alert("Couldnotinitialiseshaders");
}
gl.useProgram(shaderProgram);
shaderProgram.vertexPositionAttribute=gl.getAttribLocation(shaderProgram,"aVertexPosition");
gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute);
shaderProgram.vertexColorAttribute=gl.getAttribLocation(shaderProgram,"aVertexColor");
gl.enableVertexAttribArray(shaderProgram.vertexColorAttribute);
shaderProgram.pMatrixUniform=gl.getUniformLocation(shaderProgram,"uPMatrix");
shaderProgram.mvMatrixUniform=gl.getUniformLocation(shaderProgram,"uMVMatrix");
}
There is a shader, but how to make the graphics card execute? Program is such a bridge. It is a native binary code of WebGL. Its function is basically to let the graphics card run the shader code to render the specified model data.
Here is also an auxiliary method getShader. This method is to traverse the html document, find the definition of the shader, and create the shader after getting the definition. I won't go into details here:
functiongetShader(gl,id){
varshaderScript, theSource,currentChild,shader;
shaderScript=document.getElementById(id);
if(!shaderScript){
returnnull;
}
theSource="";
currentChild=shaderScript.firstChild;
while(currentChild){
if(currentChild.nodeType==currentChild.TEXT_NODE){
theSource+=currentChild.textContent;
}
currentChild=currentChild.nextSibling;
}
if(shaderScript.type=="x-shader/x-fragment"){
shader=gl.createShader(gl.FRAGMENT_SHADER);
}elseif(shaderScript.type=="x-shader/x-vertex"){
shader=gl.createShader(gl.VERTEX_SHADER);
}else{
//Unknownshadertype
returnnull;
}
gl.shaderSource(shader,theSource);
//Compiletheshaderprogram
gl.compileShader(shader);
//Seeifitcompiledsuccessfully
if(!gl.getShaderParameter(shader,gl.COMPILE_STATUS)){
alert("Anerroroccurredcompilingtheshaders:"+gl.getShaderInfoLog(shader));
returnnull;
}
returnshader;
}
Step 3: Create/Load Model Data - initBuffers In these small examples, the model data is basically generated directly. In actual programs, these data should be obtained from the model loading:vartriangleVertexPositionBuffer;
vartriangleVertexColorBuffer;
functioninitBuffers(){
triangleVertexPositionBuffer=gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER,triangleVertexPositionBuffer);
varvertices=[
0.0,1.0,0.0,
-1.0,-1.0,0.0,
1.0,-1.0,0.0
];
gl.bufferData(gl.ARRAY_BUFFER,newFloat32Array(vertices),gl.STATIC_DRAW);
triangleVertexPositionBuffer.itemSize=3;
triangleVertexPositionBuffer.numItems=3;
triangleVertexColorBuffer=gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER,triangleVertexColorBuffer);
varcolors=[
1.0,0.0,0.0,1.0,
0.0,1.0,0.0,1.0,
0.0,0.0,1.0,1.0
];
gl.bufferData(gl.ARRAY_BUFFER,newFloat32Array(colors),gl.STATIC_DRAW);
triangleVertexColorBuffer.itemSize=4;
triangleVertexColorBuffer.numItems=3;
}
The above code creates the vertices and color data of the triangle and puts them in the buffer.
Step 4: Rendering - drawScene After preparing the data, just hand it over to WebGL for rendering. The gl.drawArrays method is called here. Look at the code:functiondrawScene(){
gl.viewport(0,0,gl.viewportWidth,gl.viewportHeight);
gl.clear(gl.COLOR_BUFFER_BIT|gl.DEPTH_BUFFER_BIT);
pMatrix=okMat4Proj(45.0,gl.viewportWidth/gl.viewportHeight,0.1,100.0);
mvMatrix=okMat4Trans(-1.5, 0.0,-7.0);
gl.bindBuffer(gl.ARRAY_BUFFER,triangleVertexPositionBuffer);
gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute,triangleVertexPositionBuffer.itemSize,gl.FLOAT,false,0,0);
gl.bindBuffer(gl.ARRAY_BUFFER,triangleVertexColorBuffer);
gl.vertexAttribPointer(shaderProgram.vertexColorAttribute,triangleVertexColorBuffer.itemSize,gl.FLOAT,false,0,0);
setMatrixUniforms();
gl.drawArrays(gl.TRIANGLES,0,triangleVertexPositionBuffer.numItems);
}
This function first sets the background of the 3D world to black, then sets the projection matrix, sets the position of the object to be drawn, and then draws the object according to the vertex and color data in the buffer. There are also some auxiliary methods for generating projection matrix and model view rectangles (using the matrix auxiliary method in the Oak3D graphics library) that have little to do with the topic, so I will not explain it in detail here.
Basically there are so many processes. More complex textures, light, etc. are implemented based on these. Please refer to the Chinese tutorial below, which contains detailed examples.
How about it? What is it like to use native WebGL development? Not only do you need to have deep 3D knowledge, but you also need to know various implementation details. WebGL does this to adapt to various application scenarios flexibly, but for most non-professionals like me, many details do not need to be known. This has given rise to various class libraries for assisting development, such as the Oak3D library used in this section (in order to demonstrate WebGL development, only matrix assisting methods were used in the examples). The next section will introduce a more widely used Three.js graphics library.
Practical reference:Chinese tutorial: http://www.hiwebgl.com/?p=42
Development Center: https://developer.mozilla.org/en/WebGL