Реализация алгоритма теневых объемов в DX10 Юрий Степаненко
NVIDIA Confidential Формирование теней с помощью теневых объемов Z-pass Light
NVIDIA Confidential Формирование теней с помощью теневых объемов Z-fail Light
NVIDIA Confidential Проблемы алгоритма теневых объемов в DX9 Нахождение теневого силуэта
NVIDIA Confidential Проблемы алгоритма теневых объемов в DX9 Нахождение теневого силуэта Генерирование новой геометрии (собственно теневого объема)
NVIDIA Confidential Решение проблем в DX10: Геометрический шейдер Triangle with adjacency Input Point Line Strips Triangle Strips Output Point list Line strip Triangle strip Geometry Shader Vertex Shader Raster Pixel Shader From CPU Output Merger Line with adjacency
NVIDIA Confidential Традиционный алгоритм определения теневого силуэта Вычисляем геометрическую нормаль N для текущего треугольника N Light
NVIDIA Confidential Проверяем, направлена ли нормаль к источнику освещения Light L N Традиционный алгоритм определения теневого силуэта
NVIDIA Confidential Вычисляем геометрическую нормаль N i для соседних треугольников Light NiNi N Традиционный алгоритм определения теневого силуэта
NVIDIA Confidential Проверяем, повернута ли нормаль N i также на источник освещения? Light NiNi Li N Традиционный алгоритм определения теневого силуэта
NVIDIA Confidential Если нормали направлены по-разному, то добавить это ребро в теневой силуэт Традиционный алгоритм определения теневого силуэта NiNi N Light
NVIDIA Confidential N NiNi Традиционный алгоритм определения теневого силуэта Light Из выбранного ребра формируем грань теневого объема
NVIDIA Confidential Недостатки традиционного метода Нужна информация о соседних треугольниках Теневой силуэт отличается от гладкого силуэта освещенности (артефактам в виде «ступенек») Теневой силуэт перемещается скачками Много идентичных вычислений для каждого из треугольников Численная неустойчивость*
NVIDIA Confidential Недостатки традиционного метода N1 = { , , } N2 = { , , } N1 = { , , } N2 = { , , } L1 = { , , } L2 = { , , } dot( N1, L1 ) = dot( N2, L2 ) = dot( N1, L1 ) = dot( N2, L2 ) = Численная неустойчивость
NVIDIA Confidential Недостатки традиционного метода Прмер «ступенчатых» артефактов
NVIDIA Confidential Какой метод нам нужен? Без дополнительной информации Без артефактов в виде «ступенек» Вычислительно эффективный Численно устойчивый
NVIDIA Confidential Новый метод определения теневого силуэта
NVIDIA Confidential Достоинства нового метода Не нужна информация о соседних треугольниках, достаточно сглаженной нормали Теневой силуэт не отличается от гладкого силуэта освещенности Теневой силуэт перемещается плавно, без скачков по ребрам модели Идентичные вычислений выполняются один раз на вершину в вершинном шейдере Численная устойчивость
NVIDIA Confidential N1 Light N2 N3 Новый метод определения теневого силуэта Используем просто сглаженную нормаль в вершинах треугольника
NVIDIA Confidential Новый метод определения теневого силуэта Находим для каждой вершины: NdotL[i] = dot(N[i], normalize(LightPos - Pos[i])); L2 L3 L1 Light
NVIDIA Confidential Light NdotL[0]>0 NdotL[1]0 Новый метод определения теневого силуэта Строим новое ребро, используя lerp(...) позиций вершин на ребрах, где NdotL меняет свой знак
NVIDIA Confidential Light Новый метод определения теневого силуэта Из построенного ребра формируем грань теневого объема
NVIDIA Confidential Особенности нового метода определения теневого силуэта Ребро силуэта вычисляется (строится), а не выбирается среди ребер объекта Меньше лишних вычислений
NVIDIA Confidential [maxvertexcount(4)] void GSShadowmain( triangleadj GSShadowIn In[6], inout TriangleStream ShadowTriangleStream ) { int nIndx; // Write pos for new verticies int nSign [3]; // Sign of dot(N, L) per vertex (-1 or zero) float fNDotL [3]; // dot(N, L) per vertex [-1; 1] float3 vNewPos [2]; // Position of new two verticies [unroll] for( int i=0; i
NVIDIA Confidential [branch] if( nIndx ) // OK, extrude shadow edge now { int i0, i1; [flatten] if( nSign[0] < 0 ) // We must swap positions { i0 = 1; i1 = 0; } else { i0 = 0; i1 = 1; } float3 vOutPos [4]; float3 vExtrude [2]; vExtrude[0] = normalize(vNewPos[i0] - g_vLightPos); vExtrude[1] = normalize(vNewPos[i1] - g_vLightPos); vOutPos[0] = vNewPos[i0] + vExtrude[0]; vOutPos[1] = vNewPos[i0] + vExtrude[0] * g_fExtrudeAmt; vOutPos[2] = vNewPos[i1] + vExtrude[1]; vOutPos[3] = vNewPos[i1] + vExtrude[1] * g_fExtrudeAmt; [unroll] for( int i=0; i
NVIDIA Confidential Нормаль в вершинах должна быть сглаженной Объект должен быть не только сглаженным, но и замкнутым Слишком «изогнутые» треугольники могут обрабатываться некорректно Утечки освещения для вогнутых поверхностей Недостатки нового метода
NVIDIA Confidential Утечки освещения для вогнутых поверхностей Недостатки нового метода Light
NVIDIA Confidential Ссылки [1] Morgan McGuire, John F. Hughes, and Kevin T. Egan; Mark J. Kilgard and Cass Everitt Fast, Practical and Robust Shadows umes.html umes.html [2] Cass Everitt and Mark J. Kilgard Practical and Robust Stenciled Shadow Volumes for Hardware- Accelerated Rendering volumes.html volumes.html
NVIDIA Confidential Вопросы?