2014-01-18 6 views
0

Я студент в видеоиграх, и мы работаем над raytracer на C++. Мы используем библиотеку наших учителей.Нормальное отображение на процедурной сфере

Мы создаем процедурные объекты (в нашем случае сферу), Камера посылает луч для каждого пикселя экрана, а луч отправляет обратно информацию о том, что он ударил.

Некоторые из нас решили интегрировать Normal Maps. Итак, сначала мы отправили лучи на объект, посмотрели на значение Normal map texel, где мы попали в сферу, преобразовали его в вектор, нормализировали и отправили обратно вместо нормали объекта. Результат был довольно хорошим, но, конечно, он не принял ориентацию «лица» (это процедурный, так что лица нет, но он дает идею), поэтому рендер был плоским.

Мы по-прежнему не знаем, как «смешивать» нормаль текстуры (в касательном пространстве) и нормали объекта вместе. Вот наш код:

// TGfxVec3 is part of our teachers library, and is a 3d vector like this: 
// TGfxVec3(12.7f, -13.4f, 52.0f) 

// The sphere being at the origin and of radius 1, and tHit.m_tPosition being the 
// exact position at the surface of the sphere where the ray hit, the normal of this 
// point is the position hit by the ray. 
TGfxVec3 tNormal = tHit.m_tPosition; 
TGfxVec3 tTangent = Vec3CrossProduct(tNormal , m_tAxisZ); 

TGfxVec3 tBiNormal = Vec3CrossProduct(tNormal , tTangent); 

TGfxVec3 tTextureNorm = 2*(TGfxVec3(pNorm[0], pNorm[1], pNorm[2])/255)-TGfxVec3(-1.0f, -1.0f, -1.0f); 
// pNorm[0], pNorm[1], pNorm[2] are respectively the channels Red, Green, 
// and Blue of the Normal Map texture. 
// We put them in a 3D vector, divid them by 255 so their value go from 0 to 1, 
// multiply them by 2, and then substract a vector, so their rang goes from -1 to +1. 

tHit.m_tNorm = TGfxVec3(tTangente.x*tTextNorm.x + tCoTangente.x*tTextNorm.x + 
tNorm.x*tTextNorm.x, tTangente.y*tTextNorm.y + tCoTangente.y*tTextNorm.y + 
tNorm.y*tTextNorm.y, tTangente.z*tTextNorm.z + tCoTangente.z*tTextNorm.z + 
tNorm.z*tTextNorm.z).Normalize(); 
// Here, after some research, I came across this : http://www.txutxi.com/?p=316 , 
// that allow us to convert the normal map tangent space to the object space. 

Результаты по-прежнему не очень хорошие. Моя главная забота - это тангенс и бинормалы. Ось, взятая в качестве ссылки (здесь: m_tAxisZ, ось Z сферы), неверна. Но я не знаю, что взять, или даже если то, что я делаю, действительно хорошо. Поэтому я пришел сюда за помощью.

+0

Я кратко изложил вопрос, надеюсь, что я не слишком сильно перерезал. – bigstones

+0

Извините, я забыл сказать спасибо за это. На самом деле это более ясно. :) – Ellenack

ответ

0

Вы в основном правы и совершенно ошибаетесь в то же время.

Касательное пространство нормального отображения использует матрицу преобразования, чтобы преобразовать нормальное касательное пространство от текстуры к другому пространству, например объекту или мировому пространству, или преобразовать свет в касательное пространство, чтобы вычислить освещение со всем в одном и том же пространстве.

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

Иногда можно вычислить TBN на лету на простой геометрии, например, на карте высоты, так как легко вывести касательную и би-касательную на регулярной сетке. Но на сфере кросс-трюк с фиксированной осью приведет к сингулярности на полюсе, где поперечное произведение дает вектор нулевой длины.

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

Из-за этого мы чаще всего храним TBN как дополнительную информацию в геометрии, вычисляемую по координате текстуры (ссылка на ссылку, ссылающуюся на это описание вычисления), и интерполируем во время выполнения с другими значениями.

Рем: есть грубое упрощение, чтобы использовать геометрию норнала как нормальный TBN, но нет причин, в первую очередь, чтобы они совпадали.

+0

Soooo ... Что мне делать? Я не могу хранить TBN своей сферы, потому что у нее нет реального существования (не как 3D-сетка, где вы храните информацию о каждой вершине). Сфера генерируется raytracer, поэтому я не могу хранить такую ​​информацию в любой геометрии. На самом деле, у меня нет другого выбора, кроме как вычислить его на лету. И, поскольку я не могу получить хороший TBN, я не сомневаюсь в том, что я должен делать. Как я мог преобразовать норму, данную мне текстурой в объектно-мировом пространстве? Я попытался перенести матрицу TNB, но это все еще неправильно. Я продолжаю искать, но не могу найти решения. – Ellenack

+0

Лучшее, что я могу вам предложить, это http://www.iquilezles.org/www/articles/patchedsphere/patchedsphere.htm. Идея заключалась бы в том, чтобы извлечь из положения сферы и нормализовать параметризацию s и t путем проецирования на виртуальный куб, затем применить формулу на веб-страницах для вычисления тангенциального базиса. – galop1n

+0

Ну, это действительно интересно, спасибо большое. Я должен уметь что-то понять. У меня уже есть «q», поэтому я могу выяснить другие компоненты и получить хорошее aproximation (В и, я не думаю, что я смогу получить что-то лучше). Я свяжусь с вами чтобы он работал. – Ellenack

0

Итак, мы, наконец, сделали это. : D Хорошо, я постараюсь быть ясным. Для этого два изображения:

(1): http://i.imgur.com/cHwrR9A.png

(2): http://i.imgur.com/mGPH1RW.png

(Мой рисунок мастерство не имеет себе равных, я знаю).

Итак, главная проблема заключалась в том, чтобы найти касательную «Т» и би-касательную «В».У нас уже есть нормальный «N». Наш круг всегда находится в начале координат с радиусом 1, точка на его поверхности равна нормали к этой точке (черный и красный вектор на первом изображении). Итак, мы должны найти касательную к этой точке (зеленым). Для этого, мы просто должны вращать вектор из PI 2 рад /:

С N (х, у):

T = (-N.y , N.x) 

Тем не менее, мы в 3D. Таким образом, точка не всегда будет на экваторе. Мы можем легко решить эту проблему, проигнорировав положение в Y нашей точки и нормализовать вектор только с двумя другими компонентами. Итак, на втором изображении мы имеем P (мы устанавливаем его значение Y равным 0) и нормируем новый вектор, чтобы получить P '.

С Р (х, у, г):

P' = (P.x, 0, P.z).Normalize(); 

Затем мы вернемся к моему первому сообщению, чтобы найти T. Наконец, мы получаем B с поперечным продуктом между N Э.Н. Т. Наконец, мы вычисляем нормаль к этой точке, принимая во внимание нормальную карту.

С переменной "Map", содержащий три канала (RGB) нормальной карты, каждая из которых зажимают от -1 до 1, и Т, N и B все являются 3D векторов:

(Map.R*T + Map.G*B + Map.B*N).Normalize(); 

И вот и все, у вас нормальная точка, учитывающая вашу нормальную карту. :) Надеюсь, это будет полезно для других.

Смежные вопросы