在使用 vulkan 光线跟踪使 uvs 正常工作时遇到一些问题

问题描述

我已经使用光线追踪大约一个月了,所以我仍在使用它。我在让紫外线看起来正确时遇到了一些问题。这是我正在使用的着色器,我认为问题与 v.uv = vec2(d0.x,d1.y);在解包功能中。我已经玩了一段时间了,但一直没有运气。我也试过制作一个 uv 缓冲区并直接将信息发送到其中并从中工作,但它只适用于一个网格,然后看起来一团糟。

enter image description here

#version 460
#extension GL_EXT_ray_tracing : require
#extension GL_EXT_nonuniform_qualifier : enable

layout(location = 0) rayPayloadInEXT vec3 hitValue;
layout(location = 2) rayPayloadEXT bool shadowed;
hitAttributeEXT vec2 attribs;

struct VertexData
{
    vec3 Position;
    vec3 normal;
    vec2 UV;
    vec3 Tangent;
    vec3 BiTangent;
};


struct DirectionalLight
{
    vec3 direction;
    vec3 ambient;
    vec3 diffuse;
    vec3 specular;
};

struct PointLight 
{
    vec3 position;
    vec3 ambient;
    vec3 diffuse;
    vec3 specular;
    float constant;
    float linear;
    float quadratic;
};

struct MaterialInfo
{
    vec3 Ambient;
    vec3 Diffuse;
    vec3 specular;    
    float Shininess;
    float Reflectivness;

    uint DiffuseMapID;
    uint specularMapID;
    uint normalMapID;
    uint DepthMapID;
    uint AlphaMapID;
    uint EmissionMapID;
};

struct Material
{
    vec3 Ambient;
    vec3 Diffuse;
    vec3 specular;    
    float Shininess;
    float Reflectivness;

    vec3 DiffuseMap;
    vec3 specularMap;
    vec3 normalMap;
    vec3 DepthMap;
    vec3 AlphaMap;
    vec3 EmissionMap;
};

layout(binding = 0) uniform accelerationStructureEXT topLevelAS;
layout(binding = 2) uniform UBO 
{
    mat4 viewInverse;
    mat4 projInverse;
    mat4 modelInverse;
    DirectionalLight dlight;
    vec3 viewPos;
    PointLight plight;
    int vertexSize;
} ubo;
layout(binding = 3) buffer Vertices { vec4 v[]; } vertices[];
layout(binding = 4) buffer Indices { uint i[]; } indices[];
layout(binding = 5) buffer MaterialInfos { MaterialInfo materialInfo[]; } MaterialList;
layout(binding = 6) uniform sampler2D TextureMap[];

struct Vertex
{
  vec3 pos;
  vec3 normal;
  vec2 uv;
  vec4 tangent;
  vec4 BiTangant;
  vec4 Color;
  vec4 BoneID;
  vec4 BoneWeights;
 };


Vertex unpack(uint index)
{
    const int m = ubo.vertexSize / 16;

    vec4 d0 = vertices[gl_InstanceCustomIndexEXT].v[m * index + 0];
    vec4 d1 = vertices[gl_InstanceCustomIndexEXT].v[m * index + 1];
    vec4 d2 = vertices[gl_InstanceCustomIndexEXT].v[m * index + 2];

    Vertex v;
    v.pos = d0.xyz;
    v.normal = vec3(d0.w,d1.x,d1.y);
    v.Color = vec4(d2.x,d2.y,d2.z,1.0);
    v.uv = vec2(d0.x,d1.y);
    v.tangent = vec4(d0.w,d1.y,0.0f);

    return v;
}

Material BuildMaterial(vec2 UV)
{
    Material material;
    material.Ambient = MaterialList.materialInfo[gl_InstanceCustomIndexEXT].Ambient;
    material.Diffuse = MaterialList.materialInfo[gl_InstanceCustomIndexEXT].Diffuse;
    material.specular = MaterialList.materialInfo[gl_InstanceCustomIndexEXT].specular;
    material.Shininess = MaterialList.materialInfo[gl_InstanceCustomIndexEXT].Shininess;
    material.Reflectivness = MaterialList.materialInfo[gl_InstanceCustomIndexEXT].Reflectivness;
    material.DiffuseMap = vec3(texture(TextureMap[MaterialList.materialInfo[gl_InstanceCustomIndexEXT].DiffuseMapID],UV));
    material.specularMap = vec3(texture(TextureMap[MaterialList.materialInfo[gl_InstanceCustomIndexEXT].specularMapID],UV));
    material.normalMap = vec3(texture(TextureMap[MaterialList.materialInfo[gl_InstanceCustomIndexEXT].normalMapID],UV));
    material.AlphaMap = vec3(texture(TextureMap[MaterialList.materialInfo[gl_InstanceCustomIndexEXT].AlphaMapID],UV));
    material.EmissionMap = vec3(texture(TextureMap[MaterialList.materialInfo[gl_InstanceCustomIndexEXT].EmissionMapID],UV));
    return material;
};

void main()
{
    const ivec3 index = ivec3(indices[gl_InstanceCustomIndexEXT].i[3 * gl_PrimitiveID],indices[gl_InstanceCustomIndexEXT].i[3 * gl_PrimitiveID + 1],indices[gl_InstanceCustomIndexEXT].i[3 * gl_PrimitiveID + 2]);

    const Vertex v0 = unpack(index.x);
    const Vertex v1 = unpack(index.y);
    const Vertex v2 = unpack(index.z);

    const vec2 uv0 = getTexCoord(index.x);
    const vec2 uv1 = getTexCoord(index.y);
    const vec2 uv2 = getTexCoord(index.z);

    // Interpolate normal
    const vec3 barycentricCoords = vec3(1.0f - attribs.x - attribs.y,attribs.x,attribs.y);
    vec3 normal = normalize(v0.normal * barycentricCoords.x + v1.normal * barycentricCoords.y + v2.normal * barycentricCoords.z);
    vec2 UV = v0.uv * barycentricCoords.x + v1.uv * barycentricCoords.y + v2.uv * barycentricCoords.z;
     vec3 worldPos = v0.pos * barycentricCoords.x + v1.pos * barycentricCoords.y + v2.pos * barycentricCoords.z;

        const Material material = BuildMaterial(UV);

    vec3 lightDir = normalize(-ubo.dlight.direction);
    float diff = max(dot(ubo.dlight.direction,lightDir),0.0);

    vec3 ambient = ubo.dlight.ambient *  material.DiffuseMap;
    vec3 diffuse = ubo.dlight.diffuse * diff *  material.DiffuseMap;
 
     hitValue = ambient + diffuse;


        vec3 lightDir2 = normalize(ubo.plight.position - worldPos);
    float diff2 = max(dot(ubo.plight.position,lightDir2),0.0);
     float distance = length(ubo.plight.position - worldPos);
    float attenuation = 1.0 / (ubo.plight.constant + ubo.plight.linear * distance + ubo.plight.quadratic * (distance * distance));    
    
    vec3 ambient2 = ubo.plight.ambient * material.DiffuseMap;
    vec3 diffuse2 = ubo.plight.diffuse * diff * material.DiffuseMap;
//  ambient2 *= attenuation;
  //  diffuse2 *= attenuation;

     hitValue += ambient2 + diffuse2;















    float spec = 0.0f;
//  if(dot(normal,L) > 0)
//  {
    // Shadow casting
    float tmin = 0.001;
    float tmax = 10000.0;
    vec3 origin = gl_WorldRayOriginEXT + gl_WorldRayDirectionEXT * gl_HitTEXT;
    shadowed = true;  
    // Trace shadow ray and offset indices to match shadow hit/miss shader group indices
    traceRayEXT(topLevelAS,gl_RayFlagsTerminateOnFirstHitEXT | gl_RayFlagsOpaqueEXT | gl_RayFlagsSkipClosestHitShaderEXT,0xFF,1,origin,tmin,lightDir,tmax,2);
    if (shadowed) {
        hitValue *= 0.3f;
    }
    else
    {
        vec3 halfwayDir = normalize(ubo.dlight.direction + ubo.viewPos);  
         spec = pow(max(dot(normal,halfwayDir),0.0),material.Shininess);
        vec3 specular = ubo.dlight.specular * spec * material.specular;
        hitValue += specular;
    }

    traceRayEXT(topLevelAS,lightDir2,2);
    if (shadowed) {
        hitValue *= 0.3f;
    }
    else
    {
        vec3 halfwayDir2 = normalize(ubo.plight.position + ubo.viewPos);  
        spec = pow(max(dot(normal,halfwayDir2),material.Shininess);
        vec3 specular2 = ubo.plight.specular * spec * material.specular;
        //specular2 *= attenuation;
        hitValue += specular2;
    }
        
 //  }

}

解决方法

v.uv = vec2(d0.x,d1.y); 肯定看起来是错误的,因为 d0.x 包含顶点位置的 x 分量,而不是纹理坐标的 u 分量。错误地取自法线的 v 组件的 w 组件也是如此。由于您没有在主机端发布顶点布局,我只能猜测,但是如果您的主机顶点布局是这样的:

glm::vec3 pos;
glm::vec3 normal;
glm::vec2 uv;

然后你解压成多个 vec4,你会得到这个:

vec4 0: pos.x|pos.y|pos.z|normal.x 
vec4 1: normal.y|normal.z|uv.u|uv.v

这意味着您需要像这样获取数据:

v.pos = d0.xyz;
v.normal = vec3(d0.w,d1.x,d1.y);
v.uv = d1.zw;