struct VertexShaderOut { @builtin(position) position: vec4, @location(0) texcoord: vec2 } struct FrameUniforms { camera_transform: mat3x3f, viewport_size: vec2f, } struct LocalUniforms { transform: mat3x3f, } @group(0) @binding(2) var frame_uni: FrameUniforms; @group(0) @binding(3) var local_uni: LocalUniforms; @vertex fn vs( @builtin(vertex_index) vertexIndex : u32 ) -> VertexShaderOut { let pos = array( vec2(-0.5, -0.5), vec2(0.5, -0.5), vec2(-0.5, 0.5), vec2(-0.5, 0.5), vec2(0.5, -0.5), vec2(0.5, 0.5) ); var vsOutput: VertexShaderOut; let homogeneous_position = frame_uni.camera_transform * local_uni.transform * vec3f(pos[vertexIndex], 1); let position = homogeneous_position.xy / homogeneous_position.z; // convert from pixels to 0.0 to 1.0 let zeroToOne = position / frame_uni.viewport_size; // convert from 0 - 1 to 0 - 2 let zeroToTwo = zeroToOne * 2.0; // convert from 0 - 2 to -1 - +1 (clip space) let flippedClipSpace = zeroToTwo - 1.0; // flip Y let clipSpace = flippedClipSpace * vec2f(1, -1); vsOutput.position = vec4f(clipSpace, 0.0, 1.0); vsOutput.texcoord = pos[vertexIndex] + vec2f(0.5, 0.5); return vsOutput; } @group(0) @binding(0) var tex_sampler: sampler; @group(0) @binding(1) var tex: texture_2d; @fragment fn fs(fsInput: VertexShaderOut) -> @location(0) vec4 { return textureSample(tex, tex_sampler, fsInput.texcoord); }