【发布时间】:2021-03-21 22:27:54
【问题描述】:
我正在使用 InstancedBufferGeometry 来绘制许多 .gltf 对象,并使用像 https://imgur.com/a/G9CBldQ 这样的 spritesheet 来应用多种纹理。
为了使用 spritesheet,我使用的是基于 MeshLambertMaterial 的材质,使用 onBeforeCompile 函数,并且在threejs v116之前,它工作得很好。
但是将threejs和GLTFLoader升级到v117后,什么都没有显示。
我正在像这样实现onBeforeCompile:
class InstancedLambertMaterial extends THREE.MeshLambertMaterial {
constructor(params) {
super(params);
this.spriteGrids = params?.spriteGrids;
this.userData = {
uniforms: {
vUvScale: { value: 1 / Math.sqrt(params?.spriteGrids) }
}
};
}
onBeforeCompile(shader) {
Object.assign(shader.uniforms, this.userData.uniforms);
shader.vertexShader = `#define USE_INSTANCING_CUSTOM\n${shader.vertexShader}`;
const instancedAttributes = `
attribute vec3 translation;
attribute vec4 orientation;
attribute vec3 scale;
attribute vec2 vUvOffsets;
varying vec2 v_vUvOffsets;
uniform float vUvScale;
`;
shader.vertexShader = shader.vertexShader.replace('#include <common>', `${instancedAttributes}\n#include <common>`);
const replacedProjectVertex = `
vec4 mvPosition = vec4( transformed, 1.0 );
#ifdef USE_INSTANCING
mvPosition = instanceMatrix * mvPosition;
#endif
#ifdef USE_INSTANCING_CUSTOM
vUv = uv;
transformed *= scale;
vec3 vcV = cross(orientation.xyz, transformed);
transformed = vcV * (2.0 * orientation.w) + (cross(orientation.xyz, vcV) * 2.0 + transformed);
mvPosition = vec4(translation + transformed, 1.0);
#endif
mvPosition = modelViewMatrix * mvPosition;
gl_Position = projectionMatrix * mvPosition;
#ifdef USE_INSTANCING_CUSTOM
v_vUvOffsets = vUvOffsets;
#endif
`;
shader.vertexShader = shader.vertexShader.replace('#include <project_vertex>', replacedProjectVertex);
shader.fragmentShader = `#define USE_SPRITESHEET\n${shader.fragmentShader}`;
const spriteSheetUniforms = `
#include <map_pars_fragment>
#ifdef USE_SPRITESHEET
uniform float vUvScale;
varying vec2 v_vUvOffsets;
#endif
`;
shader.fragmentShader = shader.fragmentShader.replace('#include <map_pars_fragment>', spriteSheetUniforms);
const spriteSheetTexelColorBranch = `
#ifdef USE_SPRITESHEET
vec4 texelColor = texture2D( map, (vUv * vUvScale) + (v_vUvOffsets * vUvScale) );
texelColor = mapTexelToLinear( texelColor );
diffuseColor *= texelColor;
#endif
`;
shader.fragmentShader = shader.fragmentShader.replace('#include <map_fragment>', spriteSheetTexelColorBranch);
this.userData = shader;
}
}
并像这样准备每个转换属性并应用它。
const scales = new THREE.InstancedBufferAttribute(new Float32Array(instances * 3), 3, false);
const translations = new THREE.InstancedBufferAttribute(new Float32Array(instances * 3), 3, false);
const orientations = new THREE.InstancedBufferAttribute(new Float32Array(instances * 4), 4, false);
const tex_vec = new THREE.InstancedBufferAttribute(new Float32Array(instances * 2), 2, false);
我检查了着色器输出(通过故意提高着色器错误)并且看起来与绘制我的对象相关的没有任何更改。
我查看了relase notes of v117,但看起来与我的项目没有任何变化。
我希望能够为最新版本的threejs 执行这些代码。
我做了一个工作示例。两个代码都是一样的,除了threejs和GLTFLoader的版本。
这是 v116 的结果
https://jsfiddle.net/maemaemae3/o9t1wxrm/1/
和 v117
https://jsfiddle.net/maemaemae3/2cgym7n3/1/
【问题讨论】:
标签: three.js