WebGL 绘制与变换使用示例详解
作者:H_World
这篇文章主要为大家介绍了WebGL 绘制与变换使用示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
缓冲区对象(buffer object)
其中的API
方法的说明官方网址:WebGLRenderingContext
紧接上一篇的问题,其实通过片元着色器可以修改点的颜色,但是会发现每一次颜色的都是一样的,两种方式的区别就是第一种用到了缓冲区对象
解释:buffer object,它可以一次性向着色器中传入多个顶点数据,而缓冲区对象是WebGL中一块内存区域,我们可以一次性向其中传入大量的顶点数据。
再来看一眼相关代码
api说明
createBuffer
: creates and initializes aWebGLBuffer
storing data such as vertices or colors -- 创建和初始化一个可以存储类似顶点和颜色数据的对象bindBuffer
: binds a givenWebGLBuffer
to a target -- 将buffer
对象绑定到目标对象上bufferData
: initializes and creates the buffer object's data store -- 存储数据到创建的buffer
对象中enableVertexAttribArray
: turns on the generic vertex attribute array at the specified index into the list of attribute arrays. -- 传入的参数是一个vertex
类型的数组对象,这个方法可以依次打开这个数组vertexAttribPointer
: binds the buffer currently bound togl.ARRAY_BUFFER
to a generic vertex attribute of the current vertex buffer object and specifies its layout. -- 将整个数组中的所有值一次性分配给一个attribute
变量
解析:首先创建多个长度的数组,用来装着色器中需要修改的顶点或是颜色信息,之后创建一个buffer
,再将webgl
对象和当前创建的buffer
地址绑定一起,bufferData
方法就是往buffer
地址中传入数组数据
绘制图形
上面的例子中都是绘制一个点,只不过这个点的size
可以自定义设置
webgl.drawArrays(webgl.POINTS, 0, points.length / 4)
其中的drawArrays
中的第一个参数指的是不同的绘制方式
参数类型
gl.POINTS
点,绘制在坐标系内gl.LINES
线,分别是点1和点2的线,点3和点4的线...gl.LINE_STRIP
线,连接点1-点2-点3...gl.LINE_LOOP
线,连接点1-点2-点3-点1,点的首尾相连gl.TRIANGLES
三角形, 绘制在(点1,点2,点3)...gl.TRIANGLE_STRIP
三角带,第二个三角形和第一个三角形共享一条边gl.gl.TRIANGLE_FAN
三角扇
移动、旋转、缩放
const VSHADER_SOURCE = ` attribute vec4 a_Position; uniform vec4 u_Translate; void main() { gl_Position = u_Translate + a_Position; } ` const u_Translate = gl.getUniformLocation(gl.program, 'u_Translate') gl.uniform4f(u_Translate, 0.5, 0.5, 0.0, 0)
创建初始的坐标点
const u_Translate = gl.getUniformLocation(program, 'u_Translate'); // 定义顶点数据 const positions = [ 0, 0, 0.5, 0, 0.5, 0.5, 0, 0.5, ]; // 将顶点数据写入缓冲区 gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW); // 启用属性并指定数据格式 gl.enableVertexAttribArray(aPosition); gl.vertexAttribPointer(aPosition, 2, gl.FLOAT, false, 0, 0); // 设置平移向量 const translation = [0.5, 0.5]; // 将平移向量传递给uniform变量 gl.uniform2fv(translationUniformLocation, translation); // 绘制图形 gl.drawArrays(gl.TRIANGLE_FAN, 0, positions.length / 2);
u_Translate + a_Position为每一个分量相加得到一个新的vec4值。
自动旋转
定义顶点着色器:一个顶点的信息,然后可以设置旋转中心点的锚点,旋转的角度,和一个需要改变的颜色
const vertexShaderSource = ` attribute vec2 a_position; uniform vec2 u_rotationCenter; uniform float u_angle; varying vec3 v_color; void main() { vec2 rotatedPosition = vec2( cos(u_angle) * (a_position.x - u_rotationCenter.x) - sin(u_angle) * (a_position.y - u_rotationCenter.y) + u_rotationCenter.x, sin(u_angle) * (a_position.x - u_rotationCenter.x) + cos(u_angle) * (a_position.y - u_rotationCenter.y) + u_rotationCenter.y ); gl_Position = vec4(rotatedPosition, 0, 1); v_color = vec3(cos(u_angle), 3.14 - cos(u_angle), cos(u_angle)); } `
这样在片元着色器中就需要
const fragmentShaderSource = ` precision mediump float; varying vec3 v_color; void main() { gl_FragColor = vec4(v_color, 1); } `
v_color
属性是从顶点着色器中绑定而来的
// 设置旋转中心和旋转角度 const rotationCenter = [0.25, 0.25]; let angle = 0 function render() { // 更新旋转角度 angle += 0.01 if (angle === 3.1415926) { angle = 0 } // 将旋转中心和旋转角度传递给uniform变量 webgl.uniform2fv(rotationCenterUniformLocation, rotationCenter) webgl.uniform1f(angleUniformLocation, angle) draw() // 绘制图形 webgl.drawArrays(webgl.TRIANGLE_FAN, 0, 4); // 请求浏览器调用下一帧动画 requestAnimationFrame(render) } // 开始动画 render()
缩放
demo
实现:根据滑动鼠标控制三角形中的缩放大小
代码实现
var vertexShaderSource = ` attribute vec3 aVertexPosition; uniform float uScale; void main() { gl_Position = vec4(aVertexPosition * uScale, 1.0); } `
顶点着色器中定义了uniform
的变量uScale
,比例因子,通过之后的代码中
const scaleUniformLocation = webgl.getUniformLocation(webgl.program, "uScale") webgl.uniform1f(scaleUniformLocation, scale)
重新设置该变量的值 监听鼠标滑动事件
canvas.addEventListener("wheel", function (event: any) { scale += event.deltaY / 1000 })
补充说明
变换中主要用到是矩阵的知识,矩阵按储存方式分为按行矩阵和按列矩阵,而WebGL
中主要是按列矩阵
那么使用矩阵可以 <新坐标> = <变换矩阵> * <旧坐标>
以上就是WebGL 绘制与变换使用示例详解的详细内容,更多关于WebGL绘制变换的资料请关注脚本之家其它相关文章!