【问题标题】:Best method to get Outline effect with animated skinned mesh使用动画蒙皮网格获得轮廓效果的最佳方法
【发布时间】:2020-05-04 07:27:00
【问题描述】:

使用动画蒙皮网格获得轮廓效果的最佳方法是什么?

模型以特定姿势暂停的示例: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/

据我了解,这是由于在显卡中进行了转换,因此代码没有顶点位置的引用。 这个问题也会影响到光线投射器。

我已经阅读了多次尝试和实验。其中一些使用发光材质,另一些使用具有多个渲染通道的两个甚至三个网格实例来完成轮廓(例如:http://jsfiddle.net/Nv7Up/)。

使用发光材料的缺点:

  • 轮廓粗细会随着相机距离的变化而变化。
  • 如果所选对象前面有另一个对象,则轮廓可能不会完全可见。
  • 具有多个网格的对象可能看起来有点奇怪(尽管我可以接受)。

使用多个网格的缺点:

  • 对于具有低多边形的简单对象可能没问题,但对于具有多个网格的自定义对象来说是地狱?例如:一支带有随机配件(如剑、盾等)的士兵。不确定使用自定义属性克隆每个蒙皮对象会有多复杂或性能成本。
  • 不是使用多个网格,而是使用原始网格并在辅助场景中渲染它以获得蒙版或轮廓不是更容易吗?

问题:

  1. 是否可以使当前的 ThreeJS Outline 效果与动画 SkinnedMesh 一起正常工作?
  2. 如果转换后的顶点信息在显卡上,轮廓着色器是否可以 直接从中获取顶点信息或渲染图像?
  3. 如果上述方法不可行,是否有一种方法可以将 SkinnedMesh 变换应用于顶点,以便着色器具有正确的姿势信息?

【问题讨论】:

  • 你所理解的并不是它实际上是如何工作的。 OutlinePass.prepareMaskMaterial 用于渲染OutlinePass.selectedObjects,这种材质非常基础,因此不支持骨骼动画。当然可以使用骨骼动画和任何你想要的效果来获得这种效果,尽管可能没有实现,我怀疑这里有人会为你实现它。

标签: three.js outline post-processing


【解决方案1】:

是否可以让当前的 ThreeJS Outline 效果与动画 SkinnedMesh 一起正常工作?

是的,但是需要增强内部顶点着色器。我在这个更新的小提琴中添加了相应的着色器块(morphtarget_pars_vertexskinbase_vertexskinning_pars_vertexbegin_vertexmorphtarget_vertexskinning_vertexproject_vertex)。

https://jsfiddle.net/35vrtm42/

但请注意,马动画是基于变形目标的。

使用此增强功能,您只需告诉OutlinePass 即可启用相应的动画类型。对于小提琴,有必要这样做。

outlinePass.depthMaterial.morphTargets = true;
outlinePass.prepareMaskMaterial.morphTargets = true;

如果您的模型使用骨骼动画,只需将 morphTargets 属性替换为 skinning

three.js R112

【讨论】:

  • 抱歉 Mugen87,我进行了“剥皮”替换,但在冲锋队示例中出现以下错误:THREE.WebGLProgram: shader error: 1286 35715 false gl.getProgramInfoLog No compiled vertex shader when at least one graphics shader is attached. 请参阅:jsfiddle.net/Eketol/5z3u047m
  • 抱歉,着色器块仍然丢失。让我更新答案:jsfiddle.net/6k1x8bfq
  • 现在完美。再次感谢!
  • 顺便说一句:在下一个版本R113 中,着色器修改已经完成。所以你可以直接使用 repo/npm 包中的文件。
【解决方案2】:

在 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;   // <-----

【讨论】:

    猜你喜欢
    • 2021-09-18
    • 2020-10-10
    • 2020-02-16
    • 1970-01-01
    • 2013-10-01
    • 1970-01-01
    • 2015-04-02
    • 2015-07-06
    • 2010-10-01
    相关资源
    最近更新 更多