HLSL - Как настроить фильтры сэмплера Min / Mag / Mip для отключения всех фильтров / сглаживания? - PullRequest
0 голосов
/ 23 апреля 2010

У меня есть сэмплер tex2D. Я хочу вернуть только те цвета, которые присутствуют на моей текстуре. Я использую Shader Model 3, поэтому не могу использовать load .

В случае, когда тексель перекрывает несколько цветов, я хочу, чтобы он выбрал один и весь цвет был таким.

Я думаю, что для этого я хочу отключить mipmapping или, по крайней мере, трилинейную фильтрацию mips.

sampler2D gColourmapSampler : register(s0) = sampler_state {
    Texture = <gColourmapTexture>; //Defined above
    MinFilter = None; //Controls sampling. None, Linear, or Point.
    MagFilter = None; //Controls sampling. None, Linear, or Point.
    MipFilter = None; //Controls how the mips are generated. None, Linear, or Point.
    //...
};

Моя проблема в том, что я не совсем понимаю фильтрацию Min / Mag / Mip, поэтому не уверен, в какую комбинацию мне нужно их установить, или это даже то, что мне нужно.

Как выглядит часть моей исходной текстуры;
http://img689.imageshack.us/img689/6171/sourcev.png http://img689.imageshack.us/img689/6171/sourcev.png

Снимок экрана того, как выглядит соответствующая область после отображения полной текстуры на моей сфере;
http://img717.imageshack.us/img717/9202/resultc.png http://img717.imageshack.us/img717/9202/resultc.png
Артефакты сглаживания / смешивания / фильтрации хорошо видны; Я не хочу это.


MSDN имеет это сказать;

D3DSAMP_MAGFILTER: Фильтр увеличения типа D3DTEXTUREFILTERTYPE

D3DSAMP_MINFILTER: Фильтр минификации типа D3DTEXTUREFILTERTYPE .

D3DSAMP_MIPFILTER: фильтр Mipmap для использования во время минимизации. См. D3DTEXTUREFILTERTYPE .

D3DTEXF_NONE: При использовании с D3DSAMP_MIPFILTER отключает отображение.

Еще одна полезная ссылка на понимание внутренностей hlsl .


ПОСТАНОВИЛИ

Совсем не проблема HLSL! Извините все. Кажется, я задаю много вопросов, на которые невозможно ответить. Огр перешагнул через вышеуказанные настройки. Это было исправлено с помощью

Ogre::MaterialManager::getSingleton().setDefaultTextureFiltering(Ogre::FO_NONE , Ogre::FO_NONE, Ogre::FO_NONE);

Ответы [ 3 ]

2 голосов
/ 24 апреля 2010

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

MipFilter = None 

должно предотвратить это, если что-то в коде не переопределит это. Так что ищите вызовы SetSamplerState.

1 голос
/ 23 апреля 2010

То, что вы сделали, должно отключить фильтрацию. Есть 2 потенциальные проблемы, о которых я могу подумать, хотя

1) Водитель просто игнорирует вас и фильтрует в любом случае (если это происходит, вы ничего не можете сделать) 2) У вас включена некоторая форма сглаживания краев.

Глядя на ваше получившееся изображение, которое не очень похоже на билинейную фильтрацию, я думаю, что вы страдаете от того, что сглаживание где-то включено. Вы устанавливали флаг сглаживания при создании устройства / рендер-текстуры?

1 голос
/ 23 апреля 2010

Если вы хотите, чтобы на самом деле был только один тексель, используйте load вместо sample. load принимает (насколько мне известно) int2 в качестве аргумента, который указывает фактические координаты массива в текстуре. load затем просматривает запись в вашей текстуре по заданным координатам массива.

Итак, просто масштабируйте float2, например используя ceil(float2(texCoord.x*textureWidth, texCoord.y*textureHeight)).

MSDN для загрузки: http://msdn.microsoft.com/en-us/library/bb509694(VS.85).aspx

При использовании только шейдерной модели 3 вы могли бы немного взломать, чтобы добиться этого: Опять, давайте предположим, что вы знаете textureWidth и textureHeight.

// compute floating point stride for texture
float step_x = 1./textureWidth;
float step_y = 1./textureHeight;

// compute texel array coordinates
int target_x = texCoord.x * textureWidth;
int target_y = texCoord.y * textureHeight;

// round to values, such that they're multiples of step_x and step_y
float2 texCoordNew;
texCoordNew.x = target_x * step_x;
texCoordNew.y = target_y * step_y;

Я не проверял, но думаю, что это может сработать.

...