Skip to content

Commit

Permalink
add texture
Browse files Browse the repository at this point in the history
  • Loading branch information
shi-yan committed Nov 7, 2023
1 parent 6e41405 commit 37e6627
Show file tree
Hide file tree
Showing 3 changed files with 239 additions and 0 deletions.
229 changes: 229 additions & 0 deletions 1_7_working_with_textures/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,229 @@
<html>

<body>
<canvas id="canvas" width="640" height="480"></canvas>
</body>
<script src="../utils/utils.js"></script>
<script id="shader" type="wgsl">
// Vertex shader

@group(0) @binding(0)
var<uniform> offset: vec3<f32>;

struct VertexOutput {
@builtin(position) clip_position: vec4<f32>,
@location(0) tex_coords: vec2<f32>,
};

@vertex
fn vs_main(
@location(0) inPos: vec3<f32>,
@location(1) inTexCoords: vec2<f32>
) -> VertexOutput {
var out: VertexOutput;
out.clip_position = vec4<f32>(inPos + offset, 1.0);
out.tex_coords = inTexCoords;
return out;
}

// Fragment shader

@group(0) @binding(1)
var t_diffuse: texture_2d<f32>;
@group(0) @binding(2)
var s_diffuse: sampler;

@fragment
fn fs_main(in: VertexOutput) -> @location(0) vec4<f32> {
return textureSample(t_diffuse, s_diffuse, in.tex_coords);
}

</script>

<script>
async function webgpu() {
const response = await fetch('../data/baboon.png');
const blob = await response.blob();
const imgBitmap = await createImageBitmap(blob);

const adapter = await navigator.gpu.requestAdapter();
console.log(adapter);

let device = await adapter.requestDevice();
console.log(device);

const context = configContext(device, canvas)

// create shaders
const textureDescriptor = {
size: { width: imgBitmap.width, height: imgBitmap.height },
format: 'rgba8unorm',
usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST | GPUTextureUsage.RENDER_ATTACHMENT
};
const texture = device.createTexture(textureDescriptor);

device.queue.copyExternalImageToTexture({ source: imgBitmap }, { texture }, textureDescriptor.size);

const sampler = device.createSampler({
addressModeU: 'repeat',
addressModeV: 'repeat',
magFilter: 'linear',
minFilter: 'linear',
mipmapFilter: 'linear',
});

let shaderModule = shaderModuleFromCode(device, 'shader');

const positionAttribDesc = {
shaderLocation: 0, // @location(0)
offset: 0,
format: 'float32x3'
};

const positionBufferLayoutDesc = {
attributes: [positionAttribDesc],
arrayStride: 4 * 3, // sizeof(float) * 3
stepMode: 'vertex'
};

const texCoordsAttribDesc = {
shaderLocation: 1, // @location(1)
offset: 0,
format: 'float32x2'
};

const texCoordsBufferLayoutDesc = {
attributes: [texCoordsAttribDesc],
arrayStride: 4 * 2, // sizeof(float) * 3
stepMode: 'vertex'
};

const positions = new Float32Array([
1.0, -1.0, 0.0,
-1.0, -1.0, 0.0,
0.0, 1.0, 0.0
]);

let positionBuffer = createGPUBuffer(device, positions, GPUBufferUsage.VERTEX);

const texCoords = new Float32Array([
1.0,
1.0,
// 🔴
0.0,
1.0,

0.5,
0.0,

]);

let texCoordsBuffer = createGPUBuffer(device, texCoords, GPUBufferUsage.VERTEX);

const uniformData = new Float32Array([
0.1, 0.1, 0.1
]);

let uniformBuffer = createGPUBuffer(device, uniformData, GPUBufferUsage.UNIFORM);

let uniformBindGroupLayout = device.createBindGroupLayout({
entries: [
{
binding: 0,
visibility: GPUShaderStage.VERTEX,
buffer: {}
},
{
binding: 1,
visibility: GPUShaderStage.FRAGMENT,
texture: {}
},
{
binding: 2,
visibility: GPUShaderStage.FRAGMENT,
sampler: {}
}
]
});

let uniformBindGroup = device.createBindGroup({
layout: uniformBindGroupLayout,
entries: [
{
binding: 0,
resource: {
buffer: uniformBuffer
}
},
{
binding: 1,
resource: texture.createView()
},
{
binding: 2,
resource:
sampler

}
]
});

const pipelineLayoutDesc = { bindGroupLayouts: [uniformBindGroupLayout] };
const layout = device.createPipelineLayout(pipelineLayoutDesc);

const colorState = {
format: 'bgra8unorm'
};

const pipelineDesc = {
layout,
vertex: {
module: shaderModule,
entryPoint: 'vs_main',
buffers: [positionBufferLayoutDesc, texCoordsBufferLayoutDesc]
},
fragment: {
module: shaderModule,
entryPoint: 'fs_main',
targets: [colorState]
},
primitive: {
topology: 'triangle-list',
frontFace: 'cw',
cullMode: 'back'
}
};

pipeline = device.createRenderPipeline(pipelineDesc);

let colorTexture = context.getCurrentTexture();
let colorTextureView = colorTexture.createView();

let colorAttachment = {
view: colorTextureView,
clearValue: { r: 1, g: 0, b: 0, a: 1 },
loadOp: 'clear',
storeOp: 'store'
};

const renderPassDesc = {
colorAttachments: [colorAttachment]
};
commandEncoder = device.createCommandEncoder();

passEncoder = commandEncoder.beginRenderPass(renderPassDesc);
passEncoder.setViewport(0, 0, canvas.width, canvas.height, 0, 1);
passEncoder.setPipeline(pipeline);
passEncoder.setBindGroup(0, uniformBindGroup);
passEncoder.setVertexBuffer(0, positionBuffer);
passEncoder.setVertexBuffer(1, texCoordsBuffer);
passEncoder.draw(3, 1);
passEncoder.end();

device.queue.submit([commandEncoder.finish()]);
}

webgpu();
</script>

</html>
Binary file added data/baboon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 10 additions & 0 deletions manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,16 @@
}
]
},
{
"folder": "1_7_working_with_textures",
"title": "1.7 Working with Textures",
"files": [
{
"filename": "index.html",
"is_readonly": false
}
]
},
{
"folder": "1_14_loading_models",
"title": "1.14 Loading Models",
Expand Down

0 comments on commit 37e6627

Please sign in to comment.