如何优化“软正态"计算功能? [英] How can I optimize my Soft Normal calculation function?

查看:70
本文介绍了如何优化“软正态"计算功能?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要为OpenGL应用程序生成软法线,但是此函数的处理时间是荒谬的.对它进行概要分析后,看来我的多地图放置处理时间非常高.我进行了一些研究,发现可以在插入/位置上使用提示,但是不知道如何实现它,即使我的方法是生成法线的最佳方法也不知道.如果您知道更好的方法或方法来加快此代码段的速度,我将很乐意听到.

I need to generate soft normals for my OpenGL application, but the processing time on this function is absurd. After profiling it, it seems that my multimap emplace processing times are absurdly high. I did some research and found out you can use hints on insertion/emplaces but don't know how to implement it or even if my method is the best way of generating normals. If you know of a better method or a way to speed up this code segment I would love to hear it.

void Controller::TerrainFactory::GenerateNormals(std::vector<Blue::Vertex> &verticies,
                                             std::vector<unsigned int> indicies) {
std::vector<Blue::Faces> faces;
std::multimap<unsigned int, size_t> setFaces;

for (size_t index = 0; index < indicies.size(); index += 3) {
    faces.push_back(Blue::Faces{});
    auto &face       = faces.at(faces.size() - 1);
    face.indicies[0] = indicies.at(index);
    face.indicies[1] = indicies.at(index + 1);
    face.indicies[2] = indicies.at(index + 2);
    face.normal      = glm::triangleNormal(verticies.at(face.indicies[0]).position,
                                      verticies.at(face.indicies[1]).position,
                                      verticies.at(face.indicies[2]).position);
    const auto size  = faces.size() - 1;
    setFaces.emplace(face.indicies[0], size);
    setFaces.emplace(face.indicies[1], size);
    setFaces.emplace(face.indicies[2], size);
}

for (unsigned index = 0; index < verticies.size(); ++index) {
    int count      = 0;
    auto itr1      = setFaces.lower_bound(index);
    auto itr2      = setFaces.upper_bound(index);
    auto avgNormal = glm::vec3{};
    while (itr1 != itr2) {
        if (itr1->first == index) {
            avgNormal += faces.at(itr1->second).normal;
            ++count;
        }
        ++itr1;
    }
    verticies.at(index).normals = avgNormal / static_cast<float>(count);
}


struct Vertex {
    glm::vec3 position = {};
    glm::vec2 texCoords = {};
    glm::vec3 normals = {};
};

struct Faces {
    unsigned int indicies[3] = {};
    glm::vec3 normal = {};
};

推荐答案

此任务无需将按面法线收集到专用结构(如 std :: multimap )中.由于不需要将一张脸与另一张脸区分开,并且法线是归一化向量-将每个三角形的法线直接累加到顶点数据中然后再对其进行归一化就更简单,直接了.

Collecting per-face normals into dedicated structures like std::multimap are not necessary for this task. As there is no need to distinguish one face from another and normals are normalized vectors - it is simpler and more straightforward accumulating per-triangle normals directly into vertex data and then normalize it.

复制 indicies 参数而不是通过引用传递参数,这听起来很多余而且昂贵.

Copying indicies parameter instead of passing it by reference also sound redundant and expensive.

glm :: triangleNormal()可能会归一化计算的矢量,但是对于这些计算,在此跳过三角形法线的归一化速度更快(更好-较小的三角形对结果法线的影响较小).步骤.

glm::triangleNormal() probably normalizes computed vector, but for these calculation it is faster (and better - smaller triangles will have smaller impact on result normal) to skip normalization of triangle normal at this step.

void Controller::TerrainFactory::GenerateNormals(std::vector<Blue::Vertex>& verticies,
                                                 const std::vector<unsigned int>& indicies)
{
  // first loop could be skipped, if verticies[i].normals were no spoiled before
  for (size_t vert = 0; vert < verticies.size(); ++vert)
  {
    verticies[vert].normals = glm::vec3();
  }

  // append triangle normals to every vertex
  for (size_t index = 0; index < indicies.size(); index += 3)
  {
    Blue::Vertex& vert1 = verticies[indicies[index]];
    Blue::Vertex& vert2 = verticies[indicies[index + 1]];
    Blue::Vertex& vert3 = verticies[indicies[index + 2]];
    // glm::triangleNormal() probably returns normalized vector,
    // which is better to compute unnormalized
    glm::vec3 triNormal = glm::triangleNormal(vert1.position,
                                              vert2.position,
                                              vert3.position);
    vert1.normals += triNormal;
    vert2.normals += triNormal;
    vert3.normals += triNormal;
  }

  // normalize normal vectors
  for (size_t vert = 0; vert < verticies.size(); ++vert)
  {
    Blue::Vertex& vertBlue = verticies[vert];
    vertBlue.normals = glm::normalize(vertBlue.normals);
  }

这篇关于如何优化“软正态"计算功能?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆