Войти
ПрограммированиеФорум2D графика и изометрия

Блендинг по альфа-маске в Direct3D (3 стр)

Страницы: 1 2 3 4 Следующая »
#30
23:45, 28 дек 2013

x
> Хотя ты сделай нормальный порог, не 00, а там 0x00000020 какие-нибудь. Чтобы точно убедиться.
Убедился. Увы, так и есть: при пороге 0x00000060 блик выводится целиком, а при пороге 0x00000070 целиком не выводится. Получается, что альфа блика где-то между и т.к. она одинаковая во всех точках спрайта, то альфа тест рубит его либо целиком, либо вообще не рубит.

Я почитал тут: http://msdn.microsoft.com/en-us/library/windows/desktop/bb172254%… vs.85%29.aspx
Альфа-тест это, типа, штука для того, чтобы сэкономить на блендинге пикселя, поэтому он проводится раньше него.

#31
6:51, 29 дек 2013

x
Жжошь. То есть мои рассчеты с пониманием где именно работает не так (который кстати решил проблему для тех мест, где они проводились) - это метод тыка.
А вот это:
> Хотя ты сделай нормальный порог, не 00, а там 0x00000020 какие-нибудь. Чтобы точно убедиться.
Это не метод тыка, да?


Kozinaka
В общем подумал что нам надо более внимательно, и пришел к выводу что нам это не сделать на блендинге. Для внутренней части нам нужен INVSRCALPHA на dest, а для внешней - ONE.
1. Так что увы, остается мультитекстурирование (напомни почему ты не хочешь его использовать)
2. Рендер в стенсил буфер с альфатестом твоей маски, чтобы потом по ней резать

#32
9:32, 29 дек 2013

MrShoor
> Это не метод тыка, да?
Как будто метод тыка, это что-то негодяйское. Иногда бывает совсем не лишним ткнуть для верности. :)

> В общем подумал что нам надо более внимательно, и пришел к выводу что нам это не сделать на блендинге.
На самом деле для бликов может подойти и аддитивное наложение. Это же, по сути, отражение на стекле окружения и, больше всего, источников света с потолка, поэтому лёгкое свечение может быть вполне уместно. А общего уровня, равномерно  высветляющего подложку на спрайте не будет. На моих картинках он тестовый. Будет полностью прозрачный спрайт с редкими светлыми полосами. Так чтобы они относительно неожиданно появлялись и проползали по стелку при движении камеры.

Итого, количество методов для вывода по альфа-маске более чем достаточно:

1. Мультитекстурирование.

2. Аддитивное наложение при получившимся в процессе обсуждения подходе. Остаётся прозрачность на накладываемом спрайте, но наложение аддитивное.

3. Наложение без прозрачности, если тупо использовать альфу из DEST. Это у меня случай извращенский - мне "стекло" на "стекло" надо накладывать.
В большинстве случаев сработает метод отсюда: http://stackoverflow.com/questions/5097145/opengl-mask-with-multiple-textures

4. Пиксельный шейдер. Возможно, если использовать ещё и вертексный шейдер, то всю логику наложения бликов можно в одном батче реализовать внутри шейдеров. Я в этом пока не силён, да и сложно в этом случае разделить графический движок от отрисовщика сцены, поэтому оставляю для себя это последним вариантом.

5. Рендер в стенсил буфер с альфатестом маски. Но обрезание попиксельное, поэтому в целом решение грубоватое.

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

Плюс немного смущает, что мне нужно расширить формат вершины двумя лишними float'ами, которые реально нужны в 5% случаев отрисовки эффектов.

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

В целом, недостатки мультитекстурирования в моём случае не такие уж и серьёзные. Поэтому если не подойдёт аддитивное наложение бликов, то заряжу всё через мультитекстурирование.

#33
10:59, 29 дек 2013

Я не знаю, это еще нужно постараться, чтобы найти карточку, не поддерживающую мультитекстурирование. Это карточки произведенные в конце 90-х примерно. :)
А вообще я бы конечно на шейдеры переписал. Во первых FFP сейчас все равно эмулируется шейдерами. Во вторых - у тебя бы появилась шикарная гибкость в способах отрисовки. Тебе не придется жонглировать стейтами, как приходится это делать сейчас. Заморачиваться с какими-то премульт альфами, и прочей магией.
Я когда первый раз изучал шейдеры - тоже их не понимал и боялся. Сейчас пишу код только на шейдерах, а FFP использую максимум только для рендера дебагинфы.

#34
11:31, 29 дек 2013

MrShoor
> Сейчас пишу код только на шейдерах, а FFP использую максимум только для рендера дебагинфы.
В целом согласен, если железо хоть сколько-нибудь современное, то там будет и мультитекстурирование и шейдеры, а со вторыми работать гораздно гибче (если только тему прорубить). На старом железе всё равно придётся убирать эффекты, для которых все эти балалайки требуются.

Попробую в вершинном шейдере рассчитывать отрисовываемый фрагмент из спрайта бликов в зависимости от положения на экране.

#35
21:28, 29 дек 2013

MrShoor
>То есть мои рассчеты с пониманием где именно работает не так
Там не было понимания. Замена обычного блендинга на аддитивный это не есть понимание.

>Это не метод тыка, да?
Вряд ли. У автора в альфе черный цвет не был черным, во всяком случае на приведенном скриншоте.

#36
21:40, 29 дек 2013

x
> Там не было понимания. Замена обычного блендинга на аддитивный это не есть
> понимание.
То есть у автора фон вокруг затемнялся, я провел рассчеты и наобум угадал как сделать так, чтобы окружение не затемнялось? И причем тут аддитивный и понимание? Аддитивный блендинг - это блендинг, понимание - это понимание. Что за чушь ты несешь? Я с таким же успехом могу сказать, что ник x - это не есть наличие интеллекта. :) Вот и ищи логику.

#37
21:58, 29 дек 2013

MrShoor
Ясно.

#38
22:45, 29 дек 2013

MrShoor, x, не ругайтесь, пожалуйста.
Помогите, если не сложно, с шейдерами, а то застрял, как на грех, на самом начале.

Мой вершинный шейдер просто игнорируется и чтобы я из него не передавал, в пиксельный ничего не приходит.
Вот он:

struct VertexInput
{
  float4 Position : POSITION;
  float2 TexCoord : TEXCOORD0;
};

struct VertexOutput
{
  float4 Position : POSITION;
  float2 TexCoord : TEXCOORD0;
  float2 Shift : TEXCOORD1;
};

VertexOutput main(VertexInput input)
{
  VertexOutput output;

  output.Position = input.Position;
  output.TexCoord = input.TexCoord;
  //output.TexCoord.x = 0.3;
  //output.TexCoord.y = 0.3;
  output.Shift.x = 0.5;
  output.Shift.y = 0.5;

  return output;
}

А вот пиксельный:

sampler BlinkTexture : register(s0);
sampler MaskTexture : register(s1);

float4 main(float2 texCoord : TEXCOORD0, 
      float2 shift : TEXCOORD1) : COLOR0
{  
  //Сдвиг текстурных координат блика
  float2 blinkTex = texCoord;
  blinkTex.x = blinkTex.x + shift.x;
  blinkTex.y = blinkTex.y + shift.y;

  float4 blink = tex2D(BlinkTexture, blinkTex);

  float4 mask = tex2D(MaskTexture, texCoord * 2 /* блик в два раза растянут */);

  return float4(  blink.r, blink.g, blink.b, 
          blink.a * mask.a);
}

В параметре shift - (0, 0) чем его не заряжай, причём даже если в вершинном шейдере output.TexCoord.x и y в константы выставлять то это ни на что не влияет.
Устанавливается вершинный шейдер успешно, но такое ощущение, что работает всё равно дефолтовый.

_d3dDevice->SetVertexShader(_blinkVertexShader) -> S_OK.

А с пиксельным всё хорошо, он работает как надо. Вот только ничего не получает дополнительного.
У меня в коде шейдеров ошибка или я где-то в их подключении туплю?

#39
22:54, 29 дек 2013

P.S. А формат вершины в вершинном буфере у меня такой:

struct Vertex
{
  float x;
  float y;
  float z;
  float rhw;
  D3DCOLOR colour;
  float u;
  float v;
};

Может иметь значение, что я его не повторяю точно во входных данных вершинного шейдера?

#40
5:38, 30 дек 2013

Имеет значение как ты заполнил декларации. Гугли D3DVERTEXELEMENT9

#41
10:59, 30 дек 2013

Скажи пожалуйста, а я могу не используя _d3dDevice->SetVertexDeclaration просто подогнать входные параметры вершинного шейдера под формат моих вершин в вершинном буфере (в моём предыдущем посте) выставленного с помощью _d3dDevice->SetFVF?

Сейчас я вот так пытаюсь подключать свой вершинный шейдер:

D3DVERTEXELEMENT9 vertexElement[] =
{
    {0, 0,  D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT,
        D3DDECLUSAGE_POSITION, 0},
    {0, 16, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT,
        D3DDECLUSAGE_TEXCOORD, 0},
    D3DDECL_END()
};

IDirect3DVertexDeclaration9* _decl = 0;
HRESULT res = _d3dDevice->CreateVertexDeclaration(vertexElement, &_decl);
_d3dDevice->SetVertexDeclaration(_decl);

_d3dDevice->SetVertexShader(_blinkVertexShader);

Эта тема и сама, по ходу, не работает и рушит весь FFP вывод с прозрачностью (хотя я там убираю шейдеры и вызываю обратно SetFVF). :(

Кстати, если всё-таки использовать CreateVertexDeclaration, то вершинный буфер тоже нужно соответствующий для шейдеров создавать?

#42
11:24, 30 дек 2013

SetFVF плох тем привязывает тебя к четкому порядку данных в вершине, а так же ограниченным кол-вом данных.
Вот тут описано, как автоматически мапится/анмапится SetFVF на VertexDeclaration.
Но я бы от SetFVF уходил, ибо он ограничивает в гибкости.

Суммируя:
Для твоего формата вершин:

struct Vertex
{
  float x;
  float y;
  float z;
  float rhw;
  D3DCOLOR colour;
  float u;
  float v;
};

константа в SetFVF должна быть обязательно такой: D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1

Но в шейдере ты хочешь оперировать еще одной текстурной координатой. Соответственно твоя вершина уже не подходит, и нужно менять её на:

struct Vertex
{
  float x;
  float y;
  float z;
  float rhw;
  D3DCOLOR colour;
  float u1;
  float v1;
  float v2;
  float u2;
};

и константу для SetFVF менять на: D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1 | D3DFVF_TEX2


Тот D3DVERTEXELEMENT9 vertexElement[] работать не будет, потому что для вертекса:

struct Vertex
{
  float x;
  float y;
  float z;
  float rhw;
  D3DCOLOR colour;
  float u;
  float v;
};

Он должен быть такой:

D3DVERTEXELEMENT9 vertexElement[] =
{
    {0, 0,  D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
    {0, 20, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
    D3DDECL_END()
};

потому что второй параметр - смещение от начала структуры, а утебя там D3DCOLOR colour;

#43
11:40, 30 дек 2013

Kozinaka
> Кстати, если всё-таки использовать CreateVertexDeclaration, то вершинный буфер
> тоже нужно соответствующий для шейдеров создавать?
Ну и по поводу этого вопроса. Суть VertexDeclaration - описать как у тебя данные располагаются внутри твоей структуры. Например у тебя есть стуктура:

struct Vertex
{
  float x;
  float y;
  float z;
  float some_dummy1;
  float some_dummy2;
  float u1;
  float v1;
  float some_dummy3;
  float v2;
  float u2;
};

в ней данные, которые ты хочешь в шейдере обработать, а именно координата, и две текстурные кооринаты.
Ты в VertexDeclaration указываешь смещение до данных, тип данных, семантику и индекс. Что такое смещение - я думаю понятно, это разница в указателях между адресом поля и адресом начала структуры.
Тип данных в виде D3DDECLTYPE_ я думаю тоже понятен. Чтобы DX мог понять размерность вектора в структуре и как его преобразовать к float4.
А семантика + индекс - это такая штука, чтобы разобраться какой вектор куда "присвоить" в шейдере. В принципе достаточно просто индекса, и ты можешь тупо брать и использовать скажем TEXCOORD семантику абсолютно для всего. Название же семантики тут введено только для удобства понимания.

Для вышеприведнной вершины семантика будет какая-то такая:

D3DVERTEXELEMENT9 vertexElement[] =
{
    {0, 0,  D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
    {0, 20, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
    {0, 32, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1}
    D3DDECL_END()
};

Так что суть всего этого VertexDeclaration - описать что где лежит в уже существующих форматах вершины, и понятное дело - ничего создавать не надо. Это просто правила конвертирования вершины в твоем С++ коде в стурктуру, описанную в HLSL.

#44
12:30, 30 дек 2013

Спасибо большое за подробный ответ! Исчерпывающе.

Попробую использовать только VertexDeclaration.

Страницы: 1 2 3 4 Следующая »
ПрограммированиеФорум2D графика и изометрия

Тема в архиве.