Vulkan纹理模糊问题

5
我可以帮您进行翻译。这段内容是关于编程的,讲述了一个简单的Vulkan设置,加载了一个相当大的网格文件(女人),并应用了漫反射和法线贴图纹理。
顶点着色器:
#version 450 core

layout (set = 0, binding = 0) uniform ModelMatrix {
    mat4 model;
} modelMatrix;

layout (push_constant) uniform ViewProjection {
    mat4 view;
    mat4 projection;
} viewProjection;

layout (location = 0) in vec3 inPos;

layout (location = 1) in vec3 inNor;

layout (location = 2) in vec2 inUV;

layout (location = 3) in vec3 inTan;

layout (location = 4) in vec3 inBitan;

layout (location = 0) out vec3 fragPos;

layout (location = 1) out vec2 fragUV;

layout (location = 2) out vec3 fragNor;

layout (location = 3) out vec3 fragTan;

layout (location = 4) out vec3 fragBitan;


void main()
{
    fragPos     = vec3(viewProjection.view * modelMatrix.model * vec4(inPos, 1.0));
    fragNor     = mat3(viewProjection.view * modelMatrix.model) * inNor;
    fragUV      = inUV;
    fragTan     = mat3(viewProjection.view * modelMatrix.model) * inTan;
    fragBitan   = mat3(viewProjection.view * modelMatrix.model) * inBitan;


    gl_Position = viewProjection.projection * vec4(fragPos, 1.0);
}

片段着色器:

#version 450 core

layout (location = 0) in vec3 fragPos;

layout (location = 1) in vec2 fragUV;

layout (location = 2) in vec3 fragNor;

layout (location = 3) in vec3 fragTan;

layout (location = 4) in vec3 fragBitan;

layout (location = 0) out vec4 outFragColor;

layout (set = 0, binding = 0) uniform MVP {
    mat4 model;
} mvp;

layout (set = 0, binding = 1) uniform sampler2D textureSampler;

layout (set = 0, binding = 2) uniform sampler2D normalSampler;

layout (set = 0, binding = 3) uniform sampler2D specSampler;

layout (push_constant) uniform VP {
    mat4 view;
    mat4 projection;
} vp;

const vec3 lightPos = vec3(0.0, 0.0, 300.0);

const float lightIntensity = 1.0f;

const float shininess = 50.0;

void main()
{
    mat3 TBN = transpose(mat3(
        fragTan,
        fragBitan,
        fragNor
    ));

    vec3 normapFragNor = normalize(texture(normalSampler, fragUV).rgb * 2.0 - 1.0);

    vec3 lightDirectionTangSpace = TBN * (lightPos - fragPos);

    float dotProduct = dot(normalize(lightDirectionTangSpace), normalize(normapFragNor));

    float meshNormalDotProduct = dot(normalize(lightDirectionTangSpace), normalize(fragNor));

    float diffuse = min(max(dotProduct, 0.0), 1.0);


    float specular = pow(diffuse, shininess);

    vec4 texelColor = texture(textureSampler, fragUV);

    vec3 specularColor = vec3(texture(specSampler, fragUV));


    float specResultColorComponent = min(1.0, diffuse);

    outFragColor = vec4(diffuse * vec3(texelColor)  , texelColor.a); // For Spec Map: diffuse * vec3(texelColor) + (specular * specularColor)
}

结果: enter image description here 可以看到,整个网格的碎片被涂得有点模糊和嘈杂,特别是在手臂上。
每当我在Unity3D中使用相同的纹理加载此网格时,结果就没有提到的噪声: enter image description here 另一个带有法线图+光泽地图的模型完美地工作,所以这对我来说听起来很矛盾,因为Unity3D可以正确渲染这三种模型,但我的程序仅针对特定模型无法生成照明值,这意味着着色器可能会解释纹理/模型中的数据! enter image description here 这个问题的根源是什么?
[更新]
在使用几何着色器可视化法线之后: enter image description here

1
可能是转换、顶点属性或数据插值的问题。分别检查每个输入数据/顶点属性,并将它们显示为颜色。然后对着色器中的每个步骤执行相同的操作。考虑它们应该是什么样子的,尝试找出哪一个是错误的。如果您找到了不正确的数据/操作/属性,那么找到问题的源头就会更容易。 - Ekzuzy
1
@chakmeshma: 为什么您会将模型矩阵设为描述符集变量,但却使用推送常量进行投影呢?模型矩阵的更改频率比投影高得多(通常对整个场景而言投影是相同的)。推送常量用于快速更改值。 - Nicol Bolas
1
@chakmeshma:您是否尝试按照我上面描述的方式调试您的问题?您获得了任何结果,将工作模型与不工作的模型进行了比较吗?您只分享了您的着色器代码。当然,这可能是您的着色器中的问题,一个难以发现的问题。但它也可能是由其他原因引起的,例如上述顶点属性、输入数据格式、数据传输问题、着色器阶段之间的数据插值等。如果没有更多来自您的信息,我们可能无法帮助您。 - Ekzuzy
我怀疑Unity模型加载器对实际模型数据进行了一些清理/魔法处理,将模型在其他软件中重新加载和重新导出可能会解决问题。此外,我发现提供的截图太小/距离太远,无法正确查看伪影或调试法线等问题。 - LJᛃ
@chakmeshma,我看到这个问题已经很长时间没有更新了。您解决了您的问题吗?如果是,问题出在哪里?如果没有,您是否尝试使用我描述的方法来调试问题? - Ekzuzy
1个回答

2

我认为你对法线(以及其他可能的向量)的转换有误。通常情况下,你不会使用与顶点相同的矩阵进行变换。通常会使用逆转置矩阵。

建议您使用几何着色器(发出线条)来可视化您的法线。


3
实际上,对于顶点和法线变换使用相同的矩阵是一种有效的方法。如果我们只是均匀地缩放对象(所有尺寸应用相同的缩放比例),那么我们可以这样做。如果对象的比例不均匀,则需要对法线进行逆转置变换。但即使在这种情况下我们使用相同的矩阵,结果也会与上面所见的不同。 - Ekzuzy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接