Это популярное сообщение. Anonim 680 Опубликовано 29 Сентября 2019 Это популярное сообщение. Поделиться Опубликовано 29 Сентября 2019 Как и обещал, разбор полётов по 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 6 1 7 Ссылка на комментарий
DDamian724 18 Опубликовано 30 Сентября 2019 Поделиться Опубликовано 30 Сентября 2019 Очень хороший учебник. Спасибо) У меня вопрос, как я могу применить отражения только к воде? 1 Ссылка на комментарий
Это популярное сообщение. Anonim 680 Опубликовано 30 Сентября 2019 Автор Это популярное сообщение. Поделиться Опубликовано 30 Сентября 2019 @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 Ссылка на комментарий
Expropriator 2 118 Опубликовано 3 Октября 2019 Поделиться Опубликовано 3 Октября 2019 @Anonim, это для R2 ТЧ. А в R3 ЧН я впух. Там код шейдеров другой. Ссылка на комментарий
Romann 623 Опубликовано 5 Октября 2019 Поделиться Опубликовано 5 Октября 2019 (изменено) В 04.10.2019 в 00:52, Expropriator сказал: Там код шейдеров другой Та же беда и под ЗП r3-r4, пытался переписать - не взлетает, говорит не порядок с вектором в SSLR, там как минимум "tex2D" не используется, переписывал на примерах из шейдеров, но ему не нравится..( Да и с r2 на ЗП тоже непорядок, сделал из репо - лужа есть, при чём она постоянна, не зависит от дождя, отражение вроде есть, но при разных углах взгляда артефактит дико. Да ещё - лужа есть, идёт дождь или нет, но афальт всегда стоит сухой, так же с дождём или без. Или я может в репо что-то упустил? ************************************************************************************************************** В общем, что сделал: движок "OXR_CoC", из вышеуказанного репозитория всё по SSLR перетянул сначала для r2, потом сделал тоже самое для r3-r4, с небольшими изменениями под эти рендеры(оказалось больше файлов где надо добавить дополнительные аргументы, чем у r2), движок скомпилил. По шейдерам для r2 сделал всё так же, как в репозитории, различий много не увидел, для r3-r4 пытался переписать - не вышло, не взлетает. На r2.5 вот такие получились "Типа лужи". Изменено 6 Октября 2019 пользователем Romann Мать: ASRock X470 Master SLI. Процессор: AMD Ryzen 9 3900X 12-Core(4200 MHz). Память: Patriot Memory 3200 C16 Series. DDR4-3200(1600МГц), 16Гбх2(32Гб). Видео: GeForce GTX 1060 6GB. Блок питания: CoolerMaster 750 Вт. Корпус: Zalman i3 Edge. Химера конечно сильный хищник, а все держится дома. Чего же ты пришел к ней домой и пытаешься её убить? © Болотный Доктор Ссылка на комментарий
Zagolski 74 Опубликовано 30 Октября 2019 Поделиться Опубликовано 30 Октября 2019 (изменено) Нормалек. Качество не ахти, но для сталка пойдет. Правда, обозначенный выше алгоритм трассировки активно пропускает мелкие объекты, такие как провода, листва и пр. Да и не только мелкие. Хотя и достаточно быстр. Но все равно 6 итераций - мало, лучше хотя бы с десяток. Марш луча лучше делать в скринспейсе, т.е. по пикселям, а не в мировых или видовых координатах. Нормаль для воды можно не переводить в пространство касательных и не делать лишних умножений матриц, потому как вода всегда расположена горизонтально. Изменено 30 Октября 2019 пользователем Zagolski 2 1 Ссылка на комментарий
_ХоЗаР_ 47 Опубликовано 30 Октября 2019 Поделиться Опубликовано 30 Октября 2019 (изменено) 6 часов назад, Zagolski сказал: как вода всегда расположена горизонтально Ну для воды тогда как минимум придется вектора резать получаемые из-за того что вода не пишется в буфер глубины (В ЗП покрай мере.) Изменено 30 Октября 2019 пользователем _ХоЗаР_ Ну или добавить воду в буфер глубины :-) Скрытый текст 6 ГБ ОЗУ DDR3 1098 мГц (Разносорт) Процессор Intel Xeon E5420 4/4 2.5 ГГц Видеокарта Gigabyte GeForce GT 240 512 МБ GDDR5 (Samsung) DirectX v10.1 Ссылка на комментарий
Romann 623 Опубликовано 5 Ноября 2019 Поделиться Опубликовано 5 Ноября 2019 (изменено) Кто нибудь пробовал реализовать эти отражения на ЗП? @Anonim, получилось сделать(ЗП - r2), но вот незадача - когда вертишь головой, по краям камеры возникают такие полосы/искажения: Скрытый текст Что с этим можно сделать? Если использовать в шейдере такой код: Скрытый текст Вот тот, что закомментирован: float4 get_6x6_image(float2 tc) { half depth = tex2D(s_position, tc).z; half depth_s = depth * (1 - step(0.001, abs(depth - 10000))); float4 sample; sample.xyz = tex2D(s_image, tc).xyz; float red_normal = tex2D(s_image, tc).x; /* float red_low1, red_high1, red_low2, red_high2, red_low3, red_high3, red_low4, red_high4, red_low5, red_high5, red_low6, red_high6, red_low7, red_high7, red_low8, red_high8, red_low9, red_high9, red_low10, red_high10, red_low11, red_high11, red_low12, red_high12; red_low1 = tex2D(s_image, float2(tc.x,tc.y-screen_res.w*1)).x; red_high1 = tex2D(s_image, float2(tc.x,tc.y+screen_res.w*1)).x; red_low2 = tex2D(s_image, float2(tc.x,tc.y-screen_res.w*4)).x; red_high2 = tex2D(s_image, float2(tc.x,tc.y+screen_res.w*4)).x; red_low3 = tex2D(s_image, float2(tc.x-screen_res.w*4,tc.y)).x; red_high3 = tex2D(s_image, float2(tc.x+screen_res.w*4,tc.y)).x; red_low4 = tex2D(s_image, float2(tc.x-screen_res.w*8,tc.y)).x; red_high4 = tex2D(s_image, float2(tc.x+screen_res.w*8,tc.y)).x; red_low5 = tex2D(s_image, float2(tc.x,tc.y-screen_res.w*8)).x; red_high5 = tex2D(s_image, float2(tc.x,tc.y+screen_res.w*8)).x; red_low6 = tex2D(s_image, float2(tc.x,tc.y-screen_res.w*12)).x; red_high6 = tex2D(s_image, float2(tc.x,tc.y+screen_res.w*12)).x; red_low7 = tex2D(s_image, float2(tc.x-screen_res.w*12,tc.y)).x; red_high7 = tex2D(s_image, float2(tc.x+screen_res.w*12,tc.y)).x; red_low8 = tex2D(s_image, float2(tc.x-screen_res.w*16,tc.y)).x; red_high8 = tex2D(s_image, float2(tc.x+screen_res.w*16,tc.y)).x; red_low9 = tex2D(s_image, float2(tc.x,tc.y-screen_res.w*16)).x; red_high9 = tex2D(s_image, float2(tc.x,tc.y+screen_res.w*16)).x; red_low10 = tex2D(s_image, float2(tc.x,tc.y-screen_res.w*20)).x; red_high10 = tex2D(s_image, float2(tc.x,tc.y+screen_res.w*20)).x; red_low11 = tex2D(s_image, float2(tc.x-screen_res.w*1,tc.y)).x; red_high11 = tex2D(s_image, float2(tc.x+screen_res.w*1,tc.y)).x; red_low12 = tex2D(s_image, float2(tc.x-screen_res.w*20,tc.y)).x; red_high12 = tex2D(s_image, float2(tc.x+screen_res.w*20,tc.y)).x; if(depth == depth_s) {sample.w = 0.012345;} if ( (red_normal != red_low1) && (red_normal != red_high1) && (red_normal != red_low2) && (red_normal != red_high2) && (red_normal != red_low3) && (red_normal != red_high3) && (red_normal != red_low4) && (red_normal != red_high4) && (red_normal != red_low5) && (red_normal != red_high5) && (red_normal != red_low6) && (red_normal != red_high6) && (red_normal != red_low7) && (red_normal != red_high7) && (red_normal != red_low8) && (red_normal != red_high8) && (red_normal != red_low9) && (red_normal != red_high9) && (red_normal != red_low10) && (red_normal != red_high10) && (red_normal != red_low11) && (red_normal != red_high11) && (red_normal != red_low12) && (red_normal != red_high12) ) { sample.w = 1; } else { sample.w = 0; } */ sample.w = 1; return sample; } То этих полос нету, но тогда если на модель/геометрию не попадает свет - отражение бьётся, иногда в отражении просто дырки - а иногда всё побито... -> Изменено 5 Ноября 2019 пользователем Romann Мать: ASRock X470 Master SLI. Процессор: AMD Ryzen 9 3900X 12-Core(4200 MHz). Память: Patriot Memory 3200 C16 Series. DDR4-3200(1600МГц), 16Гбх2(32Гб). Видео: GeForce GTX 1060 6GB. Блок питания: CoolerMaster 750 Вт. Корпус: Zalman i3 Edge. Химера конечно сильный хищник, а все держится дома. Чего же ты пришел к ней домой и пытаешься её убить? © Болотный Доктор Ссылка на комментарий
Romann 623 Опубликовано 8 Ноября 2019 Поделиться Опубликовано 8 Ноября 2019 Ну на r2 получилось сделать нормально на движке OXR_CoC, есть там конечно несколько проблемных моментов, но они прям в глаза не бросаются. Мать: ASRock X470 Master SLI. Процессор: AMD Ryzen 9 3900X 12-Core(4200 MHz). Память: Patriot Memory 3200 C16 Series. DDR4-3200(1600МГц), 16Гбх2(32Гб). Видео: GeForce GTX 1060 6GB. Блок питания: CoolerMaster 750 Вт. Корпус: Zalman i3 Edge. Химера конечно сильный хищник, а все держится дома. Чего же ты пришел к ней домой и пытаешься её убить? © Болотный Доктор Ссылка на комментарий
Рекомендуемые сообщения