1

我有一个 3D 场景,其中只有一个球体,我有两种纹理 - 一种用于夜晚,一种用于地球的白天。此外,我的场景中有一个位于 (15,15,15) 的光源。对于球体上的每个顶点,我也有法线。

现在我想在这两种纹理之间混合,使白天和黑夜之间的褪色看起来很逼真。因此,我使用点积计算法线和光线之间的角度,但是通过这种方法,如果我检查角度是否> 0(这将是白天),我会得到硬交叉。我需要根据角度混合纹理,这是一个软交叉。

谁能帮助我如何混合纹理?到目前为止我的代码:

float angle = dot(L,N);
vec4 texture = texture2D(day, textureCoord);         

texture = texture2D(night,textureCoord) * (1-angle)  +  texture * angle;
vec4 light = vec4(ambientTerm + diffuseTerm + specularTerm , 1);

if(angle > 0) {
    color = light * texture;
} else if(angle >= -0.25) {
    color = texture2D(night,textureCoord)*(angle-1) + texture * (angle);
} else if( angle < -0.25) {
    color = texture2D(night,textureCoord);
}
4

1 回答 1

2

您可以使用该smoothstep函数将连续值转换为 0/1 决策,其间有一个小的平滑过渡。所以基本上你定义了一个过渡范围,让我们只取 [-0.25,0.25],这将是一个大约 75 到 105 度的角度范围(为更大的过渡区域取更大的值,但尽量使其对称,因此以 90 度为中心,因为人们已经在黄昏时开灯了;))。然后我们使用变换我们的 [-1,1] 单调余弦

angle = smoothstep(-0.25, 0.25, angle)

这将导致angle(尽管这个名称有点不幸地被选择,因为它不是一个角度并且行为与实际角度成反比)0如果它是< -0.251如果它是> 0.25,并且如果介于两者之间则平滑过渡。整个纹理看起来像(从奇怪的 if 中清除并使用内置mix函数):

float angle = dot(N, L);
vec4 nightColor = texture2D(night, textureCoord);
vec4 dayColor = texture2D(day, textureCoord);
color = light * mix(nightColor, dayColor, smoothstep(-0.25, 0.25, angle));

或者,为了乐趣和完整性,更精简

color = light * mix(texture2D(night, textureCoord), 
                    texture2D(day, textureCoord), 
                    smoothstep(-0.25, 0.25, dot(N, L)));
于 2013-06-07T14:10:31.143 回答