- 前言
在前面程序中,我们一般会创建一个缓冲区对象,在其中存储顶点的坐标数据,然后在缓冲区传入顶点数据.然而在三维坐标中,不仅包括顶点数据,还包括颜色,大小等数据.如果每个顶点数据都创建一个缓冲对象,那么会导致创建很多缓冲对象,而且在编码的过程中会产生相同的代码.所以 webgl 推出使用 vertexAttribPointer()的步进和偏移参数
vertexAttribPointer()步进和偏移函数
参数 | 参数说明 | 参数值 |
---|---|---|
location | 指定分配 attribute 中的存储地址 | - |
size | 指定缓冲区每个顶点分量的个数 1-4 | - |
type | 指定数据个数 | - |
normalize | 是否将非浮点型数据归一化true | - |
stride | 指定相邻两个顶点间的字节数 | 默认 0 |
offset | 指定缓冲区对象中的偏移量 | 默认 0 |
示例程序
- 需要画 3 个点,每个点的大小不一样
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body onload="main()">
<canvas id="webgl" width="400" height="400"></canvas>
</body>
<script id="vertextShader" type="x-shader/x-vertex">
attribute vec4 a_Position;
attribute float a_PointSize;
void main () {
gl_Position = a_Position;
gl_PointSize = a_PointSize;
}
</script>
<script id="fragmentShader" type="x-shader/x-fragment">
// 全局设置浮点数的精确度,其他类型都有默认的精度类型,浮点数需要单独的设置
// precision mediump float;
// uniform vec4 u_FragColor;
void main () {
gl_FragColor = vec4(1.0,0.0,0.0,1.0);
}
</script>
<script src="./jsm/util.js"></script>
<script src="tool/cuon-matrix.js"></script>
<script>
function main() {
const canvas = document.getElementById('webgl')
const gl = canvas.getContext('webgl')
const vertextShader = document.getElementById('vertextShader').innerText
const fragmentShader = document.getElementById('fragmentShader').innerText
if (!initShaders(gl, vertextShader, fragmentShader)) return
if (!gl) return
const a_Position = gl.getAttribLocation(gl.program, 'a_Position')
const a_PointSize = gl.getAttribLocation(gl.program, 'a_PointSize')
if (a_Position < 0) return
// debugger
let n = initVertexBuffers(gl,a_Position,a_PointSize)
gl.clearColor(0.0, 0.0, 0.0, 1.0)
gl.drawArrays(gl.POINTS, 0, n)
}
function initVertexBuffers(gl, a_Position, a_PointSize) {
var vertices = new Float32Array([
0.0, 0.5,10.0,
-0.5, -0.5,20.0,
0.5, 0.5,30.0
])
var n = 3
var buffer = gl.createBuffer()
gl.bindBuffer(gl.ARRAY_BUFFER, buffer)
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW)
let fsize = vertices.BYTES_PER_ELEMENT;
gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, fsize * 3, 0)
gl.enableVertexAttribArray(a_Position)
gl.clearColor(0.0,0.0,0.0,1.0)
gl.clear(gl.COLOR_BUFFER_BIT)
gl.vertexAttribPointer(a_PointSize, 1, gl.FLOAT, false, fsize * 3, fsize * 2)
gl.enableVertexAttribArray(a_PointSize)
return n
}
</script>
</html>
varying 变量
当我们使用 vertexAttribPointer 传入多种数据到顶点着色器 的时候,往往需要将顶点着色器的数据传递给片元着色器.这时候需要使用 varying 变量将顶点着色器的数据传递给片元着色器.使用分以下几步
- 在顶点着色器创建一个 varying 变量
- 在顶点着色器对 varying 变量进行赋值
- 在片元着色器中命名一个相同变量的 varying 变量
注意
varying 变量一般命名已 v_开头.varying 变量在赋值的时候需要相同类型的,不然会报错.
varying变量示例程序
绘制一个3 个位置 颜色,大小都通过变量的形式传递.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body onload="main()">
<canvas id="webgl" width="400" height="400"></canvas>
</body>
<script id="vertextShader" type="x-shader/x-vertex">
attribute vec4 a_Position;
attribute float a_PointSize;
attribute vec4 a_Color;
varying vec4 v_Color;
void main () {
gl_Position = a_Position;
gl_PointSize = a_PointSize;
v_Color = a_Color;
}
</script>
<script id="fragmentShader" type="x-shader/x-fragment">
// 全局设置浮点数的精确度,其他类型都有默认的精度类型,浮点数需要单独的设置
precision mediump float;
// uniform vec4 u_FragColor;
varying vec4 v_Color;
void main () {
gl_FragColor = v_Color;
}
</script>
<script src="./jsm/util.js"></script>
<script src="tool/cuon-matrix.js"></script>
<script>
function main() {
const canvas = document.getElementById('webgl')
const gl = canvas.getContext('webgl')
const vertextShader = document.getElementById('vertextShader').innerText
const fragmentShader = document.getElementById('fragmentShader').innerText
if (!initShaders(gl, vertextShader, fragmentShader)) return
if (!gl) return
const a_Position = gl.getAttribLocation(gl.program, 'a_Position')
const a_PointSize = gl.getAttribLocation(gl.program, 'a_PointSize')
const a_Color = gl.getAttribLocation(gl.program, 'a_Color')
if (a_Position < 0) return
// debugger
let n = initVertexBuffers(gl,a_Position,a_PointSize,a_Color)
gl.clearColor(0.0, 0.0, 0.0, 1.0)
gl.clear(gl.COLOR_BUFFER_BIT)
gl.drawArrays(gl.POINTS, 0, n)
}
function initVertexBuffers(gl, a_Position, a_PointSize,a_Color) {
var vertices = new Float32Array([
0.0, 0.5, 10.0, 1.0,0.0,0.0,
-0.5, -0.5, 20.0, 0.0,1.0,0.0,
0.5, 0.5, 30.0, 0.0,0.0,1.0
])
var n = 3
var buffer = gl.createBuffer()
gl.bindBuffer(gl.ARRAY_BUFFER, buffer)
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW)
let fsize = vertices.BYTES_PER_ELEMENT;
gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, fsize * 6, 0)
gl.enableVertexAttribArray(a_Position)
gl.vertexAttribPointer(a_PointSize, 1, gl.FLOAT, false, fsize * 6, fsize * 2)
gl.enableVertexAttribArray(a_PointSize)
gl.vertexAttribPointer(a_Color, 3, gl.FLOAT, false, fsize * 6, fsize * 3)
gl.enableVertexAttribArray(a_Color)
return n
}
</script>
</html>
网友评论