webgl和threejs
WebGL是一种3D绘图标准,这种绘图技术标准允许把JavaScript和OpenGL ES 2.0结合在一起,通过增加OpenGL ES 2.0的一个JavaScript绑定,WebGL可以为HTML5 Canvas提供硬件3D加速渲染,这样Web开发人员就可以借助系统显卡来在浏览器里更流畅地展示3D场景和模型了,还能创建复杂的导航和数据视觉化。
Three.js是一款开源的主流3D绘图JS引擎(名字Three就是3D的含义), threejs对webgl进行了封装 , 让我们更容易的创建3D应用 . 框架内置了很多现成工具 , 比如模型加载器 , 支持obj , fbx , 等通用模型格式 . 还提供了鼠标控制如缩放 , 放大等等 .
使用threejs虽然能快速创建3D应用 , 但是对理解底层的webgl代码没有了解 . 更别谈webgl的爸爸OpenGL了 .
下面我将用webgl绘制一个矩形
最终效果
创建一个canvas
<canvas id="box" width=300 height=300></canvas>
// 获取canvas的dom对象
const canvas = document.getElementById('box')
// 获取绘制webgl的上下文, 之后我们就可以使用webgl这个对象来创建3d应用
const webgl = canvas.getContext('webgl')
准备要绘制的矩形的坐标
// v1--------v0
// | |
// | |
// | |
// v2--------v3
// 改正方形由4个点组成
let jsArrayData = new Float32Array([
// x y z
-0.5, +0.5, 0.0, // v1
+0.5, +0.5, 0.0, // v0
+0.5, -0.5, 0.0, // v3
-0.5, -0.5, 0.0, // v2
])
// 通过绘制两个三角形来组成一个正方形, 下面的数组里的数字表示jsArrayData里的索引,
// 如: 0表示-0.5, 2表示0.0
// 0, 1, 2表示用这三个点绘制一个三角形
let indexDatas = [
0, 1, 2,
0, 2, 3
]
将正方形的顶点和三角形的顶点索引绑定到webgl中
// 创建顶点缓冲区
triangleBuffer = webgl.createBuffer()
// 指明缓冲区的类型
// webgl.bindBuffer(webgl.ARRAY_BUFFER, triangleBuffer)
// // 分配内存
// webgl.bufferData(webgl.ARRAY_BUFFER, new Float32Array(jsArrayData), webgl.STATIC_DRAW)
webgl.bindBuffer(webgl.ARRAY_BUFFER, triangleBuffer)
// 分配内存
webgl.bufferData(webgl.ARRAY_BUFFER, new Float32Array(jsArrayData), webgl.STATIC_DRAW)
// 创建索引缓冲区
indexBuffer = webgl.createBuffer()
// 指明缓冲区的类型
webgl.bindBuffer(webgl.ELEMENT_ARRAY_BUFFER, indexBuffer)
// 分配内存
webgl.bufferData(webgl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indexDatas), webgl.STATIC_DRAW)
// 使用缓冲区, 指定绘制所用的顶点数据, 从该缓冲区中获取
webgl.bindBuffer(webgl.ELEMENT_ARRAY_BUFFER, indexBuffer)
将顶点数据传到shader中
// 将v3PositionIndex变量绑定到顶点shader里的v3Position
webgl.bindAttribLocation(programObject, v3PositionIndex, 'v3Position')
// 启用v3PositionIndex
webgl.enableVertexAttribArray(v3PositionIndex)
// 3表示每个顶点有三个数据(x, y, z)
// 4 * 3 表示所有顶点在内存中占用的字节数, 4表示一个顶点占用的字节数, 3表示一个顶点有3个数据
// 0 表示取数据的时候从第0个元素开始
webgl.vertexAttribPointer(v3PositionIndex, 3, webgl.FLOAT, false, 4 * 3, 0)
绑定顶点着色器和片元着色器
// 创建shader
vertexShaderObject = webgl.createShader(webgl.VERTEX_SHADER)
fragmentShaderObject = webgl.createShader(webgl.FRAGMENT_SHADER)
webgl.shaderSource(vertexShaderObject, `
attribute vec3 v3Position;
void main(void)
{
gl_Position = vec4(v3Position, 1.0);
}
`)
webgl.shaderSource(fragmentShaderObject, `
precision lowp float;
void main(void)
{
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
`)
// 编译shader
webgl.compileShader(vertexShaderObject)
webgl.compileShader(fragmentShaderObject)
绑定着色器和顶点数据到webgl
// 创建一段空程序
programObject = webgl.createProgram()
// 绑定顶点着色器和片元着色器
webgl.attachShader(programObject, vertexShaderObject)
webgl.attachShader(programObject, fragmentShaderObject)
// 将v3PositionIndex变量绑定到顶点shader里的v3Position
webgl.bindAttribLocation(programObject, v3PositionIndex, 'v3Position')
// 执行连接, 此段程序不再是空
webgl.linkProgram(programObject)
// 使用这段程序
webgl.useProgram(programObject)
执行绘制
// 设置重绘背景的颜色
webgl.clearColor(0.0, 0.0, 0.0, 1.0)
// 清空背景
webgl.clear(webgl.COLOR_BUFFER_BIT)
// 两个面的索引总共有6个数据
webgl.drawElements(webgl.TRIANGLES, 6, webgl.UNSIGNED_SHORT, 0)
总代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>WebGL</title>
</head>
<body>
<canvas id="box" style="border: 1px solid black;" width=300 height=300></canvas>
<script>
let vertexShaderObject = null
let fragmentShaderObject = null
let programObject = null
let indexBuffer = null
let v3PositionIndex = 0
let uniformColor
// 1 创建上下文
const canvas = document.getElementById('box')
const webgl = canvas.getContext('webgl')
webgl.viewport(0, 0, canvas.clientWidth, canvas.clientHeight)
// 2 创建shader
vertexShaderObject = webgl.createShader(webgl.VERTEX_SHADER)
fragmentShaderObject = webgl.createShader(webgl.FRAGMENT_SHADER)
webgl.shaderSource(vertexShaderObject, `
attribute vec3 v3Position;
void main(void)
{
gl_Position = vec4(v3Position, 1.0);
}
`)
webgl.shaderSource(fragmentShaderObject, `
precision lowp float;
void main(void)
{
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
`)
// 3 编译shader
webgl.compileShader(vertexShaderObject)
webgl.compileShader(fragmentShaderObject)
if (!webgl.getShaderParameter(vertexShaderObject, webgl.COMPILE_STATUS)) {
console.log('err---vertexShaderObject', webgl.getShaderInfoLog(vertexShaderObject))
}
if (!webgl.getShaderParameter(fragmentShaderObject, webgl.COMPILE_STATUS)) {
console.log('err---fragmentShaderObject', webgl.getShaderInfoLog(fragmentShaderObject))
}
// 创建一段空程序
programObject = webgl.createProgram()
// 绑定顶点着色器和片元着色器
webgl.attachShader(programObject, vertexShaderObject)
webgl.attachShader(programObject, fragmentShaderObject)
// 将v3PositionIndex变量绑定到顶点shader里的v3Position
webgl.bindAttribLocation(programObject, v3PositionIndex, 'v3Position')
// 执行连接, 此段程序不再是空
webgl.linkProgram(programObject)
// 使用这段程序
webgl.useProgram(programObject)
// v1--------v0
// | |
// | |
// | |
// v2--------v3
let jsArrayData = new Float32Array([
// x y z
-0.5, +0.5, 0.0, // v1
+0.5, +0.5, 0.0, // v0
+0.5, -0.5, 0.0, // v3
-0.5, -0.5, 0.0, // v2
])
let indexDatas = [
0, 1, 2,
0, 2, 3
]
// 创建顶点缓冲区
triangleBuffer = webgl.createBuffer()
// 指明缓冲区的类型
// webgl.bindBuffer(webgl.ARRAY_BUFFER, triangleBuffer)
// // 分配内存
// webgl.bufferData(webgl.ARRAY_BUFFER, new Float32Array(jsArrayData), webgl.STATIC_DRAW)
webgl.bindBuffer(webgl.ARRAY_BUFFER, triangleBuffer)
// 分配内存
webgl.bufferData(webgl.ARRAY_BUFFER, new Float32Array(jsArrayData), webgl.STATIC_DRAW)
// 创建索引缓冲区
indexBuffer = webgl.createBuffer()
// 指明缓冲区的类型
webgl.bindBuffer(webgl.ELEMENT_ARRAY_BUFFER, indexBuffer)
// 分配内存
webgl.bufferData(webgl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indexDatas), webgl.STATIC_DRAW)
// 使用缓冲区, 指定绘制所用的顶点数据, 从该缓冲区中获取
webgl.bindBuffer(webgl.ELEMENT_ARRAY_BUFFER, indexBuffer)
webgl.enableVertexAttribArray(v3PositionIndex)
// 指定绘制顶点的数据
// v3PositionIndex 绑定shader里的v3Position
// 3 每个顶点有3个数据组成, 每取一个顶点都会往后偏移3个
// 4*3 4是一个float占的字节数, 6是指每个顶点有6个数据, 表示每隔24个字节到下一个顶点
// 0 从缓冲区的第0个开始往后取
webgl.vertexAttribPointer(v3PositionIndex, 3, webgl.FLOAT, false, 4 * 3, 0)
// 设置重绘背景的颜色
webgl.clearColor(0.0, 0.0, 0.0, 1.0)
// 执行绘制
webgl.clear(webgl.COLOR_BUFFER_BIT)
// 两个面的索引总共有6个数据
webgl.drawElements(webgl.TRIANGLES, 6, webgl.UNSIGNED_SHORT, 0)
</script>
</body>
</html>
分享我私藏的TS教程,从0到高阶全系列,点击链接,0元获取 www.yidengxuetang.com/pub-page/in…
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!