rasander Posted April 5, 2022 Share Posted April 5, 2022 Hi, I am currently trying to generate the polyline example of OGL (v0.0.90) (https://oframe.github.io/ogl/examples/?src=polylines.html) with PIXI.js (v6.3.0). I have created a new PIXI.Mesh and created the appropriate shaders and buffers. Only at some point I'm stuck and don't know why no object is visible. Is it because of the change of the buffer values or does PIXI use a different coordinate reference? For the mathematical operations I use the Vec3 class from OGL, but I could change that later. Here is the code I wrote. import * as PIXI from 'pixi.js'; import * as OGL from "ogl"; const canvas = document.createElement('canvas'); canvas.id = 'stage'; canvas.width = window.innerWidth; canvas.height = window.innerHeight; const rendererOptions = { width: canvas.width, height: canvas.height, view: canvas, }; const stage = new PIXI.Container(); const renderer = new PIXI.Renderer(rendererOptions); renderer.backgroundColor = 0xff0000; document.body.appendChild(canvas); const vertexLines = ` attribute vec3 position; attribute vec3 next; attribute vec3 prev; attribute vec2 uv; attribute float side; uniform vec2 uResolution; uniform float uDPR; uniform float uThickness; vec4 getPosition() { vec2 aspect = vec2(uResolution.x / uResolution.y, 1); vec2 nextScreen = next.xy * aspect; vec2 prevScreen = prev.xy * aspect; vec2 tangent = normalize(nextScreen - prevScreen); vec2 normal = vec2(-tangent.y, tangent.x); normal /= aspect; normal *= 1.0 - pow(abs(uv.y - 0.5) * 1.9, 2.0); float pixelWidth = 1.0 / (uResolution.y / uDPR); normal *= pixelWidth * uThickness; // When the points are on top of each other, shrink the line to avoid artifacts. float dist = length(nextScreen - prevScreen); normal *= smoothstep(0.0, 0.02, dist); vec4 current = vec4(position, 1); current.xy -= normal * side; return current; } void main() { gl_Position = getPosition(); } `; const fragmentLines = /* glsl */ ` precision highp float; uniform vec3 uColor; varying vec2 vUv; void main() { gl_FragColor.rgb = uColor; gl_FragColor.a = 1.0; } `; const countPoints = 20; const polylines = [{ spring: 0.05, friction: 0.7, mouseVelocity: new OGL.Vec3(), mouseOffset: new OGL.Vec3(0.01), position: new Float32Array(countPoints * 3 * 2), prev: new Float32Array(countPoints * 3 * 2), next: new Float32Array(countPoints * 3 * 2), side: new Float32Array(countPoints * 1 * 2), uv: new Float32Array(countPoints * 2 * 2), index: new Uint16Array((countPoints - 1) * 3 * 2), tmp: new OGL.Vec3(), points: [], }]; polylines.forEach((polyline) => { // set static buffer values for (let i = 0; i < countPoints; i++) { polyline.side.set([-1, 1], i * 2); const v = i / (countPoints - 1); polyline.uv.set([0, v, 1, v], i * 4); if (i === countPoints - 1) continue; const ind = i * 2; polyline.index.set([ind + 0, ind + 1, ind + 2], (ind + 0) * 3); polyline.index.set([ind + 2, ind + 1, ind + 3], (ind + 1) * 3); } // set empty points for (let i = 0; i < countPoints; i++) polyline.points.push(new OGL.Vec3()); let geometry = new PIXI.Geometry(); geometry.addAttribute('position', new PIXI.Buffer(polyline.position, false, false), 3, false); geometry.addAttribute('prev', new PIXI.Buffer(polyline.prev, false, false), 3, false); geometry.addAttribute('next', new PIXI.Buffer(polyline.next, false, false), 3, false); geometry.addAttribute('side', polyline.side, 1, false); geometry.addAttribute('uv', polyline.uv, 2, false); geometry.addIndex(polyline.index); let shader = PIXI.Shader.from(vertexLines, fragmentLines, { uColor: { value: new OGL.Color('#fff') }, uThickness: { value: 50 }, uResolution: { value: new OGL.Vec2() }, uDPR: { value: 1 }, uMiter: { value: 1 } }); let mesh = new PIXI.Mesh( geometry, shader ); polyline.mesh = mesh; stage.addChild(mesh); }); // Add handlers to get mouse position const mouse = new OGL.Vec3(); if ('ontouchstart' in window) { window.addEventListener('touchstart', updateMouse, false); window.addEventListener('touchmove', updateMouse, false); } else { window.addEventListener('mousemove', updateMouse, false); } function updateGeometry(polyline) { console.log(mouse); polyline.points.forEach((p, i) => { p.toArray(polyline.position, i * 3 * 2); p.toArray(polyline.position, i * 3 * 2 + 3); if (!i) { // If first point, calculate prev using the distance to 2nd point polyline.tmp.copy(p).sub(polyline.points[i + 1]).add(p); polyline.tmp.toArray(polyline.prev, i * 3 * 2); polyline.tmp.toArray(polyline.prev, i * 3 * 2 + 3); } else { p.toArray(polyline.next, (i - 1) * 3 * 2); p.toArray(polyline.next, (i - 1) * 3 * 2 + 3); } if (i === polyline.points.length - 1) { // If last point, calculate next using distance to 2nd last point polyline.tmp.copy(p).sub(polyline.points[i - 1]).add(p); polyline.tmp.toArray(polyline.next, i * 3 * 2); polyline.tmp.toArray(polyline.next, i * 3 * 2 + 3); } else { p.toArray(polyline.prev, (i + 1) * 3 * 2); p.toArray(polyline.prev, (i + 1) * 3 * 2 + 3); } }); polyline.mesh.geometry.getBuffer('position').update(polyline.position); polyline.mesh.geometry.getBuffer('prev').update(polyline.prev); polyline.mesh.geometry.getBuffer('next').update(polyline.next); } function updateMouse(e) { if (e.changedTouches && e.changedTouches.length) { e.x = e.changedTouches[0].pageX; e.y = e.changedTouches[0].pageY; } if (e.x === undefined) { e.x = e.pageX; e.y = e.pageY; } // Get mouse value in -1 to 1 range, with y flipped mouse.set((e.x / renderer.width) * 2 - 1, (e.y / renderer.height) * -2 + 1, 0); } function update() { updateId = requestAnimationFrame(update.bind(this)); polylines.forEach((polyline) => { for (let i = polyline.points.length - 1; i >= 0; i--) { if (!i) { // For the first point, spring ease it to the mouse position polyline.tmp.copy(mouse).add(polyline.mouseOffset).sub(polyline.points[i]).multiply(polyline.spring); polyline.mouseVelocity.add(polyline.tmp).multiply(polyline.friction); polyline.points[i].add(polyline.mouseVelocity); } else { // The rest of the points ease to the point in front of them, making a line polyline.points[i].lerp(polyline.points[i - 1], 0.9); } } updateGeometry(polyline); }); renderer.render(stage); }; function resize() { canvas.width = window.innerWidth; canvas.height = window.innerHeight; renderer.resize(canvas.width, canvas.height); polylines.forEach((polyline) => { if (polyline.resolution) polyline.resolution.value.set(canvas.width, canvas.height); if (polyline.dpr) polyline.dpr.value = renderer.resolution; }); } resize(); window.addEventListener('resize', resize.bind(this)); let updateId = 0; update(); Quote Link to comment Share on other sites More sharing options...
ivan.popelyshev Posted April 5, 2022 Share Posted April 5, 2022 Looks like a serious task and you almost nailed it. Unfortunately im away from pixijs at the moment, so you have to wait for someone else or post it in pixijs discussions on github ) Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.