Skip to content

Commit

Permalink
add centroid examples
Browse files Browse the repository at this point in the history
  • Loading branch information
greggman committed Jan 10, 2024
1 parent a947953 commit 21795c3
Show file tree
Hide file tree
Showing 3 changed files with 347 additions and 2 deletions.
172 changes: 172 additions & 0 deletions webgpu/webgpu-multisample-center-issue.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
<title>WebGPU Simple Triangle with Multisampling</title>
<style>
@import url(resources/webgpu-lesson.css);
html, body {
margin: 0; /* remove the default margin */
height: 100%; /* make the html,body fill the page */
}
canvas {
image-rendering: pixelated;
display: block; /* make the canvas act like a block */
width: 100%; /* make the canvas fill its container */
height: 100%;
}
</style>
</head>
<body>
<canvas></canvas>
</body>
<script type="module">
async function main() {
const adapter = await navigator.gpu?.requestAdapter();
const device = await adapter?.requestDevice();
if (!device) {
fail('need a browser that supports WebGPU');
return;
}

// Get a WebGPU context from the canvas and configure it
const canvas = document.querySelector('canvas');
const context = canvas.getContext('webgpu');
const presentationFormat = navigator.gpu.getPreferredCanvasFormat();
context.configure({
device,
format: presentationFormat,
});

const module = device.createShaderModule({
label: 'our hardcoded red triangle shaders',
code: `
struct VOut {
@builtin(position) position: vec4f,
@location(0) baryCoord: vec3f,
};
@vertex fn vs(
@builtin(vertex_index) vertexIndex : u32
) -> VOut {
let pos = array(
vec2f( 0.0, 0.5), // top center
vec2f(-0.5, -0.5), // bottom left
vec2f( 0.5, -0.5) // bottom right
);
let bary = array(
vec3f(1, 0, 0),
vec3f(0, 1, 0),
vec3f(0, 0, 1),
);
var vout: VOut;
vout.position = vec4f(pos[vertexIndex], 0.0, 1.0);
vout.baryCoord = bary[vertexIndex];
return vout;
}
@fragment fn fs(vin: VOut) -> @location(0) vec4f {
let inside = all(vin.baryCoord >= vec3f(0)) && all(vin.baryCoord <= vec3f(1));
let red = vec4f(1, 0, 0, 1);
let yellow = vec4f(1, 1, 0, 1);
return select(yellow, red, inside);
}
`,
});

const pipeline = device.createRenderPipeline({
label: 'our hardcoded red triangle pipeline',
layout: 'auto',
vertex: {
module,
entryPoint: 'vs',
},
fragment: {
module,
entryPoint: 'fs',
targets: [{ format: presentationFormat }],
},
multisample: {
count: 4,
},
});

const renderPassDescriptor = {
label: 'our basic canvas renderPass',
colorAttachments: [
{
// view: <- to be filled out when we render
clearValue: [0.3, 0.3, 0.3, 1],
loadOp: 'clear',
storeOp: 'store',
},
],
};

let multisampleTexture;

function render() {
// Get the current texture from the canvas context
const canvasTexture = context.getCurrentTexture();

// If the multisample texture doesn't exist or
// is the wrong size then make a new one.
if (!multisampleTexture ||
multisampleTexture.width !== canvasTexture.width ||
multisampleTexture.height !== canvasTexture.height) {

// If we have an existing multisample texture destroy it.
if (multisampleTexture) {
multisampleTexture.destroy();
}

// Create a new multisample texture that matches our
// canvas's size
multisampleTexture = device.createTexture({
format: canvasTexture.format,
usage: GPUTextureUsage.RENDER_ATTACHMENT,
size: [canvasTexture.width, canvasTexture.height],
sampleCount: 4,
});
}

// Set the multisample texture as the texture to render to
renderPassDescriptor.colorAttachments[0].view =
multisampleTexture.createView();
// Set the canvas texture as the texture to "resolve"
// the multisample texture to.
renderPassDescriptor.colorAttachments[0].resolveTarget =
canvasTexture.createView();

const encoder = device.createCommandEncoder({ label: 'our encoder' });
const pass = encoder.beginRenderPass(renderPassDescriptor);
pass.setPipeline(pipeline);
pass.draw(3); // call our vertex shader 3 times
pass.end();

const commandBuffer = encoder.finish();
device.queue.submit([commandBuffer]);
}

const observer = new ResizeObserver(entries => {
for (const entry of entries) {
const canvas = entry.target;
const width = entry.contentBoxSize[0].inlineSize / 16 | 0;
const height = entry.contentBoxSize[0].blockSize / 16 | 0;
canvas.width = Math.max(1, Math.min(width, device.limits.maxTextureDimension2D));
canvas.height = Math.max(1, Math.min(height, device.limits.maxTextureDimension2D));
// re-render
render();
}
});
observer.observe(canvas);
}

function fail(msg) {
// eslint-disable-next-line no-alert
alert(msg);
}

main();
</script>
</html>
173 changes: 173 additions & 0 deletions webgpu/webgpu-multisample-centroid.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
<title>WebGPU Simple Triangle with Multisampling</title>
<style>
@import url(resources/webgpu-lesson.css);
html, body {
margin: 0; /* remove the default margin */
height: 100%; /* make the html,body fill the page */
}
canvas {
image-rendering: pixelated;
display: block; /* make the canvas act like a block */
width: 100%; /* make the canvas fill its container */
height: 100%;
}
</style>
</head>
<body>
<canvas></canvas>
</body>
<script type="module">
async function main() {
const adapter = await navigator.gpu?.requestAdapter();
const device = await adapter?.requestDevice();
if (!device) {
fail('need a browser that supports WebGPU');
return;
}

// Get a WebGPU context from the canvas and configure it
const canvas = document.querySelector('canvas');
const context = canvas.getContext('webgpu');
const presentationFormat = navigator.gpu.getPreferredCanvasFormat();
context.configure({
device,
format: presentationFormat,
});

const module = device.createShaderModule({
label: 'our hardcoded red triangle shaders',
code: `
struct VOut {
@builtin(position) position: vec4f,
@location(0) @interpolate(perspective, centroid)
baryCoord: vec3f,
};
@vertex fn vs(
@builtin(vertex_index) vertexIndex : u32
) -> VOut {
let pos = array(
vec2f( 0.0, 0.5), // top center
vec2f(-0.5, -0.5), // bottom left
vec2f( 0.5, -0.5) // bottom right
);
let bary = array(
vec3f(1, 0, 0),
vec3f(0, 1, 0),
vec3f(0, 0, 1),
);
var vout: VOut;
vout.position = vec4f(pos[vertexIndex], 0.0, 1.0);
vout.baryCoord = bary[vertexIndex];
return vout;
}
@fragment fn fs(vin: VOut) -> @location(0) vec4f {
let inside = all(vin.baryCoord >= vec3f(0)) && all(vin.baryCoord <= vec3f(1));
let red = vec4f(1, 0, 0, 1);
let yellow = vec4f(1, 1, 0, 1);
return select(yellow, red, inside);
}
`,
});

const pipeline = device.createRenderPipeline({
label: 'our hardcoded red triangle pipeline',
layout: 'auto',
vertex: {
module,
entryPoint: 'vs',
},
fragment: {
module,
entryPoint: 'fs',
targets: [{ format: presentationFormat }],
},
multisample: {
count: 4,
},
});

const renderPassDescriptor = {
label: 'our basic canvas renderPass',
colorAttachments: [
{
// view: <- to be filled out when we render
clearValue: [0.3, 0.3, 0.3, 1],
loadOp: 'clear',
storeOp: 'store',
},
],
};

let multisampleTexture;

function render() {
// Get the current texture from the canvas context
const canvasTexture = context.getCurrentTexture();

// If the multisample texture doesn't exist or
// is the wrong size then make a new one.
if (!multisampleTexture ||
multisampleTexture.width !== canvasTexture.width ||
multisampleTexture.height !== canvasTexture.height) {

// If we have an existing multisample texture destroy it.
if (multisampleTexture) {
multisampleTexture.destroy();
}

// Create a new multisample texture that matches our
// canvas's size
multisampleTexture = device.createTexture({
format: canvasTexture.format,
usage: GPUTextureUsage.RENDER_ATTACHMENT,
size: [canvasTexture.width, canvasTexture.height],
sampleCount: 4,
});
}

// Set the multisample texture as the texture to render to
renderPassDescriptor.colorAttachments[0].view =
multisampleTexture.createView();
// Set the canvas texture as the texture to "resolve"
// the multisample texture to.
renderPassDescriptor.colorAttachments[0].resolveTarget =
canvasTexture.createView();

const encoder = device.createCommandEncoder({ label: 'our encoder' });
const pass = encoder.beginRenderPass(renderPassDescriptor);
pass.setPipeline(pipeline);
pass.draw(3); // call our vertex shader 3 times
pass.end();

const commandBuffer = encoder.finish();
device.queue.submit([commandBuffer]);
}

const observer = new ResizeObserver(entries => {
for (const entry of entries) {
const canvas = entry.target;
const width = entry.contentBoxSize[0].inlineSize / 16 | 0;
const height = entry.contentBoxSize[0].blockSize / 16 | 0;
canvas.width = Math.max(1, Math.min(width, device.limits.maxTextureDimension2D));
canvas.height = Math.max(1, Math.min(height, device.limits.maxTextureDimension2D));
// re-render
render();
}
});
observer.observe(canvas);
}

function fail(msg) {
// eslint-disable-next-line no-alert
alert(msg);
}

main();
</script>
</html>
4 changes: 2 additions & 2 deletions webgpu/webgpu-points-3d-fixed-size.html
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
// see https://webgpufundamentals.org/webgpu/lessons/webgpu-utils.html#wgpu-matrix
import {mat4} from '/3rdparty/wgpu-matrix.module.js';

function createSphereVertices({
function createFibonacciSphereVertices({
numSamples,
radius,
}) {
Expand Down Expand Up @@ -130,7 +130,7 @@
},
});

const vertexData = createSphereVertices({
const vertexData = createFibonacciSphereVertices({
radius: 1,
numSamples: 1000,
});
Expand Down

0 comments on commit 21795c3

Please sign in to comment.