渲染“硬"使用自定义着色器的边缘 [英] Render "hard" edges using custom shader

查看:49
本文介绍了渲染“硬"使用自定义着色器的边缘的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想重现使用 THREE.EdgesHelper(在硬"对象边缘绘制边界)创建的效果,但使用自定义着色器而不是添加单独的 THREE.Line 对象.基本上,我想做这个演示 中所做的事情,但仅限于硬"边界;例如不在两个共面面之间的边界

I'd like to reproduce the effect created by using THREE.EdgesHelper (drawing a boundary on "hard" object edges), but using a custom shader rather than adding a separate THREE.Line object. Essentially I'd like to do what's done in this demo, but only for the "hard" boundaries; e.g. boundaries that are not between two coplanar faces

方法:对EdgesHelper应用类似的例程,但使用自定义属性(例如isEdge)标记硬边中的顶点;可能需要使用 BufferGeometry,因为常规的 Geometry 允许在多个面中重复使用顶点,但是 BufferGeometry 复制顶点,使得每个顶点都是一部分只有一张脸(至少,这是我的理解;文档并不明确).

Approach: apply similar routine to EdgesHelper, but mark vertices that are in hard edges with a custom attribute (e.g. isEdge); probably need to use BufferGeometry, since regular Geometry allows re-use of vertices in multiple faces, but BufferGeometry duplicates vertices such that each vertex is part of only one face (at least, this is my understanding; the documentation isn't explicit).

目前的进展:

  1. 重现线框材料示例中的效果,但使用了BufferGeometry:http://jsfiddle.net/ogav6o77/
  2. EdgesHelper 的逻辑移植到一个BufferEdgesHelper"函数,该函数与BufferGeometry 一起工作(但仍使用它来创建一个THREE.Line):http://jsfiddle.net/L2aertya/
  3. 尝试调整 BufferEdgesHelper 以将其结果保存在自定义属性 (isEdge) 中,然后在决定是渲染边缘还是渲染边缘时在自定义着色器中读取该属性不是:http://jsfiddle.net/4tf4c6sf/
  1. Reproduced the effect in the wireframe materials example, but using BufferGeometry: http://jsfiddle.net/ogav6o77/
  2. Port the logic of EdgesHelper to a "BufferEdgesHelper" function that works with BufferGeometry (but still use it to create a THREE.Line): http://jsfiddle.net/L2aertya/
  3. Attempted to adapt the BufferEdgesHelper to save its results in a custom attribute (isEdge), then read that attribute in the custom shader when deciding whether to render the edge or not: http://jsfiddle.net/4tf4c6sf/

前两个小提琴按预期工作,显示 (1) 着色器渲染的白色线框边缘,然后 (2) 着色器的白色边缘加上 Line.但是,(3)给出了与(2)相同的结果,而不是使用 isEdge 属性来决定是否画一条线;我不明白为什么会这样.

The first two fiddles work as expected, showing (1) the white wireframe edge rendered by the shader, then (2) the white edges from the shader plus the red "hard" edges from the Line. However, (3) gives the same results as (2), rather than using the isEdge attribute to decide whether to draw a line or not; I can't figure out why that is.

知道如何解决这个问题,以便着色器渲染硬边(例如,红线和白线重叠)?

Any idea how to fix this so that only the hard edges are rendered by the shader (e.g. the red and white lines overlap)?

谢谢!

推荐答案

首先,需要稍微调整边缘修剪算法.您需要保存两个面的顶点,而不仅仅是第一个面,因为您需要更改与边关联的两个三角形,以便它们使用重心坐标正确渲染.

First off, the edge-pruning algorithm needs to be tuned a bit. You need to save the vertices for both faces, not just the first face, because you need to alter both triangles associated with the edge for them to render properly using barycentric coordinates.

其次,我认为这可以在没有新的 isEdge 变量的情况下完成,而只需更改 centers.

Second, I think that this can be done without a new isEdge variable, but just by altering centers.

重心坐标的正常设置是三个顶点分别为 (1,0,0), (0,1,0), (0,0,1).但是,如果我们不想在顶点 0 和 1 之间绘制边,我们可以将其更改为 (1,0,1), (0,1,1),(0,0,1),这样无论我们得到的顶点2有多远,vCenter.z总是为1.那么,我们可以从centers 填充一个(禁用所有边缘),并在我们看到哪些边缘应该保留时一一启用边缘.

The normal setup for barycentric coordinates is having the three vertices be (1,0,0), (0,1,0), (0,0,1). However, if we want to not draw the edge between vertices 0 and 1, we can change this to (1,0,1), (0,1,1), (0,0,1), so that no matter how far from vertex 2 we get, vCenter.z is always 1. Then, we can start with centers filled with ones (all edges disabled), and enable the edges one by one as we see which edges should stay.

考虑到这一点,我对您的代码进行了一些修改.我去掉了边缘对象,只留下了重心的东西:http://jsfiddle.net/v72rn4bk/4/

With that in mind, I've reworked your code a bit. I've stripped out the edge object and just left the barycentric stuff: http://jsfiddle.net/v72rn4bk/4/

我发现计算法线的调用应该在转换为 BufferGeometry 之后完成.调用 .fromGeometry 确实会复制顶点,但如果您正在处理的对象具有共享顶点,则必须重新计算法线.

I found that the call to compute normals should be done after the conversion to BufferGeometry. Calling .fromGeometry does indeed duplicate the vertices, but the normals have to be recomputed if the object you're working has shared vertices.

这篇关于渲染“硬"使用自定义着色器的边缘的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆