模型周围有奇怪的白色轮廓


19

我正在使用XNA 4开发游戏,最近我按照本指南切换到了延迟着色实现。现在,我的模型上出现了一个奇怪的白色轮廓,我不确定是什么原因引起的。我认为可能是普通渲染目标或深度渲染目标缺乏精确度,但将它们提高到64位(Rgba64)而不是32位(彩色)没有帮助。我还认为镜面反射计算可能存在一些问题,因此我尝试将镜面反射设置为0,但这也没有帮助。在PIX中调试像素显示该像素的漫反射值被计算为接近白色。有任何想法吗?我在下面提供了该问题的图片,以完整尺寸查看时更容易。

像素着色器:

float4 PixelShaderFunction(VertexShaderOutput input) : COLOR0
{
    input.ScreenPosition.xy /= input.ScreenPosition.w;

    float2 texCoord = 0.5f * (float2(input.ScreenPosition.x, -input.ScreenPosition.y) + 1) - halfPixel;

    float4 normalData = tex2D(normalSampler, texCoord);

    //Transform normal back into [-1, 1] range
    float3 normal = normalize(2.0f * normalData.xyz - 1.0f);

    float specularPower = normalData.a;
    float specularHardness = tex2D(colorSampler, texCoord).a * 255;
    float depthVal = tex2D(depthSampler, texCoord).r;

    //Compute screen-space position
    float4 position = float4(input.ScreenPosition.xy, depthVal, 1.0f);

    //Transform to world space
    position = mul(position, InvertViewProjection);
    position /= position.w;

    //Surface-to-light vector
    float3 lightVector = lightPosition - position;

    float3 projectedTexCoords = position - lightPosition;
    projectedTexCoords = mul(projectedTexCoords, float3x3(
                            float3(-1, 0, 0),
                            float3(0, 1, 0),
                            float3(0, 0, 1)));

    float distanceToLight = length(lightVector) / lightRadius;
    float shadow = ShadowContribution(projectedTexCoords, distanceToLight);

    float attenuation = saturate(1.0f - distanceToLight);

    lightVector = normalize(lightVector);

    //Compute diffuse light
    float normalDotLight = max(0, dot(normal, lightVector));
    float3 diffuseLight = normalDotLight * Color.rgb;

    float3 reflectionVector = normalize(reflect(-lightVector, normal));
    float3 directionToCamera = normalize(cameraPosition - position);
    float specularLight = specularPower * pow(saturate(dot(reflectionVector, directionToCamera)), specularHardness);

    return shadow * attenuation * lightIntensity * float4(diffuseLight.rgb, specularLight);
}

编辑:对不起JPG,stackexchange的上传器是自己完成的。Roy T:对于从XNA3更改的部分,我确实参考了本教程的XNA4转换。由于我没有对代码进行任何大的更改,因此我以为可能是该错误存在于原始代码中,但是由于周围有太多的灯光移动而无法看到,所以我只移除了一个灯光,然后再次出现了该错误(看一下在蜥蜴的肘部附近)

这是我的场景的GBuffer内容:

颜色缓冲区: 深度缓冲区: 普通缓冲区: 最终渲染:

编辑2

我开始怀疑问题是在对颜色图进行采样时的CombineFinal.fx。这是对白色像素旁边正确着色的像素的计算:

diffuseColor        : (0.435, 0.447, 0.412)
diffuseLight        : (1.000, 1.000, 0.902)
light               : (1.000, 1.000, 0.902, 0.000)
PixelShaderFunction : (0.435, 0.447, 0.371, 1.000)
specularLight       : 0.000

这是紧邻其旁边的颜色不正确的白色像素的输出:

diffuseColor        : (0.824, 0.792, 0.741)
diffuseLight        : (1.000, 1.000, 0.902)
light               : (1.000, 1.000, 0.902, 0.000)
PixelShaderFunction : (0.824, 0.792, 0.669, 1.000)
specularLight       : 0.000

diffuseColor是唯一的区别,该颜色直接从颜色图中获取。也许在计算要采样的纹理坐标时会出现一点错误?

照明通行证:


4
请不要jpeg压缩显示细微图形故障的屏幕截图。人们会希望以完美的再现看待这个问题。
aaaaaaaaaaaaaa

好吧,我认为jpeg压缩实际上可以很好地使毛刺通过,仅当一个像素重新组合在一起时才出现故障(Z深度的差异很大,并且所有像素的照明都很高)。祝您好运,延期渲染技术性很强。
Valmond 2011年

2
不确定是否有帮助,但您使用的是旧版本的代码/教程,Catalin Zima的实际代码/教程现在位于:catalinzima.com/tutorials/deferred-rendering-in-xna和认可的XNA4.0版本位于此处:roy-t.nl/index.php/2010/12/28/…–
Roy T.

同样,与调试延迟渲染一样,您是否可以发布所有缓冲区的屏幕截图?它可能在照明缓冲区中,但可能还有其他东西。
罗伊(Roy T.)

我的直觉是,算法部分处理正好90度角的方式将是一个问题,但是我将不得不在工作之后继续研究ode来进一步研究它。
Jordaan Mylonas

Answers:


4

当我开始使用自己的延迟渲染器时,我的模型周围也有白色轮廓或“光晕”。问题在于未正确设置用于覆盖渲染目标的纹理偏移值。需要将某些纹理的偏移量设置为+0.5像素,而不是-0.5像素。

只是在调整了某些纹理偏移的值之后,轮廓才消失了。最有可能在一个照明着色器中。

编辑:顺便说一下,我也是从Catalin Zima的教程中学到的,它是您示例的分支,因此它应该可以工作。


是的,就是这样。我将其更改为+ halfPixel,以用于灯光着色器中的所有坐标采样,并且光晕现在消失了。
Telanor 2011年

0

我不确定到底是怎么回事,但是有几件事需要仔细检查:

  1. 确保在采样G缓冲区时已关闭纹理过滤-不能使用双线性或各向异性或其他任何东西。

  2. 我看到您正在向纹理坐标添加半像素偏移;再次检查是正确的。我对XNA不够熟悉,无法知道正确的偏移量,但是您应该能够通过编写对G缓冲区之一进行采样并仅输出样本的着色器来对其进行检查。然后在此之间来回翻转并直接在屏幕上显示G缓冲区。如果偏移量正确,则应该看不到任何差异,甚至看不到单个像素。


我去了,并将与GBuffer有关的所有内容都更改为POINT(我假设禁用过滤功能?),并且它仍然相同。关于您的第二点,不是直接输出GBuffer就是完全一样:创建仅输出数据的着色器吗?您能再详细说明一下吗?
Telanor 2011年

那么,您是如何生成上述G缓冲区的屏幕截图的?我假设您调用某种内置的API函数,以将像素从G缓冲区一对一复制到屏幕(后缓冲区)?(我不知道XNA,所以我不知道它叫什么。)我是说,将内置的一对一复制函数的输出与编写为执行此操作的像素着色器的输出进行比较一对一的副本...这样一来,您可以确保纹理坐标完全正确,并且确实可以进行一对一的采样。
内森·里德
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.