我正在使用像素弯曲器为基于高度图的地形生成光照效果。我想制作一个地形的法线贴图,并从那里点出每个法线与给定的太阳方向。真的很标准的东西,但像素弯曲不是很好玩。我有这段代码:
void
evaluatePixel()
{
float2 pt = outCoord();
pixel3 a = sampleNearest(src,pt);
pixel3 b = sampleNearest(src,float2(pt.x + 1.0, pt.y));
pixel3 c = sampleNearest(src,float2(pt.x, pt.y + 1.0));
float3 v1 = float3(1.0, 0.0, b.r - a.r);
float3 v2 = float3(0.0, 1.0, c.r - a.r);
normalize(v1);
normalize(v2);
float3 n = cross(v1,v2);
dst = pixel3(n.x,n.y,n.z);
}
我希望这会产生一个普通的地图。为了测试,我假设光线直指向下,只使用n.z
作为输出颜色。这产生纯色。如果您使用上面的代码并运行它,您会看到虽然红色和绿色有变化,但蓝色总是满255.这是为什么?我希望将v1
和v2
归一化为不应该总是输出全蓝色?
我做错了什么?!?
答案 0 :(得分:0)
我实际上在这里做了一些非常类似的东西,我的三角形条带高度图。
input image3 verts;
output pixel3 triNorms;
void
evaluatePixel()
{
float2 tCoord = outCoord() - 0.5; //move coord from pixel center to lower-left corner
float quadIdx = mod(tCoord[0], 2.0); //potentially faster to use sign(fract(tCoord[0] / 2.0))
float2 vCoord0 = float2(floor(tCoord.x / 2.0), tCoord.y);
float2 vCoord1 = float2(vCoord0.x + 1.0, vCoord0.y + 1.0 - quadIdx);
float2 vCoord2 = float2(vCoord0.x + quadIdx, vCoord0.y + 1.0);
float3 v0 = sampleNearest(verts, vCoord0 + 0.5);
float3 v1 = sampleNearest(verts, vCoord1 + 0.5);
float3 v2 = sampleNearest(verts, vCoord2 + 0.5);
float3 s0 = v1 - v0;
float3 s1 = v2 - v0;
float3 n = cross(s0, s1);
float len = 1.0 / length(n);
n.x *= len;
n.y *= len;
n.z *= len;
triNorms = float3(n.x, n.y, n.z);
}
这对我来说非常好。在不到100ms的时间内运行1.8M顶点。为了澄清,我将三角形定义为顶点之间的列。这意味着每4个顶点有两个三角形。我用“quadIdx”识别每个四边形的两个三角形。
注意:您正在规范化然后计算交叉 - 这是向后的,您需要在之后进行标准化。另外,我实际上相信我在normalize()中发现了一个错误。它创造了我没想到的NaN。我用length()实现了自己的规范化,一切都很好!