Как добиться гладких касательных пространственных нормалей?

Я пытаюсь добавить функциональность рельефного отображения в свое приложение, но получаю очень граненые модели:

Причина, по которой это происходит, заключается в том, что я вычисляю тангенциальные, бинормальные и нормальные значения для каждого лица и полностью игнорирую нормали, полученные из файла модели.

В настоящее время в вычислениях используются два ребра пространственных векторов треугольника и текстуры для получения тангенса и бинормаля, которые затем используются для вычисления нормали по кросс-произведению. Все это выполняется на процессоре, как только модель загружается, а затем значения сохраняются как часть геометрии модели.

    vector1 = vertex2.coords - vertex1.coords;      
    vector2 = vertex3.coords - vertex1.coords;

    tuVector = vertex2.texcoords - vertex1.texcoords;
    tvVector = vertex3.texcoords - vertex1.texcoords;

    float den = 1.0f / (tuVector.x * tvVector.y - tuVector.y * tvVector.x);

    tangent.x = (tvVector.y * vector1.x - tvVector.x * vector2.x) * den;
    tangent.y = (tvVector.y * vector1.y - tvVector.x * vector2.y) * den;
    tangent.z = (tvVector.y * vector1.z - tvVector.x * vector2.z) * den;

    binormal.x = (tuVector.x * vector2.x - tuVector.y * vector1.x) * den;
    binormal.y = (tuVector.x * vector2.y - tuVector.y * vector1.y) * den;
    binormal.z = (tuVector.x * vector2.z - tuVector.y * vector1.z) * den;

    D3DXVec3Normalize(&tangent, &tangent);
    D3DXVec3Normalize(&binormal, &binormal);

    D3DXVec3Cross(&normal, &tangent, &binormal);    
    D3DXVec3Normalize(&normal, &normal);

Есть ли способ либо рассчитать эти значения для каждой вершины, возможно, используя нормаль, поставляемую с моделью, либо как-то сгладить их, чтобы модель не выглядела граненой?

1 ответ

Решение

Для гладких поверхностей (без краев) я делаю это так:

  1. создать пространство для каждой вершины

    double N[3]; //normal
    int cnt;
    
  2. для каждой вершины

    N={0.0,0.0,0.0}
    cnt=0;
    
  3. вычислить по лицу нормально

    норма должна быть нормализована длина =1,0!!! Добавь это Normal ко всем вершинам, используемым в грани и приращении cnt для всех вершин, используемых в лице

  4. нормализовать каждую вершину

    N/=cnt; // N = average normal from all vertex - neighbour faces
    

    быть осведомленным cnt=0 для неиспользуемых вершин (деление на ноль)

  5. на вершину Nсодержит нормальный вы хотите

    сейчас посчитаем T,B векторы для матрицы TBN (на вершину), как вы делаете сейчас

  6. выходное изображение гладкое

    Мой предварительный просмотр Земли (с атмосферным рассеянием, рельефом и многим другим...) находится здесь

Надеюсь, поможет

Другие вопросы по тегам