Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Некоторые подробности рендеринга в X-Ray
GAMEINATOR forums > S.T.A.L.K.E.R. > S.T.A.L.K.E.R.: Общий раздел
scwosh
Думаю, тем, кто балуется написанием собственного движка да и просто программерам было бы любопытно узнать, как решались некоторые проблемы визуализации разработчиками X-Ray.
Например такая, как несовместимость сглаживания и отложенного затенения.


Смотрим
К сожалению, отложенный рендеринг просто несовместим с текущей аппаратной поддержкой режимов сглаживания. Таким образом, сглаживание становится исключительной прерогативой приложения и шейдеров, мы не можем
полагаться только на GPU. Поскольку неровность сама по себе возникает в результате несоответствия частоты источника сигнала и назначения дискретного представления, хорошо приближенный фильтр сглаживания это просто фильтр низких частот, который дает обыкновенное размытие. В консолях это низкозатратная операция, так как любой телевизионный дисплей работает как фильтр низких частот ))). В мире же персональных компьютеров нам нужна альтернатива. Наше решение было поменять некоторые частоты сигнала на разрывах для гладкости и оставить другие части изображения нетронутыми. Это было выполнено по аналогии с фильтрами обнаружения краёв, используемыми в приложениях NonPhotorealistic: мы обнаруживаем разрывы в глубине и в направлении нормалей, принимая 8 +1 выборку глубины и находим, как глубина текущего пикселя отличается от идеальной линии, проходящей через противоположные угловые точки. Нормали были использованы для устранения проблем, таких как стены перпендикулярно полу, где глубина образует идеальную линию (или будет похожа на всех выборках), но на краях
возникают неровности. Нормали были обработаны способом перекрестного фильтра, а скалярное произведение нормали было использовано для определения присутствия края.

Код
struct v2p

{

  float4 tc0: TEXCOORD0; // Center

  float4 tc1: TEXCOORD1; // Left Top



  float4 tc2: TEXCOORD2; // Right Bottom

  float4 tc3: TEXCOORD3; // Right Top

  float4 tc4: TEXCOORD4; // Left Bottom



  float4 tc5: TEXCOORD5; // Left / Right

  float4 tc6: TEXCOORD6; // Top / Bottom

};





/////////////////////////////////////////////////////////////////////

uniform sampler2D s_distort;

uniform half4 e_barrier;  // x=norm(~.8f), y=depth(~.5f)

uniform half4 e_weights;  // x=norm, y=depth

uniform half4 e_kernel;   // x=norm, y=depth



/////////////////////////////////////////////////////////////////////

half4 main(v2p I) : COLOR

{

// Normal discontinuity filter

half3 nc = tex2D(s_normal, I.tc0);

half4 nd;

nd.x = dot(nc, (half3)tex2D(s_normal, I.tc1));

nd.y = dot(nc, (half3)tex2D(s_normal, I.tc2));

nd.z = dot(nc, (half3)tex2D(s_normal, I.tc3));

nd.w = dot(nc, (half3)tex2D(s_normal, I.tc4));

nd -= e_barrier.x;

nd = step(0, nd);

half ne = saturate(dot(nd, e_weights.x));



// Opposite coords



float4 tc5r = I.tc5.wzyx;

float4 tc6r = I.tc6.wzyx;



// Depth filter : compute gradiental difference:

// (c-sample1)+(c-sample1_opposite)

half4 dc = tex2D(s_position, I.tc0);

half4 dd;

dd.x = (half)tex2D(s_position, I.tc1).z +

        (half)tex2D(s_position, I.tc2).z;

dd.y = (half)tex2D(s_position, I.tc3).z +

        (half)tex2D(s_position, I.tc4).z;

dd.z = (half)tex2D(s_position, I.tc5).z +

        (half)tex2D(s_position, tc5r).z;

dd.w = (half)tex2D(s_position, I.tc6).z +

        (half)tex2D(s_position, tc6r).z;

dd = abs(2 * dc.z - dd)- e_barrier.y;

dd = step(dd, 0);

half de = saturate(dot(dd, e_weights.y));



// Weight



half w = (1 - de * ne) * e_kernel.x; // 0 - no aa, 1=full aa



// Smoothed color

// (a-c)*w + c = a*w + c(1-w)

float2 offset = I.tc0 * (1-w);

half4 s0 = tex2D(s_image, offset + I.tc1 * w);

half4 s1 = tex2D(s_image, offset + I.tc2 * w);

half4 s2 = tex2D(s_image, offset + I.tc3 * w);

half4 s3 = tex2D(s_image, offset + I.tc4 * w);

return (s0 + s1 + s2 + s3)/4.h;

}


Два детектора были затем умножены для получения единого значения, указывающего, насколько текущий пиксель "выглядит как край". Эта величина была использована, чтобы совместить выборку из четырех билинейных текстур в композит заднего буфера. Результатом было автоматическое взвешивание выборок с очень сильной политикой обнаружения краев, которое легко обрабатывает края и alpha-test/texkill неровности без размытия других частей
изображения.

Есть одно примечание к этому способу: параметры/разделители, которые настраивают для одного разрешения, не обязательно работают хорошо на другом; хуже того, они часто не работают вообще. Это потому, что чем меньше разрешение, тем больше исходного сигнала теряется во время дискретизации и размытия, становится хуже приближение фильтра сглаживания. В результате вы получите всё больше и больше ложных срабатываний, и
изображение визуально будет становится более размытым, чем необходимо. Однако,понижение радиуса размытия согласно разрешению даст хороший результат.
nuan
Цитата
Есть одно примечание к этому способу: параметры/разделители, которые настраивают для одного разрешения, не обязательно работают хорошо на другом; хуже того, они часто не работают вообще. Это потому, что чем меньше разрешение, тем больше исходного сигнала теряется во время дискретизации и размытия, становится хуже приближение фильтра сглаживания. В результате вы получите всё больше и больше ложных срабатываний, и
изображение визуально будет становится более размытым, чем необходимо. Однако,понижение радиуса размытия согласно разрешению даст хороший результат.

Не ну это то понятно .. 800х600 ... не катит...
Haper
Давным давно все подробности описаны:
http://www.gamedev.ru/community/gamedev_le...cles/r_e_n_de_r
K.D.
Познавательно: http://http.developer.nvidia.com/GPUGems2/..._chapter09.html
scwosh
Цитата(K.D. @ 21.10.2012, 04:18) *


Ага, в шапке перевод части статьи.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Форум IP.Board © 2001-2024 IPS, Inc.