共计 1814 个字符,预计需要花费 5 分钟才能阅读完成。
系列博客总目录:https://segmentfault.com/a/1190000040716735
VertexBuffer 的创立
VertexBuffer 的本体就是一个 GPUBuffer
,次要就是指定其 usage,以及在创立 ShaderModule 时配置好 VertexAttribute。
顶点属性,所谓的 VertexAttribute,在 VertexBuffer 中的排列是顶点程序优先。比方在某个 VertexBuffer 中,一个顶点领有 f32 二维坐标属性、f32 RGBA 色彩属性,那么它大略长这样:
依次排列
↓ 顶点 1(24 bytes)坐标 x 坐标 y
R 重量 G 重量 B 重量 A 重量
↓ 顶点 2(24 bytes)坐标 x 坐标 y
R 重量 G 重量 B 重量 A 重量
↓
...
上代码:
const vbodata = new Float32Array([
// 坐标 xy // 色彩 RGBA
-0.5, 0.0, 1.0, 0.0, 0.0, 1.0, // ← 顶点 1
0.0, 0.5, 0.0, 1.0, 0.0, 1.0, // ← 顶点 2
0.5, 0.0, 0.0, 0.0, 1.0, 1.0 // ← 顶点 3
])
const vbo = device.createBuffer({
size: vbodata.byteLength,
usage: GPUBufferUsage.VERTEX,
mappedAtCreation: true // 创立时立即映射,让 CPU 端能读写数据
})
// 实例化一个新的 Float32Array,并获取 GPUBuffer 的映射范畴,传入下面的数据,这样 ArrayBuffer 就有值了
new Float32Array(vbo.getMappedRange()).set(vbodata)
vbo.unmap() // 肯定要解除映射,GPU 能力读写
// ...
const vsShaderModule = device.createShaderModule({
code: vsSource,
entryPoint: 'main',
buffers: [
{
shaderLocation: 0,
offset: 0,
format: 'float32x2'
}, {
shaderLocation: 1,
offset: 2 * vbodata.BYTES_PER_ELEMENT,
format: 'float32x4'
}
]
})
WGSL 端承受输出
与 GLSL 略有不同,当新语法学习即可。
WGSL 中当初能够应用构造体作为入口点函数的输入输出,当然也能够只用插槽,见代码中的正文。
/* 顶点着色器阶段 */
struct PositionColorInput {[[location(0)]] in_position_2d: vec2<f32>;
[[location(1)]] in_color_rgba: vec4<f32>;
};
struct PositionColorOutput {[[builtin(position)]] coords_output: vec4<f32>;
[[location(0)]] color_output: vec4<f32>;
};
/*
main 的输出参数除了构造体,还能够是简略的多个参数,例如
fn main([[location(0)]] in_position_2d: vec2<f32>,
[[location(1)]] in_color_rgba: vec4<f32>) -> PositionColorOutput {/* ... */}
然而 WGSL 函数规定输入只能是单值
本例要向下一个阶段(片元着色器阶段)输入 vbo 中的 colorAttribute,只能应用构造体
*/
[[stage(vertex)]]
fn main(input: PositionColorInput)
-> PositionColorOutput {
var output: PositionColorOutput;
output.color_output = input.in_color_rgba;
output.coords_output = vec4<f32>(input.in_position_2d, 0.0, 1.0);
return output;
}
VertexBuffer 的数据传入
向 VBO 传递数据,须要用到勾销映射的 GPUBuffer 和 TypedArray 数组,其次要接口是 渲染通道编码器的 setVertexBuffer()
办法。
参考代码:
// ...
passEncoder.setVertexBuffer(0, vbo)
// ...
正文完