首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么在通过计算与边缘最近的距离来绘制内部阴影时,边缘之间有一个光区?

为什么在通过计算与边缘最近的距离来绘制内部阴影时,边缘之间有一个光区?
EN

Stack Overflow用户
提问于 2015-02-17 00:23:33
回答 1查看 610关注 0票数 1

我通过计算每个像素到边缘的最近距离来绘制一个内部阴影(与内部发光相同的概念,但不是光)。在片段着色器中,通过从顶点着色器插值顶点位置(使用varying),通过均匀数组传递形状的边缘点,并通过对每条边缘运行点到线段距离计算来计算最近的距离。

这是片段着色器:

代码语言:javascript
复制
precision mediump float;
uniform mediump sampler2D uBaseSampler;
uniform mediump vec2 uVerts[11];
varying mediump vec2 vTexCoord;
varying mediump vec4 vPosition;
float distanceSq(mediump vec2 a, mediump vec2 b)
{
    mediump vec2 c = b - a;
    return dot(c, c);
}
float distSqFromLineSegment(mediump vec2 p, mediump vec2 a, mediump vec2 b)
{
    float lenSq = distanceSq(a, b);
    /*if (lenSq == 0.0) return distanceSq(p, a);*/
    float t = dot(p - a, b - a) / lenSq;
    if (t < 0.0) return distanceSq(p, a);
    else if (t > 1.0) return distanceSq(p, b);
    mediump vec2 proj = a + t * (b - a);
    return distanceSq(p, proj);
}
void main()
{
    float nearestDistSq = 1e3;
    for (lowp int i = 0; i < 10; ++i)
    {
        lowp int j = i + 1;
        float distSq = distSqFromLineSegment(vPosition.xy, uVerts[i], uVerts[j]);
        nearestDistSq = min(nearestDistSq, sqrt(distSq));
    }
    float nearestDist = nearestDistSq;
    float coef = nearestDist;
    lowp vec4 frag = texture2D(uBaseSampler, vTexCoord);
    gl_FragColor = vec4(frag.xyz * coef, 1.0);
}

以下是仅根据边缘1计算内部阴影时的情况:

以下是仅根据边缘2计算内部阴影时的情况:

注意,内部阴影是如何正确的两个边单独。

现在,下面是根据两个边缘计算内部阴影时的样子:

注意到边缘之间的内在轻盈?作为参考,下面是基于所有边缘计算内部阴影的类似结果:

当独立地观察由边缘1和边缘2生成的内部阴影时,它看起来不像内部光是通过在两个边中同时分解而形成的。是什么引起的?光度上的点不应该比它们的相邻点有更大的距离,因为我正在计算所有边缘的最小距离。

有什么想法吗?

更新:

基于一些早期的答案,看起来我的问题是,我已经实现了一个“黑暗”算法,并且将两个梯度结合在一起会在我的屏幕截图中产生副作用。例如,如果你拿起我的前两个截图,将它们叠加在一个图像编辑器中,并将第二层设置为“黑暗”混合模式,你将得到我的第三个截图。

我真正想要的是某种乘法。如果我在图像编辑器中使用“乘”混合模式,就会得到所需的外观:

我怎样才能做到这一点?看起来我必须独立地计算每个边的内部阴影,然后把所有的系数相乘在一起,而不是根据最近的边来计算一个系数。

更新2:

执行乘法混合模式会使形状的顶点周围区域变暗。结果比我原来的版本还糟。我决定坚持原来的版本,因为它是快速的,正确的,和不想要的副作用最小化,通过缩放系数在0.8-1.0,而不是0.0-1.0。我也接受了引导我走上这条路的答案。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-02-17 01:23:02

这张照片没什么问题..。OpenGL正在绘制您所要求的内容,这是一个与边缘距离相关的亮度。距离不是一个平滑的函数,所以你的眼睛看到了距离函数的导数突然改变的边缘。

你可以自己测试一下。打开像Gimp或Photoshop之类的图像编辑程序,并形成两个线性梯度。对于第二个梯度,选择“暗”作为梯度的合成模式。我得到了以下图像:

你可以看到这里有一条类似的45度线。

如果你想摆脱锋利的边缘,你必须做更多的事情,比如模糊结果。距离场一般都有锋利的边缘。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28552704

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档