I have deployed an object using an InstancedMesh .
But it is difficult to apply the billboard.
I have deployed an object using an InstancedMesh .
But it is difficult to apply the billboard.
When I put the billboard formula in the shader, only one object is displayed.
How can I display all objects?
code is =>
// import * as THREE from ‘https://cdn.jsdelivr.net/npm/three@0.131.3/build/three.module.js’;
import {OrbitControls} from 'https://cdn.skypack.dev/three@0.131.3/examples/jsm/controls/OrbitControls.js';
let instances = 100;
let container = document.querySelector( '[name=container]' );
let scene = new THREE.Scene();
scene.background = new THREE.Color( 0x999999 );
let camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 1, 1000 );
camera.position.set(0, 10, 10);
camera.lookAt( new THREE.Vector3( 0, 1, 0 ) );
// --- --- billboard material
class Billboard extends THREE.MeshBasicMaterial {
constructor( _customCreateOption ){
let baseCreateOption = {
onBeforeCompile: shader =>{
shader.vertexShader = shader.vertexShader.replace(
`#include <project_vertex>`,
`
vec4 mvPosition = vec4( transformed, 1.0 );
#ifdef USE_INSTANCING
mvPosition = instanceMatrix * mvPosition;
#endif
mvPosition = modelViewMatrix * mvPosition;
// gl_Position = projectionMatrix * mvPosition;
gl_Position = projectionMatrix * (modelViewMatrix * vec4(0.0, 0.0, 0.0, 1.0) + vec4(position.x, position.y, 0.0, 0.0));
`
);
console.log("shader?", shader.vertexShader);
}
};
super( Object.assign({},baseCreateOption,_customCreateOption) );
}
};
// --- --- geometry
class TerrainGrass extends THREE.InstancedMesh {
constructor(){
// --- --- geometry
const geometry = new THREE.InstancedBufferGeometry();
const vertexBuffer = new THREE.InterleavedBuffer( new Float32Array( [
// - 1, 1, 0, 0, 0, 0, 0, 0,
// 1, 1, 0, 0, 1, 0, 0, 0,
// - 1, - 1, 0, 0, 0, 1, 0, 0,
// 1, - 1, 0, 0, 1, 1, 0, 0,
- 0.3, 0.3, 0, 0, 0, 0, 0, 0,
0.3, 0.3, 0, 0, 1, 0, 0, 0,
- 0.3, - 0.3, 0, 0, 0, 1, 0, 0,
0.3, - 0.3, 0, 0, 1, 1, 0, 0,
] ), 8 );
const positions = new THREE.InterleavedBufferAttribute( vertexBuffer, 3, 0 );
geometry.setAttribute( 'position', positions );
const uvs = new THREE.InterleavedBufferAttribute( vertexBuffer, 2, 4 );
geometry.setAttribute( 'uv', uvs );
const indices = new Uint16Array( [
0, 2, 1,
2, 3, 1,
] );
geometry.setIndex( new THREE.BufferAttribute( indices, 1 ) );
// --- --- material
const material = new Billboard();
// material.map = new THREE.TextureLoader().load( 'Mickey_Mouse.png' );
material.map = new THREE.TextureLoader().load( 'https://i.imgur.com/b6LjMuN.png' );
material.map.flipY = false;
// material.blending = THREE.AdditiveBlending;
material.alphaTest = 1;
// per instance data
const matrix = new THREE.Matrix4();
const offset = new THREE.Vector3( 0, 0, 0 );
const orientation = new THREE.Quaternion();
const scale = new THREE.Vector3( 1, 1, 1 );
// let mesh = new THREE.InstancedMesh( geometry, material, instances );
// mesh.setMatrixAt( 0, matrix );
super( geometry, material, instances );
this.setMatrixAt( 0, matrix );
// to deploy
this.deploy();
}
deploy(){
// per instance data
const matrix = new THREE.Matrix4();
const offset = new THREE.Vector3();
const orientation = new THREE.Quaternion();
const scale = new THREE.Vector3( 1, 1, 1 );
for( let i=0;i<instances;i++ ){
let x = i % 10 - 5;
let z = Math.floor(i/10) - 5;
offset.set( x, 0, z );
matrix.compose( offset, orientation, scale );
this.setMatrixAt( i, matrix );
}
this.instanceMatrix.needsUpdate = true;
}
}
// scene.add( mesh );
let mesh = new TerrainGrass();
mesh.position.set( 0, 0.3, 0 );
scene.add( mesh );
scene.add( new THREE.GridHelper(10, 10, "white", "white") );
let renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
container.appendChild( renderer.domElement );
// orbitcontrols
let controls = new OrbitControls( camera, renderer.domElement );
function animate() {
requestAnimationFrame( animate );
render();
}
function render() {
renderer.render( scene, camera );
}
animate();