如何解决为什么动态分支内部的纹理采样会导致不同的结果? HLSL
我正在尝试实现基于权重的高度混合着色器。 首先,我尝试找到权重最高的 4 个层(alpha 层)。 然后从这 4 层混合。
以下是我的简化代码:
// find the 4 layers with the largest weight.
void find_max_layers(float2 texCoord,out int4 max_indics)
{
max_indics = int4(-1,-1,-1);
max_weights = float4(.0001,.0001,.0001);
[unroll]
for (int Layer = 0; Layer < 2; ++Layer) // 2 is for test...
{
const int surfaceIndex = (int)cSurfaceIndex[Layer];
const float alpha = tLayerWeight.Sample(sLayerWeight,float3(texCoord,Layer)).r;
if (alpha > max_weights.x) {
max_indics = int4(surfaceIndex,max_indics.xyz);
max_weights = float4(alpha,max_weights.xyz);
}
else if (alpha > max_weights.y) {
max_indics.yzw = int3(surfaceIndex,max_indics.yz);
max_weights.yzw = float3(alpha,max_weights.yz);
}
else if (alpha > max_weights.z) {
max_indics.zw = int2(surfaceIndex,max_indics.z);
max_weights.zw = float2(alpha,max_weights.z);
}
else if (alpha > max_weights.w) {
max_indics.w = surfaceIndex;
max_weights.w = alpha;
}
}
}
// get surface albedo,normal,height.
half get_surface_color_normal_height(int surface,float3 texCoord,out half3 color)
{
const float surface_tiling[2] = { 64.0f,32.0f }; // hard coded for show my bugs.
const float tiling = surface_tiling[surface];
half4 color_h = tAlbedoMap.Sample(sLinearWrap,float3(texCoord.xy * tiling,surface));
color = color_h.rgb;
return color_h.w;
}
void blend_layers(float3 texCoord,out half3 albedo)
{
int4 surfaceIndics; // [0,1,-1] or [1,-1]
find_max_layers(texCoord.xy,surfaceIndics);
half3 colors[4] = { (half3)0,(half3)0,(half3)0 };
/*A: works
if(surfaceIndics.x == 0)
{
get_surface_color_normal_height ( 0,texCoord,colors [ 0 ] );
get_surface_color_normal_height ( 1,colors [ 1 ] );
}else
{
get_surface_color_normal_height (1,colors [ 0 ] );
get_surface_color_normal_height ( 0,colors [ 1 ] );
}*/
/*B:works
if(surfaceIndics.x == 0)
{
get_surface_color_normal_height ( 0,colors [ 1 ] );
}else
{
get_surface_color_normal_height (0,colors [ 0 ] );
get_surface_color_normal_height ( 1,colors [ 1 ] );
}
*/
//C: error!!!
if (surfaceIndics.x != -1)
{
get_surface_color_normal_height(surfaceIndics.x,colors[0]);
}
if (surfaceIndics.y != -1)
{
get_surface_color_normal_height(surfaceIndics.y,colors[1]);
}
// output
albedo = (colors[0] + colors[1]) * 0.5;
}
让我先简化一下问题,我有 2 个纹理 0,1 需要混合。 函数 find_max_layers 只有两个返回值:[0,-1] 或 [1,-1]。
函数 blend_layers 中的代码部分 A 和 B 工作正常。
但是函数 blend_layers 中的代码段 C 输出了意外的结果: C,the error result
解决方法
经过一些尝试,我发现使用SampleLevel代替Sample,并且指定纹理在相同的mipmap级别进行采样,问题就会消失。
所以我判断原因是相邻像素的mipmap采样不一致。
然后我手动构建了两种不同颜色的纹理的 mipmap。得到了进一步的验证。
根据本文(http://www.aclockworkberry.com/shader-derivative-functions/)的指导,最终使用SampleGrad代替Sample来解决问题。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。