将使用的技术是webGL和three.js,通过webGL API可以是JS实现对于原生的GPU的编程,treejs是对webgl的API开发,threejs基本上可以作为开发引擎来用。
WebGL
这种绘图技术标准允许把JavaScript和OpenGL ES 2.0结合在一起,通过增加OpenGL ES 2.0的一个JavaScript绑定,WebGL可以为HTML5 Canvas提供硬件3D加速渲染,这样Web开发人员就可以借助系统显卡来在浏览器里更流畅地展示3D场景和模型了,还能创建复杂的导航和数据视觉化。显然,WebGL技术标准免去了开发网页专用渲染插件的麻烦,可被用于创建具有复杂3D结构的网站页面,甚至可以用来设计3D网页游戏等等。
ThreeJS
threejs可以将它理解成three + js,three表示3D的意思,js表示javascript的意思。那么合起来,three.js就是使用javascript 来写3D程序的意思。Three.js是一个伟大的开源WebGL库,WebGL允许JavaScript操作GPU,在浏览器端实现真正意义的3D。
传统的小游戏,比如说俄罗斯方块,那就是使用js操作dom实现,也有一些小游戏通过H5的canvas API来实现(2D游戏,不基于DOM),也有一些web游戏基于游戏引擎来生成H5游戏代码(通过游戏引擎编译)。常用的游戏引擎有cocos或者laya,开发框架有threes.js和parse。
WebGL理论学习
- OpenGL ES 针对移动端进行了优化,其实是OpenGL的阉割版。
WebGL
- glTranslate
- glRotatef
GLSL – shading language 比较类似C语言的语法
- gl_Position 顶点着色器
- gl_FragColor 片元着色器
WEBGL渲染管线
- 顶点着色器顶点的位置计算
- 进行图元装配
- 将装配好的图元进行像素画
- 片着色器进行渲染
进行的过程:
绘制三角形的思路
实现一个旋转的三角形
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 |
var canvas = document.getElementById('myCanvas') var gl = canvas.getContext('webgl') // 获取在canvas上面绘制的能力 var program = gl.createProgram() // 创建一个可以定义顶点着色器和片元着色器的能力 var VSHADER_SOURCE, FSHADER_SOURCE VSHADER_SOURCE = 'attribute vec4 a_Position;\n' + 'uniform mat4 u_ModelMatrix;\n' + 'uniform mat4 u_ViewMatrix;\n' + 'uniform mat4 u_ProjectionMatrix;\n' + 'void main () {\n' + 'gl_Position = u_ProjectionMatrix * u_ViewMatrix * u_ModelMatrix * a_Position;\n' + '}\n' FSHADER_SOURCE = 'void main () {\n' + 'gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n' + '}\n' var vertexShader, fragmentShader function createShader (gl, sourceCode, type) { // create shader var shader = gl.createShader(type) gl.shaderSource(shader, sourceCode) gl.compileShader(shader) // 编译shader return shader } // define vertex shader vertexShader = createShader(gl, VSHADER_SOURCE, gl.VERTEX_SHADER) // define frament shader fragmentShader = createShader(gl, FSHADER_SOURCE, gl.FRAGMENT_SHADER) // 将shader和program绑定 // 可以定义多个program在多个shader上,要用的时候调用不同的 gl.attachShader(program, vertexShader) gl.attachShader(program, fragmentShader) // link program to context gl.linkProgram(program) gl.useProgram(program) gl.program = program var currentAngle = 0 var g_last = Date.now() var tick = function () { // update the new rotation angle animate() // draw draw() requestAnimationFrame(tick) } // 实现a_position也就是三角形顶点坐标和buffer data的绑定 function initVertexBuffers (gl) { var vertices = new Float32Array([ 0, 0.5, -0.5, -0.5, 0.5, -0.5 ]) var n = 3 var vertexBuffer = gl.createBuffer() gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer) // write data into the buffer object gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW) // get attribute a_Position address in vertex shader var a_Position = gl.getAttribLocation(gl.program, 'a_Position') gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 0, 0) // enable a_Position variable gl.enableVertexAttribArray(a_Position) return n } // write the positions of vertices to a vertex shader // 顶点数 var n = initVertexBuffers(gl) // 清空掉之前绘制的结果,因为实际上是一帧一帧的绘制的 gl.clearColor(0, 0, 0, 1) var u_ModelMatrix = gl.getUniformLocation(gl.program, 'u_ModelMatrix') var modelMatrix = new Matrix4() var u_ViewMatrix = gl.getUniformLocation(gl.program, 'u_ViewMatrix') var viewMatrix = new Matrix4() viewMatrix.lookAt(100, 100, 100, 0, 0, 0, 0, 1, 0) var u_ProjectionMatrix = gl.getUniformLocation(gl.program, 'u_ProjectionMatrix') var projectionMatrix = new Matrix4() // projectionMatrix.perspective(120, 1, 0.1, 1000) projectionMatrix.ortho(-1, 1, -1, 1, 0.1, 1000) function animate () { var now = Date.now() var duration = now - g_last g_last = now currentAngle = currentAngle + duration / 1000 * 180 } function draw () { // clear canvas and add background color modelMatrix.setRotate(currentAngle, 0, 1, 0) gl.uniformMatrix4fv(u_ModelMatrix, false, modelMatrix.elements) gl.uniformMatrix4fv(u_ViewMatrix, false, viewMatrix.elements) gl.uniformMatrix4fv(u_ProjectionMatrix, false, projectionMatrix.elements) gl.clear(gl.COLOR_BUFFER_BIT) gl.drawArrays(gl.TRIANGLES, 0, n) } tick() |
Three.js实现同样旋转三角形
threejs要渲染一个场景需要三个东西:
- WebGLRenderer 是一个webgl渲染器,类似于webgl获取一个一个context的过程,
- 相机
- 场景THREE.Scene()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
var width = 400 var height = 400 var canvas = document.getElementById('demo-canvas') var renderer = new THREE.WebGLRenderer({ canvas: canvas }) var scene = new THREE.Scene() var camera = new THREE.OrthographicCamera(-width / 2, width / 2, height / 2, -height / 2, -1000, 1000) renderer.setClearColor(new THREE.Color(0x000000, 1.0)) renderer.setSize(400, 400) var triangleShape = new THREE.Shape() triangleShape.moveTo(0, 100) triangleShape.lineTo(-100, -100) triangleShape.lineTo(100, -100) triangleShape.lineTo(0, 100) var geometry = new THREE.ShapeGeometry(triangleShape) var material = new THREE.MeshBasicMaterial({ color: 0xff0000, side: THREE.DoubleSide }) var mesh = new THREE.Mesh(geometry, material) mesh.position.x = 0 mesh.position.y = 0 mesh.position.z = 1 scene.add(mesh) camera.position.x = 0 camera.position.y = 0 camera.position.z = 0 camera.lookAt(new THREE.Vector3(0, 0, 1)) var currentAngle = 0 var lastTimestamp = Date.now() var animate = function () { var now = Date.now() var duration = now - lastTimestamp lastTimestamp = now currentAngle = currentAngle + duration / 1000 * Math.PI } var render = function () { animate() mesh.rotation.set(0, 0, currentAngle) renderer.render(scene, camera) requestAnimationFrame(render) } render() |