The webGL API addresses are as follows:
www.khronos.org/registry/we… www.khronos.org/registry/we…
Shader language in a web page in several ways
1. Write the shader language in a separate file, such as vtrtex.bns. Get text content by getting files.
There is no official extension in the shader language specification. OpenGL can’t handle loading shaders from files; You just pass the shader code as a string, so there is no specific file format. However, Khronos’ reference GLSL compiler/validator GLSLANG uses the following extension to determine the type of shader this file is used for: Tesc – Mosaic control shader. Tese – Mosaic evaluation shader. Geom – geometry shader. Frag – fragment shader
2. Write the shader language as a string and assign it to the js variable.
// Vertex shader program
var VSHADER_SOURCE =
'void main() {\n' +
'gl_Position = vec4(0.0, 0.0, 0.0, 1.0); \n' + // Set the vertex coordinates of the point
'gl_PointSize = 10.0; \n' + // Set the point size
'}\n';
Copy the code
3. Insert HTML through the script tag, and then get the text inside the tag by id.
<script id="shader-vs" type="x-shader/x-vertex">
attribute vec3 v3Position; // Vertex coordinates
attribute vec3 av3Color; // Vertex color attribute
varying vec3 vv3Color; // The vertex shader and fragment shader communicate with each other. Note that the vertex and fragment shader define variables with the same name
void main(void){
vv3Color = av3Color;
gl_Position = vec4(v3Position, 1.0);
}
</script>
Copy the code
The general flow of a WebGL application
We say it takes three steps to put an elephant in a fridge, so writing a WebGL application should only take three steps:
- 1. Put the data into the buffer
- 2. Pass the buffer data to the shader
- 3. Shaders feed data to the GPU.
Here is a rough flow chart of a WebGL application:
demo1
<! DOCTYPE html><html>
<head>
<meta charset="utf-8">
<title></title>
<script>
var webgl = null;
function Init(){
var canvas = document.getElementById('myCanvas');
webgl = canvas.getContext("webgl");// Similar to create draw engine or initialization
// Set the render area of WebGL (viewarea)
webgl.viewport(0.0,canvas.clientWidth,canvas.clientHeight)
The // method is used to set the color value when the color buffer is cleared
webgl.clearColor(0.0.0.0.0.0.1.0);
The // method uses default values to clear the buffer
// gl.color_buffer_bit // color buffer
// gl.depth_buffer_bit // depth buffer
// gl.stencil_buffer_bit // template buffer
webgl.clear(webgl.COLOR_BUFFER_BIT);
// It must be emphasized
// 1. GlClearColor is Set and does not Clear anything! Don't confuse ~
// 2. GlClearColor specifies the color to use when flushing the color buffer.
// So, to complete a refresh process, use glClearColor(COLOR) in conjunction with glClear(GL_COLOR_BUFFER_BIT). GlClearColor (0.0, 0.0, 1.0, 1.0); / / blue
// glClear(GL_COLOR_BUFFER_BIT);
// The purpose of clearing the color buffer is to prevent the color information in the buffer from affecting the drawing. When the drawing area is the entire window, as is usually seen, the clear value of the color buffer is the background color of the window. Therefore, these two clear instructions are not necessary: for static images only need to be set once, for example, the background color is not required/the background color is white.
// glClear is more efficient and less effort than manually painting a background canvas, so this method is usually used.
}
// Frame buffer (more than one) two-dimensional image color buffer, depth buffer, template buffer
</script>
</head>
<body onload='Init()'>
<canvas id="myCanvas" style="border:1px solid red;" width="600" height="450"></canvas>
</body>
</html>
Copy the code
demo2
WebGL is designed to interact directly with the graphics card, first by compiling the shader code:
function initShaders(webgl, vertexShaderId, framentShaderId, bindVariableData) {
/ / generated shaderobject
var vertexShaderObject = webgl.createShader(webgl.VERTEX_SHADER);
var fragmentShaderObject = webgl.createShader(webgl.FRAGMENT_SHADER);
/ / compile a shader
compileShader(webgl, shaderSourceFromScript(vertexShaderId), shaderSourceFromScript(framentShaderId), vertexShaderObject, fragmentShaderObject);
/ / links shader
// Create a program object
programObject = webgl.createProgram();
// Associate the shader variable to an attribute index. This operation must be performed before linking
if(! bindVariableDatainstanceof Array) {
alert("Incorrect input parameter");
return;
}
for(var i = 0; i < bindVariableData.length; i++) {
// Bind the generic vertex index to the property variable
webgl.bindAttribLocation(programObject, bindVariableData[i][0], bindVariableData[i][1]);
}
programObject = linkShader(webgl, programObject, vertexShaderObject, fragmentShaderObject);
return programObject;
}
/ / compile a shader
ShaderVectexCode shaderFramentCode GLSL string
function compileShader(webgl, shaderVectexCode, shaderFramentCode, vertexShaderObj, fragmentShaderObj) {
// Load the shader code into the Shader Object
webgl.shaderSource(vertexShaderObj, shaderVectexCode);
webgl.shaderSource(fragmentShaderObj, shaderFramentCode);
// Compile the shader code
webgl.compileShader(vertexShaderObj);
webgl.compileShader(fragmentShaderObj);
// Check whether the compilation is successful
if(! webgl.getShaderParameter(vertexShaderObj, webgl.COMPILE_STATUS)) { alert("error:vertexShaderObject");
return;
}
if(! webgl.getShaderParameter(fragmentShaderObj, webgl.COMPILE_STATUS)) { alert("error:framentShaderObject");
return; }}Copy the code
Compile two pieces of code, which act as library files, into binary code that can be executed on the video card, and then create a program, which acts as an exe, that links the two shader codes. Then perform the link operation to form a program that can be executed on the graphics card. Association via programObject handle.
Handle is a term often used in C++ programming. It is not a specific, fixed data type or entity, but represents a broad concept in programming. A handle generally refers to a method of obtaining another object — a generalized pointer, which may take the form of an integer, an object, or just a real pointer, and its purpose is to establish a unique connection to the object being accessed.
To run a program, input and output are vec3 v3Position and VEC3 vv3Color in the GLSL Vertex shader code
webgl.bindAttribLocation(programObject,v3PositionIndex,"v3Position")
Copy the code
Bind v3PositionIndex to v3Position, which is the input
Now it’s time to upload the vertex data to the video card. Create a buffer on the video card to store the data, declare the buffer storage type, and then pass the ArrayData data to the buffer.
triangleBuffer = webgl.createBuffer();// Create a buffer on the graphics card
webgl.bindBuffer(webgl.ARRAY_BUFFER,triangleBuffer);// declare that the storage type of the cache is ARRAY_BUFFER
webgl.bufferData(webgl.ARRAY_BUFFER,new Float32Array(ArrayData),webgl.STATIC_DRAW);// Assign a value to the cache
Copy the code
The next step is to run the above application on the graphics card, using a buffer (bufferData()), enabling v3PositionIndex, telling the graphics card application how to use the data in the graphics card buffer (vertexAttribPointer ()), and then drawing.
webgl.bindBuffer(webgl.ARRAY_BUFFER, triangleBuffer);
webgl.enableVertexAttribArray(v3PositionIndex);
webgl.vertexAttribPointer(v3PositionIndex, 3, webgl.FLOAT, false.0.0);
webgl.bindBuffer(webgl.ARRAY_BUFFER, triangleColorBuffer);
webgl.enableVertexAttribArray(v3ColorIndex);
webgl.vertexAttribPointer(v3ColorIndex, 3, webgl.FLOAT, false.0.0);
// Draw data
webgl.drawArrays(webgl.TRIANGLES, 0.3);
Copy the code
The complete code
<html>
<head>
<! Use GLSL ES language, write vertex shader and slice shader, and the corresponding shader program. 3. Prepare the vertex data of the image you want to draw. 4. Match the variables in the shader to the buffer containing the vertex data. 5.
<script id="shader-vs" type="x-shader/x-vertex">
attribute vec3 v3Position; // Vertex coordinates
attribute vec3 av3Color; // Vertex color attribute
varying vec3 vv3Color; // The vertex shader and fragment shader communicate with each other. Note that the vertex and fragment shader define variables with the same name
void main(void){
vv3Color = av3Color;
gl_Position = vec4(v3Position, 1.0);
}
</script>
<script id="shader-fs" type="x-shader/x-fragment">
#ifdef GL_FRAGMENT_PRECISION_HIGH
precision highp float;
#else
precision mediump float;
#endif
varying vec3 vv3Color;
void main(void){
gl_FragColor = vec4(vv3Color, 1.0);
}
</script>
<script>
var webgl = null;
var vertexShaderObject = null;
var fragmentShaderObject = null;
var programObject = null;
var triangleBuffer = null;
var triangleColorBuffer = null;
var v3PositionIndex = 0;
var v3ColorIndex = 1;
var r = 1.0;
var g = 1.0;
var b = 1.0;
var isDesc = false;
// Initialize the code
function init() {
// Initialize the WebGL render area
webgl = initCanvas("webglCanvas");
// Initialize the shader program
var bind1 = [v3PositionIndex, "v3Position"];
var bind2 = [v3ColorIndex, "av3Color"]; / / av3Color variable names
var bindData = new Array(a); bindData.push(bind1); bindData.push(bind2);// Initializes the Shader program and returns the linked program object
var programObject = initShaders(webgl, "shader-vs"."shader-fs", bindData);
// Add the defined WebGLProgram object to the current render state.
webgl.useProgram(programObject);
/ / discoloration
window.setInterval("changeColor()".10);
// Initialize vertex data
triangleBuffer = initVextexData(webgl);
}
// Initializes the Shader program and returns the linked program object
function initShaders(webgl, vertexShaderId, framentShaderId, bindVariableData) {
/ / generated shaderobject
var vertexShaderObject = webgl.createShader(webgl.VERTEX_SHADER);
var fragmentShaderObject = webgl.createShader(webgl.FRAGMENT_SHADER);
/ / compile a shader
compileShader(webgl, shaderSourceFromScript(vertexShaderId), shaderSourceFromScript(framentShaderId),vertexShaderObject, fragmentShaderObject);
/ / links shader
// Create a program object
programObject = webgl.createProgram();
// Associate the shader variable to an attribute index. This operation must be performed before linking
if(! bindVariableDatainstanceof Array) {
alert("Incorrect input parameter");
return;
}
for (var i = 0; i < bindVariableData.length; i++) {
// Bind the generic vertex index to the property variable
//console.log(programObject, bindVariableData[i][0], bindVariableData[i][1])
webgl.bindAttribLocation(programObject, bindVariableData[i][0], bindVariableData[i][1]);
}
programObject = linkShader(webgl, programObject, vertexShaderObject, fragmentShaderObject);
return programObject;
}
/ / compile a shader
ShaderVectexCode shaderFramentCode GLSL string
function compileShader(webgl, shaderVectexCode, shaderFramentCode, vertexShaderObj, fragmentShaderObj) {
// Load the shader code into the Shader Object
webgl.shaderSource(vertexShaderObj, shaderVectexCode);
webgl.shaderSource(fragmentShaderObj, shaderFramentCode);
// Compile the shader code
webgl.compileShader(vertexShaderObj);
webgl.compileShader(fragmentShaderObj);
// Check whether the compilation is successful
if(! webgl.getShaderParameter(vertexShaderObj, webgl.COMPILE_STATUS)) { alert("error:vertexShaderObject");
return;
}
if(! webgl.getShaderParameter(fragmentShaderObj, webgl.COMPILE_STATUS)) { alert("error:framentShaderObject");
return; }}// Vertex data
function initVextexData(webgl) {
// Vertex coordinates
var jsArrayData = [
0.0.1.0.0.0,
-1.0.0.0, -1.0.1.0.0.0.0.0
]
// Create a buffer that webGL can access
var triangleBuffer = webgl.createBuffer();
/ / binding buffer
webgl.bindBuffer(webgl.ARRAY_BUFFER, triangleBuffer);
// Copy the js data to buffer
webgl.bufferData(webgl.ARRAY_BUFFER, new Float32Array(jsArrayData), webgl.STATIC_DRAW);
// Color data
var jsArrayColor = [
1.0.0.0.0.0./ / on the vertex
0.0.1.0.0.0./ / left vertex
0.0.0.0.1.0 / / right vertex
];
// Create a color buffer and copy the color data into the color buffer
triangleColorBuffer = webgl.createBuffer();
webgl.bindBuffer(webgl.ARRAY_BUFFER, triangleColorBuffer);
webgl.bufferData(webgl.ARRAY_BUFFER, new Float32Array(jsArrayColor), webgl.STATIC_DRAW);
return triangleBuffer;
}
// Render the scene
function renderScene() {
// Start drawing
// Clear the screen
webgl.clearColor(0.0.0.0.0.0.1.0);
webgl.clear(webgl.COLOR_BUFFER_BIT);
// WebGL can have N vertex arrays, we need to tell WebGL which one we use,
// Use a buffer
// Bind an array of vertex data
webgl.bindBuffer(webgl.ARRAY_BUFFER, triangleBuffer);
// To illustrate how enableVertexArray() activates vertex properties and transfers vertex data to shader.
// Start data on an associative index // Open a generic vertex property array at the specified index in the property array list
webgl.enableVertexAttribArray(v3PositionIndex);
// Specify the data element on the associated index or the correct information variable interval for the element data
webgl.vertexAttribPointer(v3PositionIndex, 3, webgl.FLOAT, false.0.0);
// Bind the color buffer
webgl.bindBuffer(webgl.ARRAY_BUFFER, triangleColorBuffer);
webgl.enableVertexAttribArray(v3ColorIndex);
webgl.vertexAttribPointer(v3ColorIndex, 3, webgl.FLOAT, false.0.0);
//https://blog.csdn.net/ithanmang/article/details/89520623
// Draw data
webgl.drawArrays(webgl.TRIANGLES, 0.3);
}
// Change the RGB value continuously to achieve color changing animation
function changeColor() { / / isDesc false by default
if (isDesc && r <= 0.1){
isDesc = false;
}
if(! isDesc && r >=1.0){
isDesc = true;
}
!isDesc ? r += 0.01 : r -= 0.01; ! isDesc ? g +=0.01 : g -= 0.01; ! isDesc ? b +=0.01 : b -= 0.01;
var jsArrayColor = [// Data -- graphics card
r, 0.0.0.0./ / on the vertex
0.0, g, 0.0./ / left vertex
0.0.0.0, b / / right vertex
];
// Memory graphics card
triangleColorBuffer = webgl.createBuffer(); // A WebGLBuffer object used to store vertex data or coloring data
webgl.bindBuffer(webgl.ARRAY_BUFFER, triangleColorBuffer);// Bind the given WebGLBuffer to the target store's type, the vertex type
// assign //webgl.STATIC_DRAW
webgl.bufferData(webgl.ARRAY_BUFFER, new Float32Array(jsArrayColor), webgl.STATIC_DRAW);
renderScene();
}
// Initialize canvas
function initCanvas(canvasId) {
// Get the drawing context
var myCanvasObject = document.getElementById(canvasId);
var context = null;
try {
context = myCanvasObject.getContext("experimental-webgl");
// Set the viewport
context.viewport(0.0, myCanvasObject.width, myCanvasObject.height);
} catch (ex) {
alert(ex.toString());
}
if(! context) { alert("Holy crap, your browser doesn't support WebGL, switch to another browser.");
return null;
}
return context;
}
// Parse the Shader code
function shaderSourceFromScript(scriptID) {
var shaderScript = document.getElementById(scriptID);
if (shaderScript == null) return "";
var sourceCode = "";
var child = shaderScript.firstChild;
while (child) {
if (child.nodeType == child.TEXT_NODE) sourceCode += child.textContent;
child = child.nextSibling;
}
return sourceCode;
}
// Link the Shader program
function linkShader(webgl, programObj, vertexShaderObj, fragmentShaderObj) {
// A program object can and must have one vertex shader and one fragment shader
webgl.attachShader(programObj, vertexShaderObj);
webgl.attachShader(programObj, fragmentShaderObj);
// Associate the shader variable with an attribute index
// webgl.bindAttribLocation(programObj, v3PositionIndex, "v3Position");
webgl.linkProgram(programObj);
// Check whether the link is successful
if(! webgl.getProgramParameter(programObj, webgl.LINK_STATUS)) { alert("error:ProgramObject");
return;
}
return programObj;
}
</script>
</head>
<body onload="init()">
<canvas id="webglCanvas" style="border:1px solid red" width="600" height="600"></canvas>
</body>
</html>
Copy the code