Выбор лучей с буфером глубины: ужасно неточно?

Я пытаюсь реализовать алгоритм выбора лучей для рисования и выбора блоков (поэтому мне нужна изрядная точность). Изначально я выбрал реализацию лучей, но не чувствовал, что она достаточно точна (хотя ошибка могла быть связана с моим тестированием пересечения). Тем не менее, я решил попробовать выбрать с помощью буфера глубины и преобразовать координаты мыши в мировые координаты. Реализация ниже:

glm::vec3 Renderer::getMouseLocation(glm::vec2 coordinates) {
    float depth = deferredFBO->getDepth(coordinates);

    // Calculate the width and height of the deferredFBO
    float viewPortWidth = deferredArea.z - deferredArea.x;
    float viewPortHeight = deferredArea.w - deferredArea.y;

    // Calculate homogenous coordinates for mouse x and y
    float windowX = (2.0f * coordinates.x) / viewPortWidth - 1.0f;
    float windowY = 1.0f - (2.0f * coordinates.y) / viewPortHeight;

    // cameraToClip = projection matrix
    glm::vec4 cameraCoordinates = glm::inverse(cameraToClipMatrix) 
                                * glm::vec4(windowX, windowY, depth, 1.0f);

    // Normalize
    cameraCoordinates /= cameraCoordinates.w;

    glm::vec4 worldCoordinates = glm::inverse(worldToCameraMatrix) 
                               * cameraCoordinates;

    return glm::vec3(worldCoordinates);
}

Проблема в том, что значения легко составляют ± 3 единицы (блоки имеют ширину 1 единицу), и становятся достаточно точными, только когда они очень близки к ближней плоскости отсечения.

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

И, наконец, если этот метод не работает, лучше ли мне использовать идентификаторы цвета, чтобы точно определить, какой многоугольник был выбран?


person Fault    schedule 03.12.2013    source источник
comment
Он должен быть более точным, когда он находится близко к ближнему, а не к дальнему. Да, вы должны использовать цвета, чтобы определить, какой полигон выбран. Если только вы не хотите выбрать луч.   -  person Jean-Simon Brochu    schedule 04.12.2013
comment
Упс, исправил, вы правы, точнее ближе к ближайшей плоскости. Однако приближение дальней плоскости отсечения помогло. Если игнорировать тот факт, что более половины модели обрезается ...   -  person Fault    schedule 04.12.2013
comment
Вы уверены, что deferredFBO->getDepth(...) возвращает координату z клипа (в [-1,1]), а не значение глубины, как вы получили бы от glReadPixels (в [0,1])?   -  person Mike Dinsdale    schedule 04.12.2013
comment
Я визуализирую значения глубины текстуры и захватываю пиксель с помощью ‹code› glGetTexImage ‹/code›. Довольно неэффективно, учитывая, что мне нужно захватить всю текстуру, и я не могу просто прочитать один пиксель, но я предполагаю, что это координата z клипа?   -  person Fault    schedule 04.12.2013
comment
Я бы подумал, что вы получите число в [0,1] от glGetTexImage, но опять же вы, вероятно, заметили бы это - эффект будет больше, чем то, что вы, кажется, описываете (и, вероятно, будет хуже всего приближаться к возле самолета). Так что, возможно, он дает значение z клипа.   -  person Mike Dinsdale    schedule 04.12.2013


Ответы (1)


Цвета - это лучший выбор, точность буферов глубины зависит от расстояний до плоскости, разрешения текстуры FBO, а также от нормали или наклона поверхности. Та же проблема точности возникает при стандартном затенении. (Использование цветов немного проще, потому что с тестом пересечения глубины один объект имеет больше "цвета", значений глубины. Это более точно, если один объект имеет один цвет.)

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

Для значений с двойной точностью это может сильно снизить производительность. Я столкнулся с таким падением производительности, для меня было примерно в 3 раза медленнее использовать удвоения, а не числа с плавающей запятой:

мое сообщение: Производительность GLSL - возвращаемое значение / тип функции и статья об этом : https://superuser.com/questions/386456/why-does-a-geforce-card-perform-4x-slower-in-double-precision-than-a-tesla-card

так что да, вы можете использовать 64-битные числа с плавающей запятой (двойные): http://www.opengl.org/registry/specs...hader_fp64.txt и http://www.opengl.org/registry/specs...trib_64bit.txt, но вам не следует этого делать.

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

РЕДАКТИРОВАТЬ: подробнее о глубине двойной точности: http://www.opengl.org/discussion_boards/showthread.php/173450-Double-Precision, это довольно хорошее обсуждение

person David Szalai    schedule 03.12.2013
comment
Что ж, процессору необходимо выполнить дополнительную матричную математику только один раз за щелчок, так что это не так уж и плохо. Но спасибо за информативный пост! Жаль, что этот метод не более эффективен, мне очень нравится концепция. Ну что ж, вернемся к цветам. - person Fault; 04.12.2013