The cube has six sides, all of which need to be textured. We also need to rotate the cube to show it in three dimensions. Again, the difficulty lies in the construction of the vertex data. The code looks like this:
1. Vertex shader code
<script id="vertexShader" type="x-shader/x-vertex">
// Float is set to medium precision
precision mediump float;
// The vertex coordinate data passed from js
attribute vec3 apos;
// A 4-dimensional matrix rotated along the X-axis
uniform mat4 mx;
// A 4-dimensional matrix rotated along the Y-axis
uniform mat4 my;
// the texture coordinate data passed from the.js
attribute vec2 inUV;
// Texture coordinates passed to the slice shader after interpolation
varying vec2 outUV;
void main() {
// Multiply two rotation matrices, vertex homogeneous coordinates
gl_Position = mx*my*vec4(apos, 1);
// Interpolate
outUV=inUV;
}
</script>
Copy the code
2, chip shader code
Receive texture coordinate data from vertex shader in slice shader, and texture data passed from JS code, and finally generate the cube slice color.
<script id="fragmentShader" type="x-shader/x-fragment">
// All float data has a lowp precision
precision mediump float;
varying vec2 outUV;
uniform sampler2D texture;
void main() {
gl_FragColor=texture2D(texture,outUV);
}
</script>
Copy the code
3. Javascript code
- To obtain
WebGL
context
In this function, the following functions are mainly realized: + obtaining WebGL context + initializing shader + vertex data construction and shader interaction
function init() {
// Get the canvas canvas with the getElementById() method
const canvas = document.getElementById('webgl');
// Get the WebGL context using the getContext() method
const gl = canvas.getContext('webgl');
// Vertex shader source code
const vertexShaderSource = document.getElementById('vertexShader').innerText;
// Chip shader source code
const fragShaderSource = document.getElementById('fragmentShader').innerText;
// Initialize the shader
const program = initShader(gl, vertexShaderSource, fragShaderSource);
initBuffer(gl, program);
}
Copy the code
- Cube vertex data construction and interaction with shaders
The main functions of this function can be divided into the following: + get variable address in shader + build vertex data and texture coordinate data + build vertex index data + create vertex buffer + create index buffer + assign variable in shader + enable depth test + load texture image + WebGL rendering
function initBuffer(gl, program) {
// Get the vertex shader position variable apos
const aposLocation = gl.getAttribLocation(program, 'apos');
const inUV = gl.getAttribLocation(program, 'inUV');
const texture = gl.getUniformLocation(program, 'texture');
// Allow data transfer
gl.enableVertexAttribArray(aposLocation);
// Allow data transfer
gl.enableVertexAttribArray(inUV);
// Create the cube's vertex coordinates and texture coordinates
const data = new Float32Array([-0.5, -0.5.0.5.0.0.0.0.0.5, -0.5.0.5.1.0.0.0.0.5.0.5.0.5.1.0.1.0,
-0.5.0.5.0.5.0.0.1.0,
-0.5.0.5.0.5.1.0.1.0,
-0.5.0.5, -0.5.0.0.1.0,
-0.5, -0.5, -0.5.0.0.0.0,
-0.5, -0.5.0.5.1.0.0.0.0.5.0.5.0.5.0.0.1.0.0.5, -0.5.0.5.0.0.0.0.0.5, -0.5, -0.5.1.0.0.0.0.5.0.5, -0.5.1.0.1.0.0.5.0.5, -0.5.0.0.1.0.0.5, -0.5, -0.5.0.0.0.0,
-0.5, -0.5, -0.5.1.0.0.0,
-0.5.0.5, -0.5.1.0.1.0,
-0.5.0.5.0.5.0.0.1.0.0.5.0.5.0.5.1.0.1.0.0.5.0.5, -0.5.1.0.0.0,
-0.5.0.5, -0.5.0.0.0.0,
-0.5, -0.5.0.5.0.0.0.0,
-0.5, -0.5, -0.5.0.0.1.0.0.5, -0.5, -0.5.1.0.1.0.0.5, -0.5.0.5.1.0.0.0
]);
// Build vertex index data
const indexdata = new Uint16Array([
0.1.2.0.2.3.4.5.6.4.6.7.8.9.10.8.10.11.12.13.14.12.14.15.16.17.18.16.18.19.20.21.22.20.22.23
])
// Create a buffer object
const buffer = gl.createBuffer();
// Bind the buffer object
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
// The vertex array data is passed into the buffer
gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW);
// Create an index buffer object
const indexBuffer = gl.createBuffer();
// Bind the index buffer object
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
// // vertex array data data is passed into the index buffer
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indexdata, gl.STATIC_DRAW);
/// The data in the buffer is passed to the position variable APOS according to certain rules
gl.vertexAttribPointer(aposLocation, 3, gl.FLOAT, false.4 * 5.0);
gl.vertexAttribPointer(inUV, 2, gl.FLOAT, false.4 * 5.4 * 3);
// gl.vertexAttribPointer(acolor, 4, gl.FLOAT, false, 4 * 9, 4*3);
gl.enable(gl.DEPTH_TEST);
// gl.enable(gl.CULL_FACE);
// render(gl, program, indexdata.length)
initTexture(gl, '.. /images/1.jpg', texture, function () {
render(gl, program, indexdata.length)
})
}
Copy the code
- Loading texture images
In this function, we create a sample image and finally pass the image data to the GPU. + Create texture image buffer + set texture image inversion + activate texture unit 0 + bind texture buffer + set texture pixel format, JPG format corresponds to GL.rgb, and transfer image data to GPU. + set the texture map filling method + global variable assignment, the color data in the texture buffer unit TEXTURE0 is passed to the slice shader
function initTexture(gl, src, attribute, callback) {
let img = new Image();
img.onload = function () {
let texture = gl.createTexture();// Create a texture image buffer
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true); // Invert the texture image up and down
gl.activeTexture(gl.TEXTURE0);// Activate TEXTURE0
gl.bindTexture(gl.TEXTURE_2D, texture);// Bind the texture buffer
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT);
gl.uniform1i(attribute, 0);
callback && callback();
};
img.src = src;
}
Copy the code
WebGL
Apply colours to a drawing
function render(gl, program, count = 36) {
// Rotate along the x and y axes
tranlate(gl, program);
// Set the clear color to black.
gl.clearColor(0.0.0.1);
gl.clear(gl.COLOR_BUFFER_BIT);
// gl.drawArrays(gl.TRIANGLES, 0, count);
gl.drawElements(gl.TRIANGLES, count, gl.UNSIGNED_SHORT, 0);
}
Copy the code
The above JS code is only part of the example, the other function code implementation, in the previous examples are listed. The final texture map for the cube looks like this: