瀏覽代碼

WebGLRenderer: Enable rendering without vertex data. (#24179)

* Clean up of #19451.

* Additional check and example.

* Removed temporary inline objects.

* Added screenshot for example.

* Updated draw range in example.

* Added screenshot for example.

* Added description for example.

* Removed old code from example.

* Changed noise function in example.

* Renamed example.

* Prettier example.

* Simplified conditional.

* Fixed _maxInstanceCount undefined.

* Directly initialize drawStart/drawEnd from drawRange.
Daniel Filonik 2 年之前
父節點
當前提交
00c4ff6f4e

+ 1 - 0
examples/files.json

@@ -310,6 +310,7 @@
 	],
 	"webgl2": [
 		"webgl2_buffergeometry_attributes_integer",
+		"webgl2_buffergeometry_attributes_none",
 		"webgl2_materials_texture2darray",
 		"webgl2_materials_texture3d",
 		"webgl2_materials_texture3d_partialupdate",

二進制
examples/screenshots/webgl2_buffergeometry_attributes_none.jpg


+ 179 - 0
examples/webgl2_buffergeometry_attributes_none.html

@@ -0,0 +1,179 @@
+<!DOCTYPE html>
+<html lang="en">
+	<head>
+		<title>three.js WebGL 2 - buffergeometry - attributes - none</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" rel="noopener">three.js</a> WebGL 2 - buffergeometry - attributes - none</div>
+
+		<script id="vertexShader" type="x-shader/x-vertex">			
+			
+			uniform mat4 modelViewMatrix;
+			uniform mat4 projectionMatrix;
+			
+			uniform float seed;
+			
+			/*
+			const float PHI = 1.61803398874989484820459;  // Φ = Golden Ratio
+			
+			float goldNoise(vec2 xy){
+				return fract(tan(distance(xy*PHI, xy)*seed)*xy.x);
+			}
+			*/
+			
+			const uint ieeeMantissa = 0x007FFFFFu;
+			const uint ieeeOne      = 0x3F800000u;
+
+			uint hash(uint x) {
+				x += ( x << 10u );
+				x ^= ( x >>  6u );
+				x += ( x <<  3u );
+				x ^= ( x >> 11u );
+				x += ( x << 15u );
+				return x;
+			}
+			
+			uint hash(uvec2 v) { return hash( v.x ^ hash(v.y) ); }
+			
+			float hashNoise(vec2 xy) {
+				uint m = hash(floatBitsToUint(xy)); 
+				
+				m &= ieeeMantissa;
+				m |= ieeeOne;
+				
+				return uintBitsToFloat( m ) - 1.0;
+			}
+			
+			float pseudoRandom(float lower, float delta, in vec2 xy) {
+				return lower + delta*hashNoise(xy);
+			}
+			
+			vec3 pseudoRandomVec3(float lower, float upper, int index) {
+				float delta = upper - lower;
+				float x = pseudoRandom(lower, delta, vec2(index, 0));
+				float y = pseudoRandom(lower, delta, vec2(index, 1));
+				float z = pseudoRandom(lower, delta, vec2(index, 2));
+				return vec3(x, y, z);
+			}
+			
+			out vec3 vColor;
+
+			void main()	{
+
+				const float scale = 1.0/64.0;
+				vec3 position = pseudoRandomVec3(-1.0, +1.0, gl_VertexID/3) + scale * pseudoRandomVec3(-1.0, +1.0, gl_VertexID);
+				vec3 color = pseudoRandomVec3(0.25, 1.0, gl_VertexID/3);
+				gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0 );
+				vColor = color;
+
+			}
+		</script>
+
+		<script id="fragmentShader" type="x-shader/x-fragment">
+					
+			precision mediump float;
+
+			in vec3 vColor;
+			
+			out vec4 fColor;
+
+			void main()	{
+
+				fColor = vec4(vColor, 1);
+
+			}
+		</script>
+
+		<!-- Import maps polyfill -->
+		<!-- Remove this when import maps will be widely supported -->
+		<script async src="https://unpkg.com/[email protected]/dist/es-module-shims.js"></script>
+
+		<script type="importmap">
+			{
+				"imports": {
+					"three": "../build/three.module.js"
+				}
+			}
+		</script>
+
+		<script type="module">
+
+			import * as THREE from 'three';
+
+			import WebGL from './jsm/capabilities/WebGL.js';
+
+			if ( WebGL.isWebGL2Available() === false ) {
+
+				document.body.appendChild( WebGL.getWebGL2ErrorMessage() );
+
+			}
+
+			let camera, scene, renderer, mesh;
+
+			init();
+			animate();
+
+			function init() {
+
+				camera = new THREE.PerspectiveCamera( 27, window.innerWidth / window.innerHeight, 1, 3500 );
+				camera.position.z = 4;
+
+				scene = new THREE.Scene();
+				scene.background = new THREE.Color( 0x050505 );
+				scene.fog = new THREE.Fog( 0x050505, 2000, 3500 );
+
+				// geometry
+
+				const triangleCount = 10000;
+				const vertexCountPerTriangle = 3;
+				const vertexCount = triangleCount*vertexCountPerTriangle;
+
+				const geometry = new THREE.BufferGeometry();				
+				geometry.setDrawRange(0, vertexCount);
+
+				// material
+
+				const material = new THREE.RawShaderMaterial( {
+					uniforms: {
+						seed: { value: 42 },
+					},
+					vertexShader: document.getElementById( 'vertexShader' ).textContent,
+					fragmentShader: document.getElementById( 'fragmentShader' ).textContent,
+					side: THREE.DoubleSide,
+					glslVersion: THREE.GLSL3
+				} );
+
+				// mesh
+
+				mesh = new THREE.Mesh( geometry, material );
+				mesh.frustumCulled = false;
+				scene.add( mesh );
+
+				// renderer
+
+				renderer = new THREE.WebGLRenderer( { antialias: true } );
+				renderer.setSize( window.innerWidth, window.innerHeight );
+				document.body.appendChild( renderer.domElement );
+
+			}
+
+			function animate(time) {
+
+				requestAnimationFrame( animate );
+
+				mesh.rotation.x = time/1000.0 * 0.25;
+				mesh.rotation.y = time/1000.0 * 0.50;
+				
+				renderer.render( scene, camera );
+
+			}
+
+		</script>
+
+	</body>
+</html>

+ 29 - 28
src/renderers/WebGLRenderer.js

@@ -700,31 +700,48 @@ function WebGLRenderer( parameters = {} ) {
 		//
 
 		let index = geometry.index;
-		const position = geometry.attributes.position;
+		let rangeFactor = 1;
+
+		if ( material.wireframe === true ) {
+
+			index = geometries.getWireframeAttribute( geometry );
+			rangeFactor = 2;
+
+		}
 
 		//
 
-		if ( index === null ) {
+		const drawRange = geometry.drawRange;
+		const position = geometry.attributes.position;
 
-			if ( position === undefined || position.count === 0 ) return;
+		let drawStart = drawRange.start * rangeFactor;
+		let drawEnd = ( drawRange.start + drawRange.count ) * rangeFactor;
 
-		} else if ( index.count === 0 ) {
+		if ( group !== null ) {
 
-			return;
+			drawStart = Math.max( drawStart, group.start * rangeFactor );
+			drawEnd = Math.min( drawEnd, ( group.start + group.count ) * rangeFactor );
 
 		}
 
-		//
+		if ( index !== null ) {
 
-		let rangeFactor = 1;
+			drawStart = Math.max( drawStart, 0 );
+			drawEnd = Math.min( drawEnd, index.count );
 
-		if ( material.wireframe === true ) {
+		} else if ( position !== undefined && position !== null ) {
 
-			index = geometries.getWireframeAttribute( geometry );
-			rangeFactor = 2;
+			drawStart = Math.max( drawStart, 0 );
+			drawEnd = Math.min( drawEnd, position.count );
 
 		}
 
+		const drawCount = drawEnd - drawStart;
+
+		if ( drawCount < 0 || drawCount === Infinity ) return;
+
+		//
+
 		bindingStates.setup( object, material, program, geometry, index );
 
 		let attribute;
@@ -741,23 +758,6 @@ function WebGLRenderer( parameters = {} ) {
 
 		//
 
-		const dataCount = ( index !== null ) ? index.count : position.count;
-
-		const rangeStart = geometry.drawRange.start * rangeFactor;
-		const rangeCount = geometry.drawRange.count * rangeFactor;
-
-		const groupStart = group !== null ? group.start * rangeFactor : 0;
-		const groupCount = group !== null ? group.count * rangeFactor : Infinity;
-
-		const drawStart = Math.max( rangeStart, groupStart );
-		const drawEnd = Math.min( dataCount, rangeStart + rangeCount, groupStart + groupCount ) - 1;
-
-		const drawCount = Math.max( 0, drawEnd - drawStart + 1 );
-
-		if ( drawCount === 0 ) return;
-
-		//
-
 		if ( object.isMesh ) {
 
 			if ( material.wireframe === true ) {
@@ -809,7 +809,8 @@ function WebGLRenderer( parameters = {} ) {
 
 		} else if ( geometry.isInstancedBufferGeometry ) {
 
-			const instanceCount = Math.min( geometry.instanceCount, geometry._maxInstanceCount );
+			const maxInstanceCount = geometry._maxInstanceCount !== undefined ? geometry._maxInstanceCount : Infinity;
+			const instanceCount = Math.min( geometry.instanceCount, maxInstanceCount );
 
 			renderer.renderInstances( drawStart, drawCount, instanceCount );