S.T.A.L.K.E.R.: Global War <<<>>> Инструмент - теперь и для ТЧ! <<<>>> NS OGSR: Сборка от 30.12.2023
-
Число публикаций
766 -
Регистрация
-
Последнее посещение
-
Дней в топе
15 -
AMKoin
187 [Подарить AMKoin]
Сообщения опубликованы Anonim
-
-
@shuherist, смотря какие шейдеры у тебя указаны в скриптовом шейдере, проходишь в пиксельный шейдер и удаляешь там макрос NEED_SOFT_WATER.
Шедейвр для воды один основной water.ps\vs, который другие(water_soft,water_studen etc...) юзают в кач-ве родительского лишь оперируя макросами.
- 1
-
- Это популярное сообщение.
- Это популярное сообщение.
Accurate Atmospheric Scattering
and
The Real-time Volumetric Cloudscapes
https://developer.nvidia.com/gpugems/GPUGems2/gpugems2_chapter16.html
https://www.guerrilla-games.com/read/the-real-time-volumetric-cloudscapes-of-horizon-zero-dawn
А почему бы нет? Отложим текстуры скайбокосов и будем генерировать небо с облаками в рилтайме. Я уже попробовал реализацию по выше предложенным статьям, моя реализация на стуклир пока что сыра и рано её публиковать в народы. Конкретно что вышло у меня в видео здесь -> https://yadi.sk/i/z43YN5FVXJUWuw
Что думаете по этому поводу, нужно ли оно вообще? Сразу скажу что мой компуктер положило до 10 фпс.
Ну и конечно давайте делитесь своими успехами по этой теме. Может быть есть более лёгкие альтернативы.
- 1
- 2
- 3
-
- Это популярное сообщение.
- Это популярное сообщение.
@DDamian724, Привет, вода в сталкере является forward'ом, как и стёкла, поэтому применить блюр к отражениям у тебя не получится без всяческих ухищрений. А адаптировать сам SSLR шейдер проще простого. Достаточно удалить функции получения позиции и нормали и заменить их на те, что есть в шейдере воды.
eye_vec у тебя уже посчитан в вершинном шейдере воды
o.v2point = P-eye_position ;
И нормализован в пиксельном шейдере
half3 v2point = normalize (I.v2point);
v2point = eye_vec
Получается вектор взгляда у тебя есть, мировая нормаль воды тоже есть в оригинальном шейдере, она так же нормализована
half3 Nw = mul (half3x3(I.M1, I.M2, I.M3), Navg); Nw = normalize (Nw);
И вектор отражения
half3 vreflect = reflect (v2point, Nw) ;
Создавай хэдер SSLR и во входных параметрах укажи vreflect вместо refl_vec.
Код примерно такой будет:
Скрытый текст#ifndef SSLR_header_h #define SSLR_header_h float3 SSLR(float3 refl_vec) { float2 refl_tc = float2(0,0);//текстурные координаты отражённой геометрии float L = sslr_params.z;// начальная длина луча for(int i = 0; i < 6; i++)// как показали тесты 6 проходов вполне достаточно для получения приемлимого результата { float3 new_pos = pos.xyz + refl_vec*L; // получаем новую позицию float4 new_pos_proj = mul(m_VP,float4(new_pos,1));//переводим её в скрин спейс new_pos_proj.xyz /= new_pos_proj.w; //нормализуем float2 sample_tc = float2(0,0);// создаём новую переменную в теле цикла, куда будем толкать новые текстурные координаты //мы получаем позицию пикселя в диапазоне от -1 до 1, это дело нам как то нужно перевести в диапазон от 0 до 1 //вот так sample_tc.x = (new_pos_proj.x+1)*0.5; sample_tc.y = 1-((new_pos_proj.y+1)*0.5); float3 hit_pos = getWSpos(sample_tc);//каждый проход цикла мы будем получать позицию, но уже с новыми текстурными координатами L=length(Hpos-pos); refl_tc=sample_tc;//отправим полученные текстурные координаты на выход } float3 refl_img=tex2D(s_image,refl_tc); return refl_img; } #endif
И в шейдере воды:
#include "SSLR_header.h" ........ half4 main(){ ........ half3 env = SSLR(vreflect); ........
- 1
- 4
-
-
- Это популярное сообщение.
- Это популярное сообщение.
Как и обещал, разбор полётов по SSLR и создание луж под ногами от всех этих махинаций.
Такс, для начала создадим новый рендер таргет формата D3DFMT_A8R8G8B8 с размерами экранного квада, этого нам будет достаточно. Ага, сделали мы уже много, а отражений всё ещё нет. Будем разбираться почему же так.
В данный РТ'шник мы будем писать/записывать/зачитывать/засовывать результат работы нашего SSLR шейдера.
Начнём, напишем основу шейдера:
#include "common.h" // подключим стандартную библиотеку с ощими функциями struct v_SQ // обычная simple quad структура с позицией и текстурными координатами // с учётом того что мы рендерим без вертексного шейдера { float4 hpos:POSITION; float2 tc0:TEXCOORD0; }; float4 main(v_SQ inst):COLOR { return float4(1,0,0,1);// пока что возвратим красный цвет }
Для расчёта вектора отражения нам нужно найти вектор взгляда на позицию пикселя и найти отражение этого вектора от нормали. И так, сначала будем искать позицию пикселя в ворлд спейсе
float3 pos = tex2D(s_position,inst.tc0); return float4(pos,1); //return float4(1,0,0,1);
Так не канает, ведь нам нужна позиция пикселя в ворлд спейсе, а не скрин спейсе. Для этого я состряпал такую функцию
float3 getWSpos(float2 tc)//текстурные координаты { float3 VSpos = tex2D(s_position,tc); // скрин спейс позиция пикселя float3 WSpos = mul(m_inverse_view,float4(VSpos,1)); // умножаем на иверсную матрицу вида проекции и получаем позицию в мировом пространстве return WSpos;// отдаём }
Теперь попробуем её
//float3 pos = tex2D(s_position,inst.tc0); float3 pos = getWSpos(inst.tc0); return float4(pos,1); //return float4(1,0,0,1);
Посмотрим
Вот так интереснее. Теперь найдём вектор взгляда на этот пиксель
float3 eye_vec = normalize(pos-eye_position);//сразу же нормализуем этот вектор
Теперь для расчёта вектора отражения нам нужно найти мировую нормаль, не буду таить и сразу выкачу функцию которая так же преобразует сс нормаль в вс
float3 getWSnorm(float2 tc) { float posZ = tex2D(s_position,tc).z;//определим глубину float3 VSnorm = tex2D(s_normal,tc);//сс нормаль float3 WSnorm = mul(m_inverse_view,float4(VSnorm,0));//находим таким же способом вс нормалю WSnorm.y *= clamp(posZ,sslr_params.x,sslr_params.y);//кое-где сгладим нормаль в зависимости от расстояния WSnorm=normalize(WSnorm);//нормализуем return WSnorm;//отдадим }
sslr_params.xy - факторы расстояния
Всё, находим вектор отражения
float3 norm = getWSnorm(inst.tc0); float3 refl_vec = normalize(reflect(eye_vec,norm));
Заранее объявим несколько переменных
float2 refl_tc = float2(0,0);//текстурные координаты отражённой геометрии float L = sslr_params.z;// начальная длина луча
Всё пускаем в бой тяжёлую артиллерию, а именно, цикл
for(int i = 0; i < 6; i++)// как показали тесты 6 проходов вполне достаточно для получения приемлимого результата { float3 new_pos = pos.xyz + refl_vec*L; // получаем новую позицию float4 new_pos_proj = mul(m_VP,float4(new_pos,1));//переводим её в скрин спейс new_pos_proj.xyz /= new_pos_proj.w; //нормализуем float2 sample_tc = float2(0,0);// создаём новую переменную в теле цикла, куда будем толкать новые текстурные координаты //мы получаем позицию пикселя в диапазоне от -1 до 1, это дело нам как то нужно перевести в диапазон от 0 до 1 //вот так sample_tc.x = (new_pos_proj.x+1)*0.5; sample_tc.y = 1-((new_pos_proj.y+1)*0.5); float3 hit_pos = getWSpos(sample_tc);//каждый проход цикла мы будем получать позицию, но уже с новыми текстурными координатами L=length(Hpos-pos); refl_tc=sample_tc;//отправим полученные текстурные координаты на выход }
Почти всё, осталось только вывести отражённую геометрию
float3 refl_img=tex2D(s_image,refl_tc); return float4(refl_img,1);
Я объяснил базовую реализацию SSLR, улучшать технику можно сколько угодно и это в ваших руках. О реализации луж, чуть позже, как только соберётся время.
Пока можете посмотреть сурсы с базовой реализацией SSLR и лужами вот тут
SSLR
https://github.com/Baryshev194/x-ray1.0007/commit/b07e191b9f545dc47d71d457a12817b7ced87a82
SSLR blur
https://github.com/Baryshev194/x-ray1.0007/commit/8408d0c04e6980cf476e526739c8551b11d4c3f0
Wetness buffer + Puddles effect
https://github.com/Baryshev194/x-ray1.0007/commit/0b9d9975711a86c0cc14c9236c2bd318eb5da65b
- 2
- 7
- 1
- 7
-
Муви-пикча -> https://yadi.sk/i/z43YN5FVXJUWuw
- 2
-
Всем привет, статейка по SSLR и реализации луж в S.T.A.L.K.E.R. пока откладывается, так как я начал делать кое-что новое, а именно физически корректное атмосферное рассеивание. Что же это? Смотрите ссылку->Accurate Atmospheric Scattering
Зачем оно? Использование skybox текстуры отпадает, ведь цвет неба расcчитывается шейдером исходя из положения солнца в world space.
Как оно получилось в S.T.A.L.K.E.R.:
Возвращаемые значения шейдера будут явно больше еденицы, поэтому стоит применить им тональную компрессию.
Оставлять это так нельзя, ведь в реале на небе ещё и облака есть. Наверное многие знают о игре Horizon Zero Dawn и о её технологии создания volumetric clouds.
Конечно, и раньше умели рендерить объёмные облака в реалтайме, но эта игра привнесла некий стандарт по которому сейчас реализуют эту фичу.
Собственно, исследуя интернет и папирусы Horizon Zero Dawn начал реализацию.
Вот так оно, конечно же Work in Progress:
Толкового освещения ещё нет, но всё же, я убедился что вполне реально это реализовать.
Конечно же, на скриншотах нет skybox текстуры, всё сделано в реалтайме, убедиться в этом можно сравнивая скриншоты по порядку.
- 1
-
- Это популярное сообщение.
- Это популярное сообщение.
Недавно задался темой реализации wet dynamic asphalt roads puddles with screen space local reflections and light road on surface, хех
Соб-сна что у меня вышло https://yadi.sk/i/PamHVm-pXqdkOg <-ВИДЕО
Кому интересна данная тема, можете заглянуть в клуб https://www.amk-team.ru/forum/clubs/6-klub-texcoordn/, в скором времени я опишу там реализацию данного эффекта.
Немного экспериментов с самими отражениями
- 5
- 1
-
Мб кому тоже полезно будет. Для своей модификации решил одолжить деревья из другой игры, но столкнулся с одной проблемой. Текстуры веток были отличными от сталкерского формата (много маленьких деталей на текстуре) и alpha test тупо сожрал все пиксели и на большом расстоянии остались только, грубо говоря, стволы.
Что вышло:
Добавить ещё анти алиасинга и может даже тошнить не будет. Для большей наглядности можно быстро пощёлкать скрины между собой.
- 4
-
@mauvais effects_lightplanes
-
1 минуту назад, warwer сказал:
@Anonim разве этот файл отвечает за выход воды "из берегов"? Он, вроде, за рябь на поверхности отвечает, нет?..
Нет, для этого я и говорил где шейдер править) Если кому-то нужна стоящая вода, могу поглядеть как это можно нормально сделать.
-
@warwer дак нужно ещё нормал мап править) Он же в оригинале seq файл.
-
Ты сам же на свой вопрос и ответил, но я начинаю думать, что ты хочешь запилить стоячую воду для помещений. Тогда просто сделай как я говорил выше и поправь нормал мап для нужной водички.
-
3 минуты назад, Tolyan сказал:
Народ подскажите как воду сделать неподвижной, чтобы она не ходила вверх и вниз. Просто стояла на месте.
Привет, править вершинный шейдер.
o.tnorm0 = watermove_tc (o.tbase*W_DISTORT_BASE_TILE_0, P.xz, W_DISTORT_AMP_0); o.tnorm1 = watermove_tc (o.tbase*W_DISTORT_BASE_TILE_0, P.xz, W_DISTORT_AMP_0);
Допустим можно так, а можно и во фрагментном, но там дольше.
- 1
-
- 2
- 1
-
- Это популярное сообщение.
- Это популярное сообщение.
Привет всем, недавно задался вопросом реализации бликов like battlefield, наткнулся на статью:
John Chapman Pseudo Lens Flares
Демонстрационное видео мне понравилось, посему взялся за реализацию прямо по статье. Вот что вышло у меня: клик
Собтсвенно, а как оно делается на сталкере, весь код приведу ниже с пояснением.
Шейдер Treshold/Downsample, так как реализация в статье не подходит для сталкера, пришлось делать совсем иначе, на выходе почти идентичный результат. А что он делает? Говоря "поруски", отбрасывает пиксели с низкой яркостью оставляя только светлые участки, т.е. те участки которые и будут учавствовать в создании призраков и гало эффекта. Шейдер можно сказать необходимый, его можно использовать и для эффекта Dirty Lens, похожим способом и блум пилится и ещё много чего. Из входных данных, это люминанс вектор и rt_Generic_0(сцена до фазы combine).
Пишется всё это дело в новый рендер таргет, который мы дальше будем использовать для генерирования бликов.
Скрытый текст#include "common.h" uniform sampler2D samplerScene;//rt_Generic_0 uniform half4 uLuminance;//luminance vector ////////////////////////////////////////////////////////////////////////////////////////// // half4 main ( AntiAliasingStruct INStruct ) : COLOR { half3 color =tex2D(samplerScene,INStruct.texCoord0.xy).rgb; half3 brightColor =max(color -uLuminance.xyz, 0); half bright =dot(brightColor, 1); bright =smoothstep(0, .5, bright); half3 outColor =lerp(0, color, bright); return half4 (outColor, 1); }
Терь сам шейдер генерирующий блики. Входные данные:
-ранее созданный рендер таргет downsample, "обозванный" samplerTreshold
-1D текстура, в нашем случае фейковая, т.к. нельзя в dds сохранить текстуру с высотой в один пиксель, у меня она 256x4. Используется она для окрашивания бликов.
Всё это тоже пишется в новый РТшник.
Скрытый текст#include "common.h" half3 tex2Ddistorted(sampler2D inputSampler, float2 texCoord, float2 direction, float3 distortion) { return half3 ( tex2D(inputSampler, texCoord +direction *distortion.r).r, tex2D(inputSampler, texCoord +direction *distortion.g).g, tex2D(inputSampler, texCoord +direction *distortion.b).b ); } #define GHOSTS int(5)//num of ghosts uniform sampler2D samplerTreshold;//treshold sampler uniform sampler2D samplerLensColor;//fake1D texture uniform half4 uGhostDispersal; uniform half4 uHaloWidth; uniform half4 uDistortion; ////////////////////////////////////////////////////////////////////////////////////////// // half4 main ( AntiAliasingStruct INStruct ) : COLOR { float2 texCoord =-INStruct.texCoord0.xy +float2(1,1); float3 distortion =float3(-screen_res.z *uDistortion.x, 0, screen_res.z *uDistortion.x); float2 ghostVector =(float2(.5,.5) -texCoord) *uGhostDispersal.x; float2 direction =normalize(ghostVector); half3 outColor=half3(0,0,0); // half4 outColor=half4(0,0,0,0); for ( int i=0; i<GHOSTS; i++ ) { float2 offset =frac(texCoord +ghostVector *float(i)); float weight =length(float2(.5,.5) -offset)/length(float2(.5,.5)); weight =pow(1-weight,10); //outColor +=tex2D(samplerTreshold,offset) *weight;//.rgb *weight; outColor +=tex2Ddistorted(samplerTreshold,offset,direction,distortion).rgb *weight; } //outColor*=tex2D(samplerLensColor,length(float2(.5,.5) -texCoord)/length(float2(.5,.5)));//.rgb; outColor*=tex2Ddistorted(samplerLensColor,length(float2(.5,.5) -texCoord)/length(float2(.5,.5)),direction,distortion).rgb; float2 haloVector =normalize(ghostVector) *uHaloWidth.x; float haloWeight =length(float2(.5,.5) -frac(texCoord +haloVector))/length(float2(.5,.5)); haloWeight =pow(1-haloWeight,5); //outColor +=tex2D(samplerTreshold,texCoord +haloVector) *haloWeight;//.rgb *haloWeight; outColor +=tex2Ddistorted(samplerTreshold,texCoord +haloVector,direction,distortion).rgb *haloWeight; return half4(outColor, 1); //return outColor; }
Терь нужно "пустить под блюр" сгенерированные блики, обычно я это делаю незамысловатым Gauss блюром, но в сей раз хотел испробовать что-нибудь новенькое. На самом деле я не ручаюсь за правильность работы этого шейдера , так как не выводил его на результ для проверки. Чтобы перестраховаться можно использовать проверенный блюр, код будет прямо под этим.
Скрытый текст#include "common.h" uniform sampler2D samplerBlur; ////////////////////////////////////////////////////////////////////////////////////////// // half4 main ( AntiAliasingStruct INStruct ) : COLOR { float offset[3] = { 0, 1.3846153846, 3.2307692308 }; float weight[3] = { 0.2270270270, 0.3162162162, 0.0702702703 }; half4 outColor =tex2D(samplerBlur,(INStruct.texCoord0.xy)) *weight[0];///1024 ); // float offset[3] = // { // 0, // 1.3846153846, // 3.2307692308 // }; // float weight[3] = // { // 0.2270270270, // 0.3162162162, // 0.0702702703 // }; //for ( int i=0; i<2; i++) for ( int i=1; i<3; i++) { outColor +=tex2D(samplerBlur,(INStruct.texCoord0.xy +float2(0,offset) ))*weight;///1024 ) *weight; outColor +=tex2D(samplerBlur,(INStruct.texCoord0.xy -float2(0,offset) ))*weight;///1024 ) *weight; } return outColor; }
Тут Gauss.
Входные параметры:
-семплер обречённый на блюр
-текстурные координаты
-сила блюра (почему в int? потомучто я всегда его использую только в цикле и как сила блюра у меня выступает кол-во оборотов цикла, к тому же значение динамическое)
for ( int i=0; i<BLUR_SAMPLES; i++ ) { outColor =Gauss(samplerBlur,texCoord,i,false); }
-бул значение для юза оптимизированного блюра
Примечание: по сути, юниформ screen_res здесь не так важен и можно заменить универсальной константой 1024.f
Скрытый текст#ifndef GAUSSBLUR_H_INCLUDED #define GAUSSBLUR_H_INCLUDED half4 Gauss(sampler2D inputSampler, float2 texCoord, int factor, bool optimize) { half4 outColor; if(!optimize) { float dx = factor*.5f/screen_res.x; float dy = factor*.5f/screen_res.y; outColor = ( //1.f * tex2Dlod(inputSampler,float4(texCoord,0,0)).rgba + 1.f * tex2Dlod(inputSampler,float4(texCoord+float2(dx,0),0,0)).rgba + 1.f * tex2Dlod(inputSampler,float4(texCoord+float2(dy,0),0,0)).rgba + 1.f * tex2Dlod(inputSampler,float4(texCoord+float2(-dx,0),0,0)).rgba + 1.f * tex2Dlod(inputSampler,float4(texCoord+float2(-dx,-dy),0,0)).rgba + 1.f * tex2Dlod(inputSampler,float4(texCoord+float2(dx,-dy),0,0)).rgba )/5.f; } else { const float delta = factor * (.5f/screen_res.x); outColor = ( tex2Dlod(inputSampler,float4(texCoord+delta,0,0)).rgba + tex2Dlod(inputSampler,float4(texCoord-delta,0,0)).rgba )*(1.f/2.f); } return outColor; } #endif//GAUSSBLUR_H_INCLUDED
В идеале, конечно, я бы и Dawnsample обрёк на блюр, но переделывать было уже лень.
Ну и последняя фаза комбайн с основным изображением. Не стал парится с SturBurst эффектом, оставил статичным, оно и так прилично выглядит, DirtyLens Тоже не стал делать, так как у меня это отдельная история, хотя смешивать его тоже в этом шейдере буду.
Скрытый текст#include "common.h" uniform sampler2D samplerFlares;//lens flares sampler //uniform sampler2D samplerDirt;//dirty texture uniform sampler2D samplerScene;//rt_Generic_0 uniform sampler2D samplerStarbust;// ////////////////////////////////////////////////////////////////////////////////////////// // half4 main ( AntiAliasingStruct INStruct ) : COLOR { // half4 lensDirt =tex2D(samplerDirt,INStruct.texCoord0.xy); // half4 lensMod =tex2D(samplerFlares,INStruct.texCoord0.xy) *lensDirt; half4 starbust =tex2D(samplerStarbust,INStruct.texCoord0.xy); half4 lensMod =tex2D(samplerFlares,INStruct.texCoord0.xy) *starbust; half4 scene =tex2D(samplerScene,INStruct.texCoord0.xy) +lensMod; return scene; }
Ну вроде всё. Надеюсь кому-нибудь пригодится.
- 2
- 7
-
-
Гляжу на форуме появились клубы, мб кому интересно создать свой, что-нибудь типа "Клуб TEXCOORDN;", где можно обсуждать реализацию тех или иных графических фич на стулкире, перенос из других игр, перенос кода из более младших частей в старшие, например из ЗП в ТЧ. Как вам идея?
- 1
- 3
- 1
-
Как вариант, выкинуть кривое SSAO
Замутил для своего хоррора эффект поломанной камеры, мб кому-нибудь тоже пригодится. Для смерти ГГ или иных задач.
float3 brCamEffect(float2 texCoord) { float3 Ret; float amount; amount = (1+sin(timers.x*6))*0.5; amount *= 1+sin(timers.x*16)*0.5; amount *= 1+sin(timers.x*19)*0.5; amount *= 1+sin(timers.x*27)*0.5; amount = pow(amount,3); amount *= 0.05; float2 Offsets = saturate(distance(float2(0.5,0.5),texCoord))*float2(amount,amount); Ret.r = tex2D(s_image,texCoord+Offsets).r; Ret.g = tex2D(s_image,texCoord).g; Ret.b = tex2D(s_image,texCoord-Offsets).b; return Ret; }
- 1
- 1
- 2
-
Здравствуйте! Что за пункт "Звание" в редактировании профиля?
-
Привет!
Правильные тени от солнца (R2)Двиглоправка.
Мягкие тени - r2_soft_shadowsБиблиотека shadow.h
Детальный бамп - r2_detail_bumpБиблиотека sload.h
-
@Zotac, насколько я знаю, настройки сан рейсов в шейдерах meltac'а находятся в отдельном конфигурационном файле.
-
смешивание партиклов и тумана (партиклы не видны сквозь туман)
Привет, прикрепи скрин, не совсем понятно о чём ты говоришь.
как можно исправить смешивание травы и тумана на 1 рендере?На геймру есть фикс, выкладывал его макрон'сан. Гляди в тему "доработки графики финалки".
-
@MADMAX666, смотри accum_volumetric_sun_far, наверняка что-нибудь найдёшь.
Physically based rendering
в Форум клуба
Опубликовано
Physically based rendering, хотя в нашем случае вернее всего сказать shading но оставим так, ибо звучнее.
На неделе сделаю полноценную статью с разбором о реализации на наш сталкер, пока просто тема чтобы посмотреть насколько эта тема интересна, короче обсуждаем.