Skip to content

Commit

Permalink
chore: add polygon offset example
Browse files Browse the repository at this point in the history
  • Loading branch information
xiaoiver committed May 21, 2024
1 parent bc89ec0 commit 1cfef88
Show file tree
Hide file tree
Showing 2 changed files with 334 additions and 0 deletions.
1 change: 1 addition & 0 deletions examples/demos/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,4 @@ export { render as ARThree } from './ar-three';
export { render as SetImageData } from './set-image-data';
export { render as RenderBundle } from './render-bundle';
export { render as Raymarching } from './raymarching';
export { render as PolygonOffset } from './polygon-offset';
333 changes: 333 additions & 0 deletions examples/demos/polygon-offset.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,333 @@
import {
DeviceContribution,
VertexStepMode,
Format,
TransparentWhite,
BufferUsage,
BufferFrequencyHint,
BlendMode,
BlendFactor,
TextureUsage,
CullMode,
ChannelWriteMask,
TransparentBlack,
CompareFunction,
} from '../../src';
import { vec3, mat4 } from 'gl-matrix';
import {
cubeVertexArray,
cubeVertexSize,
cubeVertexCount,
} from '../meshes/cube';

export async function render(
deviceContribution: DeviceContribution,
$canvas: HTMLCanvasElement,
useRAF = true,
) {
// create swap chain and get device
const swapChain = await deviceContribution.createSwapChain($canvas);

// TODO: resize
swapChain.configureSwapChain($canvas.width, $canvas.height);
const device = swapChain.getDevice();

const program2 = device.createProgram({
vertex: {
glsl: `
layout(location = 0) in vec2 a_Position;
void main() {
gl_Position = vec4(a_Position, 0, 1.0);
}
`,
},
fragment: {
glsl: `
out vec4 outputColor;
void main() {
outputColor = vec4(1.0, 0.0, 0.0, 1.0);
}
`,
},
});

const vertexBuffer2 = device.createBuffer({
viewOrSize: new Float32Array([0, 0.5, -0.5, -0.5, 0.5, -0.5]),
usage: BufferUsage.VERTEX,
hint: BufferFrequencyHint.DYNAMIC,
});
device.setResourceName(vertexBuffer2, 'a_Position');

const inputLayout2 = device.createInputLayout({
vertexBufferDescriptors: [
{
arrayStride: 4 * 2,
stepMode: VertexStepMode.VERTEX,
attributes: [
{
shaderLocation: 0,
offset: 0,
format: Format.F32_RG,
},
],
},
],
indexBufferFormat: null,
program: program2,
});

const pipeline2 = device.createRenderPipeline({
inputLayout: inputLayout2,
program: program2,
colorAttachmentFormats: [Format.U8_RGBA_RT],
depthStencilAttachmentFormat: Format.D24_S8,
megaStateDescriptor: {
attachmentsState: [
{
channelWriteMask: ChannelWriteMask.ALL,
rgbBlendState: {
blendMode: BlendMode.ADD,
blendSrcFactor: BlendFactor.SRC_ALPHA,
blendDstFactor: BlendFactor.ONE_MINUS_SRC_ALPHA,
},
alphaBlendState: {
blendMode: BlendMode.ADD,
blendSrcFactor: BlendFactor.ONE,
blendDstFactor: BlendFactor.ONE_MINUS_SRC_ALPHA,
},
},
],
blendConstant: TransparentBlack,
depthWrite: true,
depthCompare: CompareFunction.LESS,
cullMode: CullMode.BACK,
stencilWrite: false,
},
});

const program = device.createProgram({
vertex: {
glsl: `
layout(std140) uniform Uniforms {
mat4 u_ModelViewProjectionMatrix;
};
layout(location = 0) in vec3 a_Position;
out vec4 v_Position;
void main() {
v_Position = vec4(a_Position, 1.0);
gl_Position = u_ModelViewProjectionMatrix * vec4(a_Position, 1.0);
}
`,
},
fragment: {
glsl: `
in vec4 v_Position;
out vec4 outputColor;
void main() {
outputColor = v_Position;
}
`,
},
});

const vertexBuffer = device.createBuffer({
viewOrSize: cubeVertexArray,
usage: BufferUsage.VERTEX,
});

const uniformBuffer = device.createBuffer({
viewOrSize: 16 * 4, // mat4
usage: BufferUsage.UNIFORM,
hint: BufferFrequencyHint.DYNAMIC,
});

const inputLayout = device.createInputLayout({
vertexBufferDescriptors: [
{
arrayStride: cubeVertexSize,
stepMode: VertexStepMode.VERTEX,
attributes: [
{
shaderLocation: 0,
offset: 0,
format: Format.F32_RGB,
},
],
},
],
indexBufferFormat: null,
program,
});

const pipeline = device.createRenderPipeline({
inputLayout,
program,
colorAttachmentFormats: [Format.U8_RGBA_RT],
depthStencilAttachmentFormat: Format.D24_S8,
megaStateDescriptor: {
attachmentsState: [
{
channelWriteMask: ChannelWriteMask.ALL,
rgbBlendState: {
blendMode: BlendMode.ADD,
blendSrcFactor: BlendFactor.SRC_ALPHA,
blendDstFactor: BlendFactor.ONE_MINUS_SRC_ALPHA,
},
alphaBlendState: {
blendMode: BlendMode.ADD,
blendSrcFactor: BlendFactor.ONE,
blendDstFactor: BlendFactor.ONE_MINUS_SRC_ALPHA,
},
},
],
blendConstant: TransparentBlack,
depthWrite: true,
depthCompare: CompareFunction.LESS,
cullMode: CullMode.BACK,
stencilWrite: false,
polygonOffset: true,
polygonOffsetFactor: 2,
polygonOffsetUnits: 3,
},
});

const bindings = device.createBindings({
pipeline,
uniformBufferBindings: [
{
binding: 0,
buffer: uniformBuffer,
size: 16 * 4,
},
],
});

const mainColorRT = device.createRenderTargetFromTexture(
device.createTexture({
format: Format.U8_RGBA_RT,
width: $canvas.width,
height: $canvas.height,
usage: TextureUsage.RENDER_TARGET,
}),
);
const mainDepthRT = device.createRenderTargetFromTexture(
device.createTexture({
format: Format.D24_S8,
width: $canvas.width,
height: $canvas.height,
usage: TextureUsage.RENDER_TARGET,
}),
);

let id: number;
const frame = () => {
const aspect = $canvas.width / $canvas.height;
const projectionMatrix = mat4.perspective(
mat4.create(),
(2 * Math.PI) / 5,
aspect,
0.1,
1000,
);
const viewMatrix = mat4.identity(mat4.create());
const modelViewProjectionMatrix = mat4.create();
mat4.translate(viewMatrix, viewMatrix, vec3.fromValues(0, 0, -4));
const now = useRAF ? Date.now() / 1000 : 0;
mat4.rotate(
viewMatrix,
viewMatrix,
1,
vec3.fromValues(Math.sin(now), Math.cos(now), 0),
);
mat4.multiply(modelViewProjectionMatrix, projectionMatrix, viewMatrix);
uniformBuffer.setSubData(
0,
new Uint8Array((modelViewProjectionMatrix as Float32Array).buffer),
);
// WebGL1 need this
program.setUniformsLegacy({
u_ModelViewProjectionMatrix: modelViewProjectionMatrix,
});

/**
* An application should call getCurrentTexture() in the same task that renders to the canvas texture.
* Otherwise, the texture could get destroyed by these steps before the application is finished rendering to it.
*/
const onscreenTexture = swapChain.getOnscreenTexture();

device.beginFrame();
const renderPass = device.createRenderPass({
colorAttachment: [mainColorRT],
colorResolveTo: [onscreenTexture],
colorClearColor: [TransparentWhite],
depthStencilAttachment: mainDepthRT,
depthClearValue: 1,
});
renderPass.setPipeline(pipeline);
renderPass.setVertexInput(
inputLayout,
[
{
buffer: vertexBuffer,
},
],
null,
);
renderPass.setViewport(0, 0, $canvas.width, $canvas.height);
renderPass.setBindings(bindings);
renderPass.draw(cubeVertexCount);

renderPass.setPipeline(pipeline2);
renderPass.setVertexInput(
inputLayout2,
[
{
buffer: vertexBuffer2,
},
],
null,
);
renderPass.draw(3);

device.submitPass(renderPass);
device.endFrame();
if (useRAF) {
id = requestAnimationFrame(frame);
}
};

frame();

return () => {
if (useRAF && id) {
cancelAnimationFrame(id);
}
program.destroy();
program2.destroy();
vertexBuffer.destroy();
vertexBuffer2.destroy();
uniformBuffer.destroy();
inputLayout.destroy();
inputLayout2.destroy();
bindings.destroy();
pipeline.destroy();
pipeline2.destroy();
mainColorRT.destroy();
mainDepthRT.destroy();
device.destroy();

// For debug.
device.checkForLeaks();
};
}

render.params = {
targets: ['webgl1', 'webgl2', 'webgpu'],
default: 'webgl2',
};

0 comments on commit 1cfef88

Please sign in to comment.