Как включить аппаратную процентную фильтрацию?

Я пытаюсь внедрить фильтрацию PCF в свои теневые карты и поэтому изменил статью о GPU Gems ( http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html ), чтобы его можно было запускать на текущих шейдерах. Модификация включает замену функции tex2Dproj на функцию Texture2D.Sample(), поэтому она принимает состояния семплера, созданные в DirectX11. Затем я сравнил значения смещения с обычным сравнением карты теней:

float2 ShTex;
ShTex.x = PSIn.ShadowMapSamplingPos.x/PSIn.ShadowMapSamplingPos.w/2.0f +0.5f;
ShTex.y = -PSIn.ShadowMapSamplingPos.y/PSIn.ShadowMapSamplingPos.w/2.0f +0.5f;
float realDistance = PSIn.ShadowMapSamplingPos.z/PSIn.ShadowMapSamplingPos.w;


(realDistance - xShBias) <= offset_lookup(xTextureSh, texSampler, ShTex, float2(x, y), scale); //Blocker-receiver comparison (the usual stuff, only that it gets 4*4 samples from near offsets then divides the final value with 16)

Теперь я получаю взамен следующее: Эффект лестницы

Где в статье сказано и показано, что железо должно волшебным образом интерполировать результаты. Я предполагаю, что tex2Dproj может это сделать, но не может заставить его работать.

Недавно я наткнулся на функцию SampleCmpLevelZero, которую я опробовал с этим состоянием сэмплера:

SamplerComparisonState cmpSampler
{
   Filter = COMPARISON_MIN_MAG_MIP_LINEAR;
   AddressU = Clamp;
   AddressV = Clamp;

   ComparisonFunc = LESS;
};

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

xTextureSh.SampleCmpLevelZero( cmpSampler, ShTex.xy, realDistance - xShBias );

К сожалению, я нашел кого-то с такой же проблемой, но ему удалось исправить ее, переписав фильтр в режим, который я уже применил.

Моя текстура глубины имеет следующий формат: DXGI_FORMAT_R24_UNORM_X8_TYPELESS.

Я сейчас в большом замешательстве из-за этой тайны относительно правильной фильтрации PCF, есть ли кто-нибудь, кто может что-нибудь подсказать? Спасибо заранее и за то, что дочитали до конца.


person János Turánszki    schedule 15.06.2013    source источник


Ответы (2)


Итак, я завершил его. Используя SampleCmpLevelZero, я попытался объявить SamplerComparisonState внутри кода HLSL, но это оказалось неисправным. Билинейная фильтрация карты теней не работала. Затем я попытался создать состояние Sampler внутри API D3D11, установив D3D11_FILTER_COMPARISON_MIN_MAG_LINEAR_MIP_POINT в качестве фильтра описания, D3D11_COMPARISON_LESS для функции сравнения описания. Внутри шейдера я объявил SamplerComparisonState вместо обычного SamplerState, и не заполнил там описание, а прописал из апи:

SamplerComparisonState compSampler:register(s2);

Затем, наконец, началось волшебство: Билинейная фильтрация с ручной выборкой сетки текселей 4*4

Как видите, вместо лестницы получается бесшовная полутень вокруг тени. Даже без ручной выборки предыдущей картинки, Мы можем добиться вполне приемлемых результатов с одной ручной выборкой (и несколькими автоматическими выборками, сделанными SampleCmpLevelZero):Один образец вручную

К сожалению, я не знаю, что вызвало сбой объявления сэмплера внутри шейдера, и мне это не нравится. Если кто-то сталкивался с чем-то подобным, я был бы рад, если бы он/она зашейдерил это вместе со мной.

Также спасибо MHGameWork за попытку помочь мне решить эту проблему.

ОБНОВЛЕНИЕ: Поскольку с момента вопроса прошло много времени, проблема объявления сэмплеров в шейдерах стала известна мне тем временем, поэтому я ставлю ее здесь: вы можете объявлять объекты сэмплера внутри шейдера, только если вы используют фреймворк эффектов. При использовании базовых шейдеров их необходимо загружать с помощью вызовов API.

person János Turánszki    schedule 17.06.2013

Из http://msdn.microsoft.com/en-us/library/windows/desktop/bb205073(v=vs.85).aspx#Mapping_Texels_to_Pixels_DX10

Координаты текстуры изменены в D3D10, вы это учитывали? Теперь они в полединицы, как пиксели (и где в D3D9).

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

Изменить: так как вы сделали это правильно :) У меня может быть другое решение:

GenerateMips молча терпит неудачу, если не может сгенерировать.
Я думаю, что невозможно сгенерировать MIP-карты для DXGI_FORMAT_R24_UNORM_X8_TYPELESS. Вы можете проверить список поддерживаемых форматов здесь: http://msdn.microsoft.com/en-us/library/windows/desktop/bb173569(v=vs.85).aspx.

person MHGameWork    schedule 15.06.2013
comment
Я переписал смещения в соответствии с этой статьей, но результат все тот же. Спасибо за предложение, хотя! - person János Turánszki; 16.06.2013
comment
Я просто подбрасываю некоторые идеи: что произойдет, если вы не используете мипмэппинг. Или, если вы используете мипмэппинг, уверены ли вы, что мипмапы сгенерированы правильно? - person MHGameWork; 16.06.2013
comment
Я уже пробовал ставить выборку точек для мип карт, пробовал линейную, но это ни на что не влияет. Также я не знаю, генерируются ли мип-карты для текстуры глубины, я уж точно не давал указаний апи генерировать их для этой текстуры. - person János Turánszki; 16.06.2013
comment
Вы должны попробовать D3D10Device::GenerateMips. Не забудьте установить rendertarget и сгенерировать MIP-флаги! =› (msdn.microsoft. com/en-us/library/windows/desktop/) - person MHGameWork; 16.06.2013
comment
Я использую D3D11, поэтому я генерировал мип-карты с контекстом устройства, а также не использовал rendertarget, а рендерил прямо в представление трафарета глубины, которое я передал шейдеру через связанное представление ресурсов шейдера. Теперь, если я использую Sample(), то сравнение глубины тени не работает на определенном расстоянии (я думаю, где оно меняет уровень мип). И все еще блочный, как показано на скриншоте выше. Если я попробую SampleCmpLevelZero(), то все равно никаких изменений, мерцание существует. - person János Turánszki; 16.06.2013
comment
Я изменил свой ответ, вы должны проверить поддерживаемые типы ресурсов. - person MHGameWork; 16.06.2013
comment
Я переделал его с помощью R32_FLOAT ShaderResourceView и получил тот же эффект, что и с R24_UNORM. Я даже пытался переключить рендеринг карты теней в текстуру с DepthStencilView-ShaderResourceView на RenderTarget-ShaderResourceView. Все равно не повезло, я начинаю чувствовать, что подвожу даже тебя. :) - person János Turánszki; 17.06.2013