instanceMesh需要讓實例像粒子一樣始終朝向相機 可以如下處理
shader
export const billboarding = `
// billboarding函數的GLSL實現
// 參數:
// - position: 頂點動態位置偏移
// - positionLocal: mesh的position
// - horizontal: 水平方向是否朝向相機
// - vertical: 垂直方向是否朝向相機
vec4 billboarding(vec3 position,vec3 positionLocal, bool horizontal, bool vertical) {// 如果提供了自定義位置,更新模型矩陣的位置部分// 復制原始模型矩陣并更新位置mat4 adjustedModelMatrix = modelMatrix;adjustedModelMatrix[3][0] = position.x;adjustedModelMatrix[3][1] = position.y;adjustedModelMatrix[3][2] = position.z;mat4 modelViewMatrix = viewMatrix * adjustedModelMatrix;// 計算原始模型矩陣行的長度float xScale = length(vec3(modelMatrix[0][0], modelMatrix[0][1], modelMatrix[0][2]));float yScale = length(vec3(modelMatrix[1][0], modelMatrix[1][1], modelMatrix[1][2]));// 應用水平billboardingif (horizontal) {modelViewMatrix[0][0] = xScale;modelViewMatrix[0][1] = 0.0;modelViewMatrix[0][2] = 0.0;}// 應用垂直billboardingif (vertical) {modelViewMatrix[1][0] = 0.0;modelViewMatrix[1][1] = yScale;modelViewMatrix[1][2] = 0.0;}// 設置Z軸為朝向相機modelViewMatrix[2][0] = 0.0;modelViewMatrix[2][1] = 0.0;modelViewMatrix[2][2] = 1.0;// 計算最終的裁剪空間位置return projectionMatrix * modelViewMatrix * vec4(positionLocal, 1.0);
}
`
參考webgpu版本tsl函數
import { modelWorldMatrix } from '../accessors/ModelNode.js';
import { cameraViewMatrix, cameraProjectionMatrix } from '../accessors/Camera.js';
import { positionLocal } from '../accessors/Position.js';
import { Fn, defined } from '../tsl/TSLBase.js';/*** This can be used to achieve a billboarding behavior for flat meshes. That means they are* oriented always towards the camera.** ```js* material.vertexNode = billboarding();* ```** @tsl* @function* @param {Object} config - The configuration object.* @param {?Node<vec3>} [config.position=null] - Can be used to define the vertex positions in world space.* @param {boolean} [config.horizontal=true] - Whether to follow the camera rotation horizontally or not.* @param {boolean} [config.vertical=false] - Whether to follow the camera rotation vertically or not.* @return {Node<vec3>} The updated vertex position in clip space.*/
export const billboarding = /*@__PURE__*/ Fn( ( { position = null, horizontal = true, vertical = false } ) => {let worldMatrix;if ( position !== null ) {worldMatrix = modelWorldMatrix.toVar();worldMatrix[ 3 ][ 0 ] = position.x;worldMatrix[ 3 ][ 1 ] = position.y;worldMatrix[ 3 ][ 2 ] = position.z;} else {worldMatrix = modelWorldMatrix;}const modelViewMatrix = cameraViewMatrix.mul( worldMatrix );if ( defined( horizontal ) ) {modelViewMatrix[ 0 ][ 0 ] = modelWorldMatrix[ 0 ].length();modelViewMatrix[ 0 ][ 1 ] = 0;modelViewMatrix[ 0 ][ 2 ] = 0;}if ( defined( vertical ) ) {modelViewMatrix[ 1 ][ 0 ] = 0;modelViewMatrix[ 1 ][ 1 ] = modelWorldMatrix[ 1 ].length();modelViewMatrix[ 1 ][ 2 ] = 0;}modelViewMatrix[ 2 ][ 0 ] = 0;modelViewMatrix[ 2 ][ 1 ] = 0;modelViewMatrix[ 2 ][ 2 ] = 1;return cameraProjectionMatrix.mul( modelViewMatrix ).mul( positionLocal );} );