Adding uniform buffers

But still resolution problem
This commit is contained in:
2026-02-20 17:25:42 +01:00
parent 0d2e7c97ec
commit f499b78fd5
3 changed files with 31 additions and 41 deletions

View File

@@ -17,13 +17,15 @@ import {PENDULUM_FRAGMENT_SHADER_WGSL, PENDULUM_PHYSIC_COMPUTE_SHADER_WGSL, PEND
styleUrl: './pendulum.component.scss', styleUrl: './pendulum.component.scss',
}) })
export class PendulumComponent { export class PendulumComponent {
renderConfig: RenderConfig = { renderConfig: RenderConfig = {
mode: '2D', mode: '2D',
initialViewSize: 2, initialViewSize: 2,
shaderLanguage: ShaderLanguage.WGSL, shaderLanguage: ShaderLanguage.WGSL,
vertexShader: PENDULUM_VERTEX_SHADER_WGSL, vertexShader: PENDULUM_VERTEX_SHADER_WGSL,
fragmentShader: PENDULUM_FRAGMENT_SHADER_WGSL, fragmentShader: PENDULUM_FRAGMENT_SHADER_WGSL,
uniformNames: ["params"] uniformNames: [],
uniformBufferNames: ["params"]
}; };
onSceneReady(event: SceneReadyEvent) { onSceneReady(event: SceneReadyEvent) {
@@ -36,17 +38,11 @@ export class PendulumComponent {
const height = engine.getRenderHeight(); const height = engine.getRenderHeight();
const totalPixels = width * height; const totalPixels = width * height;
console.log("Width and Height ", width, height);
// A. Buffer Setup
// 1. Pixel Buffer (wie gehabt)
const pixelBuffer = new StorageBuffer(engine, totalPixels * 4); const pixelBuffer = new StorageBuffer(engine, totalPixels * 4);
// 2. State Buffer (4 Floats: theta1, theta2, v1, v2)
const stateBuffer = new StorageBuffer(engine, 4 * 4); const stateBuffer = new StorageBuffer(engine, 4 * 4);
stateBuffer.update(new Float32Array([Math.PI / 4, Math.PI / 2, 0, 0])); stateBuffer.update(new Float32Array([Math.PI / 4, Math.PI / 2, 0, 0]));
// 3. Params Uniform Buffer
const ubo = new UniformBuffer(engine); const ubo = new UniformBuffer(engine);
ubo.addUniform("resolution", 2); ubo.addUniform("resolution", 2);
ubo.addUniform("time", 1); ubo.addUniform("time", 1);
@@ -57,13 +53,10 @@ export class PendulumComponent {
ubo.addUniform("l1", 1); ubo.addUniform("l1", 1);
ubo.addUniform("l2", 1); ubo.addUniform("l2", 1);
ubo.addUniform("damping", 1); ubo.addUniform("damping", 1);
ubo.addUniform("pad1", 1); //Alignment ubo.addUniform("pad1", 1);
ubo.addUniform("pad2", 1); //Alignment ubo.addUniform("pad2", 1);
ubo.update(); ubo.update();
// B. Compute Shaders Setup
// CS1: Physics
const csPhysics = new ComputeShader("physics", engine, { const csPhysics = new ComputeShader("physics", engine, {
computeSource: PENDULUM_PHYSIC_COMPUTE_SHADER_WGSL computeSource: PENDULUM_PHYSIC_COMPUTE_SHADER_WGSL
}, { }, {
@@ -75,7 +68,6 @@ export class PendulumComponent {
csPhysics.setStorageBuffer("state", stateBuffer); csPhysics.setStorageBuffer("state", stateBuffer);
csPhysics.setUniformBuffer("p", ubo); csPhysics.setUniformBuffer("p", ubo);
// CS2: Render/Trail
const csRender = new ComputeShader("render", engine, { const csRender = new ComputeShader("render", engine, {
computeSource: PENDULUM_RENDER_COMPUTE_SHADER_WGSL computeSource: PENDULUM_RENDER_COMPUTE_SHADER_WGSL
}, { }, {
@@ -89,7 +81,6 @@ export class PendulumComponent {
csRender.setUniformBuffer("p", ubo); csRender.setUniformBuffer("p", ubo);
csRender.setStorageBuffer("state", stateBuffer); csRender.setStorageBuffer("state", stateBuffer);
// C. Material Setup (Anzeige)
const plane = scene.getMeshByName("plane"); const plane = scene.getMeshByName("plane");
if (plane?.material) { if (plane?.material) {
const mat = plane.material as any; const mat = plane.material as any;
@@ -97,39 +88,33 @@ export class PendulumComponent {
mat.setUniformBuffer("params", ubo); mat.setUniformBuffer("params", ubo);
} }
// D. Simulation Loop
let time = 0; let time = 0;
// Physik Parameter
const dt = 0.015; const dt = 0.015;
const g = 9.81;
const m1 = 2.0;
const m2 = 1.0;
const l1 = 1.5;
const l2 = 1.2;
const damping = 0.99;
// Du hast die Physik wieder drin gelassen, das ist super:
scene.onBeforeRenderObservable.add(() => { scene.onBeforeRenderObservable.add(() => {
time += dt; time += dt;
// Update Params const currentWidth = engine.getRenderWidth();
ubo.updateFloat2("resolution", width, height); const currentHeight = engine.getRenderHeight();
ubo.updateFloat2("resolution", currentWidth, currentHeight);
ubo.updateFloat("time", time); ubo.updateFloat("time", time);
ubo.updateFloat("dt", dt); ubo.updateFloat("dt", dt);
ubo.updateFloat("g", g); ubo.updateFloat("g", 9.81);
ubo.updateFloat("m1", m1); ubo.updateFloat("m1", 2.0);
ubo.updateFloat("m2", m2); ubo.updateFloat("m2", 1.0);
ubo.updateFloat("l1", l1); ubo.updateFloat("l1", 1.5);
ubo.updateFloat("l2", l2); ubo.updateFloat("l2", 1.2);
ubo.updateFloat("damping", damping); ubo.updateFloat("damping", 0.99);
ubo.updateFloat("pad1", 0); ubo.updateFloat("pad1", 0);
ubo.updateFloat("pad2", 0); ubo.updateFloat("pad2", 0);
ubo.update(); ubo.update();
// Do physics (1 thread) // Physik Dispatch an
csPhysics.dispatch(1, 1, 1); csPhysics.dispatch(1, 1, 1);
// Paint per pixel const totalPixels = currentWidth * currentHeight;
const dispatchCount = Math.ceil(totalPixels / 64); const dispatchCount = Math.ceil(totalPixels / 64);
csRender.dispatch(dispatchCount, 1, 1); csRender.dispatch(dispatchCount, 1, 1);
}); });

View File

@@ -15,7 +15,7 @@
export const PENDULUM_FRAGMENT_SHADER_WGSL = ` export const PENDULUM_FRAGMENT_SHADER_WGSL = `
varying vUV : vec2<f32>; varying vUV : vec2<f32>;
var<storage, read> pixelBuffer : array<f32>; var<storage, read> pixelBuffer : array<f32>;
var<uniform> params : Params; var<uniform> params : Params; // Zurück zum bewährten Struct!
struct Params { struct Params {
resolution: vec2<f32>, resolution: vec2<f32>,
@@ -27,23 +27,26 @@ export const PENDULUM_FRAGMENT_SHADER_WGSL = `
l1: f32, l1: f32,
l2: f32, l2: f32,
damping: f32, damping: f32,
pad1: f32, // <-- Alignment pad1: f32,
pad2: f32 // <-- Alignment pad2: f32
}; };
@fragment @fragment
fn main(input : FragmentInputs) -> FragmentOutputs { fn main(input : FragmentInputs) -> FragmentOutputs {
let width = u32(params.resolution.x); let width = u32(params.resolution.x);
let x = u32(input.vUV.x * params.resolution.x); let height = u32(params.resolution.y);
let y = u32(input.vUV.y * params.resolution.y);
// clamp schützt uns vor Abstürzen durch Rundungsfehler am Bildschirmrand
let x = clamp(u32(input.vUV.x * params.resolution.x), 0u, width - 1u);
let y = clamp(u32(input.vUV.y * params.resolution.y), 0u, height - 1u);
let index = y * width + x; let index = y * width + x;
let val = pixelBuffer[index]; let val = pixelBuffer[index];
// Hintergrund = Dunkelgrau, Linien = Grau, Massen = Weiß
var color = vec3<f32>(0.1, 0.1, 0.15); var color = vec3<f32>(0.1, 0.1, 0.15);
if (val > 0.1) { color = vec3<f32>(0.5, 0.5, 0.5); } // Linie if (val > 0.1) { color = vec3<f32>(0.5, 0.5, 0.5); }
if (val > 0.8) { color = vec3<f32>(1.0, 1.0, 1.0); } // Masse if (val > 0.8) { color = vec3<f32>(1.0, 1.0, 1.0); }
fragmentOutputs.color = vec4<f32>(color, 1.0); fragmentOutputs.color = vec4<f32>(color, 1.0);
return fragmentOutputs; return fragmentOutputs;

View File

@@ -8,6 +8,7 @@ export interface RenderConfig {
vertexShader: string; vertexShader: string;
fragmentShader: string; fragmentShader: string;
uniformNames: string[]; uniformNames: string[];
uniformBufferNames?: string[];
} }
export type RenderCallback = (material: ShaderMaterial, camera: Camera, canvas: HTMLCanvasElement, scene: Scene) => void; export type RenderCallback = (material: ShaderMaterial, camera: Camera, canvas: HTMLCanvasElement, scene: Scene) => void;
@@ -142,6 +143,7 @@ export class BabylonCanvas implements AfterViewInit, OnDestroy {
{ {
attributes: ["position", "uv"], attributes: ["position", "uv"],
uniforms: ["resolution", "cameraPosition", ...this.config.uniformNames], uniforms: ["resolution", "cameraPosition", ...this.config.uniformNames],
uniformBuffers: this.config.uniformBufferNames ?? [],
shaderLanguage: this.config.shaderLanguage ?? ShaderLanguage.GLSL shaderLanguage: this.config.shaderLanguage ?? ShaderLanguage.GLSL
} }
); );