当前位置: 首页 > news >正文

可以做产品推广的网站湖南北山建设集团股份有限公司官方网站

可以做产品推广的网站,湖南北山建设集团股份有限公司官方网站,二维码生成器在线制作二维码,wordpress 添加滑块这篇文章是关于存储缓冲区的&#xff0c;我们从上一篇文章暂停的地方继续。 存储缓冲区在许多方面类似于统一缓冲区。如果我们所做的只是将 JavaScript 中的 UNIFORM 更改为 STORAGE 并将 WGSL 中的 var 更改为 var<storage, read> &#xff0c;那么上一页中的示例就可以…

这篇文章是关于存储缓冲区的,我们从上一篇文章暂停的地方继续。

存储缓冲区在许多方面类似于统一缓冲区。如果我们所做的只是将 JavaScript 中的 UNIFORM 更改为 STORAGE 并将 WGSL 中的 var 更改为 var<storage, read> ,那么上一页中的示例就可以正常工作。

其实区别就在这里,不用重命名变量就可以有更合适的名字。

    const staticUniformBuffer = device.createBuffer({label: `static uniforms for obj: ${i}`,size: staticUniformBufferSize,// usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST,});...const uniformBuffer = device.createBuffer({label: `changing uniforms for obj: ${i}`,size: uniformBufferSize,// usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST,});

在我们的 WSGL 中

      @group(0) @binding(0) var<storage, read> ourStruct: OurStruct;@group(0) @binding(1) var<storage, read> otherStruct: OtherStruct;

无需其他更改即可正常工作,就像以前一样
在这里插入图片描述

统一缓冲区和存储缓冲区之间的差异 Differences between uniform buffers and storage buffers

统一缓冲区和存储缓冲区之间的主要区别是:

  1. 对于特定的用例,统一缓冲区可以更快
    这真的取决于用例。一个典型的应用程序需要绘制很多不同的东西。对于3D游戏,该应用程序可能会绘制汽车、建筑物、岩石、灌木丛、人等……每一个都需要传递与我们上面的示例类似的方向和材料属性。在这种情况下,使用统一缓冲区是推荐的解决方案。

  2. 存储缓冲区可以比统一缓冲区大得多。

    The minimum maximum size of a uniform buffer is 64k
    统一缓冲区的最小最大大小为64k
    The minimum maximum size of a storage buffer is 128meg
    存储缓冲区的最小最大大小为 128meg

    By minimum maximum, there is a maximum size a
    buffer of certain type can be. For uniform buffers that maximum size
    is at least 64k. For storage buffers it’s at least 128meg. We’ll
    cover limits in another article.
    通过最小最大值,某种类型的缓冲区可以达到最大大小。对于最大大小至少为
    64k 的统一缓冲区。对于存储缓冲区,它至少为 128 兆。我们将在另一篇文章中介绍限制。
    3.存储缓冲区可以读/写,统一缓冲区是只读
    我们在第一篇文章的计算着色器示例中看到了写入存储缓冲区的示例。

鉴于上面的前两点,让我们以最后一个示例为例,将其更改为在一次绘制调用中绘制所有 100 个三角形。这是一个可能适合存储缓冲区的用例。我说可能是因为,WebGPU 与其他编程语言相似。有很多方法可以实现同一件事,比如 array.forEach 对比 for (const elem of array) 对比 for (let i = 0; i < array.length; ++i) 。每个都有它的用途。 WebGPU 也是如此。我们尝试做的每一件事都有多种实现方式。当谈到绘制三角形时**,WebGPU 关心的只是我们从顶点着色器返回 builtin(position) 的值**,并从片段着色器返回 location(0) 的颜色/值。 见【注释1】

我们要做的第一件事是将存储声明更改为运行时大小的数组。

// @group(0) @binding(0) var<storage, read> ourStruct: OurStruct;
// @group(0) @binding(1) var<storage, read> otherStruct: OtherStruct;
@group(0) @binding(0) var<storage, read> ourStructs: array<OurStruct>;
@group(0) @binding(1) var<storage, read> otherStructs: array<OtherStruct>;

然后我们将更改着色器以使用这些值

@vertex fn vs(@builtin(vertex_index) vertexIndex : u32,@builtin(instance_index) instanceIndex: u32
) -> @builtin(position) {var pos = array<vec2f, 3>(vec2f( 0.0,  0.5),  // top centervec2f(-0.5, -0.5),  // bottom leftvec2f( 0.5, -0.5)   // bottom right);let otherStruct = otherStructs[instanceIndex];let ourStruct = ourStructs[instanceIndex];return vec4f(pos[vertexIndex] * otherStruct.scale + ourStruct.offset, 0.0, 1.0);
}

我们向顶点着色器添加了一个名为 instanceIndex 的新参数,并赋予它 @builtin(instance_index) 属性,这意味着它从 WebGPU 为绘制的每个“实例”获取其值。当我们调用 draw 时,我们可以传递实例数的第二个参数,对于绘制的每个实例,正在处理的实例数将传递给我们的函数。

使用 instanceIndex 可以从结构数组中获取指定的结构元素。

We also need to some get the color from the correct array element and use it in our fragment shader. The fragment shader doesn’t have access to @builtin(instance_index) because that would make no sense. We could pass it as an inter-stage variable but it would be more common to look up the color in the vertex shader and just pass the color.
我们还需要从正确的数组元素中获取颜色,并在我们的片段着色器中使用它。片段着色器无法访问 @builtin(instance_index) ,因为那没有任何意义。我们可以将它作为阶段间变量传递,但更常见的做法是在顶点着色器中查找颜色并传递颜色。

为此,我们将使用另一个结构,就像我们在关于阶段间变量的文章中所做的那样

struct VSOutput {@builtin(position) position: vec4f,@location(0) color: vec4f,
}@vertex fn vs(@builtin(vertex_index) vertexIndex : u32,@builtin(instance_index) instanceIndex: u32
// ) -> @builtin(position) vec4f {
) -> VSOutput {var pos = array<vec2f, 3>(vec2f( 0.0,  0.5),  // top centervec2f(-0.5, -0.5),  // bottom leftvec2f( 0.5, -0.5)   // bottom right);let otherStruct = otherStructs[instanceIndex];let ourStruct = ourStructs[instanceIndex];// return vec4f(//  pos[vertexIndex] * otherStruct.scale + ourStruct.offset, 0.0, 1.0);var vsOut: VSOutput;vsOut.position = vec4f(pos[vertexIndex] * otherStruct.scale + ourStruct.offset, 0.0, 1.0);vsOut.color = ourStruct.color;return vsOut;
}// @fragment fn fs() -> @location(0) vec4f {
//   return ourStruct.color;
@fragment fn fs(vsOut: VSOutput) -> @location(0) vec4f {return vsOut.color;
}

现在我们已经修改了 WGSL 着色器,让我们更新 JavaScript。

代码如下:

  const kNumObjects = 100;const objectInfos = [];// create 2 storage buffersconst staticUnitSize =4 * 4 + // color is 4 32bit floats (4bytes each)2 * 4 + // offset is 2 32bit floats (4bytes each)2 * 4;  // paddingconst changingUnitSize =2 * 4;  // scale is 2 32bit floats (4bytes each)const staticStorageBufferSize = staticUnitSize * kNumObjects;const changingStorageBufferSize = changingUnitSize * kNumObjects;const staticStorageBuffer = device.createBuffer({label: 'static storage for objects',size: staticStorageBufferSize,usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST,});const changingStorageBuffer = device.createBuffer({label: 'changing storage for objects',size: changingStorageBufferSize,usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST,});// offsets to the various uniform values in float32 indicesconst kColorOffset = 0;const kOffsetOffset = 4;const kScaleOffset = 0;{const staticStorageValues = new Float32Array(staticStorageBufferSize / 4);for (let i = 0; i < kNumObjects; ++i) {const staticOffset = i * (staticUnitSize / 4);// These are only set once so set them nowstaticStorageValues.set([rand(), rand(), rand(), 1], staticOffset + kColorOffset);        // set the colorstaticStorageValues.set([rand(-0.9, 0.9), rand(-0.9, 0.9)], staticOffset + kOffsetOffset);      // set the offsetobjectInfos.push({scale: rand(0.2, 0.5),});}device.queue.writeBuffer(staticStorageBuffer, 0, staticStorageValues);}// a typed array we can use to update the changingStorageBufferconst storageValues = new Float32Array(changingStorageBufferSize / 4);const bindGroup = device.createBindGroup({label: 'bind group for objects',layout: pipeline.getBindGroupLayout(0),entries: [{ binding: 0, resource: { buffer: staticStorageBuffer }},{ binding: 1, resource: { buffer: changingStorageBuffer }},],});

上面我们创建了 2 个存储缓冲区。一个用于 OurStruct 数组,另一个用于 OtherStruct 数组。

然后我们用偏移量和颜色填充 OurStruct 数组的值,然后将该数据上传到 staticStorageBuffer 。

我们只创建一个引用两个缓冲区的绑定组。

新的渲染代码是

  function render() {// Get the current texture from the canvas context and// set it as the texture to render to.renderPassDescriptor.colorAttachments[0].view =context.getCurrentTexture().createView();const encoder = device.createCommandEncoder();const pass = encoder.beginRenderPass(renderPassDescriptor);pass.setPipeline(pipeline);// Set the uniform values in our JavaScript side Float32Arrayconst aspect = canvas.width / canvas.height;//for (const {scale, bindGroup, uniformBuffer, uniformValues} of objectInfos) {//   uniformValues.set([scale / aspect, scale], kScaleOffset); // set the scale//    device.queue.writeBuffer(uniformBuffer, 0, uniformValues);//  pass.setBindGroup(0, bindGroup);//    pass.draw(3);  // call our vertex shader 3 times// }// set the scales for each objectobjectInfos.forEach(({scale}, ndx) => {const offset = ndx * (changingUnitSize / 4);storageValues.set([scale / aspect, scale], offset + kScaleOffset); // set the scale});// upload all scales at oncedevice.queue.writeBuffer(changingStorageBuffer, 0, storageValues);pass.setBindGroup(0, bindGroup);pass.draw(3, kNumObjects);  // call our vertex shader 3 times for each instancepass.end();const commandBuffer = encoder.finish();device.queue.submit([commandBuffer]);}

上面的代码将绘制 kNumObjects 实例。对于每个实例,WebGPU 将调用顶点着色器 3 次, vertex_index 设置为 0、1、2, instance_index 设置为 0 到 kNumObjects - 1

在这里插入图片描述
我们绘制了 100 个三角形,每个三角形具有不同的比例、颜色和偏移量。对于您想要绘制同一对象的大量实例的情况,这是一种实现方法。

顶点数据使用存储缓冲区

到目前为止,我们一直在着色器中直接硬编码三角形。存储缓冲区的一个用例是存储顶点数据。就像我们在上面的示例中通过 instance_index 索引当前存储缓冲区一样,我们可以使用 vertex_index 索引另一个存储缓冲区来获取顶点数据。

我们开始吧!

struct OurStruct {color: vec4f,offset: vec2f,
};struct OtherStruct {scale: vec2f,
};struct Vertex {position: vec2f,
};struct VSOutput {@builtin(position) position: vec4f,@location(0) color: vec4f,
};@group(0) @binding(0) var<storage, read> ourStructs: array<OurStruct>;
@group(0) @binding(1) var<storage, read> otherStructs: array<OtherStruct>;
@group(0) @binding(2) var<storage, read> pos: array<Vertex>;@vertex fn vs(@builtin(vertex_index) vertexIndex : u32,@builtin(instance_index) instanceIndex: u32
) -> VSOutput {//var pos = array<vec2f, 3>(//  vec2f( 0.0,  0.5),  // top center//  vec2f(-0.5, -0.5),  // bottom left//  vec2f( 0.5, -0.5)   // bottom right//);let otherStruct = otherStructs[instanceIndex];let ourStruct = ourStructs[instanceIndex];var vsOut: VSOutput;vsOut.position = vec4f(pos[vertexIndex].position * otherStruct.scale + ourStruct.offset, 0.0, 1.0);vsOut.color = ourStruct.color;return vsOut;
}@fragment fn fs(vsOut: VSOutput) -> @location(0) vec4f {return vsOut.color;
}

现在我们需要为一些顶点数据再设置一个存储缓冲区。首先让我们创建一个函数来生成一些顶点数据。大概是一个圆。

function createCircleVertices({radius = 1,numSubdivisions = 24,innerRadius = 0,startAngle = 0,endAngle = Math.PI * 2,
} = {}) {// 2 triangles per subdivision, 3 verts per tri, 2 values (xy) each.const numVertices = numSubdivisions * 3 * 2;const vertexData = new Float32Array(numSubdivisions * 2 * 3 * 2);let offset = 0;const addVertex = (x, y) => {vertexData[offset++] = x;vertexData[offset++] = y;};// 2 vertices per subdivision//// 0--1 4// | / /|// |/ / |// 2 3--5for (let i = 0; i < numSubdivisions; ++i) {const angle1 = startAngle + (i + 0) * (endAngle - startAngle) / numSubdivisions;const angle2 = startAngle + (i + 1) * (endAngle - startAngle) / numSubdivisions;const c1 = Math.cos(angle1);const s1 = Math.sin(angle1);const c2 = Math.cos(angle2);const s2 = Math.sin(angle2);// first triangleaddVertex(c1 * radius, s1 * radius);addVertex(c2 * radius, s2 * radius);addVertex(c1 * innerRadius, s1 * innerRadius);// second triangleaddVertex(c1 * innerRadius, s1 * innerRadius);addVertex(c2 * radius, s2 * radius);addVertex(c2 * innerRadius, s2 * innerRadius);}return {vertexData,numVertices,};
}

上面的代码用这样的三角形制作了一个圆
在这里插入图片描述
所以我们可以用它来用圆的顶点填充存储缓冲区

  // setup a storage buffer with vertex dataconst { vertexData, numVertices } = createCircleVertices({radius: 0.5,innerRadius: 0.25,});const vertexStorageBuffer = device.createBuffer({label: 'storage buffer vertices',size: vertexData.byteLength,usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST,});device.queue.writeBuffer(vertexStorageBuffer, 0, vertexData);
And then we need to add it to our bind group.
然后我们需要将它添加到我们的绑定组中。const bindGroup = device.createBindGroup({label: 'bind group for objects',layout: pipeline.getBindGroupLayout(0),entries: [{ binding: 0, resource: { buffer: staticStorageBuffer }},{ binding: 1, resource: { buffer: changingStorageBuffer }},{ binding: 2, resource: { buffer: vertexStorageBuffer }},],});

最后在渲染时,我们需要要求渲染圆圈中的所有顶点。

    pass.draw(3, kNumObjects);  // call our vertex shader 3 times for several instancespass.draw(numVertices, kNumObjects);

在这里插入图片描述
上面我们用了

struct Vertex {pos: vec2f;
};@group(0) @binding(2) var<storage, read> pos: array<Vertex>;

我们可以不使用 struct 而直接使用 vec2f 。

@group(0) @binding(2) var<storage, read> pos: vec2f;

但是,通过使它成为一个结构,以后添加顶点数据不是更容易吗?

通过存储缓冲区传递顶点越来越受欢迎。有人告诉我,尽管一些较旧的设备比我们将在接下来的一篇关于顶点缓冲区中介绍的经典方法慢。


【注释1】We can have multiple color attachments and then we’ll need to return more colors/value for location(1), location(2), etc… ↩︎
我们可以有多个颜色附件,然后我们需要为 location(1) 、 location(2) 等返回更多颜色/值……↩︎

http://www.yayakq.cn/news/547129/

相关文章:

  • 品牌网站建设策划外链建设工具
  • 自己开公司 自己做网站wordpress设置上传大小
  • 张家港企业网站asp网站文章自动更新
  • 网站开发的理解无锡seo公司
  • 九歌人工智能诗歌写作网站wordpress 移动端双模板
  • 公司门户网站商城小程序哪家好
  • 建设网站用新域名还是老域名网页软件开发
  • 石家庄做网站公司有哪些建设网站赚钱的方法
  • 计算机网站开发的目的为什么有些网站更新的信息看不到
  • 奥联网络网站建设东莞凌峰建设公司
  • 兴化建设局网站对网站建设的描述
  • 海南美容网站建设企业营销型网站建设规划
  • 聊城医院网站建设公司简介怎么写模板
  • 建行互联网站青岛官网seo
  • 做网站有没有效果线上编程课程
  • 17网站一起做网店怎么下单网站开发人员要求
  • 网站建设仟首先金手指14免费域名网站php
  • 格尔木哪里有做网站的免费咨询皮肤医生
  • 开贴纸网站要怎么做安徽建站网站
  • 济宁 创意大厦 网站建设电子商务公司营业执照经营范围
  • 网站建设与维护的案例网页设计与网站建设-学用一册通
  • 网站模板带手机站查询网站备案号app
  • 镇江网站建设报价服装市场调研报告范文
  • 网站建设 计入哪个科目紧急通知页面升级
  • seo网站优化培训阿里巴巴国际站买家版app
  • 简述建立网站的步骤建设网站多久
  • 青岛微信网站建设2016市网站建设总结
  • 营口旅游网站建设网站从制作到使用的全过程
  • wordpress points昆明官网seo公司
  • 2个域名指向同一个网站丰台网站建设多少钱