动画蒙皮网格物体获得轮廓效果的最佳方法

时间:2020-01-17 11:52:12

标签: three.js outline post-processing

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

ThreeJS Outline issue

示例在特定姿势下暂停的示例: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转换应用于顶点,以便着色器具有正确的姿势信息?

2 个答案:

答案 0 :(得分:2)

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

是的,但是必须增强内部顶点着色器。我已在此更新的小提琴中添加了各自的着色器块(morphtarget_pars_vertexskinbase_vertexskinning_pars_vertexbegin_vertexmorphtarget_vertexskinning_vertex,{ {1}}。

https://jsfiddle.net/35vrtm42/

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

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

OutlinePass

如果您的模型使用骨骼动画,只需将outlinePass.depthMaterial.morphTargets = true; outlinePass.prepareMaskMaterial.morphTargets = true; 属性替换为morphTargets

skinning

答案 1 :(得分:0)

在OutlinePass.js v121(6-Okt-2020)L38中,缺少外观参数:

Controller/__ui/Core

应该是这样

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