3D ортогональная проекция

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

glViewport (0, 0, (GLsizei)shadowMap.x, (GLsizei)shadowMap.y);
glMatrixMode (GL_PROJECTION);
glLoadIdentity();

//suns use this
glOrtho(0, shadowMap.x, 0, shadowMap.y, 0.1,1000.0);

glMatrixMode (GL_MODELVIEW);
glLoadIdentity();

Насколько я понимаю, это должно быть правильно. Однако после быстрой отладочной визуализации я заметил, что сцена визуализируется в крошечной части экрана. После некоторых экспериментов я обнаружил, что изменение значений shadowMap в glOrtho заставило их покрыть всю текстуру, но было действительно увеличено. В моей перспективной проекции я использую 0,1 и 1000,0 для ближнего и дальнего, и я экспериментировал с ними и с ним. изменяет результаты, но все еще не дает желаемых результатов. Единственный раз, когда я получаю правильные результаты, это когда значения сохраняются в shadowMap.x и shadowMap.y, но, как я уже сказал, его рендеринг очень маленький.

Что я здесь делаю не так? Все, что я прочитал, говорит о том, что исходный код правильный.

РЕДАКТИРОВАТЬ: По-видимому, было непонятно, что это для прохода карты теней, обычный проход отображается с перспективой и в порядке.


person BlueSpud    schedule 08.01.2015    source источник


Ответы (2)


Отображение теней - это многопроходный алгоритм. Вы переходите к первому проходу (пункт 1).

  1. Рендеринг сцены из вида источника света в текстуру глубины

  2. Визуализируйте сцену из вида камеры с включенным отображением текстуры глубины.

    • текущий фрагмент xy + глубина затем преобразуется в координаты световой проекции и сравнивается с сохраненной глубиной на текстуре глубины

    • если обе глубины равны (или почти равны) текущий фрагмент следует считать освещенным, в противном случае - затененным.

Итак, с вашим кодом все в порядке, сохраните значения глубины от этого перехода до текстуры глубины и переходите к пункту 2.

Одна вещь, о которой вы должны подумать, - это то, какую широкую область должен охватывать ваш свет (в мировом пространстве). С loadidentity в обзоре модели вы пытаетесь покрыть 1 мировую единицу x 1 мировую единицу площади только для вашего света.

  • Предположим, у нас есть сфера в точке 0,0,0 и радиусом 5,0.
  • У нас есть текстура глубины 256 256 димов.
  • Мы хотим спроецировать его по Z на сферу.

    glVieport (0,0,256,256); glMatrixMode (GL_PROJECTION); glLoadidentity (); glOrtho (-2,5,2,5, -2,5,2,5, -1000,1000); glMatrixMode (GL_MODELVIEW); glLoadidentity (); // перевернуть z, мы проливаем свет сверху glRotate (1,0,0,180);

person Anonymous    schedule 08.01.2015
comment
Я знаю, как работает отображение теней, это код для проекции источника света. Я предполагаю, что это не было разъяснено в вопросе, обновлено. Кроме того, вы ошибаетесь, говоря, что этот код правильный, потому что в любом случае сцена все равно будет отображаться в неправильной проекции, поэтому технически это не зависит от карты теней. - person BlueSpud; 09.01.2015
comment
Обновлено последнее примечание :) - person Anonymous; 09.01.2015
comment
Я не знаю, является ли ваш окончательный вариант орфографическим, потому что я никогда не рассматривал его, но в дальнейшем при рендеринге геометрия переводится в пространство камеры. Поскольку ортогональная проекция не использует трансформации, следует ли исключить перевод камеры из вида модели? - person BlueSpud; 09.01.2015
comment
Орто будет масштабировать -1 +1 квадрат к вашей текстуре глубины, это нормально. Но вам нужно масштабировать матрицу просмотра модели, чтобы уместить ваш мир на эту проекцию. Если вы этого не сделаете, ваша текстура будет содержать только -1 +1 квадрат. - person Anonymous; 09.01.2015

Я не вижу, где вы устанавливаете световую матрицу просмотра модели. Вы можете визуализировать карту теней, используя приведенный ниже код:

double* getOrthoMVPmatrix(vector3 position,vector3 lookat,
                          GLdouble  left,  GLdouble  right,
                          GLdouble  bottom,  GLdouble  top,
                          GLdouble  nearVal,  GLdouble  farVal)
{

 glPushMatrix();

 double projection[16];
 double modelView[16];
 double *matrix = new double [16];

 glMatrixMode(GL_PROJECTION);
 glLoadIdentity();
 glOrtho(  left, right, bottom, top, nearVal,  farVal) ;
 glMatrixMode(GL_MODELVIEW);
 glEnable(GL_DEPTH_TEST);
 glLoadIdentity();
 gluLookAt(position.x,position.y,position.z,lookat.x,lookat.y,lookat.z,0,1,0);

 glGetDoublev(GL_MODELVIEW_MATRIX, modelView);
 glGetDoublev(GL_PROJECTION_MATRIX, projection);


 glPopMatrix();

 matrix  = projection*modelView;

 return matrix ;

}


void renderShadowMap(void)
{

 //"Bind your depth framebuffer"

 glViewport(0,0,"Your SM SIZE","Your SM SIZE");
 glEnable(GL_CULL_FACE);
 glCullFace(GL_FRONT);
 glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

 double *MVP =  getOrthoMVPmatrix( "your light position","your light position" + "your light direction",
                          -"left","right",
                           "bottom","top",
                           "near","far"
                          ) ;


 //"call glUseProgram to bind your shader"

 // set the uniform MVP we made "

 //"Draw your scene "

 glViewport(0,0,"screen width","screen height");


}



Вам нужно будет сделать оператор умножения для массива double [16]. В моем случае я сделал матричный класс, но делаю это по-своему. Не забудьте вызвать glCullFace (GL_BACK) перед рисованием вашей реальной сцены и освободить MVP после.

person CLOYZ    schedule 09.01.2015
comment
Проблема не в том, как я визуализирую карту теней, а в том, как я делаю ортопроекцию. - person BlueSpud; 09.01.2015