Mr.Sталин Опубликовано 12 декабря, 2015 Опубликовано 12 декабря, 2015 Есть тут гении кто разбирается в написании пиксельных шейдеров?т.е. вот в такой вот лабуде string texname1 = "weather\\mask-inv.png"; texture tex1; string texname2 = ""; texture tex2; static const float tscale=3; int tickcount; float multi; float speed; sampler s0; sampler s1 = sampler_state { texture = <tex1>; }; sampler s2 = sampler_state { texture = <tex2>; addressu=wrap; addressv=wrap; }; float4 ps_p0(float2 tex : TEXCOORD0) : COLOR0 { float3 r1=tex2D(s0, tex); float offset=(float)tickcount/speed; float2 y={0.342, 0.940}; y*=offset; float3 r2=tex2D(s2, tex*tscale-y)*tex2D(s1, tex)*multi; float alpha=r2.g; r1=r1*(1-alpha) + r2*alpha; return float4(saturate(r1), 1); } technique T0 { pass P0 { PixelShader = compile ps_2_0 ps_p0(); } } 1
Mr.Sталин Опубликовано 13 декабря, 2015 Автор Опубликовано 13 декабря, 2015 В общем в чем суть, есть идея реализовать аля HUD в Fallout2 и нужно написать анимированный шейдер появление/затухание текстуры(картинки) - и вообще мне неизвестно возможно ли реализовать анимацию посредством шейдера. Вот в чем вопрос? Я написал анимацию скриптово, работает но не так как хотелось.вот че получилось, правда анимация зафрапсилась не так плавно как в игре.https://yadi.sk/i/ykqJIpBpmC3UD 2
Foxx Опубликовано 13 декабря, 2015 Опубликовано 13 декабря, 2015 Я не сразу понял. Но потом увидел знак радиации.Для записи Bandicam лучше использовать. 1
Pyran Опубликовано 13 декабря, 2015 Опубликовано 13 декабря, 2015 аналогично, Foxxи поджать free videojoiner'om Fallout 2: Путеводитель по модам | FAQ | Перевод модов | Путеводитель по RP Nevada Band: Путеводитель по играм серии | FAQ Fallout Tactics: Путеводитель по модам | FAQ База Данных: YD\YD\MF Цитата: "Помогая другим, не забывай о себе..."
Mr.Sталин Опубликовано 14 декабря, 2015 Автор Опубликовано 14 декабря, 2015 выкладываю сделанные наработки аля HUD исходники F2_HUDреализовано две пиктограммы, радиация и биологическая опасность.скрип вполне рабочий, но его еще нужно отшлифовать.включается пиктограммы из любого скрипта в игре такими строчками:set_sfall_global("RAD_SHEN", 6); - вкл. значка радиации. set_sfall_global("BIO_SHEN", 6); - вкл. значка биолог. заражения. цифра 6 это то сколько раз раз будет мигать значек. если кто дружит со скриптами то может с легкостью реализовать к примеру в неваде отображение значка радиации вместо(или вместе с) "пикаюшего" звука.а я пойду дальше пилить свое чудо) демонстрация (на видео анимация выглядит тормознутой, но в игре выглядит отлично) 2
Necrys Опубликовано 15 декабря, 2015 Опубликовано 15 декабря, 2015 Написать шейдер можно, если знать, что мы можем получить из движка. Я с sfall не знаком просто. Вот этот вот шейдер в #1 например, он вообще о чём?
Mr.Sталин Опубликовано 15 декабря, 2015 Автор Опубликовано 15 декабря, 2015 Написать шейдер можно, если знать, что мы можем получить из движка. Я с sfall не знаком просто. Вот этот вот шейдер в #1 например, он вообще о чём?с движка игры ничего не получишь там же нет никаких 3d объектов.можно только параметры передавать из скипта игры в шейдер. грубо говоря этот шейдер берет картинку(текстуру) и накладывает ее поверх изображения игры, типа оверлей. и одновременно анимирует ее, т.е. сдвигает ее по диагонали - вот этим кодомfloat offset=(float)tickcount/speed;float2 y={0.342, 0.940};y*=offset; я пару дней пытался вникнуть и разобраться в систему шейдеров, но для без хорошего учебника для новичков и практики многое не понятно.
Necrys Опубликовано 16 декабря, 2015 Опубликовано 16 декабря, 2015 с движка игры ничего не получишь там же нет никаких 3d объектов. можно только параметры передавать из скипта игры в шейдер. Ну, я про параметры и говорил. То есть например, нам нужен будет некий параметр контролирующий уровень прозрачности твоего HUD. Для более сложной анимации, сопряжённой например с переключениями кадров анимации - шейдер не годится. Наверное такое лучше делать из скрипта. Разобраться в системе шейдеров конечно мне как уже знающему человеку, кажется довольно просто. Задавай вопросы, попробую на них тебе ответить. Я сейчас прокапитаню базовые вещи, наверное они тебе известны. В базе - пиксельный (иногда называемый - фрагментный) шейдер - некая программа, отвечающая за цвет пикселя при отрисовке. В простейшем виде - за цвет пикселя на экране. Если у нас экран с разрешением 1920х1080, получаем 2073600 пикселей, соответственно столько раз будет вызван шейдер - по разу на пиксель. На вход пиксельного шейдера подаются данные с конвейера (в твоём примере - float2 tex : TEXCOORD0) - они вообще говоря могут иметь самый разный смысл, но в твоём случае - это текстурные координаты - т.е. указание - из какой части текстуры взять данные о цвете. Плюс, из шейдера есть доступ к глобальным данным - т.н. uniforms. У тебя это tickcount, multi, speed. Я так понимаю, их в sfall можно подать из скрипта? Дальше, чего ты там хочешь со всей этой ботвой, то и делаешь. Любая математика. Главное что на выходе шейдера ты получаешь некоторый вектор float4, обозначающий интенсивность цветовых компонентов пикселя. (r, g, b, a). Цифры должны находиться в диапазоне [0.0; 1.0], 0.0 - нулевая интенсивность, 1.0 - полная интенсивность. Цифры за пределами этих диапазонов имеют смысл только при промежуточных расчётах, либо при наличии HDR (чего в sfall врядли есть). 1
Mr.Sталин Опубликовано 16 декабря, 2015 Автор Опубликовано 16 декабря, 2015 Для более сложной анимации, сопряжённой например с переключениями кадров анимации - шейдер не годится. Наверное такое лучше делать из скрипта.Плюс, из шейдера есть доступ к глобальным данным - т.н. uniforms. У тебя это tickcount, multi, speed. Я так понимаю, их в sfall можно подать из скрипта?то есть простое мигание значка шейдером не сделать да? tickcount - это какая-то внутренняя фигня.multi, speed - это параметры которые можно передать из скрипта, multi - уровень прозрачности. а как действует техники technique T0 - я сюда подставлял blur, и чето никакого эффекта. float2 y={0.342, 0.940} - а как вот это понимать? float alpha=r2.g и вот это, я так понимаю берется цвет зеленых пикселей? семплеры s0 - сюда я так понимаю заносится изображение с экрана да?s1 - здесь у нас маска, чтобы выводить картинку в определенный участок экрана, а можно как-нибудь это выводить без маски? а то текстура покрывает все изображение на экране s2 - здесь сама текстура нашей картинки. addressu=wrap;addressv=wrap;тут тоже вопрос? убирал эти строчки никакого эффекта не заметил. и еще вот с другого шейдера примерColor = tex2D( s0, float2(Tex.x, Tex.y));Tex.x, Tex.y - c этого что мы получаем?
Necrys Опубликовано 16 декабря, 2015 Опубликовано 16 декабря, 2015 то есть простое мигание значка шейдером не сделать да?Ну как, управляя прозрачностью - можно. Это я так понимаю, можно сделать управляя из скрипта, параметром multi. а как действует техники technique T0 - я сюда подставлял blur, и чето никакого эффекта. Насколько я вижу, это всё использует интерфейсы DirectX 9. Техника в данном случае - набор пассов, каждый пасс - рендер сцены с шейдером, с каким - указано внутри пасса. Опять же я не знаю, насколько гибко сделан sfall, возможно у пользователя нет возможности управлять техниками и пассами и здесь это - чистая формальность. float2 y={0.342, 0.940} - а как вот это понимать? В первом случае просто создаётся двумерный вектор с заданными значениями. В дальнейшем он используется для сдвига текстурных координат. Тут надо расплыться текстом про текстурные координаты и вообще выборку. Выборка цвета из текстурки берётся по координатам вот таким макаром по координатам (0.0, 0.0) берётся верхний левый угол текстуры, по координатам (1.0, 1.0) - нижний правый. Промежуточные значения - соответственно где-то в середине текстуры. Если значения координат поданные в tex2D выходят за эти рамки - выборка регулируется вот этими параметрами в семплере: addressu=wrap; addressv=wrap; В данном случае написано, чтобы текстура повторялась. Так же возможно значение clamp - при выходе за границы - будет взято пограничное значение. mirror - текстура будет повторяться, но зеркально. В конечном итоге, физический смысл при расчётах далее float2 y={0.342, 0.940} - сдвиг координат на треть по горизонтали и почти на целую текстуру по вертикали. float alpha=r2.g и вот это, я так понимаю берется цвет зеленых пикселей? Тут у нас берётся зелёная компонента цвета, рассчитанного здесь float3 r2=tex2D(s2, tex*tscale-y)*tex2D(s1, tex)*multi; Чо это всё значит. tex2D(s2, tex*tscale-y) в этой части, берётся цвет из семплера s2, который соответствует текстуре string texname2 = ""; <- кстати - где путь? texture tex2; Цвет берётся по координатам tex*tscale-y - вектор tex покомпонентно умножен на число tscale, и из него вычтен вектор y. Физически это значит что картинку увеличили в 3 раза и сдвинули (см выше - как) семплеры s0 - сюда я так понимаю заносится изображение с экрана да? s1 - здесь у нас маска, чтобы выводить картинку в определенный участок экрана, а можно как-нибудь это выводить без маски? а то текстура покрывает все изображение на экране s2 - здесь сама текстура нашей картинки. addressu=wrap; addressv=wrap; тут тоже вопрос? убирал эти строчки никакого эффекта не заметил. Смотри, про семплер вообще говоря. Семплер - это не текстура сама по себе, это некоторая фигня, которая делает выборку цвета из текстуры (семплит, ага). У неё есть настройки - вот эти addressu, addressv, ещё есть другие вещи, типа фильтрации, мипмэпинга, но это потом, если понадобится, в 2D вообще говоря плохо применимо. Про значения этих addressu я написал выше. И есть настройка texture - вот это собственно текстура. Семплер s0 вероятно захардкожен и в нём всегда текстура, содержащая уже отрисованную основную сцену. Когда ты потом в коде шейдера пишешь tex2D(s1, tex) - это значит - "семплер s1, дай мне цвет из своей texture по координатам tex" Скорей всего, тебе чтобы рисовать без маски, т.е. чтобы текстура не повторялась - достаточно будет применить в семплере s1 параметры addressu = clamp; addressv = clamp; а s2 и соответственно выборку из неё вообще убрать нафиг. и еще вот с другого шейдера пример Color = tex2D( s0, float2(Tex.x, Tex.y)); Tex.x, Tex.y - c этого что мы получаем? Здесь взяли значения x и y компонент вектора Tex, создали из этого 2-мерный вектор, который используется как координаты при выборке из текстуры. И тут кстати надо рассказать про то насколько тут шейдерный язык удобен в некоторых моментах. Например, у тебя есть вектор float4 myVector = {1.0, 2.0, 3.0, 4.0}; т.е. тут создан вектор где x = 1.0, y = 2.0, z = 3.0, w = 4.0 и ты можешь где-нибудь потом написать float2 my2DVector = myVector.xy; и будет создан 2-мерный вектор, у которого x = myVector.x, y = myVector.y более того, можно написать следующую несусветицу float2 my2DVector = myVector.yx; и будет вектор с x = myVector.y, y = myVector.x такие дела. Нифигасе портянка получилась... 1
Mr.Sталин Опубликовано 16 декабря, 2015 Автор Опубликовано 16 декабря, 2015 Ну как, управляя прозрачностью - можно. Это я так понимаю, можно сделать управляя из скрипта, параметром multi.ну вот так у меня и есть, но может есть какой способ анимировать из шейдера, ведь строчка float offset=(float)tickcount сдвигает текстуру без управления из скрипта, может и на прозрачность можно что-то повесить. Насколько я вижу, это всё использует интерфейсы DirectX 9. Техника в данном случае - набор пассов, каждый пасс - рендер сцены с шейдером, с каким - указано внутри пасса. Опять же я не знаю, насколько гибко сделан sfall, возможно у пользователя нет возможности управлять техниками и пассами и здесь это - чистая формальность.В другом шейдере было использовано blur, но может действительно оно формально. sampler s0; static const float2 rcpres = { 0.0015625, 0.0020833333333333333333333333333333 }; float4 Blur(float2 Tex : TEXCOORD0) : COLOR0 { float4 Color = 0; Color += tex2D( s0, float2(Tex.x, Tex.y)); Color += tex2D(s0, float2(Tex.x + rcpres.x, Tex.y)); Color += tex2D(s0, float2(Tex.x - rcpres.x, Tex.y)); Color += tex2D(s0, float2(Tex.x, Tex.y + rcpres.y)); Color += tex2D(s0, float2(Tex.x, Tex.y - rcpres.y)); return Color * 0.2; } float4 Blind(float2 Tex : TEXCOORD0) : COLOR0 { float4 Color = tex2D(s0, Tex); return Color * saturate(1.5 - (length(Tex - 0.5)*2)); } Technique blur { Pass P0 { PixelShader = compile ps_2_0 Blur(); } Pass P1 { PixelShader = compile ps_2_0 Blur(); } Pass P2 { PixelShader = compile ps_2_0 Blur(); } Pass P3 { PixelShader = compile ps_2_0 Blur(); } Pass P4 { PixelShader = compile ps_2_0 Blur(); } Pass P5 { PixelShader = compile ps_2_0 Blind(); } } string texname2 = ""; <- кстати - где путь? Цвет берётся по координатам tex*tscale-y - вектор tex покомпонентно умножен на число tscale, и из него вычтен вектор y. Физически это значит что картинку увеличили в 3 раза и сдвинули (см выше - как)путь в скрипте задается, но это не важно.данном случае уменьшили в 3 раза.а вообще шейдер сейчас немного по другому выглядит. string texname1 = "scrmask1.png"; texture tex1; string texname2 = "biowarn.png"; texture tex2; static const float tscale=13; float multi; sampler s0; sampler s1 = sampler_state { texture = <tex1>; }; sampler s2 = sampler_state { texture = <tex2>; }; float4 ps_p0(float2 tex : TEXCOORD0) : COLOR0 { float3 r1=tex2D(s0, tex); float2 y={0.342, 0.940}; y*=0.25; //offset; float3 r2=tex2D(s2, tex*tscale-y)*tex2D(s1, tex)*multi; float alpha=r2.g; r1=r1*(1-alpha) + r2*alpha; return float4(saturate(r1), 1); } technique T0 { pass P0 { PixelShader = compile ps_2_0 ps_p0(); } } Скорей всего, тебе чтобы рисовать без маски, т.е. чтобы текстура не повторялась - достаточно будет применить в семплере s1 параметрыaddressu = clamp;addressv = clamp; а s2 и соответственно выборку из неё вообще убрать нафиг.ты наверное имел ввиду применить к s2 ?а почему я убирал эти строчки но текстура все равно повторялась, ладно пойду практиковаться и попробую применить clamp.а как вывести картинку в определенные координаты, так-то я маской определял положение и подстраивал картинку смешением через y*=0.25; //offset upd: clamp помог, но теперь появляется какая-то малозаметная(полупрозрачная) вертикальная полоса от картинки на весь экран.видимо от того что в png нет альфа канала? и еще как работать с альфа каналом в png?
Necrys Опубликовано 16 декабря, 2015 Опубликовано 16 декабря, 2015 ну вот так у меня и есть, но может есть какой способ анимировать из шейдера, ведь строчка float offset=(float)tickcount сдвигает текстуру без управления из скрипта, может и на прозрачность можно что-то повесить.Ну, да, скорей всего tickcount даёт какую-то цифру времени прошедшего со старта игры. В некоторых тиках. Цифра условная, но постоянно растёт. Беда в том, что мы непосредственно в шейдере не можем сохранить данные на будущие вызовы, т.е. не можем замерить время между вызовами и поменять прозрачность относительно этого. Поэтому ручное управление из скрипта подходит больше. В другом шейдере было использовано blur, но может действительно оно формально.Здесь Blur() - это название функции - точки входа шейдера. Своеобразный main(). называться такая функция может как угодно. Главное чтобы она была в файле и была прописана в пассе. В этом шейдере кстати обрати внимание, несколько пассов, каждый делает blur, кроме последнего. Каждый пасс - проход рендера картинки, в первом пассе s0 - просто отрисованная сцена, в каждом последующем - в s0 лежит результат предыдущего пасса. То есть работает это так. В пассе делаются вызовы для всех пикселей экрана, получается некоторый результат. Он складывается в текстуру, и отрисованный результат предыдущего пасса можно получить из s0. И так далее. путь в скрипте задается, но это не важно.данном случае уменьшили в 3 раза.а вообще шейдер сейчас немного по другому выглядит.Да, точно, уменьшили в 3 раза. Ошибся. ты наверное имел ввиду применить к s2 ?Да, к s2. Короче к тому семплеру, который берёт из текстуры со значком. а почему я убирал эти строчки но текстура все равно повторялась, ладно пойду практиковаться и попробую применить clamp.Когда ничего не задаётся целенаправленно - используется настройка по умолчанию. Тут по умолчанию видимо стоит wrap. а как вывести картинку в определенные координаты, так-то я маской определял положение и подстраивал картинку смешением через y*=0.25; //offsetПридётся заморочиться. У тебя на входе шейдера есть float2 tex : TEXCOORD0. Изначально - это координаты для выборки из s0. В диапазоне (0.0, 0.0) - (1.0, 1.0). Зная разрешение экрана и эти координаты, мы можем вычислить - для какого пикселя на экране сделан вызов шейдера и относительно этих данных, прикинуть, какие текстурные координаты нам надо выдернуть из s2. Далее распишу на примерных числах, дальше сам подгонишь. // позиция иконки в экранных координатах const float2 icon_position = {32, 32}; // размер иконки в экранных координатах const float2 icon_size = {64, 64}; // разрешение экрана - подаём из скрипта float2 screen_resolution; float4 ps_main(float2 tex : TEXCOORD0) : COLOR0 { // коэффециент преобразования из экранных координат в текстурные float2 ratio = 1.0f / screen_resolution; // сдвиг текстурных координат иконки float2 shift = icon_position * ratio; // масштабирование текстурных координат иконки float2 scale_factor = icon_size * ratio; // берём цвет из уже отрисованной сцены float4 base_color = tex2D(s0, tex); // берём цвет из текстуры иконки float4 icon_color = tex2D(s2, (tex - shift) / scale_factor); // считаем итоговый цвет по формуле аддитивного блендинга float4 result_color = icon_color * (1.0f - icon_color.a) + base_color * icon_color.a; return float4(saturate(result_color.rgb), 1.0f); } Чёто так вроде. Вообще говоря, оптимизируя - ratio, shift и scale_factor лучше посчитать предварительно, ещё в скрипте и в шейдер уже подать готовые значения. icon_position и icon_size соответственно тоже можешь подать из скрипта, а не забивать их константами. Вот эта хреновина(tex - shift) / scale_factorв выборке из s2 - и есть вот этот пересчёт - как из текстурных координат tex получить координаты в s2. 1
Mr.Sталин Опубликовано 16 декабря, 2015 Автор Опубликовано 16 декабря, 2015 Ну, да, скорей всего tickcount даёт какую-то цифру времени прошедшего со старта игры.этот tickcount вообще никак не связан с игрой, это что-то шейдерное.да плохо что нельзя. ну да ладно. Придётся заморочиться. Я уже немного разобрался просто пишу в строке float2 y={0.342, 0.940} значения и картинка сдвигается куда надо, правда это никак не привязано к разрешению экрана. С полоской тоже разобрался и убрал - оказывается clamp крайние пиксели в текстуре дублировал(растягивал) на весь экран.а есть еще что-нибудь кроме clamp и wrap? ладно буду мозговать) спасибо за разъяснения. // считаем итоговый цвет по формуле аддитивного блендингаfloat4 result_color = icon_color * (1.0f - icon_color.a) + base_color * icon_color.a;эту строку ты сам написал или взял с какого-то примера. не работает она правильно.
Necrys Опубликовано 16 декабря, 2015 Опубликовано 16 декабря, 2015 а есть еще что-нибудь кроме clamp и wrap?Есть mirror - текстура повторяется но зеркально есть bordercolor, там тупо цвет идёт, за пределами текстуры, надо сам цвет ещё в семплер задавать. эту строку ты сам написал или взял с какого-то примера. не работает она правильно.На память писал. И естественно накосячил. Должно быть так: float4 result_color = base_color * (1.0f - icon_color.a) + icon_color * icon_color.a;
Mr.Sталин Опубликовано 16 декабря, 2015 Автор Опубликовано 16 декабря, 2015 есть bordercolor, там тупо цвет идёт, за пределами текстуры, надо сам цвет ещё в семплер задавать. float4 result_color = base_color * (1.0f - icon_color.a) + icon_color * icon_color.a;хм, а это нормально что clamp заливает экран за пределами текстуры цветом с краев текстурыможет мне bordercolor надо было писать а цвет указать черный. это я уже понял что ты перепутал местами base_color), но тут косяк в том, что не хочет оно работать с альфой icon_color.aне видит оно альфу в png в белый цвет отрисовывается.
Рекомендуемые сообщения
Для публикации сообщений создайте учётную запись или авторизуйтесь
Вы должны быть пользователем, чтобы оставить комментарий
Создать аккаунт
Зарегистрируйте новый аккаунт в нашем сообществе. Это очень просто!
Регистрация нового пользователяВойти
Уже есть аккаунт? Войти в систему.
Войти