Discover Zephyr3d, a versatile 3D rendering engine tailor-made for browsers. Built with TypeScript, it combines the power of WebGL and WebGPU. With easy-to-use APIs and a high-level Scene framework, you can create stunning visuals while enjoying seamless cross-API compatibility. Perfect for developers looking to explore graphics development.
Zephyr3D is a powerful and flexible 3D rendering engine designed for modern web browsers, utilizing advanced technologies like WebGL and WebGPU. Developed in TypeScript, this rendering framework is perfect for both beginners and experienced developers looking to enhance their web applications with engaging 3D graphics.
Key Features:
-
Dual API Support: With a unique combination of the Device API and Scene API, Zephyr3D caters to both low-level functionality and high-level graphics development.
-
Device API: This API provides an abstract interface that standardizes methods to access WebGL, WebGL2, and WebGPU graphics capabilities. It ensures a smooth cross-API rendering experience, making it easier for developers to implement complex graphics without worrying about underlying technicalities.
-
Scene API: Built on top of the Device API, the Scene API simplifies the rendering process and includes advanced features such as PBR (Physically Based Rendering), IBL (Image-Based Lighting), clustered lighting, shadow mapping, terrain rendering, and post-processing effects.
Example Usage
To illustrate Zephyr3D’s capabilities, here are a couple of examples demonstrating its rendering functionality:
Rendering a Simple 3D Cube with the Scene API:
import { Vector3, Vector4 } from '@zephyr3d/base';
import { Scene, Application, LambertMaterial, Mesh, OrbitCameraController, PerspectiveCamera, SphereShape, DirectionalLight } from '@zephyr3d/scene';
import { backendWebGL2 } from '@zephyr3d/backend-webgl';
// Initialize the application
const myApp = new Application({
backend: backendWebGL2,
canvas: document.querySelector('#my-canvas')
});
myApp.ready().then(function () {
const scene = new Scene();
const light = new DirectionalLight(scene);
light.lookAt(Vector3.one(), Vector3.zero(), Vector3.axisPY());
const material = new LambertMaterial();
material.albedoColor = new Vector4(1, 0, 0, 1);
const sphere = new Mesh(scene, new SphereShape(), material);
const camera = new PerspectiveCamera(scene, Math.PI/3, myApp.device.canvas.width/myApp.device.canvas.height, 1, 100);
camera.lookAt(new Vector3(0, 0, 4), Vector3.zero(), new Vector3(0, 1, 0));
camera.controller = new OrbitCameraController({ center: Vector3.zero() });
myApp.inputManager.use(camera.handleEvent.bind(camera));
myApp.on('tick', function () {
camera.updateController();
camera.render(scene);
});
myApp.run();
});
Using the Device API for Low-Level Rendering:
import { Vector4 } from '@zephyr3d/base';
import { backendWebGL2 } from '@zephyr3d/backend-webgl';
(async function() {
const canvas = document.querySelector('#canvas');
const device = await backendWebGL2.createDevice(canvas);
const positions = device.createVertexBuffer('position_f32x2', new Float32Array([-0.3, -0.7, 0.3, -0.7, 0, 0.7]));
const colors = device.createVertexBuffer('diffuse_u8normx4', new Uint8Array([255, 0, 0, 255, 0, 255, 0, 255, 0, 0, 255, 255]));
const vertexLayout = device.createVertexLayout({ vertexBuffers: [{ buffer: positions }, { buffer: colors }] });
const program = device.buildRenderProgram({
vertex(pb) {
this.$inputs.position = pb.vec2().attrib('position');
this.$inputs.color = pb.vec4().attrib('diffuse');
this.$outputs.color = pb.vec4();
pb.main(function(){
this.$builtins.position = pb.vec4(this.$inputs.position, 0, 1);
this.$outputs.color = this.$inputs.color;
});
},
fragment(pb) {
this.$outputs.color = pb.vec4();
pb.main(function(){
this.$outputs.color = pb.vec4(pb.pow(this.$inputs.color.rgb, pb.vec3(1/2.2)), 1);
});
}
});
function frame() {
requestAnimationFrame(frame);
if (device.beginFrame()) {
device.clearFrameBuffer(new Vector4(0, 0, 0.5, 1), 1, 0);
device.setProgram(program);
device.setVertexLayout(vertexLayout);
device.draw('triangle-list', 0, 3);
device.endFrame();
}
}
frame();
})();