WebGL---6.3D紋理貼圖
阿新 • • 發佈:2018-11-03
一、例項程式碼
<html> <canvas id='c' width='640' height='480'></canvas> <script type="x-shader/x-vertex" id="vertex-shader"> attribute vec4 a_position; attribute vec2 aTextureCoord; uniform mat4 model; uniform mat4 view; uniform mat4 projection; varying highp vec2 vTextureCoord; void main(){ gl_Position = projection * view * model * a_position; vTextureCoord = aTextureCoord; } </script> <script type="x-shader/x-fragment" id="fragment-shader"> varying highp vec2 vTextureCoord; uniform sampler2D uSampler; void main(){ gl_FragColor = texture2D(uSampler, vTextureCoord); } </script> <script src="WebGLUtils.js"> </script> <script src="gl-matrix.js"></script> <script> var rotation = 0.0 var gl = createGLContext('c') // alert(gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS)) //建立shader program var program = createProgramFromElementId(gl,'vertex-shader','fragment-shader'); gl.useProgram(program); function initBuffers(gl,program){ // 座標資料寫入GPU緩衝區 const positions = [ // Front face -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0, // Back face -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0, -1.0, // Top face -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, -1.0, // Bottom face -1.0, -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, -1.0, 1.0, -1.0, -1.0, 1.0, // Right face 1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, // Left face -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0, ]; var FSIZE = positions.BYTES_PER_ELEMENT; const positionBuffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer); gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW); // 向著色器傳遞座標資料 var a_position = gl.getAttribLocation(program,"a_position"); gl.enableVertexAttribArray(a_position); gl.vertexAttribPointer(a_position,3,gl.FLOAT,false,3*FSIZE,0); // 紋理座標資料寫入GPU緩衝區 const textureCoordinates = [ // Front 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0, // Back 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0, // Top 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0, // Bottom 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0, // Right 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0, // Left 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0, ]; const textureCoordBuffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, textureCoordBuffer); gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(textureCoordinates),gl.STATIC_DRAW); // 向著色器傳遞紋理座標資料 var textureCoord = gl.getAttribLocation(program,"aTextureCoord"); gl.enableVertexAttribArray(textureCoord); gl.vertexAttribPointer(textureCoord,2,gl.FLOAT,false,2*FSIZE,0); // 建立索引緩衝物件 const indices = [ 0, 1, 2, 0, 2, 3, // front 4, 5, 6, 4, 6, 7, // back 8, 9, 10, 8, 10, 11, // top 12, 13, 14, 12, 14, 15, // bottom 16, 17, 18, 16, 18, 19, // right 20, 21, 22, 20, 22, 23, // left ]; const indexBuffer = gl.createBuffer(); gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer); gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW); } function loadTexture(gl,program){ const image = new Image(); image.src = "./cubetexture.png" image.onload = function(){ //-----將影象資料複製到GPU緩衝區-----// const texture = gl.createTexture(); gl.activeTexture(gl.TEXTURE0); gl.bindTexture(gl.TEXTURE_2D,texture); gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1) gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image); gl.generateMipmap(gl.TEXTURE_2D); //-----向著色器傳遞紋理資料-----// var u_Sampler = gl.getUniformLocation(program, 'uSampler'); gl.uniform1i(u_Sampler, 0); } } initBuffers(gl,program); loadTexture(gl,program) function drawScene(gl,deltaTime){ gl.clearColor(0.0, 0.0, 0.0, 1.0) gl.clearDepth(1.0) gl.enable(gl.DEPTH_TEST) gl.depthFunc(gl.LEQUAL); gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); //-------建立投影矩陣-----------// var projection = mat4.create() // 視野,觀察空間的大小 const fieldOfView = 45 * Math.PI / 180; const aspect = gl.canvas.clientWidth / gl.canvas.clientHeight; const zNear = 0.1; const zFar = 100.0; mat4.perspective(projection, fieldOfView, aspect, zNear, zFar); // mat4.ortho(projection,0.0, 800, 0.0, 600, 0.1, 100.0) var projection_matrix = gl.getUniformLocation(program, 'projection') gl.uniformMatrix4fv(projection_matrix,false,projection) //---------------------------// //-------建立模型矩陣-----------// var model = mat4.create() mat4.rotate(model,model,rotation,[1,0,0]) mat4.rotate(model,model,rotation*.7,[0,1,0]) var model_matrix = gl.getUniformLocation(program, 'model') gl.uniformMatrix4fv(model_matrix,false,model) //----------------------------// //-------建立觀察矩陣-----------// var view = mat4.create() mat4.translate(view,view,[-0.0, 0.0, -6.0]) var view_matrix = gl.getUniformLocation(program, 'view') gl.uniformMatrix4fv(view_matrix,false,view) //----------------------------// { const vertexCount = 36; const type = gl.UNSIGNED_SHORT; const offset = 0; gl.drawElements(gl.TRIANGLES, vertexCount, type, offset); } rotation += deltaTime; } var old = 0 function render(now) { now *= 0.001; // convert to seconds const deltaTime = now - old; old = now; drawScene(gl,deltaTime); requestAnimationFrame(render); } requestAnimationFrame(render); </script> </html>