I am trying to set color per triangle.
But it is not working.
Only setting color per vertex works!
This is what I made:
<!DOCTYPE html><title>Color Per Triangle</title><style>
body{ background-color: #000 }
canvas{ display: block; width: 600px; height: 400px; outline: 1px solid #343438 }
</style><canvas width=900 height=600></canvas><script type=module>
const canvas=document.body.firstChild, C=canvas.getContext(`webgpu`),
red=[.9,.3,.3,1], yel=[.7,.7,.3,1],
tri=[
0,0,0,...red, 0, 1,0,...red, 1,0,0,...red, // ⚠️ Wish: avoid color repeating
0,0,0,...yel, 0,-1,0,...yel, -1,0,0,...yel,
];
/* ♻️ WANT THIS:
tri=[
0,0,0, 0, 1,0, 1,0,0, ...red, // set color per triangle
0,0,0, 0,-1,0, -1,0,0, ...yel,
]
*/
VB_$=window.VB_$=new Float32Array(tri); // Vertex Buffer Source
let code=`
struct _V {
@location(0) p: vec3f,
@location(1) c: vec4f,
};
struct V_ {
@builtin(position) p: vec4f,
@location(0) c: vec4f,
};
@vertex fn vs(_v: _V) -> V_ {
var v_: V_;
v_.p = vec4f(_v.p, 1);
v_.c = _v.c;
return v_;
}
@fragment fn fs(v_: V_) -> @location(0) vec4f {
return v_.c;
}
`,
format = `bgra8unorm`,
adapter = await navigator.gpu.requestAdapter(),
device = await adapter.requestDevice(),
Q = device.queue,
A = { loadOp: `clear`, storeOp: `store` }, // Attachments
O = { colorAttachments: [ A ] }, // Render Pass Descriptor
module = device.createShaderModule({ code }),
PO = { layout: `auto`,
vertex: { module, entryPoint: `vs`,
buffers:[
{
arrayStride: 28, // (3+4)*4.; (xyz+rgba)*4.
attributes: [
{ shaderLocation:0, offset:0, format:`float32x3` }, // p: vec3f [xyz]
{ shaderLocation:1, offset:12, format:`float32x4` }, // c: vec4f [rgba]; 3*4.
]
}
]
},
fragment: { module, entryPoint: `fs`, targets: [{ format }] }
},
P = device.createRenderPipeline( PO ),
E,R, VB = device.createBuffer({ size: VB_$.byteLength, usage: 40 }); // VERTEX | COPY_DST
function draw(){
A.view=C.getCurrentTexture().createView();
E=device.createCommandEncoder();
R=E.beginRenderPass(O);
R.setPipeline(P);
R.setVertexBuffer(0,VB);
R.draw(6); // 2*3 = 2 triangles with 3 vertices each
R.end();
Q.submit([ E.finish() ])
}
C.configure({ device, format })
Q.writeBuffer(VB,0,VB_$);
draw()
</script>
Also, it need to do without using hardcoded colors.
Colors and vertex positions must be passed to shader using Vertex Buffer !
PS – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – –
I can’t use Uniform or Storage buffers,
because browser says: "Unsupported bit-flag set (descriptor range flags 10002).
D3D12 serialize root signature failed with E_INVALIDARG (0x80070057)
at CheckHRESULTImpl (….third_partydawnsrcdawnnatived3dD3DError.cpp:96)
at Initialize (….third_partydawnsrcdawnnatived3d12PipelineLayoutD3D12.cpp:350)"
2
Answers
You can’t, all data is per-vertex. Even if you use something like SSBO, you still need to provide the lookup index in every vertex (and then of course pay the cost of the extra indirection).
You can’t access vertex buffer data per triangle vs per vertex.
You can use storage buffers. If you got an error you must have set your bits set wrong
You can see using storage buffers for vertex data here
Copying that example here and modifying to color per triangle
Note that the solution above assumed the goal was to have 1 piece of color data per triangle. If the goal is to have 1 color per triangle ignoring extra data then you can repeat the data. You can also use
@interpolate(flat)
in your inter-stage color variable to have it not interpolate the colors.