Ошибка при написании очень простого пиксельного шейдера HLSL

Я пишу приложение SlimDX для проверки пороговых значений цветовой контрастной чувствительности зрительной системы человека. Испытуемому показывают большую букву, которая слабо контрастирует с фоном, и просят идентифицировать букву. Однако мне нужна возможность отображать больше цветов, чем это доступно с простой глубиной цвета 8 бит на канал. (т.е. значения RGB 0-255). Я планирую сделать это с помощью простого алгоритма «дизеринга», реализованного в виде пиксельного шейдера HLSL. В основном, если запросить slimDX для рендеринга текста на поверхность с цветом Color4 (0,55f, 0,55f, 0,55f), который соответствует значению rgb (140,25, 140,25, 140,25), я хочу, чтобы каждый цветовой канал каждого пикселя имел с вероятностью 25% будет установлено значение 141 и с вероятностью 75% будет установлено значение 140. Это должно (в пределах нескольких пикселей) привести к тому, что буква будет отображаться как оттенок серого на 1/4 длины. между 140 и 141.
Однако я получаю ошибки в коде моего прототипа шейдера при попытке компиляции с помощью fxc. При компиляции я получаю недопустимый код символа и не знаю почему. Также, если вы гуру HLSL, просмотрите мой код и сделайте любые комментарии, которые вас поразят. Обратите внимание, что я получил случайную функцию HLSL из ответа на этот вопрос. Могу ли я сгенерировать случайное число внутри пиксельного шейдера? < / а>

Ниже мой код шейдера. Пожалуйста, простите меня, если в моем первом HLSL-коде было много ошибок:

float4 DitherByChance(float2 coords : TEXCOORD0) : COLOR0
{
    float4 newColor;    // The pixel color to return
    float4 oldColor = tex2D(s0, coords);

    // Note I know that as the code stands now rCutOff = gCutOff = bCutOff I will sort a fix for this out later
    float rCutOff = random(coords);     // A random float that determines if the red channel will be rounded up or down
    float gCutOff = random(coords);     // A random float that determines if the green channel will be rounded up or down
    float bCutOff = random(coords);     // A random float that determines if the blue channel will be rounded up or down

    float rPercentChance = frac(oldColor.r * 255);  //Chance to round red channel up
    float gPercentChance = frac(oldColor.g * 255);  //Chance to round green channel up
    float bPercentChance = frac(oldColor.b * 255);  //Chance to round blue channel up

    //In the code below (1/255) is the floating point represntaion of an incress of one on the 0-255 RGB scale

    if (rCutOff <= rPercentChance) newColor.r = oldColor.r + ((1 - rPercentChance) / 255);  //Bump up one r value
    else newColor.r = oldColor.r - rPercentChance * (1 / 255);                  //Bump down to ensure r is not rounded up

    if (gCutOff <= gPercentChance) newColor.g = oldColor.g + ((1 - gPercentChance) / 255);  //Bump up one g value
    else newColor.b = oldColor.b - bPercentChance * (1 / 255);                  //Bump down to ensure g is not rounded up

    if (bCutOff <= bPercentChance) newColor.b = oldColor.b + ((1 - bPercentChance) / 255);  //Bump up one b value
    else newColor.b = oldColor.b - bPercentChance * (1 / 255);                  //Bump down to ensure b is not rounded up

    return newColor;
}

// Input: It uses texture coords as the random number seed.
// Output: Random number: [0,1), that is between 0.0 and 0.999999... inclusive.
// Author: Michael Pohoreski
// Copyright: Copyleft 2012 :-)
float random( vec2 p )
{
  // We need irrationals for pseudo randomness.
  // Most (all?) known transcendental numbers will (generally) work.
  const vec2 r = vec2(
    23.1406926327792690,  // e^pi (Gelfond's constant)
     2.6651441426902251); // 2^sqrt(2) (Gelfond–Schneider constant)
  return fract( cos( mod( 123456789., 1e-7 + 256. * dot(p,r) ) ) );  
}

РЕДАКТИРОВАТЬ: С помощью приведенного ниже ответа я немного приблизился к решению, но у меня все еще есть некоторые проблемы. Я взял комментарии catflier о том, что случайная функция, которую я позаимствовал, написана на GLSL, а не на HLSL. Мне пришлось изменить vec2 на float2 и поместить функцию random вверху. В дополнение к этому мне также пришлось написать функцию мода, потому что GLSL mod ()! = HLSL fmod. А фрактал GLSL () был заменен на HLSL frac (). У меня также была проблема, когда мой текстовый файл был закодирован с помощью UTF-8, что, как я полагаю, вызывает некоторые проблемы с fxc. После перекодирования в ANSI я смог получить более качественные сообщения об ошибках. Однако у меня все еще есть проблемы.

Я пробовал компилировать с использованием fxc /Zi /E DitherByChance DitherByChance.fx, а также fxc /Zi /E DitherByChance /LD DitherByChance.fx, потому что я нацелен на DX9, но оба раза у меня возникала следующая ошибка:

undeclared indentifier 's0' error из этой строки float4 oldColor = tex2D(s0, coords);

Я не уверен, что это за аргумент s0, я только что видел его в другом примере шейдера. Я видел другой пример, когда у кого-то была объявлена ​​глобальная переменная sampler2D и она использовалась вместо s0, поэтому я попробовал это:

sampler2D Tex0;
...
.... 
.....
float4 oldColor = tex2D(Tex0, coords); 

Однако теперь, когда я запускаю fxc /Zi /E DitherByChance /LD DitherByChance.fx, я получаю следующую ошибку:

vs_2_0 target does not support texture lookup

Любые идеи?


person Alexander Van Atta    schedule 04.10.2012    source источник


Ответы (1)


Сначала вам нужно заменить vec2 на float2 в вашей случайной функции, поскольку vec2 - это синтаксис glsl.

Затем ваша случайная функция должна быть размещена над вашим PixelShader (стиль c).

Теперь ваш шейдер должен скомпилироваться, если нет, отправьте сообщение об ошибке.

Изменить из последних битов:

sampler2D Tex0;

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

http://msdn.microsoft.com/en-us/library/windows/desktop/bb509644(v=vs.85).aspx.

Поскольку вы компилируете пиксельный шейдер, вам необходимо использовать fxc / T ps_3_0, поскольку вы компилируете как пиксельный шейдер, а не как вершинный шейдер.

person mrvux    schedule 04.10.2012
comment
У меня все еще возникают проблемы с кодом. Я отредактировал свой вопрос с более подробной информацией. - person Alexander Van Atta; 05.10.2012
comment
Отредактировал ответ и добавил еще несколько деталей. - person mrvux; 05.10.2012
comment
Ok / T ps_2_0 fixed разрешил компиляцию кода. (Я хочу использовать 2_0 для DX9, верно?). Также как привязать блок сэмплера к текстуре? Я думаю, я хочу, чтобы он не выполнял фильтрацию, потому что я просто использую класс RenderToSurface для рисования текста в текстуре, а затем использую пакет спрайтов для рисования текстуры на экране. Я не текстурирую какие-либо объекты или что-то еще. - person Alexander Van Atta; 05.10.2012
comment
Вы также можете использовать 3_0 с DX9. Вы привязываетесь к семплеру путем привязки к соответствующему блоку текстуры - person Goz; 08.10.2012