Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
4 contributors

Users who have contributed to this file

@austinEng @vmiura @kainino0x @Kangz
293 lines (246 sloc) 9.82 KB
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=600">
<title>WebGPU Textured Cube demo</title>
<script src="third_party/gl-matrix-min.js"></script>
<script src="dist/utils.js"></script>
</head>
<body>
<div id="not-supported" style="display: none">WebGPU not supported! Please visit <a href="//webgpu.io">webgpu.io</a> to see the current implementation status.</div>
<canvas height=600 width=600></canvas>
<script>
if (!navigator.gpu) {
document.getElementById('not-supported').style.display = 'block';
alert('WebGPU not supported! Please visit webgpu.io to see the current implementation status.');
}
const vertexShaderGLSL = `#version 450
layout(set = 0, binding = 0) uniform Uniforms {
mat4 modelViewProjectionMatrix;
} uniforms;
layout(location = 0) in vec4 position;
layout(location = 1) in vec2 uv;
layout(location = 0) out vec2 fragUV;
void main() {
gl_Position = uniforms.modelViewProjectionMatrix * position;
fragUV = uv;
}
`
const fragmentShaderGLSL = `#version 450
layout(set = 0, binding = 1) uniform sampler mySampler;
layout(set = 0, binding = 2) uniform texture2D myTexture;
layout(location = 0) in vec2 fragUV;
layout(location = 0) out vec4 outColor;
void main() {
outColor = texture(sampler2D(myTexture, mySampler), fragUV);
}
`
const vertexSize = 4 * 6; // Byte size of one cube vertex.
const uvOffset = 4 * 4;
const cubeVerticesArray = new Float32Array([
// float4 position, float2 uv
1, -1, 1, 1, 1, 1,
-1, -1, 1, 1, 0, 1,
-1, -1, -1, 1, 0, 0,
1, -1, -1, 1, 1, 0,
1, -1, 1, 1, 1, 1,
-1, -1, -1, 1, 0, 0,
1, 1, 1, 1, 1, 1,
1, -1, 1, 1, 0, 1,
1, -1, -1, 1, 0, 0,
1, 1, -1, 1, 1, 0,
1, 1, 1, 1, 1, 1,
1, -1, -1, 1, 0, 0,
-1, 1, 1, 1, 0, 1,
1, 1, 1, 1, 1, 1,
1, 1, -1, 1, 1, 0,
-1, 1, -1, 1, 0, 0,
-1, 1, 1, 1, 0, 1,
1, 1, -1, 1, 1, 0,
-1, -1, 1, 1, 0, 1,
-1, 1, 1, 1, 1, 1,
-1, 1, -1, 1, 1, 0,
-1, -1, -1, 1, 0, 0,
-1, -1, 1, 1, 0, 1,
-1, 1, -1, 1, 1, 0,
1, 1, 1, 1, 1, 1,
-1, 1, 1, 1, 0, 1,
-1, -1, 1, 1, 0, 0,
-1, -1, 1, 1, 0, 0,
1, -1, 1, 1, 1, 0,
1, 1, 1, 1, 1, 1,
1, -1, -1, 1, 1, 0,
-1, -1, -1, 1, 0, 0,
-1, 1, -1, 1, 0, 1,
1, 1, -1, 1, 1, 1,
1, -1, -1, 1, 1, 0,
-1, 1, -1, 1, 0, 1,
]);
async function init() {
/* Context, Device, SwapChain */
const adapter = await navigator.gpu.requestAdapter();
const device = await adapter.requestDevice({});
await Utils.ready;
const canvas = document.querySelector('canvas');
const aspect = Math.abs(canvas.width / canvas.height);
let projectionMatrix = mat4.create();
mat4.perspective(projectionMatrix, (2 * Math.PI) / 5, -aspect, 1, 100.0);
const context = canvas.getContext('gpupresent');
const swapChain = context.configureSwapChain({
device,
format: "bgra8unorm",
});
const verticesBuffer = device.createBuffer({
size: cubeVerticesArray.byteLength,
usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST
});
verticesBuffer.setSubData(0, cubeVerticesArray);
const bindGroupLayout = device.createBindGroupLayout({
bindings: [{
// Transform
binding: 0,
visibility: GPUShaderStage.VERTEX,
type: "uniform-buffer"
}, {
// Sampler
binding: 1,
visibility: GPUShaderStage.FRAGMENT,
type: "sampler"
}, {
// Texture view
binding: 2,
visibility: GPUShaderStage.FRAGMENT,
type: "sampled-texture"
}]
});
const pipelineLayout = device.createPipelineLayout({ bindGroupLayouts: [bindGroupLayout] });
const pipeline = device.createRenderPipeline({
layout: pipelineLayout,
vertexStage: {
module: device.createShaderModule({
code: Utils.compile("v", vertexShaderGLSL),
}),
entryPoint: "main"
},
fragmentStage: {
module: device.createShaderModule({
code: Utils.compile("f", fragmentShaderGLSL),
}),
entryPoint: "main"
},
primitiveTopology: "triangle-list",
depthStencilState: {
depthWriteEnabled: true,
depthCompare: "less",
format: "depth24plus-stencil8",
stencilFront: {},
stencilBack: {},
},
vertexInput: {
indexFormat: "uint32",
vertexBuffers: [{
stride: vertexSize,
stepMode: "vertex",
attributeSet: [{
// position
shaderLocation: 0,
offset: 0,
format: "float4"
}, {
// uv
shaderLocation: 1,
offset: uvOffset,
format: "float2"
}]
}],
},
rasterizationState: {
frontFace: 'ccw',
cullMode: 'back',
},
colorStates: [{
format: "bgra8unorm",
alphaBlend: {},
colorBlend: {},
}],
});
const depthTexture = device.createTexture({
size: { width: canvas.width, height: canvas.height, depth: 1 },
arrayLayerCount: 1,
mipLevelCount: 1,
sampleCount: 1,
dimension: "2d",
format: "depth24plus-stencil8",
usage: GPUTextureUsage.OUTPUT_ATTACHMENT
});
const renderPassDescriptor = {
colorAttachments: [{
loadValue: { r: 0.5, g: 0.5, b: 0.5, a: 1.0 },
storeOp: "store",
}],
depthStencilAttachment: {
attachment: depthTexture.createDefaultView(),
depthLoadValue: 1.0,
depthStoreOp: "store",
stencilLoadValue: 0,
stencilStoreOp: "store",
}
};
const uniformBufferSize = 4 * 16; // 4x4 matrix
const uniformBuffer = device.createBuffer({
size: uniformBufferSize,
usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,
});
const cubeTexture = await Utils.createTextureFromImage(device, 'assets/img/Di-3d.png', GPUTextureUsage.SAMPLED);
const sampler = device.createSampler({
magFilter: "linear",
minFilter: "linear",
});
const uniformBindGroup = device.createBindGroup({
layout: bindGroupLayout,
bindings: [{
binding: 0,
resource: {
buffer: uniformBuffer,
offset: 0,
size: uniformBufferSize,
},
}, {
binding: 1,
resource: sampler,
}, {
binding: 2,
resource: cubeTexture.createDefaultView(),
}],
});
function getTransformationMatrix() {
let viewMatrix = mat4.create();
mat4.translate(viewMatrix, viewMatrix, vec3.fromValues(0, 0, -4));
let now = Date.now() / 1000;
mat4.rotate(viewMatrix, viewMatrix, 1, vec3.fromValues(Math.sin(now), Math.cos(now), 0));
let modelViewProjectionMatrix = mat4.create();
mat4.multiply(modelViewProjectionMatrix, projectionMatrix, viewMatrix);
return modelViewProjectionMatrix;
}
function frame() {
renderPassDescriptor.colorAttachments[0].attachment = swapChain.getCurrentTexture().createDefaultView();
const commandEncoder = device.createCommandEncoder({});
const passEncoder = commandEncoder.beginRenderPass(renderPassDescriptor);
passEncoder.setPipeline(pipeline);
passEncoder.setBindGroup(0, uniformBindGroup);
passEncoder.setVertexBuffers(0, [verticesBuffer], [0]);
passEncoder.draw(36, 1, 0, 0);
passEncoder.endPass();
device.getQueue().submit([commandEncoder.finish()]);
uniformBuffer.setSubData(0, getTransformationMatrix());
requestAnimationFrame(frame);
}
uniformBuffer.setSubData(0, getTransformationMatrix());
requestAnimationFrame(frame);
}
init();
</script>
<script data-href="https://github.com/austinEng/webgpu-samples/blob/master/textured_cube.html"
src="https://unpkg.com/github-corners/dist/embed.min.js"></script>
</body>
</html>
You can’t perform that action at this time.