2017-06-14 104 views
0

我試圖將NVidia Optix光線跟蹤渲染的Open Asset Import Library(讀取各種3D模型文件類型)模型。使用Nvidia Optix與開放資產導入庫(assimp)進行光線追蹤 - 渲染多個網格

到目前爲止,只要我渲染的模型由單個網格組成,它就會工作。當我嘗試渲染具有多個網格的文件時,我只能得到部分結果。我無法縮小問題的出處,尋找一些見解。相關代碼在這裏:

使用assimp進口商裝入一個文件,並創建Optix的緩衝區:

int loadAsset(const char* path) 
{ 
Assimp::Importer importer; 

scene = importer.ReadFile(
    path, 
    aiProcess_Triangulate 
    //| aiProcess_JoinIdenticalVertices 
    | aiProcess_SortByPType 
    | aiProcess_ValidateDataStructure 
    | aiProcess_SplitLargeMeshes 
    | aiProcess_FixInfacingNormals 
    ); 

if (scene) { 
    getBoundingBox(&scene_min, &scene_max); 
    scene_center.x = (scene_min.x + scene_max.x)/2.0f; 
    scene_center.y = (scene_min.y + scene_max.y)/2.0f; 
    scene_center.z = (scene_min.z + scene_max.z)/2.0f; 

    float3 optixMin = { scene_min.x, scene_min.y, scene_min.z }; 
    float3 optixMax = { scene_max.x, scene_max.y, scene_max.z }; 
    aabb.set(optixMin, optixMax); 

    unsigned int numVerts = 0; 
    unsigned int numFaces = 0; 

    if (scene->mNumMeshes > 0) {  
     printf("Number of meshes: %d\n", scene->mNumMeshes); 

     // get the running total number of vertices & faces for all meshes 
     for (unsigned int i = 0; i < scene->mNumMeshes; i++) { 
      numVerts += scene->mMeshes[i]->mNumVertices; 
      numFaces += scene->mMeshes[i]->mNumFaces; 
     } 
     printf("Found %d Vertices and %d Faces\n", numVerts, numFaces); 

     // set up buffers 
     optix::Buffer vertices = context->createBuffer(RT_BUFFER_INPUT, RT_FORMAT_FLOAT3, numVerts); 
     optix::Buffer normals = context->createBuffer(RT_BUFFER_INPUT, RT_FORMAT_FLOAT3, numVerts); 
     optix::Buffer faces = context->createBuffer(RT_BUFFER_INPUT, RT_FORMAT_UNSIGNED_INT3, numFaces); 
     optix::Buffer materials = context->createBuffer(RT_BUFFER_INPUT, RT_FORMAT_UNSIGNED_INT, numVerts); 

     // unused buffer 
     Buffer tbuffer = context->createBuffer(RT_BUFFER_INPUT, RT_FORMAT_FLOAT2, 0); 

     // create material 
     std::string defaultPtxPath = "C:\\ProgramData\\NVIDIA Corporation\\OptiX SDK 4.1.0\\SDK\\build\\lib\\ptx\\"; 
     Program phong_ch = context->createProgramFromPTXFile(defaultPtxPath + "optixPrimitiveIndexOffsets_generated_phong.cu.ptx", "closest_hit_radiance"); 
     Program phong_ah = context->createProgramFromPTXFile(defaultPtxPath + "optixPrimitiveIndexOffsets_generated_phong.cu.ptx", "any_hit_shadow"); 

     Material matl = context->createMaterial(); 
     matl->setClosestHitProgram(0, phong_ch); 
     matl->setAnyHitProgram(1, phong_ah); 
     matl["Kd"]->setFloat(0.7f, 0.7f, 0.7f); 
     matl["Ka"]->setFloat(1.0f, 1.0f, 1.0f); 
     matl["Kr"]->setFloat(0.0f, 0.0f, 0.0f); 
     matl["phong_exp"]->setFloat(1.0f); 

     std::string triangle_mesh_ptx_path(ptxPath("triangle_mesh.cu")); 
     Program meshIntersectProgram = context->createProgramFromPTXFile(triangle_mesh_ptx_path, "mesh_intersect"); 
     Program meshBboxProgram = context->createProgramFromPTXFile(triangle_mesh_ptx_path, "mesh_bounds"); 

     optix::float3 *vertexMap = reinterpret_cast<optix::float3*>(vertices->map()); 
     optix::float3 *normalMap = reinterpret_cast<optix::float3*>(normals->map()); 
     optix::uint3 *faceMap = reinterpret_cast<optix::uint3*>(faces->map()); 
     unsigned int *materialsMap = static_cast<unsigned int*>(materials->map()); 

     context["vertex_buffer"]->setBuffer(vertices); 
     context["normal_buffer"]->setBuffer(normals); 
     context["index_buffer"]->setBuffer(faces); 
     context["texcoord_buffer"]->setBuffer(tbuffer); 
     context["material_buffer"]->setBuffer(materials); 


     Group group = createSingleGeometryGroup(meshIntersectProgram, meshBboxProgram, vertexMap, 
      normalMap, faceMap, materialsMap, matl); 

     context["top_object"]->set(group); 
     context["top_shadower"]->set(group); 

     vertices->unmap(); 
     normals->unmap(); 
     faces->unmap(); 
     materials->unmap(); 
    } 

    return 0; 
} 
return 1; 
} 

和創建幾何形狀的相關功能和填充緩衝區:

Group createSingleGeometryGroup(Program meshIntersectProgram, Program meshBboxProgram, optix::float3 *vertexMap, 
optix::float3 *normalMap, optix::uint3 *faceMap, unsigned int *materialsMap, Material matl) { 

Group group = context->createGroup(); 
optix::Acceleration accel = context->createAcceleration("Trbvh"); 
group->setAcceleration(accel); 
std::vector<GeometryInstance> gis; 
unsigned int vertexOffset = 0u; 
unsigned int faceOffset = 0u; 

for (unsigned int m = 0; m < scene->mNumMeshes; m++) { 
    aiMesh *mesh = scene->mMeshes[m]; 
    if (!mesh->HasPositions()) { 
     throw std::runtime_error("Mesh contains zero vertex positions"); 
    } 
    if (!mesh->HasNormals()) { 
     throw std::runtime_error("Mesh contains zero vertex normals"); 
    } 

    printf("Mesh #%d\n\tNumVertices: %d\n\tNumFaces: %d\n", m, mesh->mNumVertices, mesh->mNumFaces); 

    // add points   
    for (unsigned int i = 0u; i < mesh->mNumVertices; i++) { 
     aiVector3D pos = mesh->mVertices[i]; 
     aiVector3D norm = mesh->mNormals[i]; 

     vertexMap[i + vertexOffset] = optix::make_float3(pos.x, pos.y, pos.z) + aabb.center(); 
     normalMap[i + vertexOffset] = optix::normalize(optix::make_float3(norm.x, norm.y, norm.z)); 
     materialsMap[i + vertexOffset] = 0u; 

    } 

    // add faces 
    for (unsigned int i = 0u; i < mesh->mNumFaces; i++) { 
     aiFace face = mesh->mFaces[i]; 

     // add triangles 
     if (face.mNumIndices == 3) { 
      faceMap[i + faceOffset] = optix::make_uint3(face.mIndices[0], face.mIndices[1], face.mIndices[2]); 
     } 
     else { 
      printf("face indices != 3\n"); 
      faceMap[i + faceOffset] = optix::make_uint3(-1); 
     } 
    } 

    // create geometry 
    optix::Geometry geometry = context->createGeometry(); 
    geometry->setPrimitiveCount(mesh->mNumFaces); 
    geometry->setIntersectionProgram(meshIntersectProgram); 
    geometry->setBoundingBoxProgram(meshBboxProgram); 
    geometry->setPrimitiveIndexOffset(faceOffset); 

    optix::GeometryInstance gi = context->createGeometryInstance(geometry, &matl, &matl + 1); 
    gis.push_back(gi); 

    vertexOffset += mesh->mNumVertices; 
    faceOffset += mesh->mNumFaces; 

} 

printf("VertexOffset: %d\nFaceOffset: %d\n", vertexOffset, faceOffset); 

// add all geometry instances to a geometry group 
GeometryGroup gg = context->createGeometryGroup(); 
gg->setChildCount(static_cast<unsigned int>(gis.size())); 
for (unsigned i = 0u; i < gis.size(); i++) { 
    gg->setChild(i, gis[i]); 
} 
Acceleration a = context->createAcceleration("Trbvh"); 
gg->setAcceleration(a); 

group->setChildCount(1); 
group->setChild(0, gg); 

return group; 
} 

運行以上代碼從assimp的樣本文件(使用dwarf.x,文件包含2個網格)產生此結果:enter image description here

您可以看到第二個網格(矮人的身體)的一部分被渲染。我試着分別渲染每個網格,一次一個,然後渲染全部。但是當把它們放在一起時,我會得到它。

我想這個問題是要麼與創建幾何,也許我有這行錯誤:

geometry->setPrimitiveCount(mesh->mNumFaces); 
geometry->setPrimitiveIndexOffset(faceOffset); 

或assimp後處理標誌

scene = importer.ReadFile(
    path, 
    aiProcess_Triangulate 
    //| aiProcess_JoinIdenticalVertices 
    | aiProcess_SortByPType 
    | aiProcess_ValidateDataStructure 
    | aiProcess_SplitLargeMeshes 
    | aiProcess_FixInfacingNormals 
    ); 

(注意上面,我不得不註釋掉JoinIdenticalVertices,因爲它給了我一個可怕的錯誤結果,如下所示): enter image description here

有沒有人能夠成功地將nvidia optix與開放資產導入庫結合起來,用於渲染具有多個網格的文件?

回答

0

我找到了一個解決方案,雖然不知道如何優化。每個網格仍然有它自己的幾何圖形,但是不是創建在所有幾何圖形之間共享的單個頂點,索引和常規緩衝區,而是爲每個幾何圖形創建單獨的緩衝區。

然後,而不是

context["vertex_buffer"]->setBuffer(vertices); 
context["normal_buffer"]->setBuffer(normals); 
context["index_buffer"]->setBuffer(faces); 
context["texcoord_buffer"]->setBuffer(tbuffer); 
context["material_buffer"]->setBuffer(materials); 

我用

geometry["vertex_buffer"]->setBuffer(vertices); 
geometry["normal_buffer"]->setBuffer(normals); 
geometry["index_buffer"]->setBuffer(faces); 
geometry["texcoord_buffer"]->setBuffer(tbuffer); 
geometry["material_buffer"]->setBuffer(materials); 

結果: enter image description here