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 );} );