Home

Awesome

GEngine.js

WebGPU Engine

install

$ yarn add @gengine-js/gengine

develop

# install
$ yarn

# dev
$ yarn dev

# build
$ yarn build

Usage

<script type="module">
	import {
		Mesh,
		PerspectiveCamera,
		Scene,
		PhongMaterial,
		Vector3,
		Color,
		SpotLight,
		PointLight,
		SphereGeometry,
		OrbitControl
	} from "../dist/index.js";
	const init = async () => {
		const geometry = new SphereGeometry(10);

		const phongMaterial = new PhongMaterial();
		phongMaterial.color = new Color(1.0, 0.0, 0.0);

		const primitive = new Mesh(geometry, phongMaterial);

		primitive.rotateX(-Math.PI / 2);

		const camera = new PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.01, 1000);

		camera.position.set(0, 20, 0);

		camera.lookAt(0, 0, 0);

		const spotLight = new SpotLight(new Vector3(1.0, 1.0, 1.0), 1.0, 15, 6, 1);
		spotLight.position = new Vector3(0, 20, 0);

		const scene = new Scene({ container: "app" });

		axes.scale.set(10, 10, 10);

		const control = new OrbitControl(camera, document.getElementById("app"));

		scene.add(primitive);

		scene.setCamera(camera);

		scene.add(pointLight);

		window.addEventListener("resize", onWindowResize);

		function onWindowResize() {
			camera.aspect = window.innerWidth / window.innerHeight;
			scene.resize(window.innerWidth, window.innerHeight);
		}
		function animate() {
			control.update();
			requestAnimationFrame(animate);
			scene.render();
		}
		animate();
	};
	init();
</script>

Native

<script type="module">
	import { Model, Context, Texture, RenderTarget, Attachment } from "webgpu-gengine-js";
	import { mat4, vec3 } from "gl-matrix";
	const init = async () => {
		//init context
		const context = new Context({
			canvas: null,
			container: document.getElementById("app"),
			pixelRatio: 1
		});
		const { canvas, presentationFormat } = context;
		await context.init();
		const { width, height, depth } = context.presentationSize;
		const colorAttachment = new Attachment(
			{ r: 0.0, g: 0.0, b: 0.0, a: 0 },
			{
				textureView: () => {
					return context.context.getCurrentTexture().createView();
				}
			}
		);
		const depthTexture = new Texture({
			label: "resolveDepth",
			size: { width, height, depth },
			format: "depth24plus",
			usage: GPUTextureUsage.RENDER_ATTACHMENT
		});
		const depthAttachment = new Attachment(1.0, { texture: depthTexture });
		//fbo
		const canvasRenderTarget = new RenderTarget("render", [colorAttachment], depthAttachment);
		const aspect = canvas.width / canvas.height;
		const projectionMatrix = mat4.perspective([], (2 * Math.PI) / 5, aspect, 1, 100.0);
		const modelViewProjectionMatrix = mat4.create();
		const model = new Model({
			shaderId: "model",
			frag: `
                            @fragment
                            fn main(@location(0) fragPosition: vec4<f32>) -> @location(0) vec4<f32> {
                                 return fragPosition;
                            }
                        `,
			vert: `
                            struct Uniforms {
                                modelViewProjectionMatrix : mat4x4<f32>,
                            }
                            @binding(0) @group(0) var<uniform> uniforms : Uniforms;
                            struct VertexOutput {
                                @builtin(position) Position : vec4<f32>,
                                @location(0) fragPosition: vec4<f32>,
                            }
                            @vertex
                            fn main(@location(0) position : vec4<f32>,@location(1) color : vec4<f32>) -> VertexOutput {
                                var output : VertexOutput;
                                output.Position = uniforms.modelViewProjectionMatrix * position;
                                output.fragPosition = 0.5 * (position + vec4(1.0, 1.0, 1.0, 1.0));
                                return output;
                            }
                        `,
			vertexBuffers: [
				{
					stepMode: "vertex", //optional
					uid: "vertAttr", //must
					attributes: {
						position: { size: 4, value: positions },
						color: { size: 4, value: colors }
					}
				}
			],
			uniformBuffers: [
				{
					type: "uniform",
					uid: "systemMatrix",
					uniforms: {
						modelViewProjectionMatrix: {
							type: "mat4",
							value: () => {
								let viewMatrix = mat4.identity([]);
								mat4.translate(viewMatrix, viewMatrix, vec3.fromValues(0, 0, -4));
								const now = Date.now() / 1000;
								mat4.rotate(
									viewMatrix,
									viewMatrix,
									1,
									vec3.fromValues(Math.sin(now), Math.cos(now), 0)
								);
								mat4.multiply(modelViewProjectionMatrix, projectionMatrix, viewMatrix);
								return modelViewProjectionMatrix;
							}
						}
					}
				}
			],
			renderState: {
				targets: [
					{
						format: presentationFormat
					}
				],
				primitive: {
					topology: "triangle-list",
					cullMode: "back"
				},
				depthStencil: {
					depthWriteEnabled: true,
					depthCompare: "less",
					format: "depth24plus"
				}
			},
			draw: {
				count: 36,
				instanceCount: 1
			}
		});

		function animate() {
			requestAnimationFrame(animate);
			const passEncoder = canvasRenderTarget.beginRenderPass(context.device);
			model.render({ device: context.device, passEncoder });
			canvasRenderTarget.endRenderPass();
		}
		animate();
	};
	init();
</script>

feature

Next

  1. Complete animation
  2. Complete core glTF 2.0
  3. Text and Sprite
  4. Pick