我通过计算每个像素到边缘的最近距离来绘制一个内部阴影(与内部发光相同的概念,但不是光)。在片段着色器中,通过从顶点着色器插值顶点位置(使用varying),通过均匀数组传递形状的边缘点,并通过对每条边缘运行点到线段距离计算来计算最近的距离。
这是片段着色器:
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。我也接受了引导我走上这条路的答案。
发布于 2015-02-17 01:23:02
这张照片没什么问题..。OpenGL正在绘制您所要求的内容,这是一个与边缘距离相关的亮度。距离不是一个平滑的函数,所以你的眼睛看到了距离函数的导数突然改变的边缘。
你可以自己测试一下。打开像Gimp或Photoshop之类的图像编辑程序,并形成两个线性梯度。对于第二个梯度,选择“暗”作为梯度的合成模式。我得到了以下图像:

你可以看到这里有一条类似的45度线。
如果你想摆脱锋利的边缘,你必须做更多的事情,比如模糊结果。距离场一般都有锋利的边缘。
https://stackoverflow.com/questions/28552704
复制相似问题