复杂形状的字符轮廓

13

假设我有这个字符,我想让用户选择它,所以当它被选中时,我希望显示一个轮廓线。

输入图像描述 输入图像描述

这个字符是一个包含一些网格的object3D。 我尝试克隆并设置背面材料,但是没有成功,问题在于形状中的每个立方体都在单独地呈现反面,因此轮廓线不正确。

我需要为轮廓线创建另一个网格吗?还有更简单的方法吗?


你可以克隆并设置普通材质,然后稍微缩放克隆体并将其移动到摄像机远离的位置。这样轮廓就是实际模型后面的更大模型。这只是一个想法,我记得有些游戏是这样做的... - yaku
好的,谢谢Yaku。我会尝试按照你的方法将克隆从相机移动到测试中,但问题是我的角色比这个更复杂,并且他们是在地面上行走,我想只是因为相机从上方看。那个轮廓克隆会落在地面后面并搞乱一切! - Ashkan Ghodrat
你最终成功了吗?我对这个解决方案非常感兴趣。 - spassvogel
我提供奖金是因为我真的想知道如何做到这一点。像Ashkan一样,使用背面材料创建克隆体的问题是由于形状复杂导致的。我怀疑需要做的是像这样:
  1. 首先需要渲染背景。
  2. 然后,在一个单独的透明图层上,用平面颜色创建角色模型,比原来的略大。
  3. 在另一个透明图层上,创建带有正常材质/纹理的角色。
  4. 最后,将角色图层放在轮廓图层的顶部,然后将它们合并放置在背景中。
- spassvogel
Ashkan - 请记得通过点击复选标记来“接受”答案。谢谢。 - WestLangley
5个回答

19

@spassvolgel所写的是正确的;

我怀疑需要做的是这样的:1.首先渲染背景;2.然后,在另一个透明的图层上,用一个扁平的颜色绘制角色模型,稍微比原来的大一点;3.在另一个透明图层上,使用角色的正常材质/纹理;4.最后,将角色图层放在轮廓图层的顶部,然后将它们组合放置在背景中。

您只需创建多个场景,并使用顺序渲染通道将它们组合起来:

renderer.autoClear = false;
. . . 

renderer.render(scene, camera); // the entire scene
renderer.clearDepth();
renderer.render(scene2, camera); // just the selected item, larger, in a flat color
renderer.render(scene3, camera); // the selected item again

three.js.r.129


非常感谢!这看起来非常有前途。赏金即将到期,但我时间有点紧,无法深入研究代码,所以我会授予给你。再次感谢! - spassvogel
谢谢你的回答,演示也很棒。但是还有一些事情困扰着我。我的问题重点在于这些对象不是单个网格... - Ashkan Ghodrat
@AshkanGhodrat 你无法让这种方法适用于具有子网格的对象吗? - WestLangley
我无法修改您的meshGroup代码,但您认为它是否解决了这张图片中的问题?http://s30.postimg.org/oxpnl0xsx/shaders.jpg - Ashkan Ghodrat
我认为你应该发布一个新的问题,并清楚地陈述你的额外需求。 - WestLangley

1
一个适用于任何复杂度的几何体的通用解决方案可能是通过ShaderMaterial类在three.js中应用片段着色器。不确定您的经验水平如何,但如果需要,可以在这里找到有关着色器的介绍。
一个很好的例子是使用着色器突出显示几何体,可以在这里找到。在它们的顶点着色器中,它们计算顶点的法线和用于表达发光效果强度的参数:
uniform vec3 viewVector;
uniform float c;
uniform float p;
varying float intensity;
void main() 
{
    vec3 vNormal = normalize( normalMatrix * normal );
    vec3 vNormel = normalize( normalMatrix * viewVector );
    intensity = pow( c - dot(vNormal, vNormel), p );

    gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
}

这些参数传递到片元着色器中,用于修改围绕几何体的像素颜色值。
uniform vec3 glowColor;
varying float intensity;
void main() 
{
    vec3 glow = glowColor * intensity;
    gl_FragColor = vec4( glow, 1.0 );
}

看这张图片,这是我在着色器方面遇到的问题 http://s30.postimg.org/oxpnl0xsx/shaders.jpg - Ashkan Ghodrat

1
你可以通过将轮廓对象渲染到理想情况下与目标帧缓冲区大小相同的纹理中,然后使用该纹理渲染一个帧缓冲区大小的四边形,并使用片段着色器模糊或进行其他图像变换来获得良好的结果。我有一个示例,它使用原始的WebGL,但是你也可以很容易地制作一个自定义的ShaderMaterial。

1

0

我还没有找到答案,但是我想演示一下当我创建多个网格,并在每个网格后面放置另一个网格时会发生什么。

side: THREE.BackSide  

http://jsfiddle.net/GwS9c/8/

正如您所看到的,这不是期望的效果。我希望在所有三个网格后面有一个干净的轮廓,而且不重叠。我的着色器编程水平真的很低,但在大多数在线资源中,人们都建议使用克隆网格的方法。


1
我认为,除非你编写一些复杂的着色器(而我不会),否则着色器的结果不会有太大的区别。另外,对于这个问题来说,背面不是最好的选择。 - Ashkan Ghodrat

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接