### Camera Intro Animation Setup Source: https://github.com/googlechromelabs/css-web-ui-demos/blob/main/html-in-canvas/public/demos/billboard-threejs.html Configures parameters for an introductory camera animation, defining start and end positions for both the camera and its target. This animation runs only once. ```javascript let introStartTime = performance.now(); const introDuration = 2200; // ms // Start (far cinematic position) const camStartPos = new THREE.Vector3(80, 50, 140); // End (your current composition) const camEndPos = new THREE.Vector3(30, 14, 28); // Target animation (important for OrbitControls sync) const targetStart = new THREE.Vector3(0, 0, 0); const targetEnd = new THREE.Vector3(0, 10, 0); // Flag so it runs only once let introFinished = false; ``` -------------------------------- ### Setup and Initialize Book Rendering Source: https://github.com/googlechromelabs/css-web-ui-demos/blob/main/html-in-canvas/public/demos/webgl-interactive-book.html Initializes the book rendering process by calling the setup function with the canvas element and the total number of pages. ```javascript const canvas = document.getElementById('gl-canvas'); const totalPages = 16; setupBookRendering(canvas, totalPages); ``` -------------------------------- ### Start View Transition Source: https://github.com/googlechromelabs/css-web-ui-demos/blob/main/_autodocs/configuration.md Example of initiating a View Transition using the View Transitions API. This function should wrap DOM updates. ```javascript document.startViewTransition(() => updateDOM()); ``` -------------------------------- ### Development Server Commands Source: https://github.com/googlechromelabs/css-web-ui-demos/blob/main/_autodocs/configuration.md Commands to start the development server, build for production, and preview the built site. ```bash npm run dev # Start dev server (hot reload) npm run build # Production build npm run preview # Preview built site ``` -------------------------------- ### Setup Book Rendering System Source: https://github.com/googlechromelabs/css-web-ui-demos/blob/main/_autodocs/api-reference/webgl-book.md Initializes a full 3D book rendering system on a canvas, including WebGL context, shaders, page setup, and keyboard controls for page turning. Requires HTML elements with IDs for each page. ```javascript export function setupBookRendering(canvas, numTotalPages = 6) ``` ```javascript const canvas = document.querySelector('canvas'); setupBookRendering(canvas, 6); // HTML must contain elements with IDs: page-0, page-1, ..., page-5 ``` -------------------------------- ### WebGL Setup API Source: https://github.com/googlechromelabs/css-web-ui-demos/blob/main/_autodocs/DOCUMENTATION_SUMMARY.txt APIs for WebGL initialization, buffer management, and scene rendering. ```APIDOC ## WebGL Setup API Reference ### Description Handles WebGL initialization, buffer setup, and scene drawing operations. ### Functions - **loadShader** - **initShaderProgram** - **initBuffers** - **initPositionBuffer** - **initIndexBuffer** - **initTextureBuffer** - **drawScene** - **setPositionAttribute** - **setTextureAttribute** ### Usage Examples Includes complete usage examples and type definitions for WebGL setup. ``` -------------------------------- ### Start Demo Initialization Source: https://github.com/googlechromelabs/css-web-ui-demos/blob/main/html-in-canvas/public/demos/pixijs-demo.html Calls the asynchronous function to initialize the PixiJS demo and handles any potential errors during initialization. ```javascript initDemo().catch(console.error); ``` -------------------------------- ### Run Local Server with Python Source: https://github.com/googlechromelabs/css-web-ui-demos/blob/main/html-in-canvas/README.md Starts a local static file server using Python. Ensure you are in the correct directory before running. ```bash python3 -m http.server --directory public ``` -------------------------------- ### Setup WebGL Physics Rendering Source: https://github.com/googlechromelabs/css-web-ui-demos/blob/main/html-in-canvas/public/demos/webgl-physics-elements.html Initializes the physics rendering engine with the canvas element and a selector for physics items. This is the primary setup function for the physics simulation. ```javascript import { setupPhysicsRendering } from '../js/webgl-physics-elements.js'; const canvas = document.getElementById('gl-canvas'); const physics = setupPhysicsRendering(canvas, '.physics-item'); ``` -------------------------------- ### Initialize Scene and Camera Source: https://github.com/googlechromelabs/css-web-ui-demos/blob/main/html-in-canvas/public/demos/webgl_animation_translate.html Sets up the basic WebGL scene and camera. This is a common starting point for WebGL applications. ```javascript const scene = new THREE.Scene(); const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 ); const renderer = new THREE.WebGLRenderer(); renderer.setSize( window.innerWidth, window.innerHeight ); document.body.appendChild( renderer.domElement ); ``` -------------------------------- ### Development Commands Source: https://github.com/googlechromelabs/css-web-ui-demos/blob/main/carousels-gallery/README.md Provides essential commands for managing an Astro project. Use 'npm install' to set up dependencies, 'npm run dev' to start a local development server, and 'npm run build' to prepare for production deployment. ```bash npm install ``` ```bash npm run dev ``` ```bash npm run build ``` ```bash npm run preview ``` ```bash npm run astro -- --help ``` ```bash npm run deploy ``` -------------------------------- ### WebGL Setup for Interactive Book Source: https://github.com/googlechromelabs/css-web-ui-demos/blob/main/html-in-canvas/public/demos/webgl-interactive-book.html Initializes WebGL constants and a function to create a plane geometry for rendering pages. This setup is crucial for the self-contained nature of the demo. ```javascript // We embed the WebGL setup here to allow full customization of the interaction // and to make the demo self-contained. const PAGE_WIDTH = 2.0; const PAGE_HEIGHT = 3.0; function createPlane(width, height, segX, segY) { const positions = [], normals = [], uvs = [], indices = [] for (let y = 0; y <= segY; y++) { for (let x = 0; x <= segX; x++) { const u = x / segX; const v = y / segY; positions.push(u * width, (v - 0.5) * height, 0); normals.push(0, 0, 1); uvs.push(u, 1.0 - v); } } for (let y = 0; y < segY; y++) { for (let x = 0; x < segX; x++) { const p1 = y * (segX + 1) + x; ``` -------------------------------- ### Run Local Server with Node.js Source: https://github.com/googlechromelabs/css-web-ui-demos/blob/main/html-in-canvas/README.md Starts a local static file server using Node.js (npx). Ensure you are in the correct directory before running. ```bash npx serve public ``` -------------------------------- ### Setup Navigation Event Listeners Source: https://github.com/googlechromelabs/css-web-ui-demos/blob/main/_autodocs/api-reference/navigation-api.md Initializes the lastSuccessfulEntry and listens for the navigatesuccess event to track navigation history. ```javascript navigation.lastSuccessfulEntry = navigation?.currentEntry; navigation.addEventListener('navigatesuccess', e => { navigation.lastSuccessfulEntry = e.currentTarget.currentEntry; }); ``` -------------------------------- ### Setup WebGL Book Rendering Source: https://github.com/googlechromelabs/css-web-ui-demos/blob/main/html-in-canvas/public/demos/webgl-interactive-book.html Initializes the WebGL 2 context, sets up the viewport, and links shaders for rendering an interactive book. Also sets up vertex attributes for a plane. ```javascript function setupBookRendering(canvas, numTotalPages = 6) { const gl = canvas.getContext('webgl2', { antialias: true }); if (!gl) { alert('WebGL2 not supported'); throw new Error('WebGL2 not supported'); } window.addEventListener('resize', () => { canvas.width = window.innerWidth; canvas.height = window.innerHeight; gl.viewport(0, 0, canvas.width, canvas.height); }); window.dispatchEvent(new Event('resize')); const program = gl.createProgram(); gl.attachShader(program, createShader(gl, gl.VERTEX_SHADER, vsSource)); gl.attachShader(program, createShader(gl, gl.FRAGMENT_SHADER, fsSource)); gl.linkProgram(program); const uniforms = { uProjection: gl.getUniformLocation(program, 'uProjection'), uView: gl.getUniformLocation(program, 'uView'), uModel: gl.getUniformLocation(program, 'uModel'), uTurnProgress: gl.getUniformLocation(program, 'uTurnProgress'), uPageWidth: gl.getUniformLocation(program, 'uPageWidth'), uFrontTex: gl.getUniformLocation(program, 'uFrontTex'), uBackTex: gl.getUniformLocation(program, 'uBackTex') }; const plane = createPlane(PAGE_WIDTH, PAGE_HEIGHT, 50, 50); const vao = gl.createVertexArray(); gl.bindVertexArray(vao); const posBuffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, posBuffer); gl.bufferData(gl.ARRAY_BUFFER, plane.positions, gl.STATIC_DRAW); gl.enableVertexAttribArray(0); gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0); ``` -------------------------------- ### 3D Mammoth Model Rendering Setup Source: https://github.com/googlechromelabs/css-web-ui-demos/blob/main/html-in-canvas/public/demos/webgl-mammoth-example.html Sets up the transformation matrices (model, view, projection) and uniforms for rendering the 3D mammoth model. ```javascript gl.useProgram(program); rotation += deltaTime * 0.5; const model = mat4.create(); mat4.translate(model, model, [0, 20, 50]); // Move closer to camera and center vertically mat4.rotateY(model, model, rotation); mat4.scale(model, model, [30, 30, 30]); // Adjusted scale to fit gl.uniformMatrix4fv(uProjectionMatrix, false, projection); gl.uniformMatrix4fv(uViewMatrix, false, view); gl.uniformMatrix4fv(uModelMatrix, false, model); gl.uniform2f(uResolutionLoc, canvas.width, canvas.height); ``` -------------------------------- ### JavaScript WebGL Setup and Rendering Source: https://github.com/googlechromelabs/css-web-ui-demos/blob/main/html-in-canvas/public/demos/fluid-prism-text.html Initializes WebGL2 context, sets up shaders, buffers, and handles high-DPI scaling for the canvas and text source. ```javascript const canvas = document.getElementById('gl-canvas'); const gl = canvas.getContext('webgl2'); if (!gl) { alert('WebGL 2.0 not supported. Please check browser flags.'); } const textSource = document.getElementById('text-source'); // High-DPI Support: Scale the source element to its physical rendering resolution const updateDPI = () => { const dpr = window.devicePixelRatio || 1; // Map the layout width to the physical width for 1:1 pixel rendering const targetWidth = canvas.width || (800 * dpr); const baseFontSize = 34; // Slightly larger for better clarity const basePadding = 48; textSource.style.width = targetWidth + 'px'; textSource.style.fontSize = (baseFontSize * (targetWidth / 800)) + 'px'; textSource.style.padding = (basePadding * (targetWidth / 800)) + 'px'; }; updateDPI(); ``` ```javascript function createShader(gl, type, source) { const shader = gl.createShader(type); gl.shaderSource(shader, source); gl.compileShader(shader); if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { console.error(gl.getShaderInfoLog(shader)); gl.deleteShader(shader); return null; } return shader; } ``` ```javascript const vsSource = document.getElementById('vs').text; const fsSource = document.getElementById('fs').text; const program = gl.createProgram(); gl.attachShader(program, createShader(gl, gl.VERTEX_SHADER, vsSource)); gl.attachShader(program, createShader(gl, gl.FRAGMENT_SHADER, fsSource)); gl.linkProgram(program); gl.useProgram(program); ``` ```javascript const positions = new Float32Array([ -1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, 1, ]); const texCoords = new Float32Array([ 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, ]); const positionBuffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer); gl.bufferData(gl.ARRAY_BUFFER, positions, gl.STATIC_DRAW); const aPosition = gl.getAttribLocation(program, 'a_position'); gl.enableVertexAttribArray(aPosition); ``` -------------------------------- ### WebGPU Demo API Source: https://github.com/googlechromelabs/css-web-ui-demos/blob/main/_autodocs/DOCUMENTATION_SUMMARY.txt APIs for rendering a WebGPU triangle, including device initialization and canvas setup. ```APIDOC ## WebGPU Demo API Reference ### Description Demonstrates rendering a triangle using WebGPU, covering device and canvas setup. ### Setup - GPU device initialization - Canvas context setup - Texture configuration ### Callbacks and Computation - Paint callbacks - Transform computation ### Event Handling - Resize handling ``` -------------------------------- ### Setup Physics Simulation Source: https://github.com/googlechromelabs/css-web-ui-demos/blob/main/_autodocs/INDEX.md Instructions for setting up a physics simulation with draggable elements and gravity. Elements can be configured as circles for collision detection. ```javascript setupPhysicsRendering(canvas, 'container-id') ``` ```javascript isCircle = true ``` -------------------------------- ### Three.js Scene Setup with WebGLRenderer Source: https://github.com/googlechromelabs/css-web-ui-demos/blob/main/html-in-canvas/public/demos/webgl_animation_translate.html Initializes the Three.js scene, renderer, camera, and sky effects. Sets up tone mapping and environment. ```javascript import * as THREE from 'three'; import Stats from 'three/addons/libs/stats.module.js'; import { OrbitControls } from 'three/addons/controls/OrbitControls.js'; import { Sky } from 'three/addons/objects/Sky.js'; import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js'; import { DRACOLoader } from 'three/addons/loaders/DRACOLoader.js'; import { InteractionManager } from 'three/addons/interaction/InteractionManager.js'; let mixer, model; const timer = new THREE.Timer(); timer.connect(document); const container = document.getElementById('container'); const canvas = document.getElementById('gl-canvas'); const stats = new Stats(); stats.dom.style.top = '0px'; stats.dom.style.right = '0px'; stats.dom.style.left = 'auto'; // Clear default left: 0 container.appendChild(stats.dom); // Initialize WebGLRenderer with our existing canvas const renderer = new THREE.WebGLRenderer({ canvas, antialias: true, alpha: true }); renderer.setPixelRatio(window.devicePixelRatio); renderer.setSize(window.innerWidth, window.innerHeight); renderer.toneMapping = THREE.ACESFilmicToneMapping; const scene = new THREE.Scene(); // Sky const sky = new Sky(); const skyUniforms = sky.material.uniforms; skyUniforms['turbidity'].value = 0; skyUniforms['rayleigh'].value = 3; skyUniforms['mieDirectionalG'].value = 0.7; skyUniforms['cloudElevation'].value = 1; skyUniforms['sunPosition'].value.set(- 0.8, 0.19, 0.56); const pmremGenerator = new THREE.PMREMGenerator(renderer); const environment = pmremGenerator.fromScene(sky).texture; scene.background = environment; scene.environment = environment; const camera = new THREE.PerspectiveCamera(40, window.innerWidth / window.innerHeight, 1, 100); camera.position.set(5, 2, 8); const controls = new OrbitControls(camera, canvas); controls.enableDamping = true; controls.target.set(0, 0.7, 0); controls.update(); // Initialize HIC InteractionManager const interactions = new InteractionManager(); interactions.connect(renderer, camera); ``` -------------------------------- ### Setup Physics Rendering Function Source: https://github.com/googlechromelabs/css-web-ui-demos/blob/main/_autodocs/configuration.md Initializes physics rendering on a canvas element. Uses a fixed timestep of 16ms for consistent performance. ```javascript setupPhysicsRendering(canvas, containerId) ``` -------------------------------- ### 3D Transformation Matrix Setup Source: https://github.com/googlechromelabs/css-web-ui-demos/blob/main/html-in-canvas/public/demos/webgl-mammoth-example.html Sets up projection, view, and model matrices for rendering a UI element in 3D space. Includes translation, scaling, and perspective calculations. ```javascript const projection = mat4.create(); mat4.perspective(projection, 45 * Math.PI / 180, canvas.width / canvas.height, 0.1, 1000.0); const view = mat4.create(); mat4.lookAt(view, [0, 50, 150], [0, 40, 0], [0, 1, 0]); // UI Model Matrix const uiModel = mat4.create(); mat4.translate(uiModel, uiModel, [0, 50, -50]); mat4.scale(uiModel, uiModel, [200, 200, 1]); const uiMVP = mat4.create(); mat4.multiply(uiMVP, projection, view); mat4.multiply(uiMVP, uiMVP, uiModel); // Adjust for 0..1 to -0.5..0.5 mapping const adjustment = mat4.create(); mat4.translate(adjustment, adjustment, [-0.5, 0.5, 0]); mat4.scale(adjustment, adjustment, [1, -1, 1]); const finalUiTransform = mat4.create(); mat4.multiply(finalUiTransform, uiMVP, adjustment); ``` -------------------------------- ### Initialize and Render WebGL Content Source: https://github.com/googlechromelabs/css-web-ui-demos/blob/main/html-in-canvas/public/demos/billboard-webgl-video.html Initiates the loading of a GLB model and starts the animation rendering loop. This snippet is essential for starting the application after the DOM is ready and the WebGL context is available. ```javascript // Initialize and Start loadGLBModel().then(() => { requestAnimationFrame(render); }); // Trigger first paint restartAnimations(); ``` -------------------------------- ### Start Svelte development server Source: https://github.com/googlechromelabs/css-web-ui-demos/blob/main/carousel-configurator/README.md Run the development server to see your Svelte app in action. The `--open` flag will automatically open the app in your browser. ```bash npm run dev ``` ```bash npm run dev -- --open ``` -------------------------------- ### Program Linking and Uniform Setup Source: https://github.com/googlechromelabs/css-web-ui-demos/blob/main/html-in-canvas/public/demos/webgl-mammoth-example.html Creates and links WebGL programs for both the PBR mammoth rendering and the unlit UI elements. It also retrieves uniform locations for later use. ```javascript const program = gl.createProgram(); const vs = createShader(gl, gl.VERTEX_SHADER, vsSource); const fs = createShader(gl, gl.FRAGMENT_SHADER, fsSource); gl.attachShader(program, vs); gl.attachShader(program, fs); gl.linkProgram(program); const unlitProgram = gl.createProgram(); const unlitVs = createShader(gl, gl.VERTEX_SHADER, unlitVsSource); const unlitFs = createShader(gl, gl.FRAGMENT_SHADER, unlitFsSource); gl.attachShader(unlitProgram, unlitVs); gl.attachShader(unlitProgram, unlitFs); gl.linkProgram(unlitProgram); const unlitUniforms = { uModelMatrix: gl.getUniformLocation(unlitProgram, 'uModelMatrix'), uViewMatrix: gl.getUniformLocation(unlitProgram, 'uViewMatrix'), uProjectionMatrix: gl.getUniformLocation(unlitProgram, 'uProjectionMatrix'), uSampler: gl.getUniformLocation(unlitProgram, 'uSampler'), }; const uModelMatrix = gl.getUniformLocation(program, 'uModelMatrix'); const uViewMatrix = gl.getUniformLocation(program, 'uViewMatrix'); const uProjectionMatrix = gl.getUniformLocation(program, 'uProjectionMatrix'); const uSampler = gl.getUniformLocation(program, 'uSampler'); ``` -------------------------------- ### HTML Texture and Screen Material Setup Source: https://github.com/googlechromelabs/css-web-ui-demos/blob/main/html-in-canvas/public/demos/billboard-threejs.html Creates a THREE.HTMLTexture from the provided HTML content and sets up a MeshBasicMaterial to apply this texture to a mesh. The material is configured for transparency. ```javascript // --- HTML Texture Setup (Simplifying with THREE.HTMLTexture) --- const billboardTexture = new THREE.HTMLTexture(billboardContent); const screenMaterial = new THREE.MeshBasicMaterial({ map: billboardTexture, transparent: false }); ``` -------------------------------- ### Lighting Setup Source: https://github.com/googlechromelabs/css-web-ui-demos/blob/main/html-in-canvas/public/demos/billboard-video.html Configures ambient and directional lighting for the scene, including shadow casting properties for the directional light to enhance realism. ```javascript const ambientLight = new THREE.AmbientLight(0xffffff, 0.6); scene.add(ambientLight); const dirLight = new THREE.DirectionalLight(0xffffff, 1.2); dirLight.position.set(20, 40, 20); dirLight.castShadow = true; dirLight.shadow.mapSize.width = 2048; dirLight.shadow.mapSize.height = 2048; dirLight.shadow.bias = -0.001; scene.add(dirLight); ``` -------------------------------- ### Setup Deformable Rendering Source: https://github.com/googlechromelabs/css-web-ui-demos/blob/main/html-in-canvas/public/demos/webgl-deformable-page.html Initializes the deformable rendering engine with the canvas element and the target HTML element to be rendered. This is the entry point for controlling the deformation effects. ```javascript import { setupDeformableRendering } from '../js/webgl-deformable-page.js'; const canvas = document.getElementById('gl-canvas'); const renderer = setupDeformableRendering(canvas, 'target-page'); ``` -------------------------------- ### Environment and Lighting Setup Source: https://github.com/googlechromelabs/css-web-ui-demos/blob/main/html-in-canvas/public/demos/billboard-threejs.html Adds ambient, hemisphere, and directional lights to the scene to illuminate the environment. Includes a grid helper and a ground plane that receives shadows. ```javascript // Environment & Lighting (Enhanced for PBR) const ambientLight = new THREE.AmbientLight(0xffffff, 0.6); scene.add(ambientLight); const grid = new THREE.GridHelper(100, 20); scene.add(grid); const hemisphereLight = new THREE.HemisphereLight(0xffffff, 0x444444, 1.0); scene.add(hemisphereLight); const directionalLight = new THREE.DirectionalLight(0xffffff, 2.5); directionalLight.position.set(20, 40, 20); directionalLight.castShadow = true; directionalLight.shadow.camera.top = 20; directionalLight.shadow.camera.bottom = -20; directionalLight.shadow.camera.left = -20; directionalLight.shadow.camera.right = 20; directionalLight.shadow.mapSize.width = 2048; directionalLight.shadow.mapSize.height = 2048; directionalLight.shadow.bias = -0.0001; scene.add(directionalLight); // Ground to catch shadows const groundGeom = new THREE.PlaneGeometry(100, 100); const groundMat = new THREE.ShadowMaterial({ opacity: 0.3 }); const ground = new THREE.Mesh(groundGeom, groundMat); ground.rotation.x = -Math.PI / 2; ground.position.y = 0; ground.receiveShadow = true; scene.add(ground); ``` -------------------------------- ### Setup UI and HD Textures Source: https://github.com/googlechromelabs/css-web-ui-demos/blob/main/html-in-canvas/public/demos/spectacles-example.html Initializes WebGL textures for UI elements and a high-definition texture for glass effects. Configures texture parameters for wrapping and filtering. ```javascript // UI Texture const uiTexture = gl.createTexture(); gl.bindTexture(gl.TEXTURE_2D, uiTexture); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); // HD Texture for Glass Effect const hdTexture = gl.createTexture(); gl.bindTexture(gl.TEXTURE_2D, hdTexture); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); ``` -------------------------------- ### Setup WebGL Book Curl Rendering Source: https://github.com/googlechromelabs/css-web-ui-demos/blob/main/html-in-canvas/public/demos/webgl-book-curl.html Initializes the WebGL rendering for the book curl effect. Requires a canvas element and specifies the number of pages. ```javascript import { setupCurlBookRendering } from '../js/webgl-book-curl.js'; const canvas = document.getElementById('gl-canvas'); setupCurlBookRendering(canvas, 6); ``` -------------------------------- ### Initialize WebGL Rendering Source: https://github.com/googlechromelabs/css-web-ui-demos/blob/main/_autodocs/INDEX.md Steps to initialize WebGL rendering context, create buffers, shaders, and get attribute locations. This is a foundational step for WebGL applications. ```javascript const gl = canvas.getContext('webgl2') ``` ```javascript const buffers = initBuffers(gl) ``` ```javascript const program = initShaderProgram(gl, vsSource, fsSource) ``` ```javascript const attribLoc = gl.getAttribLocation(program, 'name') ``` ```javascript drawScene(gl, programInfo, buffers, texture, rotation) ``` -------------------------------- ### Import Three.js Modules Source: https://github.com/googlechromelabs/css-web-ui-demos/blob/main/html-in-canvas/public/demos/webgl_animation_translate_color.html Imports necessary Three.js modules for WebGL rendering and examples. This is a common setup for Three.js projects. ```javascript { "imports": { "three": "https://unpkg.com/three@latest/build/three.module.js", "three/addons/": "https://unpkg.com/three@latest/examples/jsm/" } } ``` -------------------------------- ### Deploy Static HTML Demos Source: https://github.com/googlechromelabs/css-web-ui-demos/blob/main/_autodocs/INDEX.md Instructions for deploying the static HTML demos. Typically involves deploying the contents of the 'public/' directory to a web server. ```bash # Deploy public/ directory to web server ``` -------------------------------- ### Start WebGL Render Loop Source: https://github.com/googlechromelabs/css-web-ui-demos/blob/main/html-in-canvas/public/demos/webgl-interactive-book.html Initiates the animation frame request loop for rendering the WebGL scene. Ensures the loop starts only once. ```javascript let renderLoopStarted = false; function startLoop() { if (!renderLoopStarted) { renderLoopStarted = true; requestAnimationFrame(render); } } canvas.onpaint = startLoop; startLoop(); ``` -------------------------------- ### Serve Project Locally Source: https://github.com/googlechromelabs/css-web-ui-demos/blob/main/has-ua-visual-transition/README.md Run this command to serve the project locally for testing. ```bash npx serve src ``` -------------------------------- ### Grouped Bar Chart Setup Source: https://github.com/googlechromelabs/css-web-ui-demos/blob/main/html-in-canvas/public/demos/d3-data-visualisation.html Initializes data, color mapping, and DOM building logic for a grouped bar chart. This setup is used in conjunction with the onPaint function for rendering. ```javascript // ---------------------------------------------------- // Chart 1: Grouped Bar Chart // ---------------------------------------------------- { const groups = ["Q1", "Q2", "Q3", "Q4"]; const subgroups = ["Prod A", "Prod B", "Prod C"]; const data = [ { group: "Q1", "Prod A": 15, "Prod B": 55, "Prod C": 65 }, { group: "Q2", "Prod A": 50, "Prod B": 25, "Prod C": 75 }, { group: "Q3", "Prod A": 85, "Prod B": 65, "Prod C": 20 }, { group: "Q4", "Prod A": 70, "Prod B": 50, "Prod C": 80 } ]; const colorMap = { "Prod A": "#ff00cc", "Prod B": "#7b6888", "Prod C": "#00d2ff" }; const buildDom = (canvas) => { data.forEach(g => { subgroups.forEach(sub => { const segment = canvas.querySelector(".bar-segment\[data-group=\"${g.group}\"\]\[data-sub=\"${sub}\"\]"); if (segment) { bindTooltipEvents(segment, () => `${g.group} - ${sub}: ${g[sub]} `); } }); }); }; const onPaint = (canvas, ctx, width, height, dpr) => { const chartWidth = width - margin.left - margin.right; const chartHeight = height - margin.top - margin.bottom; const x0 = d3.scaleBand().domain(groups).range([0, chartWidth]).padding(0.25); const x1 = d3.scaleBand().domain(subgroups).range([0, x0.bandwidth()]).padding(0.08); const y = d3.scaleLinear().domain([0, 100]).range([chartHeight, 0]); // 1. Background Grid ctx.strokeStyle = "rgba(255, 255, 255, 0.06)"; [25, 50, 75, 100].forEach(val => { const yPos = margin.top + y(val); ctx.beginPath(); ctx.moveTo(margin.left, yPos); ctx.lineTo(margin.left + chartWidth, yPos); ctx.stroke(); }); // 2. ``` -------------------------------- ### Main WebGL Initialization Source: https://github.com/googlechromelabs/css-web-ui-demos/blob/main/html-in-canvas/public/demos/webGL.html Sets up the WebGL context, compiles shaders, initializes buffers, loads textures, and starts the rendering loop. Includes error handling for WebGL context creation. ```javascript function main() { const canvas = document.querySelector('#gl-canvas'); // Initialize the GL context const gl = canvas.getContext('webgl2'); // Only continue if WebGL is available and working if (gl === null) { alert( 'Unable to initialize WebGL. Your browser or machine may not support it.', ); return; } // Vertex shader program const vsSource = ` attribute vec4 aVertexPosition; attribute vec2 aTextureCoord; uniform mat4 uModelViewMatrix; uniform mat4 uProjectionMatrix; varying highp vec2 vTextureCoord; void main(void) { gl_Position = uProjectionMatrix * uModelViewMatrix * aVertexPosition; vTextureCoord = aTextureCoord; } `; // Fragment shader program const fsSource = ` varying highp vec2 vTextureCoord; uniform sampler2D uSampler; void main(void) { gl_FragColor = texture2D(uSampler, vTextureCoord); } `; // Initialize a shader program; this is where all the lighting // for the vertices and so forth is established. const shaderProgram = initShaderProgram(gl, vsSource, fsSource); // Collect all the info needed to use the shader program. // Look up which attribute our shader program is using // for aVertexPosition and look up uniform locations. const programInfo = { program: shaderProgram, attribLocations: { vertexPosition: gl.getAttribLocation(shaderProgram, 'aVertexPosition'), textureCoord: gl.getAttribLocation(shaderProgram, 'aTextureCoord'), }, uniformLocations: { projectionMatrix: gl.getUniformLocation(shaderProgram, 'uProjectionMatrix'), modelViewMatrix: gl.getUniformLocation(shaderProgram, 'uModelViewMatrix'), uSampler: gl.getUniformLocation(shaderProgram, 'uSampler'), }, }; const buffers = initBuffers(gl); // Load texture const texture = loadTexture(gl); // Flip image pixels into the bottom-to-top order that WebGL expects. gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true); render_context = { gl: gl, program: programInfo, buffers: buffers, texture: texture, }; requestAnimationFrame(render); } ``` -------------------------------- ### Setup UI Quad and Textures Source: https://github.com/googlechromelabs/css-web-ui-demos/blob/main/html-in-canvas/public/demos/webgl-dragon-example.html Sets up a UI quad for background display, including vertex data for positions and UVs, and configures texture parameters for the UI element and background refraction. ```javascript const uiVao = gl.createVertexArray(); gl.bindVertexArray(uiVao); // Quad Positions (centered 1x1) const uiPositions = new Float32Array([ -0.5, 0.5, 0.0, 0.5, 0.5, 0.0, -0.5, -0.5, 0.0, 0.5, -0.5, 0.0, ]); const uiPosBuffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, uiPosBuffer); gl.bufferData(gl.ARRAY_BUFFER, uiPositions, gl.STATIC_DRAW); gl.enableVertexAttribArray(0); gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0); // Quad UVs const uiUvs = new Float32Array([ 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 1.0, ]); const uiUvBuffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, uiUvBuffer); gl.bufferData(gl.ARRAY_BUFFER, uiUvs, gl.STATIC_DRAW); gl.enableVertexAttribArray(1); gl.vertexAttribPointer(1, 2, gl.FLOAT, false, 0, 0); // UI Texture const uiTexture = gl.createTexture(); gl.bindTexture(gl.TEXTURE_2D, uiTexture); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); const uiElement = document.getElementById('ui-background'); // Background Texture for Refraction const bgTexture = gl.createTexture(); gl.bindTexture(gl.TEXTURE_2D, bgTexture); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); ``` -------------------------------- ### Get Uniform Locations Source: https://github.com/googlechromelabs/css-web-ui-demos/blob/main/html-in-canvas/public/demos/webgl-dragon-example.html Retrieves the locations of uniform variables used in the WebGL shader program. ```javascript gl.getUniformLocation(unlitProgram, 'uViewMatrix'), uProjectionMatrix: gl.getUniformLocation(unlitProgram, 'uProjectionMatrix'), uSampler: gl.getUniformLocation(unlitProgram, 'uSampler'), }; const uModelMatrix = gl.getUniformLocation(program, 'uModelMatrix'); const uViewMatrix = gl.getUniformLocation(program, 'uViewMatrix'); const uProjectionMatrix = gl.getUniformLocation(program, 'uProjectionMatrix'); const uSampler = gl.getUniformLocation(program, 'uSampler'); ``` -------------------------------- ### setupBookRendering(canvas, numTotalPages) Source: https://github.com/googlechromelabs/css-web-ui-demos/blob/main/_autodocs/api-reference/webgl-book.md Initializes a complete 3D book rendering system, including page-turning animation and DOM content integration. ```APIDOC ## setupBookRendering(canvas, numTotalPages) ### Description Initializes a complete 3D book rendering system with page-turning animation and DOM integration. ### Parameters #### Path Parameters - **canvas** (HTMLCanvasElement) - Required - Canvas element to render into - **numTotalPages** (number) - Optional - Total number of pages (must be even). Defaults to 6. ### Behavior - Creates WebGL 2.0 context and shader program - Sets up vertex arrays with positions, normals, and texture coordinates - Initializes page objects with front/back DOM textures - Registers keyboard listeners (arrow keys) to advance/rewind pages - Starts animation loop with `requestAnimationFrame` - Updates page textures from DOM elements each frame - Applies transforms to DOM elements for hit-testing using `canvas.getElementTransform()` ### Page Object Structure ```javascript { frontId: string, // DOM element ID for front page backId: string, // DOM element ID for back page frontTex: WebGLTexture, // WebGL texture for front backTex: WebGLTexture, // WebGL texture for back progress: number, // Current turn progress (0 to 1) targetProgress: number // Target turn progress } ``` ### Keyboard Controls - `ArrowRight` — Turn page forward - `ArrowLeft` — Turn page backward ### Example ```javascript const canvas = document.querySelector('canvas'); setupBookRendering(canvas, 6); // HTML must contain elements with IDs: page-0, page-1, ..., page-5 ``` ``` -------------------------------- ### Get WebGPU Context Source: https://github.com/googlechromelabs/css-web-ui-demos/blob/main/_autodocs/configuration.md Code to obtain a WebGPU rendering context from a canvas element. This is required for WebGPU functionality. ```javascript const context = canvas.getContext('webgpu'); ``` -------------------------------- ### HTML Example for Carousel Slide Source: https://github.com/googlechromelabs/css-web-ui-demos/blob/main/_autodocs/types.md Illustrates how a carousel slide element is structured in HTML, including its class and data-label. ```html
``` -------------------------------- ### Common WebGL Initialization and Render Loop Source: https://github.com/googlechromelabs/css-web-ui-demos/blob/main/_autodocs/api-reference/webgl-setup.md Illustrates the typical workflow for setting up a WebGL application, including context acquisition, shader program initialization, buffer creation, texture loading, and the render loop. ```javascript // 1. Initialize const canvas = document.querySelector('canvas'); const gl = canvas.getContext('webgl') || canvas.getContext('webgl2'); const programInfo = { program: initShaderProgram(gl, vsSource, fsSource), attribLocations: { vertexPosition: gl.getAttribLocation(program, 'aPosition'), textureCoord: gl.getAttribLocation(program, 'aTextureCoord') }, uniformLocations: { projectionMatrix: gl.getUniformLocation(program, 'uProjection'), modelViewMatrix: gl.getUniformLocation(program, 'uModelView'), uSampler: gl.getUniformLocation(program, 'uSampler') } }; const buffers = initBuffers(gl); // 2. Load texture const texture = gl.createTexture(); // ... texture configuration ... // 3. Render loop let rotation = 0; function render(time) { rotation += 0.01; drawScene(gl, programInfo, buffers, texture, rotation); requestAnimationFrame(render); } requestAnimationFrame(render); ``` -------------------------------- ### HTML Canvas Element for HTML-in-Canvas API Source: https://github.com/googlechromelabs/css-web-ui-demos/blob/main/_autodocs/configuration.md Example of a canvas element with the layoutsubtree attribute, intended for use with the HTML-in-Canvas API. ```html ``` -------------------------------- ### Three.js Setup Source: https://github.com/googlechromelabs/css-web-ui-demos/blob/main/html-in-canvas/public/demos/threejs-interactive-book.html Initializes the Three.js renderer, scene, camera, and orbit controls for interactive navigation. Sets up rendering properties like pixel ratio, size, tone mapping, and color space. Enables shadow mapping. ```javascript const PAGE_WIDTH = 2.0; const PAGE_HEIGHT = 3.0; const TOTAL_PAGES = 16; const canvas = document.getElementById('gl-canvas'); // --- Three.js Setup --- const renderer = new THREE.WebGLRenderer({ canvas, antialias: true, alpha: true }); renderer.setPixelRatio(window.devicePixelRatio); renderer.setSize(window.innerWidth, window.innerHeight); renderer.toneMapping = THREE.ACESFilmicToneMapping; renderer.toneMappingExposure = 1.0; renderer.outputColorSpace = THREE.SRGBColorSpace; renderer.shadowMap.enabled = true; const scene = new THREE.Scene(); const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 100); camera.position.set(0, 2, 7); const controls = new OrbitControls(camera, renderer.domElement); controls.enableDamping = true; controls.dampingFactor = 0.05; controls.maxPolarAngle = Math.PI / 2 + 0.1; // Don't go too far below ground ``` -------------------------------- ### Initialize PixiJS Application Source: https://github.com/googlechromelabs/css-web-ui-demos/blob/main/html-in-canvas/public/demos/pixijs-demo.html Initializes a new PixiJS application instance with various configurations for rendering and display. ```javascript const app = new Application(); await app.init({ resizeTo: window, antialias: true, backgroundAlpha: 0, // Keep transparent to see background gradient resolution: window.devicePixelRatio || 1, autoDensity: true, hello: true }); ``` -------------------------------- ### WebGL Physics API Source: https://github.com/googlechromelabs/css-web-ui-demos/blob/main/_autodocs/DOCUMENTATION_SUMMARY.txt API for 2D physics simulation with draggable DOM elements, including physics setup and element properties. ```APIDOC ## WebGL Physics API Reference ### Description Enables 2D physics simulation for draggable DOM elements, supporting gravity, collision, and friction. ### Functions - **setupPhysicsRendering** ### Classes - **PhysicsElement** - Properties: [Details on properties like position, velocity, etc.] - Methods: [Details on methods for element manipulation] ### Physics Interactions - Gravity - Collision - Friction - Drag ### Rendering - DOM texture rendering - HTML-in-Canvas integration ``` -------------------------------- ### Initialize WebGL and Render HTML Element Source: https://github.com/googlechromelabs/css-web-ui-demos/blob/main/html-in-canvas/public/demos/webgl3d.html Sets up the WebGL context, compiles shaders, creates buffers, and renders an HTML element as a textured quad. Handles texture initialization for different browser versions. ```javascript const observer = new ResizeObserver(([entry]) => { canvas.width = entry.devicePixelContentBoxSize[0].inlineSize; canvas.height = entry.devicePixelContentBoxSize[0].blockSize; const gl = canvas.getContext('webgl2'); gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true); // 1. Add uniform matrix to Vertex Shader const vsSrc = `#version 300 es in vec2 a_pos; in vec2 a_uv; uniform mat4 u_matrix; out vec2 v_uv; void main(){ // Apply matrix multiplication gl_Position = u_matrix * vec4(a_pos, 0.0, 1.0); v_uv = a_uv; }`; const fsSrc = `#version 300 es precision mediump float; in vec2 v_uv; uniform sampler2D u_tex; out vec4 fragColor; void main(){ fragColor = texture(u_tex, v_uv); }`; const vs = gl.createShader(gl.VERTEX_SHADER); gl.shaderSource(vs, vsSrc); gl.compileShader(vs); const fs = gl.createShader(gl.FRAGMENT_SHADER); gl.shaderSource(fs, fsSrc); gl.compileShader(fs); const prog = gl.createProgram(); gl.attachShader(prog, vs); gl.attachShader(prog, fs); gl.linkProgram(prog); gl.useProgram(prog); const vao = gl.createVertexArray(); gl.bindVertexArray(vao); const vbo = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, vbo); // Standard quad coordinates gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ -1,-1,0,0, 1,-1,1,0, -1,1,0,1, -1,1,0,1, 1,-1,1,0, 1,1,1,1 ]), gl.STATIC_DRAW); const posLoc = gl.getAttribLocation(prog, 'a_pos'); const uvLoc = gl.getAttribLocation(prog, 'a_uv'); gl.enableVertexAttribArray(posLoc); gl.vertexAttribPointer(posLoc, 2, gl.FLOAT, false, 16, 0); gl.enableVertexAttribArray(uvLoc); gl.vertexAttribPointer(uvLoc, 2, gl.FLOAT, false, 16, 8); const tex = gl.createTexture(); gl.bindTexture(gl.TEXTURE_2D, tex); // Initialize texture // This if block is used to ensure older browser support before the breaking update in Chromium 150 // See https://github.com/WICG/html-in-canvas/pull/128/changes if (gl.texElementImage2D.length === 3) { gl.texElementImage2D(gl.TEXTURE_2D, gl.RGBA8, child); } else { gl.texElementImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, child); } gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); // Changed to Linear for better 3D look gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); gl.uniform1i(gl.getUniformLocation(prog, 'u_tex'), 0); // --- 3D MATRIX GENERATION --- // A standard perspective projection matrix (FOV ~60deg, Aspect 1.0, Near 0.1, Far 100) // Hardcoded for simplicity to avoid external math libraries. const projection = new DOMMatrix([ 1.73, 0, 0, 0, 0, 1.73, 0, 0, 0, 0, -1.002, -1, 0, 0, -0.2, 0 ]); // Use DOMMatrix to handle the Model transform (Rotate/Translate) const modelView = new DOMMatrix(); modelView.translateSelf(0, 0, -3); // Move back into the screen modelView.rotateSelf(30, 45, 0); // Rotate on X and Y axis // Multiply Projection * ModelView const finalMatrix = projection.multiply(modelView); // Upload to shader const matrixLoc = gl.getUniformLocation(prog, 'u_matrix'); gl.uniformMatrix4fv(matrixLoc, false, finalMatrix.toFloat32Array()); gl.drawArrays(gl.TRIANGLES, 0, 6); // --- COMPUTE CSS TRANSFORM --- // 1. Convert HTML Element pixels (0..100) to WebGL Model units (-1..1) // - Translate (-50, -50) to center the element // - Scale (2/100) to map 100px to 2 units // - Flip Y (CSS Y is down, WebGL Y is up) const toGLModel = new DOMMatrix() .scale(2/100, -2/100, 1) .translate(-50, -50); // 2. Convert WebGL Clip Space (-1..1) to CSS Viewport pixels (0..200) // - Translate (100, 100) to move center to canvas middle // - Scale (100) to map 1 unit to 100px (half canvas size) // - Flip Y (WebGL Y is up, CSS Y is down) const toCSSViewport = new DOMMatrix() .translate(100, 100) .scale(100, -100, 1); // 3. Combine: toCSS * finalMatrix * toGL // This maps the element's pixels through the WebGL transform and back to screen pixels const cssTransform = toCSSViewport.multiply(finalMatrix).multiply(toGLModel); child.style.transform = canvas.getElementTransform(child, cssTransform).toString(); }); observer.observe(canvas, {box: 'device-pixel-content-box', fireOnEveryPaint: true}); ``` -------------------------------- ### Setup Label Planes and Textures Source: https://github.com/googlechromelabs/css-web-ui-demos/blob/main/html-in-canvas/public/demos/webgl_animation_translate.html Configures 3D Plane meshes for each HTML label, matching their aspect ratio and using HTMLTexture for rendering. ```javascript // Setup the Label Planes, Textures, and Connector Lines in 3D Space LABELS.forEach((lbl) => { const el = document.getElementById(lbl.id); // 1. Get the actual CSS aspect ratio of this specific label const cssWidth = el.offsetWidth || 150; const cssHeight = el.offsetHeight || 50; const aspect = cssWidth / cssHeight; // 2. Create the HTMLTexture wrapping the DOM element const texture = new THREE.HTMLTexture(el); texture.colorSpace = THREE.SRGBColorSpace; // <-- CRITICAL: Prevents color shifting in sRGB renderer! // 3. Create a 3D Plane Mesh with a matching aspect ratio! // We lock the height at 0.35 and compute the width dynamically. ``` -------------------------------- ### Initialize WebGL2 Context and Canvas Source: https://github.com/googlechromelabs/css-web-ui-demos/blob/main/html-in-canvas/public/demos/webgl-dragon-example-video.html Sets up the WebGL2 rendering context and resizes the canvas to match the device's pixel density for sharp rendering. Includes error handling for unsupported WebGL2. ```javascript const canvas = document.getElementById('gl-canvas'); const gl = canvas.getContext('webgl2'); // Size the canvas grid to match the device scale factor to prevent blurriness. const observer = new ResizeObserver(([entry]) => { canvas.width = entry.devicePixelContentBoxSize[0].inlineSize; canvas.height = entry.devicePixelContentBoxSize[0].blockSize; }); observer.observe(canvas, {box: 'device-pixel-content-box'}); if (!gl) { alert('WebGL2 not supported'); throw new Error('WebGL2 not supported'); } ```