使用动画蒙皮网格获得轮廓效果的最佳方法
Best method to get Outline effect with animated skinned mesh
使用动画蒙皮网格获得轮廓效果的最佳方法是什么?
模型暂停在特定姿势的示例:https://jsfiddle.net/Eketol/uev9o0qp/
composer = new THREE.EffectComposer( renderer );
renderPass = new THREE.RenderPass(scene, camera);
renderPass.setSize(window.innerWidth, window.innerHeight);
composer.addPass(renderPass);
outlinePass = new THREE.OutlinePass( new THREE.Vector2( this.viewWidth, this.viewHeight ), scene, camera );
outlinePass.visibleEdgeColor.set( 0xff0000 );
outlinePass.hiddenEdgeColor.set( 0xffff00 );
outlinePass.edgeGlow = 0;
outlinePass.edgeThickness = 0.3; // Default is 1.
outlinePass.edgeStrength = 3; // Default is 3.
outlinePass.setSize(window.innerWidth, window.innerHeight);
composer.addPass(outlinePass);
动画模型的另一个例子:https://jsfiddle.net/Eketol/4xcd365w/
据我了解,这是由于图形卡中进行了转换,因此代码没有顶点位置的参考。
此问题也影响到 raycaster。
我已经阅读了多次尝试和实验。他们中的一些人使用发光material,其他人使用两个甚至三个网格实例和多个渲染通道来完成轮廓(例如:http://jsfiddle.net/Nv7Up/)。
使用发光的缺点material:
- 轮廓粗细会随着相机距离的变化而变化。
- 如果所选对象前面有另一个对象,轮廓可能不会完全可见。
- 具有多个网格的对象可能看起来有点奇怪(尽管我可以接受)。
使用多个网格的缺点:
- 对于具有低多边形的简单对象来说可能没问题,但对于具有多个网格的自定义对象来说就很糟糕了?例如:一支带有剑、盾牌等随机配件的士兵。不确定克隆每个蒙皮对象及其自定义属性会有多复杂或需要多少性能成本。
- 与其使用多个网格,不如使用原始网格并在次要场景中渲染它来获取蒙版或轮廓不是更容易吗?
问题:
- 是否可以使当前的 ThreeJS Outline 效果与动画 SkinnedMesh 一起正常工作?
- 如果转换后的顶点信息在显卡上,轮廓着色器是否可以
直接从中获取顶点信息或渲染图像?
- 如果以上方法不可行,是否有一种方法可以将 SkinnedMesh 变换应用于顶点,以便着色器具有正确的姿势信息?
Is it possible to get the current ThreeJS Outline effect working properly with animated SkinnedMesh?
是的,但是需要增强内部顶点着色器。我在这个更新的 fiddle 中添加了相应的着色器块(morphtarget_pars_vertex
、skinbase_vertex
、skinning_pars_vertex
、begin_vertex
、morphtarget_vertex
、skinning_vertex
, project_vertex
).
https://jsfiddle.net/35vrtm42/
但请注意,马动画是基于变形目标的。
有了这个增强功能,您只需告诉 OutlinePass
启用相应的动画类型。对于fiddle,有必要这样做。
outlinePass.depthMaterial.morphTargets = true;
outlinePass.prepareMaskMaterial.morphTargets = true;
如果您的模型使用骨骼动画,只需将 morphTargets
属性 替换为 skinning
。
three.js R112
在 OutlinePass.js v121 (6-Okt-2020) L38 中,缺少蒙皮参数:
this.depthMaterial = new THREE.MeshDepthMaterial();
this.depthMaterial.side = THREE.DoubleSide;
this.depthMaterial.depthPacking = THREE.RGBADepthPacking;
this.depthMaterial.blending = THREE.NoBlending;
this.prepareMaskMaterial = this.getPrepareMaskMaterial();
this.prepareMaskMaterial.side = THREE.DoubleSide;
this.prepareMaskMaterial.fragmentShader = replaceDepthToViewZ( this.prepareMaskMaterial.fragmentShader, this.renderCamera );
其实应该是这样的
this.depthMaterial = new THREE.MeshDepthMaterial();
this.depthMaterial.side = THREE.DoubleSide;
this.depthMaterial.depthPacking = THREE.RGBADepthPacking;
this.depthMaterial.blending = THREE.NoBlending;
this.depthMaterial.skinning = true; // <-------
this.prepareMaskMaterial = this.getPrepareMaskMaterial();
this.prepareMaskMaterial.side = THREE.DoubleSide;
this.prepareMaskMaterial.fragmentShader = replaceDepthToViewZ( this.prepareMaskMaterial.fragmentShader, this.renderCamera );
this.prepareMaskMaterial.skinning = true; // <-----
使用动画蒙皮网格获得轮廓效果的最佳方法是什么?
模型暂停在特定姿势的示例:https://jsfiddle.net/Eketol/uev9o0qp/
composer = new THREE.EffectComposer( renderer );
renderPass = new THREE.RenderPass(scene, camera);
renderPass.setSize(window.innerWidth, window.innerHeight);
composer.addPass(renderPass);
outlinePass = new THREE.OutlinePass( new THREE.Vector2( this.viewWidth, this.viewHeight ), scene, camera );
outlinePass.visibleEdgeColor.set( 0xff0000 );
outlinePass.hiddenEdgeColor.set( 0xffff00 );
outlinePass.edgeGlow = 0;
outlinePass.edgeThickness = 0.3; // Default is 1.
outlinePass.edgeStrength = 3; // Default is 3.
outlinePass.setSize(window.innerWidth, window.innerHeight);
composer.addPass(outlinePass);
动画模型的另一个例子:https://jsfiddle.net/Eketol/4xcd365w/
据我了解,这是由于图形卡中进行了转换,因此代码没有顶点位置的参考。 此问题也影响到 raycaster。
我已经阅读了多次尝试和实验。他们中的一些人使用发光material,其他人使用两个甚至三个网格实例和多个渲染通道来完成轮廓(例如:http://jsfiddle.net/Nv7Up/)。
使用发光的缺点material:
- 轮廓粗细会随着相机距离的变化而变化。
- 如果所选对象前面有另一个对象,轮廓可能不会完全可见。
- 具有多个网格的对象可能看起来有点奇怪(尽管我可以接受)。
使用多个网格的缺点:
- 对于具有低多边形的简单对象来说可能没问题,但对于具有多个网格的自定义对象来说就很糟糕了?例如:一支带有剑、盾牌等随机配件的士兵。不确定克隆每个蒙皮对象及其自定义属性会有多复杂或需要多少性能成本。
- 与其使用多个网格,不如使用原始网格并在次要场景中渲染它来获取蒙版或轮廓不是更容易吗?
问题:
- 是否可以使当前的 ThreeJS Outline 效果与动画 SkinnedMesh 一起正常工作?
- 如果转换后的顶点信息在显卡上,轮廓着色器是否可以 直接从中获取顶点信息或渲染图像?
- 如果以上方法不可行,是否有一种方法可以将 SkinnedMesh 变换应用于顶点,以便着色器具有正确的姿势信息?
Is it possible to get the current ThreeJS Outline effect working properly with animated SkinnedMesh?
是的,但是需要增强内部顶点着色器。我在这个更新的 fiddle 中添加了相应的着色器块(morphtarget_pars_vertex
、skinbase_vertex
、skinning_pars_vertex
、begin_vertex
、morphtarget_vertex
、skinning_vertex
, project_vertex
).
https://jsfiddle.net/35vrtm42/
但请注意,马动画是基于变形目标的。
有了这个增强功能,您只需告诉 OutlinePass
启用相应的动画类型。对于fiddle,有必要这样做。
outlinePass.depthMaterial.morphTargets = true;
outlinePass.prepareMaskMaterial.morphTargets = true;
如果您的模型使用骨骼动画,只需将 morphTargets
属性 替换为 skinning
。
three.js R112
在 OutlinePass.js v121 (6-Okt-2020) L38 中,缺少蒙皮参数:
this.depthMaterial = new THREE.MeshDepthMaterial();
this.depthMaterial.side = THREE.DoubleSide;
this.depthMaterial.depthPacking = THREE.RGBADepthPacking;
this.depthMaterial.blending = THREE.NoBlending;
this.prepareMaskMaterial = this.getPrepareMaskMaterial();
this.prepareMaskMaterial.side = THREE.DoubleSide;
this.prepareMaskMaterial.fragmentShader = replaceDepthToViewZ( this.prepareMaskMaterial.fragmentShader, this.renderCamera );
其实应该是这样的
this.depthMaterial = new THREE.MeshDepthMaterial();
this.depthMaterial.side = THREE.DoubleSide;
this.depthMaterial.depthPacking = THREE.RGBADepthPacking;
this.depthMaterial.blending = THREE.NoBlending;
this.depthMaterial.skinning = true; // <-------
this.prepareMaskMaterial = this.getPrepareMaskMaterial();
this.prepareMaskMaterial.side = THREE.DoubleSide;
this.prepareMaskMaterial.fragmentShader = replaceDepthToViewZ( this.prepareMaskMaterial.fragmentShader, this.renderCamera );
this.prepareMaskMaterial.skinning = true; // <-----