### Install and Run Texture Tester Example Source: https://github.com/visgl/luma.gl/blob/master/examples/api/texture-tester/README.md Install project dependencies and start the example application. ```bash yarn install yarn start ``` -------------------------------- ### Install Dependencies and Run Example Source: https://github.com/visgl/luma.gl/blob/master/docs/developer-guide/contributing.md Install project dependencies and run a specific example in development mode for quick iteration. ```bash cd examples/core/instancing yarn yarn start-local ``` -------------------------------- ### Run luma.gl Example Locally Source: https://github.com/visgl/luma.gl/blob/master/docs/tutorials/whats-next.md Clone the luma.gl repository and navigate to an example directory to run it locally. Install dependencies with yarn and start the development server with 'yarn start'. ```bash git clone git@github.com:visgl/luma.gl.git cd luma.gl/examples/tutorials/hello-cube yarn yarn start ``` -------------------------------- ### Initialize and Start luma.gl Animation Loop Source: https://github.com/visgl/luma.gl/blob/master/wip/examples-wip/notready/gltf/index.html This snippet shows the basic setup for luma.gl, including registering a WebGL device and starting the animation loop. Ensure you have the necessary luma.gl packages installed. ```typescript import {WebGLDevice} from '@luma.gl/webgl'; import {luma} from '@luma.gl/core'; import {makeAnimationLoop} from '@luma.gl/engine'; import AppAnimationLoop from './app.ts'; luma.registerDevices([ WebGLDevice ]); const animationLoop = makeAnimationLoop(AppAnimationLoop); animationLoop.start(); ``` -------------------------------- ### Initialize luma.gl with Devices and Animation Loop Source: https://github.com/visgl/luma.gl/blob/master/wip/examples-wip/rotating-cube/index.html This snippet shows the essential steps to set up luma.gl. It registers both WebGPU and WebGL devices and then starts the animation loop using a provided template. Ensure you have the necessary luma.gl packages installed. ```javascript import {luma} from '@luma.gl/core'; import {WebGPUDevice} from '@luma.gl/webgpu'; import {WebGLDevice} from '@luma.gl/webgl'; import {makeAnimationLoop} from '@luma.gl/engine'; import AnimationLoopTemplate from './app.ts'; luma.registerDevices([ WebGPUDevice, WebGLDevice ]); makeAnimationLoop(AnimationLoopTemplate).start({ canvas: 'canvas' }); ``` -------------------------------- ### ComputePipeline Usage Example Source: https://github.com/visgl/luma.gl/blob/master/docs/api-reference/core/resources/compute-pipeline.md Demonstrates how to create and use a ComputePipeline with WebGPU, including shader compilation and binding setup. ```APIDOC ## ComputePipeline Creation and Usage ### Description This example shows how to create a `ComputePipeline` using a WGSL shader and configure its bindings. It illustrates both grouped and flat binding approaches. ### Usage ```ts const source = /* wgsl */ ` @group(0) @binding(0) var data: array; struct SceneUniforms { addend: i32 }; @group(2) @binding(0) var sceneUniforms: SceneUniforms; @compute @workgroup_size(1) fn main(@builtin(global_invocation_id) id: vec3) { let i = id.x; data[i] = data[i] + sceneUniforms.addend; } `; const shader = webgpuDevice.createShader({source}); const computePipeline = webgpuDevice.createComputePipeline({ shader, shaderLayout: { bindings: [ {name: 'data', type: 'storage', group: 0, location: 0}, {name: 'sceneUniforms', type: 'uniform', group: 2, location: 0} ] } }); // Using grouped bindings computePipeline.setBindings({ 0: {data: workBuffer}, 2: {sceneUniforms} }); // Using flat bindings computePipeline.setBindings({ data: workBuffer, sceneUniforms }); ``` ### `ComputePipelineProps` Properties - `shader`: Shader object. - `entryPoint?`: Optional entry point string. - `constants?`: Optional record of constants. - `shaderLayout?`: Optional `ComputeShaderLayout` or null. ``` -------------------------------- ### Basic Animation Loop Setup Source: https://github.com/visgl/luma.gl/blob/master/examples/showcase/dof/index.html Sets up and starts a Luma.gl animation loop using WebGPU and WebGL2 adapters. Ensure the AnimationLoopTemplate is correctly defined in './app.ts'. ```javascript import {makeAnimationLoop} from '@luma.gl/engine'; import {webgl2Adapter} from '@luma.gl/webgl'; import {webgpuAdapter} from '@luma.gl/webgpu'; import AnimationLoopTemplate from './app.ts'; const animationLoop = makeAnimationLoop(AnimationLoopTemplate, { adapters: [webgpuAdapter, webgl2Adapter] }); animationLoop.start(); ``` -------------------------------- ### Debug Website Source: https://github.com/visgl/luma.gl/blob/master/AGENTS.md Start a debug server for the project website. This is part of the LLM-friendly test setup. ```bash yarn website-debug ``` -------------------------------- ### Hello Cube Rendering Example Source: https://github.com/visgl/luma.gl/blob/master/docs/tutorials/hello-cube.mdx Renders a spinning textured cube using luma.gl. It includes WGSL and GLSL shaders, uniform management, texture loading, and an animation loop. Ensure luma.gl and math.gl are installed. ```typescript import type {NumberArray, VariableShaderType} from '@luma.gl/core'; import {Texture, UniformStore} from '@luma.gl/core'; import { AnimationLoopTemplate, makeAnimationLoop, type AnimationProps, Model, CubeGeometry, loadImageBitmap, DynamicTexture } from '@luma.gl/engine'; import {webgl2Adapter} from '@luma.gl/webgl'; import {webgpuAdapter} from '@luma.gl/webgpu'; import {Matrix4} from '@math.gl/core'; const WGSL_SHADER = /* WGSL */ ` struct Uniforms { modelViewProjectionMatrix : mat4x4; }; @group(0) @binding(auto) var app : Uniforms; @group(0) @binding(auto) var uTexture : texture_2d; @group(0) @binding(auto) var uTextureSampler : sampler; struct VertexInputs { @location(0) positions : vec4; @location(1) texCoords : vec2 }; struct FragmentInputs { @builtin(position) Position : vec4, @location(0) fragUV : vec2, @location(1) fragPosition: vec4, } @vertex fn vertexMain(inputs: VertexInputs) -> FragmentInputs { var outputs : FragmentInputs; outputs.Position = app.modelViewProjectionMatrix * inputs.positions; outputs.fragUV = inputs.texCoords; outputs.fragPosition = 0.5 * (inputs.positions + vec4(1.0, 1.0, 1.0, 1.0)); return outputs; } @fragment fn fragmentMain(inputs: FragmentInputs) -> @location(0) vec4 { return textureSample(uTexture, uTextureSampler, inputs.fragUV); } `; // GLSL const VS_GLSL = /* glsl */ ` #version 300 es #define SHADER_NAME cube-vs uniform appUniforms { mat4 modelViewProjectionMatrix; } app; layout(location=0) in vec3 positions; layout(location=1) in vec2 texCoords; out vec2 fragUV; out vec4 fragPosition; void main() { gl_Position = app.modelViewProjectionMatrix * vec4(positions, 1.0); fragUV = texCoords; fragPosition = 0.5 * (vec4(positions, 1.) + vec4(1., 1., 1., 1.)); } `; const FS_GLSL = /* glsl */ ` #version 300 es #define SHADER_NAME cube-fs precision highp float; uniform sampler2D uTexture; in vec2 fragUV; in vec4 fragPosition; layout (location=0) out vec4 fragColor; void main() { fragColor = texture(uTexture, vec2(fragUV.x, 1.0 - fragUV.y)); } `; type AppUniforms = { mvpMatrix: NumberArray; }; const app: {uniformTypes: Record} = { uniformTypes: { mvpMatrix: 'mat4x4' } }; const eyePosition = [0, 0, -4]; class AppAnimationLoopTemplate extends AnimationLoopTemplate { mvpMatrix = new Matrix4(); viewMatrix = new Matrix4().lookAt({eye: eyePosition}); model: Model; uniformStore = new UniformStore<{app: AppUniforms}>({app}); constructor({device}: AnimationProps) { super(); const texture = new DynamicTexture(device, { usage: Texture.TEXTURE | Texture.RENDER_ATTACHMENT | Texture.COPY_DST, data: loadImageBitmap('vis-logo.png'), flipY: true, mipmaps: true, sampler: device.createSampler({ minFilter: 'linear', magFilter: 'linear', mipmapFilter: 'linear' }) }); this.model = new Model(device, { id: 'rotating-cube', source: WGSL_SHADER, vs: VS_GLSL, fs: FS_GLSL, geometry: new CubeGeometry({indices: false}), bindings: { app: this.uniformStore.getManagedUniformBuffer(device, 'app'), uTexture: texture }, parameters: { depthWriteEnabled: true, depthCompare: 'less-equal' } }); } onFinalize() { this.model.destroy(); this.uniformStore.destroy(); } onRender({device, aspect, tick}: AnimationProps) { this.mvpMatrix .perspective({fovy: Math.PI / 3, aspect}) .multiplyRight(this.viewMatrix) .rotateX(tick * 0.01) .rotateY(tick * 0.013); this.uniformStore.setUniforms({ app: {mvpMatrix: this.mvpMatrix} }); const renderPass = device.beginRenderPass({clearColor: [0, 0, 0, 1], clearDepth: 1}); this.model.draw(renderPass); renderPass.end(); } } const animationLoop = makeAnimationLoop(AppAnimationLoopTemplate, { adapters: [webgpuAdapter, webgl2Adapter] }); animationLoop.start(); ``` -------------------------------- ### Install luma.gl Tables Source: https://github.com/visgl/luma.gl/blob/master/docs/api-reference/tables/README.md Install the @luma.gl/tables module using npm. ```bash npm install @luma.gl/tables ``` -------------------------------- ### Transform Feedback Example Source: https://github.com/visgl/luma.gl/blob/master/website/content/examples/tutorials/transform-feedback.mdx A basic example demonstrating the setup and usage of Transform Feedback in luma.gl. This is useful for scenarios where you need to process data on the GPU and reuse the results. ```javascript import React, {useState, useEffect} from 'react'; import {useAppInit} from '@luma.gl/react'; import {Device, Buffer, TransformFeedback, Program, Model, PrimitiveTopology} from '@luma.gl/core'; const VERTEX_SHADER = ` attribute vec4 positions; attribute vec4 colors; varying vec4 v_color; void main(void) { v_color = colors; gl_Position = positions; } `; const FRAGMENT_SHADER = ` precision highp float; varying vec4 v_color; void main(void) { gl_FragColor = v_color; } `; const TRANSFORM_FEEDBACK_VARYINGS = ['positions', 'colors']; const TRANSFORM_FEEDBACK_SHADER = ` attribute vec4 positions; attribute vec4 colors; varying vec4 v_color; void main(void) { // Example: Modify positions and colors gl_Position = positions * 1.1; v_color = colors * 0.9; // Output varyings for transform feedback gl_Position = positions; colors = v_color; } `; export function TransformFeedbackExample() { const [model, setModel] = useState(null); const [tf, setTf] = useState(null); const app = useAppInit(async ({device}) => { const vertexShader = device.createShader({ stage: 'vertex', source: VERTEX_SHADER }); const fragmentShader = device.createShader({ stage: 'fragment', source: FRAGMENT_SHADER }); const program = device.createProgram({vertexShader, fragmentShader}); const tfVertexShader = device.createShader({ stage: 'vertex', source: TRANSFORM_FEEDBACK_SHADER }); const tfProgram = device.createProgram({vertexShader: tfVertexShader, fragmentShader: fragmentShader, transformFeedbackVaryings: TRANSFORM_FEEDBACK_VARYINGS}); const positions = new Float32Array([ -0.5, -0.5, 0.0, 1.0, 0.5, -0.5, 0.0, 1.0, 0.0, 0.5, 0.0, 1.0 ]); const colors = new Float32Array([ 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0 ]); const bufferLayout = [ {name: 'positions', type: 'vec4f', size: 4}, {name: 'colors', type: 'vec4f', size: 4} ]; const inputBuffer = device.createBuffer({data: {positions, colors}, layout: bufferLayout}); const outputBuffer1 = device.createBuffer({size: inputBuffer.size, layout: bufferLayout}); const outputBuffer2 = device.createBuffer({size: inputBuffer.size, layout: bufferLayout}); const tf = device.createTransformFeedback({ program: tfProgram, inputBuffers: [inputBuffer], outputBuffers: [outputBuffer1, outputBuffer2] }); const model = new Model(device, { program, geometry: { bufferLayout, attributes: { positions: inputBuffer.bind('positions'), colors: inputBuffer.bind('colors') } } }); setModel(model); setTf(tf); return () => { model.destroy(); tf.destroy(); inputBuffer.destroy(); outputBuffer1.destroy(); outputBuffer2.destroy(); }; }); useEffect(() => { if (tf && model) { // Run transform feedback tf.run(); // Use the output of transform feedback for rendering const outputBuffer = tf.getOutputBuffers()[0]; // Use the first output buffer const tfModel = new Model(device, { program: model.program, geometry: { bufferLayout: model.geometry.bufferLayout, attributes: { positions: outputBuffer.bind('positions'), colors: outputBuffer.bind('colors') } } }); tfModel.render(); tfModel.destroy(); } }, [tf, model, app.device]); return ( ); } ``` -------------------------------- ### Example Usage of GPUTableBufferPlanner Source: https://github.com/visgl/luma.gl/blob/master/docs/api-reference/tables/gpu-table-buffer-planner.md Demonstrates how to define column descriptors and use GPUTableBufferPlanner to get an allocation plan. Ensure you have the necessary imports and a 'device' object available. ```typescript import {GPUTableBufferPlanner, type GPUTableColumnDescriptor} from '@luma.gl/tables'; const columns: GPUTableColumnDescriptor[] = [ { id: 'positions', byteStride: 8, byteLength: 8 * 4, rowCount: 4, stepMode: 'vertex', supportsPackedBuffer: true }, { id: 'instancePositions', byteStride: 12, byteLength: 12 * table.numRows, rowCount: table.numRows, stepMode: 'instance', isPosition: true, supportsPackedBuffer: true, priority: 'high' }, { id: 'instanceColors', byteStride: 4, byteLength: 4 * table.numRows, rowCount: table.numRows, stepMode: 'instance', supportsPackedBuffer: true } ]; const plan = GPUTableBufferPlanner.getAllocationPlan({ device, columns, modelInfo: { isInstanced: true, reservedVertexBufferCount: 1 }, generateConstantAttributes: device.type === 'webgpu' }); ``` -------------------------------- ### Install babel-plugin-inline-webgl-constants Source: https://github.com/visgl/luma.gl/blob/master/dev-modules/babel-plugin-inline-webgl-constants/README.md Installs the plugin using npm. This is the first step before configuring it in your Babel setup. ```sh $ npm install --save-dev babel-plugin-inline-webgl-constants ``` -------------------------------- ### Install luma.gl Core and WebGPU Adapter Source: https://github.com/visgl/luma.gl/blob/master/docs/api-guide/gpu/gpu-initialization.md Install the core luma.gl library and the WebGPU backend adapter using yarn. ```sh yarn add @luma.gl/core yarn add @luma.gl/webgpu ``` -------------------------------- ### Launch Website Debugger with Example Source: https://github.com/visgl/luma.gl/blob/master/dev-modules/devtools-extensions/docs/playwright.md Use `yarn website-debug` to launch a browser and open a specific website example. Examples can be specified by route segment or alias. ```sh yarn website-debug --example showcase/persistence ``` ```sh yarn website-debug --example api/animation --backend webgpu ``` ```sh yarn website-debug --example persistence --backend webgl2 ``` -------------------------------- ### Start Local Development Server Source: https://github.com/visgl/luma.gl/blob/master/website/README.md Starts a local development server for the website. Changes are reflected live without a server restart. ```bash yarn website:start ``` -------------------------------- ### Texture Upload WIP Example Source: https://github.com/visgl/luma.gl/blob/master/docs/api-reference/core/resources/texture.md This snippet demonstrates the setup for uploading texture data, though the specific implementation for non-8-bit formats is marked as work-in-progress. ```typescript const commandEncoder = device.createCommandEncoder(); const buffer = device.createBuffer({usage: , byteLength}); const texture = device.createTexture({ }) commandEncoder.end(); ``` -------------------------------- ### Install @luma.gl/gltf Source: https://github.com/visgl/luma.gl/blob/master/docs/api-reference/gltf/README.md Install the luma.gl glTF module using npm. ```bash npm install @luma.gl/gltf ``` -------------------------------- ### Install luma.gl Core, WebGL, and WebGPU Adapters Source: https://github.com/visgl/luma.gl/blob/master/docs/api-guide/gpu/gpu-initialization.md Install the core luma.gl library along with both WebGL and WebGPU backend adapters using yarn. ```sh yarn add @luma.gl/core yarn add @luma.gl/webgl yarn add @luma.gl/webgpu ``` -------------------------------- ### Basic Postprocessing Example Source: https://github.com/visgl/luma.gl/blob/master/website/content/examples/showcase/postprocessing.mdx Renders a scene with postprocessing effects. This example requires the PostprocessingExample component. ```javascript import {PostprocessingExample} from '@site/src/examples'; ``` -------------------------------- ### Import Statements for Lighting Example Source: https://github.com/visgl/luma.gl/blob/master/docs/tutorials/lighting.mdx Imports necessary components from luma.gl and math.gl for setting up the lighting example. ```typescript import {NumberArray} from '@luma.gl/core'; import type {AnimationProps} from '@luma.gl/engine'; import { AnimationLoopTemplate, makeAnimationLoop, Model, CubeGeometry, ShaderInputs, loadImageBitmap, DynamicTexture } from '@luma.gl/engine'; import {lighting, phongMaterial, ShaderModule} from '@luma.gl/shadertools'; import {Matrix4} from '@math.gl/core'; import {webgl2Adapter} from '@luma.gl/webgl'; import {webgpuAdapter} from '@luma.gl/webgpu'; ``` -------------------------------- ### Import Lighting Example Component Source: https://github.com/visgl/luma.gl/blob/master/docs/tutorials/lighting.mdx Import the LightingExample component for use in your React application. This component is part of the luma.gl examples. ```javascript import {LightingExample} from '@site/src/examples'; ``` -------------------------------- ### Start WebGPU Animation Loop Source: https://github.com/visgl/luma.gl/blob/master/examples/gpu-tables/dggs-gpu-polygons/index.html Initializes and starts an animation loop using luma.gl with the WebGPU adapter. Requires importing necessary modules from '@luma.gl/engine' and '@luma.gl/webgpu'. ```javascript import {makeAnimationLoop} from '@luma.gl/engine'; import {webgpuAdapter} from '@luma.gl/webgpu'; import AnimationLoopTemplate from './app.ts'; const animationLoop = makeAnimationLoop(AnimationLoopTemplate, { adapters: [webgpuAdapter] }); animationLoop.start(); ``` -------------------------------- ### Install Dependencies Source: https://github.com/visgl/luma.gl/blob/master/docs/tutorials/external-webgl-context.mdx Install MapLibre GL JS alongside luma.gl dependencies. ```bash npm install @luma.gl/webgl @luma.gl/engine maplibre-gl ``` -------------------------------- ### Hello Cube Example Component Source: https://github.com/visgl/luma.gl/blob/master/website/content/examples/tutorials/hello-cube.mdx This React component renders the luma.gl Hello Cube example. It requires the '@site/src/examples' module to be imported. ```javascript import {HelloCubeExample} from '@site/src/examples'; ``` -------------------------------- ### Typical luma.gl Install Source: https://github.com/visgl/luma.gl/blob/master/docs/developer-guide/installing.md Installs core luma.gl modules including core, webgl adapter, engine for high-level constructs, and shadertools for shader composition. ```bash yarn add @luma.gl/core yarn add @luma.gl/webgl yarn add @luma.gl/engine yarn add @luma.gl/shadertools ``` -------------------------------- ### Install luma.gl and Vite Dependencies Source: https://github.com/visgl/luma.gl/blob/master/docs/tutorials/README.mdx Installs the necessary luma.gl packages and Vite for development tooling. ```bash npm i @luma.gl/engine @luma.gl/webgl @luma.gl/webgpu npm i -D vite typescript ``` -------------------------------- ### Example Index Component Source: https://github.com/visgl/luma.gl/blob/master/website/content/examples/index.mdx This component is used to display a list of examples, dynamically generating thumbnails for each item. It accepts a function to determine the thumbnail source. ```javascript import {ExamplesIndex} from '@site/src/components/examples-index'; { const exampleName = typeof item === 'string' ? item : item.docId || item.label.toLowerCase(); return `/images/examples/${exampleName}.jpg` }} /> ``` -------------------------------- ### Install Dependencies Source: https://github.com/visgl/luma.gl/blob/master/AGENTS.md Install project dependencies using yarn. This command should be run after selecting the Node version. ```bash yarn install ``` -------------------------------- ### Initialize and Start Animation Loop Source: https://github.com/visgl/luma.gl/blob/master/examples/api/animation/index.html Initializes an animation loop with specified adapters and starts it. Ensure the AnimationLoopTemplate is correctly defined. ```javascript import {makeAnimationLoop} from '@luma.gl/engine'; import {webgpuAdapter} from '@luma.gl/webgpu'; import {webgl2Adapter} from '@luma.gl/webgl'; import AnimationLoopTemplate from './app.ts'; const animationLoop = makeAnimationLoop(AnimationLoopTemplate, { adapters: [webgpuAdapter, webgl2Adapter] }); animationLoop.start(); ``` -------------------------------- ### Install @loaders.gl/gltf Source: https://github.com/visgl/luma.gl/blob/master/docs/api-reference/gltf/README.md Install the loaders.gl glTF module using npm, which is typically needed alongside @luma.gl/gltf. ```bash npm install @loaders.gl/gltf ``` -------------------------------- ### Creating Shaders Source: https://github.com/visgl/luma.gl/blob/master/docs/api-reference/core/resources/shader.md Example of creating vertex and fragment shaders using the device.createShader method. ```APIDOC ## Creating Shaders Create a pair of shaders ```typescript const vs = device.createShader({stage: 'vertex', source}); const fs = device.createShader({stage: 'fragment', source}); ``` ``` -------------------------------- ### Arrow Instancing Example Source: https://github.com/visgl/luma.gl/blob/master/website/content/examples/gpu-tables/arrow-instancing.mdx Renders instanced data using Arrow Instancing. This example requires the ArrowInstancingExample component to be imported. ```javascript import {ArrowInstancingExample} from '@site/src/examples'; ``` -------------------------------- ### Start Animation Loop with WebGPU Adapter Source: https://github.com/visgl/luma.gl/blob/master/examples/api/cubemap/index.html Initializes and starts an animation loop using the WebGPU adapter. This is suitable for modern browsers supporting WebGPU. ```javascript import {makeAnimationLoop} from '@luma.gl/engine'; import {webgl2Adapter} from '@luma.gl/webgl'; import {webgpuAdapter} from '@luma.gl/webgpu'; import AnimationLoopTemplate from './app.ts'; const animationLoop = makeAnimationLoop(AnimationLoopTemplate, { adapters: [webgpuAdapter], }); animationLoop.start(); ``` -------------------------------- ### Install luma.gl/gpgpu Source: https://github.com/visgl/luma.gl/blob/master/docs/api-reference/gpgpu/README.md Install the luma.gl/gpgpu module using npm. This command adds the necessary package to your project's dependencies. ```bash npm install @luma.gl/gpgpu ``` -------------------------------- ### Basic AnimationLoop Usage Source: https://github.com/visgl/luma.gl/blob/master/docs/api-reference/engine/animation-loop.md Demonstrates how to create and start an AnimationLoop. It sets up a device, defines initialization, rendering, and finalization callbacks, and starts the animation loop. ```typescript import {luma} from '@luma.gl/core'; import {webgl2Adapter} from '@luma.gl/webgl'; import {AnimationLoop} from '@luma.gl/engine'; const animationLoop = new AnimationLoop({ device: luma.createDevice({ adapters: [webgl2Adapter], createCanvasContext: true }), async onInitialize({device}) { // Create GPU resources here. }, onRender({device, canvasContext}) { const framebuffer = canvasContext.getCurrentFramebuffer(); const renderPass = device.beginRenderPass({framebuffer, clearColor: [0, 0, 0, 1]}); // Draw application models here. renderPass.end(); }, onFinalize() { // Destroy application-owned resources here. } }); await animationLoop.start(); ``` -------------------------------- ### PicoGL Initialization and Setup Source: https://github.com/visgl/luma.gl/blob/master/wip/examples-wip/api-v8/stress-test/picogl/index.html Initializes PicoGL, sets up rendering states, and prepares geometry and uniforms for drawing. ```javascript utils.addTimerElement(); const NUM_DRAWCALLS = 5000; const CUBES_PER_DRAWCALL = 200; const SCENE_DIM = 500; const OPAQUE_DRAWCALLS = Math.floor(NUM_DRAWCALLS / 2); const TRANSPARENT_DRAWCALLS = NUM_DRAWCALLS - OPAQUE_DRAWCALLS; const NEAR = 200; const FAR = 2000.0; document.getElementById("info").innerHTML = `Drawing ${CUBES_PER_DRAWCALL * OPAQUE_DRAWCALLS} opaque cubes and ${CUBES_PER_DRAWCALL * TRANSPARENT_DRAWCALLS} transparent cubes in ${NUM_DRAWCALLS} draw calls `; let canvas = document.getElementById("gl-canvas"); let devicePixelRation = window.devicePixelRatio || 1; cvas.width = window.innerWidth * devicePixelRatio; canvas.height = window.innerHeight * devicePixelRatio; let app = PicoGL.createApp(canvas) .clearColor(0.0, 0.0, 0.0, 1.0) .depthTest() .depthFunc(PicoGL.LEQUAL) .cullBackfaces() .blendFunc(PicoGL.ONE, PicoGL.ONE_MINUS_SRC_ALPHA); let timer = app.createTimer(); // SET UP PROGRAM let vsSource = document.getElementById("vertex-draw").text.trim(); let fsSource = document.getElementById("fragment-draw").text.trim(); const opaqueCubes = new Array(OPAQUE_DRAWCALLS); const transparentCubes = new Array(TRANSPARENT_DRAWCALLS); const offsetData = new Float32Array(CUBES_PER_DRAWCALL * 3); // SET UP GEOMETRY let box = utils.createBox({dimensions: [2.0, 2.0, 2.0]}) let positions = app.createVertexBuffer(PicoGL.FLOAT, 3, box.positions); let uv = app.createVertexBuffer(PicoGL.FLOAT, 2, box.uvs); let normals = app.createVertexBuffer(PicoGL.FLOAT, 3, box.normals); // SET UP UNIFORMS let projMatrix = mat4.create(); let viewMatrix = mat4.create(); let lightDir = new Float32Array([1, 1, 2]); ``` -------------------------------- ### Start Animation Loop with WebGL2 Adapter Source: https://github.com/visgl/luma.gl/blob/master/examples/tutorials/transform/index.html Initializes and starts an animation loop using the WebGL2 adapter. This is a common setup for web-based graphics applications. ```javascript import {makeAnimationLoop} from '@luma.gl/engine'; import {webgpuAdapter} from '@luma.gl/webgpu'; import {webgl2Adapter} from '@luma.gl/webgl'; import AnimationLoopTemplate from './app.ts'; const animationLoop = makeAnimationLoop(AnimationLoopTemplate, { adapters: [/*webgpuAdapter,*/ webgl2Adapter] }); animationLoop.start(); ``` -------------------------------- ### App Animation Loop Setup Source: https://github.com/visgl/luma.gl/blob/master/wip/examples-wip/script/index.html Sets up the main animation loop for the application. It initializes a timeline, creates the `InstancedCube`, and defines matrices for rendering. The `onInitialize` method prepares the scene, and `onRender` handles the frame-by-frame updates and drawing. ```javascript class AppAnimationLoop extends AnimationLoop { constructor() { super({createFramebuffer: true, debug: true}); } static getInfo() { return INFO_HTML; } onInitialize({device, _animationLoop}) { this.attachTimeline(new Timeline()); this.timeline.play(); const timelineChannels = { timeChannel: this.timeline.addChannel({rate: 0.01}), eyeXChannel: this.timeline.addChannel({rate: 0.0003}), eyeYChannel: this.timeline.addChannel({rate: 0.0004}), eyeZChannel: this.timeline.addChannel({rate: 0.0002}) }; this.cube = new InstancedCube(device); const modelMatrix = mat4.create(); const viewMatix = mat4.create(); const projMatrix = mat4.create(); return {timelineChannels, modelMatrix, viewMatix, projMatrix}; } onRender(animationProps) { const {device, aspect, tick, timelineChannels, modelMatrix, viewMatix, projMatrix} = animationProps; const {framebuffer, _mousePosition} = animationProps; const {timeChannel, eyeXChannel, eyeYChannel, eyeZChannel} = timelineChannels; if (_mousePosition) { // use the center pixel location in device pixel range const devicePixels = cssToDevicePixels(gl, _mousePosition); const deviceX = devicePixels.x + Math.floor(devicePixels.width / 2); const deviceY = devicePixels.y + Math.floor(devicePixels.height / 2); pickInstance(gl, deviceX, deviceY, this.cube, framebuffer); } mat4.identity(modelMatrix); mat4.rotateX(modelMatrix, modelMatrix, tick * 0.01); mat4.rotateY(modelMatrix, modelMatrix, tick * 0.013); // Draw the cubes clear(device, {color: [0, 0, 0, 1], depth: true}); this.cube.setUniforms({ uTime: this.timeline.getTime(timeChannel), uProjection: mat4.perspective(projMatrix, Math.PI / 3, aspect, 1, 2048.0), uView: mat4.lookAt(viewMatix, [ (Math.cos(this.timeline.getTime(eyeXChannel)) * SIDE) / 2, (Math.sin(this.timeline.getTime(eyeYChannel)) * SIDE) / 2, ((Math.sin(this.timeline.getTime(eyeZChannel)) + 1) * SIDE) / 4 + 32 ], [0, 0, 0], [0, 1, 0]), uModel: modelMatrix }); this.cube.draw(); } onFinalize({gl}) { this.cube.de } } ``` -------------------------------- ### Sequence Generation Examples Source: https://github.com/visgl/luma.gl/blob/master/docs/api-reference/gpgpu/operations.md Generates lazy integer sequences with customizable start and step values. The default start is 0 and the default step is 1. Count must be non-negative and step must not be 0. ```typescript const a = sequence(5); // 0, 1, 2, 3, 4 const b = sequence(4, 10, 2); // 10, 12, 14, 16 ``` -------------------------------- ### Initialize npm Project Source: https://github.com/visgl/luma.gl/blob/master/docs/tutorials/README.mdx Creates a new project directory and initializes npm for dependency management. ```bash mkdir luma-demo cd luma-demo npm init -y ``` -------------------------------- ### Initialize Animation Loop with Adapters Source: https://github.com/visgl/luma.gl/blob/master/docs/tutorials/hello-instancing.mdx Sets up the animation loop to use both WebGPU and WebGL2 adapters. The loop then starts. ```javascript const animationLoop = makeAnimationLoop(AppAnimationLoopTemplate, { adapters: [webgpuAdapter, webgl2Adapter] }); animationLoop.start(); ``` -------------------------------- ### Setting Up Lighting with ShaderInputs Source: https://github.com/visgl/luma.gl/blob/master/docs/api-reference/shadertools/shader-modules/lighting.md Demonstrates how to initialize and configure lighting properties using ShaderInputs. This includes defining various light types, their colors, intensities, positions, and directions. ```typescript import {ShaderInputs} from '@luma.gl/engine'; import {lighting, phongMaterial} from '@luma.gl/shadertools'; const shaderInputs = new ShaderInputs({lighting, phongMaterial}); shaderInputs.setProps({ lighting: { useByteColors: false, lights: [ {type: 'ambient', color: [1, 1, 1], intensity: 0.1}, {type: 'point', color: [1, 0.47, 0.04], position: [2, 4, 3]}, { type: 'spot', color: [0.31, 0.63, 1], position: [-3, -2, 2], direction: [3, 2, -2], innerConeAngle: 0.2, outerConeAngle: 0.6 }, {type: 'directional', color: [1, 1, 1], direction: [0, -1, 0]} ] } }); ``` -------------------------------- ### HTML Entry Point for luma.gl Application Source: https://github.com/visgl/luma.gl/blob/master/docs/tutorials/README.mdx Bootsraps the luma.gl application by importing necessary modules and starting the animation loop. It prioritizes WebGPU and falls back to WebGL2. ```html ``` -------------------------------- ### Register WebGL2 Adapter and Start Animation Loop Source: https://github.com/visgl/luma.gl/blob/master/examples/tutorials/hello-instancing/index.html Registers the WebGL2 adapter and starts the luma.gl animation loop using a template. Ensure necessary adapters are imported and registered before starting. ```javascript import {webgl2Adapter} from '@luma.gl/webgl'; import {webgpuAdapter} from '@luma.gl/webgpu'; import {makeAnimationLoop} from '@luma.gl/engine'; import AnimationLoopTemplate from './app.ts'; luma.registerAdapters([ webgl2Adapter ]); makeAnimationLoop(AnimationLoopTemplate).start(); ``` -------------------------------- ### Creating a RenderPipeline Source: https://github.com/visgl/luma.gl/blob/master/docs/api-reference/core/resources/render-pipeline.md Demonstrates how to create a new RenderPipeline instance with specified shaders, shader layout, and initial bindings. ```APIDOC ## createRenderPipeline ### Description Creates a new RenderPipeline instance. ### Method `device.createRenderPipeline(props)` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body - **id** (string) - Optional - An identifier for the pipeline. - **vs** (Shader | null) - Optional - The vertex shader. - **fs** (Shader | null) - Optional - The fragment shader. - **shaderLayout** (ShaderLayout | null) - Optional - The layout defining shader attributes and bindings. - **bufferLayout** (BufferLayout[]) - Optional - Defines the layout of vertex buffers. - **topology** (PrimitiveTopology) - Optional - The primitive topology for rendering (e.g., 'triangle-list'). - **parameters** (RenderPipelineParameters) - Optional - Fixed render state parameters. - **bindings** (Bindings) - Optional - Default flat bindings for the pipeline. - **bindGroups** (BindingsByGroup) - Optional - Default grouped bindings for the pipeline. - **varyings** (string[]) - Optional - List of varying outputs from the vertex shader. - **bufferMode** (number) - Optional - Specifies buffer behavior. ### Request Example ```ts const pipeline = device.createRenderPipeline({ id: 'my-pipeline', vs, fs, shaderLayout: { attributes: [{name: 'positions', location: 0, type: 'vec3'}], bindings: [ {name: 'frameUniforms', type: 'uniform', group: 0, location: 0}, {name: 'lightingUniforms', type: 'uniform', group: 2, location: 0}, {name: 'materialUniforms', type: 'uniform', group: 3, location: 0} ] } }); ``` ### Response #### Success Response (200) - **RenderPipeline** - The created RenderPipeline object. #### Response Example (No specific example provided in source) ``` -------------------------------- ### Install Plugin with npm Source: https://github.com/visgl/luma.gl/blob/master/dev-modules/babel-plugin-remove-glsl-comments/README.md Command to install the babel-plugin-remove-glsl-comments package as a development dependency. ```sh $ npm install --save-dev babel-plugin-remove-glsl-comments ``` -------------------------------- ### Initialize Data and Buffers Source: https://github.com/visgl/luma.gl/blob/master/docs/tutorials/transform.mdx Sets up initial data for instance positions, rotations, colors, and picking colors. Creates luma.gl Buffers and a Swap object for managing buffer updates. ```javascript // -- Initialize data const trianglePositions = new Float32Array([0.015, 0.0, -0.01, 0.01, -0.01, -0.01]); const instancePositions = new Float32Array(NUM_INSTANCES * 2); const instanceRotations = new Float32Array(NUM_INSTANCES); const instanceColors = new Float32Array(NUM_INSTANCES * 3); const pickingColors = new Float32Array(NUM_INSTANCES * 2); for (let i = 0; i < NUM_INSTANCES; ++i) { instancePositions[i * 2] = random() * 2.0 - 1.0; instancePositions[i * 2 + 1] = random() * 2.0 - 1.0; instanceRotations[i] = random() * 2 * Math.PI; const randValue = random(); if (randValue > 0.5) { instanceColors[i * 3 + 1] = 1.0; instanceColors[i * 3 + 2] = 1.0; } else { instanceColors[i * 3] = 1.0; instanceColors[i * 3 + 2] = 1.0; } pickingColors[i * 2] = Math.floor(i / 255); pickingColors[i * 2 + 1] = i - 255 * pickingColors[i * 2]; } this.positionBuffer = device.createBuffer({data: trianglePositions}); this.instanceColorBuffer = device.createBuffer({data: instanceColors}); this.instancePositionBuffers = new Swap({ current: device.createBuffer({data: instancePositions}), next: device.createBuffer({data: instancePositions}) }); this.instanceRotationBuffers = new Swap({ current: device.createBuffer({data: instanceRotations}), next: device.createBuffer({data: instanceRotations}) }); this.instancePickingColorBuffer = device.createBuffer({data: pickingColors}); ``` -------------------------------- ### Full package.json Example Source: https://github.com/visgl/luma.gl/blob/master/docs/tutorials/README.mdx Complete package.json file for a luma.gl project using Vite, including dependencies and devDependencies. ```json { "name": "luma-demo", "version": "1.0.0", "private": true, "scripts": { "start": "vite", "build": "tsc && vite build", "serve": "vite preview" }, "dependencies": { "@luma.gl/engine": "9.3.0-alpha.6", "@luma.gl/webgl": "9.3.0-alpha.6", "@luma.gl/webgpu": "9.3.0-alpha.6" }, "devDependencies": { "typescript": "^5.5.0", "vite": "^8.0.0" } } ``` -------------------------------- ### Transform Example Component Source: https://github.com/visgl/luma.gl/blob/master/website/content/examples/tutorials/transform.mdx Renders an example of the Transform component. This is a high-level component that encapsulates specific transformations. ```jsx import {TransformExample} from '@site/src/examples'; ``` -------------------------------- ### End-to-End RenderPipeline Example with WGSL Layout Source: https://github.com/visgl/luma.gl/blob/master/docs/api-guide/gpu/gpu-bindings.md Demonstrates creating a WebGPU render pipeline with WGSL shaders, defining explicit group and binding locations, and providing resources via bindGroups. ```typescript const vs = device.createShader({ stage: 'vertex', source: /* wgsl */ ` struct FrameUniforms { modelViewProjectionMatrix: mat4x4 }; @group(0) @binding(0) var frameUniforms: FrameUniforms; @vertex fn vertexMain(@location(0) positions: vec3f) -> @builtin(position) vec4f { return frameUniforms.modelViewProjectionMatrix * vec4f(positions, 1.0); } ` }); const fs = device.createShader({ stage: 'fragment', source: /* wgsl */ ` struct LightingUniforms { ambientColor: vec3f }; struct MaterialUniforms { baseColorFactor: vec4f }; @group(2) @binding(0) var lightingUniforms: LightingUniforms; @group(3) @binding(0) var materialUniforms: MaterialUniforms; @group(3) @binding(1) var baseColorTexture: texture_2d; @group(3) @binding(2) var baseColorSampler: sampler; @fragment fn fragmentMain() -> @location(0) vec4f { let textureColor = textureSample(baseColorTexture, baseColorSampler, vec2f(0.5, 0.5)); return vec4f(textureColor.rgb * lightingUniforms.ambientColor, textureColor.a) * materialUniforms.baseColorFactor; } ` }); const pipeline = device.createRenderPipeline({ vs, fs, shaderLayout: { attributes: [{name: 'positions', location: 0, type: 'vec3'}], bindings: [ {name: 'frameUniforms', type: 'uniform', group: 0, location: 0}, {name: 'lightingUniforms', type: 'uniform', group: 2, location: 0}, {name: 'materialUniforms', type: 'uniform', group: 3, location: 0}, {name: 'baseColorTexture', type: 'texture', group: 3, location: 1}, {name: 'baseColorSampler', type: 'sampler', group: 3, location: 2} ] }, bindGroups: { 0: {frameUniforms}, 2: {lightingUniforms}, 3: { materialUniforms, baseColorTexture: textureView, baseColorSampler: sampler } } }); ``` -------------------------------- ### Get Cube Face Index Source: https://github.com/visgl/luma.gl/blob/master/docs/api-reference/engine/dynamic-texture.md Utility method to get the layer index for a specific cube face. ```typescript const faceIndex = dynamicTexture.getCubeFaceIndex(face); ``` -------------------------------- ### ShaderLayout Example with Attributes Source: https://github.com/visgl/luma.gl/blob/master/docs/api-reference/core/shader-layout.md An example of a ShaderLayout object with vertex attribute declarations, including a stepMode instance attribute. ```typescript const shaderLayout = { attributes: [ {name: 'positions', location: 0, type: 'vec3'}, {name: 'instanceOffsets', location: 1, type: 'vec2', stepMode: 'instance'} ], bindings: [] }; ``` -------------------------------- ### Original Vertex Shader Example Source: https://github.com/visgl/luma.gl/blob/master/dev-docs/RFCs/vNext/glsl-function-replacement-rfc.md An example of an input vertex shader that uses a GLSL function 'getPosition' which can be overridden. ```glsl in vec3 instancePosition; // Shadertools would e.g. do a line-based replacement of getPosition vec3 getPosition() { return instancePosition; } main() { const position = getPosition(); // Note: shader does not assume that `position = instancePositions`, but calls an overridable GLSL function! } ``` -------------------------------- ### Initialize and Draw Cubes with PICO-GL Source: https://github.com/visgl/luma.gl/blob/master/wip/examples-wip/api-v8/stress-test/picogl/index.html Sets up the WebGL context, initializes PICO-GL, and enters a render loop to draw a large number of cubes. This snippet is the main entry point for the stress test. ```javascript const canvas = document.createElement('canvas'); document.body.appendChild(canvas); const gl = canvas.getContext('webgl'); const timer = new Timer(); const offsets = new Float32Array(CUBES_PER_DRAWCALL * 3); fillOffsetArray(offsets); const picogl = new PICO(gl); const program = picogl.createProgram( `attribute vec3 aPosition; attribute vec3 aOffset; uniform mat4 uProjection; uniform mat4 uView; void main() { vec3 position = aPosition + aOffset; gl_Position = uProjection * uView * vec4(position, 1.0); }`, `precision mediump float; void main() { gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0); }` ); const cube = [ -0.5, -0.5, -0.5, 0.5, -0.5, -0.5, 0.5, 0.5, -0.5, -0.5, 0.5, -0.5, -0.5, -0.5, 0.5, 0.5, -0.5, 0.5, 0.5, 0.5, 0.5, -0.5, 0.5, 0.5 ]; const indices = [ 0, 1, 2, 0, 2, 3, 4, 5, 6, 4, 6, 7, 0, 1, 5, 0, 5, 4, 1, 2, 6, 1, 6, 5, 2, 3, 7, 2, 7, 6, 3, 0, 4, 3, 4, 7 ]; const vertexArray = picogl.createVertexArray() .attribute(0, picogl.createVertexBuffer(new Float32Array(cube)), 3) .attribute(1, picogl.createVertexBuffer(offsets, gl.DYNAMIC_DRAW), 3) .indices(picogl.createIndexBuffer(new Uint16Array(indices))); const projMatrix = mat4.create(); const viewMatrix = mat4.create(); function draw() { timer.start(); mat4.perspective(projMatrix, Math.PI / 4, canvas.width / canvas.height, 0.1, 1000.0); mat4.lookAt(viewMatrix, vec3.fromValues(0, 0, 5), vec3.fromValues(0, 0, 0), vec3.fromValues(0, 1, 0)); picogl.clear(); program.use() .uniform("uProjection", projMatrix) .uniform("uView", viewMatrix) .draw(); timer.end(); requestAnimationFrame(draw); } requestAnimationFrame(draw); }); ```