Skip to content

Commit

Permalink
Wireframe: Add WebGPU version. (#29534)
Browse files Browse the repository at this point in the history
* Wireframe: Add WebGPU version.

* Examples: Clean up.
  • Loading branch information
Mugen87 authored Oct 1, 2024
1 parent d4ae99c commit 35127e2
Show file tree
Hide file tree
Showing 7 changed files with 327 additions and 16 deletions.
1 change: 1 addition & 0 deletions examples/files.json
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,7 @@
"webgpu_lights_phong",
"webgpu_lights_rectarealight",
"webgpu_lights_selective",
"webgpu_lines_fat_wireframe",
"webgpu_lines_fat",
"webgpu_loader_gltf",
"webgpu_loader_gltf_anisotropy",
Expand Down
2 changes: 2 additions & 0 deletions examples/jsm/lines/LineSegmentsGeometry.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@ class LineSegmentsGeometry extends InstancedBufferGeometry {
this.setAttribute( 'instanceStart', new InterleavedBufferAttribute( instanceBuffer, 3, 0 ) ); // xyz
this.setAttribute( 'instanceEnd', new InterleavedBufferAttribute( instanceBuffer, 3, 3 ) ); // xyz

this.instanceCount = this.attributes.instanceStart.count;

//

this.computeBoundingBox();
Expand Down
15 changes: 0 additions & 15 deletions examples/jsm/lines/webgpu/LineSegments2.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@ import {
} from 'three';
import { LineSegmentsGeometry } from '../../lines/LineSegmentsGeometry.js';

const _viewport = new Vector4();

const _start = new Vector3();
const _end = new Vector3();

Expand Down Expand Up @@ -358,19 +356,6 @@ class LineSegments2 extends Mesh {

}

onBeforeRender( renderer ) {

const uniforms = this.material.uniforms;

if ( uniforms && uniforms.resolution ) {

renderer.getViewport( _viewport );
this.material.uniforms.resolution.value.set( _viewport.z, _viewport.w );

}

}

}

export { LineSegments2 };
56 changes: 56 additions & 0 deletions examples/jsm/lines/webgpu/Wireframe.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import {
InstancedInterleavedBuffer,
InterleavedBufferAttribute,
Line2NodeMaterial,
Mesh,
Vector3
} from 'three';
import { LineSegmentsGeometry } from '../../lines/LineSegmentsGeometry.js';

const _start = new Vector3();
const _end = new Vector3();

class Wireframe extends Mesh {

constructor( geometry = new LineSegmentsGeometry(), material = new Line2NodeMaterial( { color: Math.random() * 0xffffff } ) ) {

super( geometry, material );

this.isWireframe = true;

this.type = 'Wireframe';

}

// for backwards-compatibility, but could be a method of LineSegmentsGeometry...

computeLineDistances() {

const geometry = this.geometry;

const instanceStart = geometry.attributes.instanceStart;
const instanceEnd = geometry.attributes.instanceEnd;
const lineDistances = new Float32Array( 2 * instanceStart.count );

for ( let i = 0, j = 0, l = instanceStart.count; i < l; i ++, j += 2 ) {

_start.fromBufferAttribute( instanceStart, i );
_end.fromBufferAttribute( instanceEnd, i );

lineDistances[ j ] = ( j === 0 ) ? 0 : lineDistances[ j - 1 ];
lineDistances[ j + 1 ] = lineDistances[ j ] + _start.distanceTo( _end );

}

const instanceDistanceBuffer = new InstancedInterleavedBuffer( lineDistances, 2, 1 ); // d0, d1

geometry.setAttribute( 'instanceDistanceStart', new InterleavedBufferAttribute( instanceDistanceBuffer, 1, 0 ) ); // d0
geometry.setAttribute( 'instanceDistanceEnd', new InterleavedBufferAttribute( instanceDistanceBuffer, 1, 1 ) ); // d1

return this;

}

}

export { Wireframe };
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 0 additions & 1 deletion examples/webgpu_lines_fat.html
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,6 @@
const geometry = new LineGeometry();
geometry.setPositions( positions );
geometry.setColors( colors );
geometry.instanceCount = positions.length / 3 - 1;

matLine = new THREE.Line2NodeMaterial( {

Expand Down
268 changes: 268 additions & 0 deletions examples/webgpu_lines_fat_wireframe.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,268 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>three.js webgpu - lines - fat - wireframe</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<link type="text/css" rel="stylesheet" href="main.css">
</head>

<body>

<div id="container"></div>

<div id="info"><a href="https://threejs.org" target="_blank">three.js</a> - fat lines</div>

<script type="importmap">
{
"imports": {
"three": "../build/three.webgpu.js",
"three/tsl": "../build/three.webgpu.js",
"three/addons/": "./jsm/"
}
}
</script>

<script type="module">

import * as THREE from 'three';
import { color } from 'three/tsl';

import Stats from 'three/addons/libs/stats.module.js';

import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
import { Wireframe } from 'three/addons/lines/webgpu/Wireframe.js';
import { WireframeGeometry2 } from 'three/addons/lines/WireframeGeometry2.js';

let wireframe, renderer, scene, camera, camera2, controls, backgroundNode;
let wireframe1;
let matLine, matLineBasic, matLineDashed;
let stats;
let gui;

// viewport
let insetWidth;
let insetHeight;

init();

function init() {

renderer = new THREE.WebGPURenderer( { antialias: true } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setClearColor( 0x000000, 0.0 );
renderer.setAnimationLoop( animate );
document.body.appendChild( renderer.domElement );

scene = new THREE.Scene();

camera = new THREE.PerspectiveCamera( 40, window.innerWidth / window.innerHeight, 1, 1000 );
camera.position.set( - 50, 0, 50 );

camera2 = new THREE.PerspectiveCamera( 40, 1, 1, 1000 );
camera2.position.copy( camera.position );

controls = new OrbitControls( camera, renderer.domElement );
controls.minDistance = 10;
controls.maxDistance = 500;

backgroundNode = color( 0x222222 );

// Wireframe ( WireframeGeometry2, Line2NodeMaterial )

let geo = new THREE.IcosahedronGeometry( 20, 1 );

const geometry = new WireframeGeometry2( geo );

matLine = new THREE.Line2NodeMaterial( {

color: 0x4080ff,
linewidth: 5, // in world units with size attenuation, pixels otherwise
dashed: false

} );

wireframe = new Wireframe( geometry, matLine );
wireframe.computeLineDistances();
wireframe.scale.set( 1, 1, 1 );
scene.add( wireframe );

// Line ( THREE.WireframeGeometry, THREE.LineBasicMaterial ) - rendered with gl.LINE

geo = new THREE.WireframeGeometry( geo );

matLineBasic = new THREE.LineBasicMaterial( { color: 0x4080ff } );
matLineDashed = new THREE.LineDashedMaterial( { scale: 2, dashSize: 1, gapSize: 1 } );

wireframe1 = new THREE.LineSegments( geo, matLineBasic );
wireframe1.computeLineDistances();
wireframe1.visible = false;
scene.add( wireframe1 );

//

window.addEventListener( 'resize', onWindowResize );
onWindowResize();

stats = new Stats();
document.body.appendChild( stats.dom );

initGui();

}

function onWindowResize() {

camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();

renderer.setSize( window.innerWidth, window.innerHeight );

insetWidth = window.innerHeight / 4; // square
insetHeight = window.innerHeight / 4;

camera2.aspect = insetWidth / insetHeight;
camera2.updateProjectionMatrix();

}

function animate() {

// main scene

renderer.setClearColor( 0x000000, 0 );

renderer.setViewport( 0, 0, window.innerWidth, window.innerHeight );

renderer.autoClear = true;

scene.backgroundNode = null;
renderer.render( scene, camera );

// inset scene

const posY = window.innerHeight - insetHeight - 20;

renderer.clearDepth(); // important!

renderer.setScissorTest( true );

renderer.setScissor( 20, posY, insetWidth, insetHeight );

renderer.setViewport( 20, posY, insetWidth, insetHeight );

camera2.position.copy( camera.position );
camera2.quaternion.copy( camera.quaternion );

renderer.autoClear = false;

scene.backgroundNode = backgroundNode;
renderer.render( scene, camera2 );

renderer.setScissorTest( false );

stats.update();

}

//

function initGui() {

gui = new GUI();

const param = {
'line type': 0,
'width (px)': 5,
'dashed': false,
'dash scale': 1,
'dash / gap': 1
};


gui.add( param, 'line type', { 'LineGeometry': 0, 'gl.LINE': 1 } ).onChange( function ( val ) {

switch ( val ) {

case 0:
wireframe.visible = true;

wireframe1.visible = false;

break;

case 1:
wireframe.visible = false;

wireframe1.visible = true;

break;

}

} );

gui.add( param, 'width (px)', 1, 10 ).onChange( function ( val ) {

matLine.linewidth = val;

} );

gui.add( param, 'dashed' ).onChange( function ( val ) {

matLine.dashed = val;
wireframe1.material = val ? matLineDashed : matLineBasic;

} );

gui.add( param, 'dash scale', 0.5, 1, 0.1 ).onChange( function ( val ) {

matLine.dashScale = val;
matLineDashed.scale = val;

} );

gui.add( param, 'dash / gap', { '2 : 1': 0, '1 : 1': 1, '1 : 2': 2 } ).onChange( function ( val ) {

switch ( val ) {

case 0:
matLine.dashSize = 2;
matLine.gapSize = 1;

matLineDashed.dashSize = 2;
matLineDashed.gapSize = 1;

break;

case 1:
matLine.dashSize = 1;
matLine.gapSize = 1;

matLineDashed.dashSize = 1;
matLineDashed.gapSize = 1;

break;

case 2:
matLine.dashSize = 1;
matLine.gapSize = 2;

matLineDashed.dashSize = 1;
matLineDashed.gapSize = 2;

break;

}

} );

}

</script>

</body>

</html>

0 comments on commit 35127e2

Please sign in to comment.