Vladimir.Semenov Posted December 22, 2025 Posted December 22, 2025 (edited) Доброго рабочего дня всем причастным, а при случае счастливом - даже доброго нерабочего. Во фрагментном шейдере я высчитываю нормаль (обычную), альтернативную нормаль и коэффициент. Я хочу в deferred light pass только для своего материала делать lerp межу результатами освещённости пикселя для этих нормалей (по коэффициенту). Концепцию работы с deferred/forward/post пассами не вполне уложил себе в голове пока, как я вижу сейчас: мне нужно при расчёте освещённости для моего конкретного material_mask добавить мой особый случай в if(material_mask==my_mask){ ... }, и это будет самый оптимальный вариант, т.к если пытаться реализовать в auxiliary pass, это заново ещё раз весь лайтинг выполнять. Т.е. использовать auxiliary/forward пассы это как я понимаю - оверхед (двойная работа буквально), и material_mask подразумевается к использованию в подобных случаях. Но я не могу найти доступный юзеру шейдер/кусочек шейдера, заполняющего lightsource diffuse & specular. Как и где его модифицировать? (в 2.13) И - верен ли мой подход к проблеме? В данном случае использование forward pass не обязательно? Edited December 22, 2025 by Vladimir.Semenov
sweetluna Posted December 24, 2025 Posted December 24, 2025 Здравствуйте Владимир, Для понимания того, как вам будет оптимальнее получить желаемый результат ответьте на несколько наводящих вопросов: 1) Как вы считаете альтернативные нормали? Можно какой-то примерный кусок кода? Они базируются на уже заполненном GBuffer-е или им нужна дополнительная информация с объектов/экрана/доп. текстуры? 2) Как вы хотите совмещать освещение? Если просто лерпить нормали через reorientVectorBlend или slerp можно ли будет получить нужный результат? // Пример реализации из core/materials/shaders/api/common.h //reorientNormalBlend -> reorientVectorBlend(float3(0,0,1), base_normal, detail_normal) float3 reorientNormalBlend(float3 base_normal, float3 detail_normal) { base_normal.z += 1.0; detail_normal.xy = -detail_normal.xy; return base_normal * dot(base_normal, detail_normal) / base_normal.z - detail_normal; } float3 reorientVectorBlend(float3 main_vec, float3 vec, float3 rotation_vec) { float4 q = float4(cross(main_vec, vec), dot(main_vec, vec) + 1.0) / sqrt(2.0 * (dot(main_vec, vec) + 1.0)); return rotation_vec * (q.w * q.w - dot(q.xyz, q.xyz)) + 2.0 * q.xyz * dot(q.xyz, rotation_vec) + 2.0 * q.w * cross(q.xyz, rotation_vec); } Как вариант можно посмотреть еще вот сюда, тут есть пример ф-ции slerp для нормалей, с объяснениями зачем это надо. Один из вариантов, что я могу предложить - это попробовать встроиться в рендер и изменить буффер нормалей по вашим коэфицентам, если такое возможно. Если такое тоже не устроит и нужно именно лерпить освещение, то тут уже придется либо встраиваться в само освещение (core/materials/shaders/render/lighting/*.h или в render_lights.basemat вызывать дважды просчет освещения для каждой нормали и лерпиться по буфферу) и там пытаться вести двойные просчеты в зависимости от нормали, либо же полностью повторять все освещение. Пути до инклудов из новой версии движка, так что они могут отличаться от 2.13. Надеюсь это поможет! May RenderDoc/Nsight Graphics/Intel GPA bless you
Vladimir.Semenov Posted December 25, 2025 Author Posted December 25, 2025 (edited) Добрый день, спасибо за идеи! В моём случае одна нормаль не подходит, как мне сейчас видится расчитывать нужно для двух. Задача - некоторый специальный случай microsurface, я могу свести её к довольно банальному примеру (правда это упрощение, но вроде суть то же самое): Spoiler Забор, или эдакий неотражающий уголковый отражатель если будет угодно, на котором мне надо добиться равномерной закраски на удалении, без появления муара. При этом переход вблизи/далеко должен быть гладким (я его сейчас по ddxy ловлю), усреднённое освещение должно сохраняться визуально - если под каким-то углом одна грань бликует, яркость этого блика должна влиять на итоговое усреднённое значение. Так же влияет и угол зрения - влияние одной либо другой грани в итоговой яркости, и естественно всё не так просто ибо под большими углами происходит перекрытие одной грани другой. Ну это в бумагах по microsurface наверняка не раз раскрыто, но у меня вопрос не в математике microsurface. От этих всех фокусов меня коэффициент мой спасает - если смогу получить две освещённости одновременно. Моя поверхность выглядит не /\/\/\/\, а скорее ГLГLГL или даже _/-\_/-\_, но это всё не суть, насколько я могу судить считаю я свой коэффициент правильно и от итоговой картинки меня отделяет только deferred light pass. nlerp нормали "kinda works", муар пропадает, но освещение летит к чертям и явно видно несоответствие яркостей между вариантами близким и далёким, а они у меня бывают одновременно на экране. Ну собственно даже на скрине если сместиться ближе к одной стороне забора и посмотреть в сторону другого конца. (Вторую нормаль я сейчас считаю из первой поворотом на угол, угол вводят художники ручками в параметр материала. В любом случае вторая нормаль считается вместе с основной, во фрагментном шейдере deferred pass) Да, видимо то чего я хочу - это залезть во внутренности render_lights.basemat, и у меня вопрос как раз: "как для проекта переопределить render_lights.basemat, не меняя его в /sdk/data/core/... ?" (Тем более что изменения в /sdk/.../render_lights.basemat не влияют на рендеринг, судя по моим экспериментам. Нужно что-то ещё чтобы они подхватились. Что?) Я-то знаю только менюшечку Settings>Runtime>World>Render>SSMaterials но там CompositeDeferred/Composite и подобное, без Light. Ну и естественно поинтересуюсь, нет ли более стандартного решения этой вроде как нередкой ситуации? (Все AA движка что нашёл я крутил-вертел, приемлимой картинки от них добиться не смог. Где недокрутил?) Спасибо! Edited December 26, 2025 by Vladimir.Semenov
sweetluna Posted December 26, 2025 Posted December 26, 2025 Не очень понимаю вашу задумку, вы хотите получить ретрорефлекшн через геометрический микросюрфейс? Не думаю что это так просто заведется, обычно для такого используют отдельную текстуры по типу Roughness, Normalmap и подобных, а уже потом по получившимся данным в GBuffer - считают аналитически. Материал заменить можно просто скопировав его из SDK/data/core/... и положить по такому же пути в проекте - <Project>/data/core/.../. Движок сам подхватит альтернативную версию, минуя core.ung. При запаковке проекта надо будет либо перепаковать core.ung с замененными шейдерами/материалами, либо же скопировать файлы data/core/ вместе с проектом. В целом ретрорефлекшн в последних версиях движка есть и используется для Translucent материалов (можно создать сферу или куб и на них сделать Translucent 1 через мат. граф). Конкретно там он реализован через кастомный BRDF (core/materials/shaders/render/shading.h), который возможно вам стоит попробовать портировать из новой версии в старую. Если вам, допустим, Translucent или Microfiber материалы не нужны, можно попробовать заиспользовать их в качестве Retroreflection параметра, естественно нужно пройтись и убрать все зависимости на Microfiber/Translucent в шейдерах, что бы они не влияли как раньше, ибо поведение у слайдеров изменится. Соответственно это нужно будет учесть в дальнейших материалах. Надеюсь поможет! May RenderDoc/Nsight Graphics/Intel GPA bless you
Vladimir.Semenov Posted January 16 Author Posted January 16 (edited) Спасибо. И вправду помогло))) Другое дело что я Вас сбил, retroreflection я повторить не пытаюсь. Задача другая, побороть муар в отдельном специфичном случае - на продольно повторяющейся геометрии. Буквально на заборе, забор который из досок или брусочков набит. (за наводку на retroreflection спасибо! Очень пригодится, как я понимаю, но совсем не по текущей моей ситуёвине). Наглядно проблема в видосике под спойлером: Spoiler Вот на правой стене видно, к примеру. (Похоже форма обрезала тайминг ссылки, в видео на 36:20 в момент когда дверь распахивается - стена справа за дверью, под фонарями) Я, насколько мог, своим материалом визуально беду замазал. Сейчас я делаю так: 1: В deferred самого материала считаю доп.нормаль и коэффициент смешивания. Пишу их в Features (не разобрался как писать в Auxiliary из deferred pass). 2.1: В deferred_light для моего материала отдельно повторяю вычисления для второй нормали, смешиваю по коэффициенту. 2.2: В sky_environment для моего материала отдельно повторяю вычисления для второй нормали, смешиваю по коэффициенту. 3: В composite deferred считаю environment отдельно для второй нормали, смешиваю. TODO: текущее решение ломается включением SSAO, но это наверное тоже в composite deferred решается, не глядел пока. Получается так: Spoiler Мой материал применён только на забор справа. Задняя стена, шар - mesh_base Для сравнения смешивание активно в верхней части экрана, низ забора - изначальное поведение аналогичное mesh_base Ну собственно вот: подскажите, пожалуйста, есть ли стандартное решение данной проблемы? В динамике всё хуже, ТАА мигает. Либо есть ли нестандартное но более подходящее нежели моё? Как я сейчас понимаю - мне надо было лезть в BRDF, но нет видения как это сделать, мне ж туда опять же надо как-то отовсюду прокидывать в BRDF дополнительный float4 (более того, откуда-то его при этом брать). Непонятно. PS: И отдельно спрошу здесь же: как можно в deferred pass писать в Auxiliary? В идеале подцепить бы её в MRT, но пока что-то мои эксперименты ни к чему не привели (ни MRT, ни RW_textures. не разобрался). PPS: И ещё - как я успел начитаться, один из минусов deferred рендеринга в том и состоит что поддержка разных материалов затруднена. Так что как мне видится в том числе для борьбы с сим недугом и нужны auxiliary + material_mask. В deferred pass их заполняем, а в освещениях по маске дёргаем нужный кастомный BRDF? Или я вижу неправильно? Ну и отдельно извините что я ещё не посмотрел новый retroreflection, возможно в нём ответы на свои вопросы и обнаружу. Но просвятите доходчиво по возможности? Спасибо! PPPS: Опять же не по теме топика, но по моей ситуации с муаром: Очевидно что решение получится более визуально правильным если применять его не одинаково по всей поверхности, а только на граничных пикселях, расчитывая коэфф для пикселя в зависимости от расстояния до края. Мои решения для этого и доп подгонку индивидуальную под геометрию подразумевают (отдельная текстура с разметкой), да и шейдер утяжеляют. Не хочется ещё больше в рантайме времени занимать, и моя замазка уже достаточно хорошо себя показывает по сравнению с тем, что было. Но спрошу: есть ли какое-то готовое/стандартное решение для определения расстояния до изгиба, или хотя бы полигона (если совсем ничего, то как хотя бы получить бароцентрические самого полигона каждого, не UV модели)? Слышал что у Nintendo3DS специально железно была реализована альфа на гранях, у нас ничего подобного нет? Edited January 21 by Vladimir.Semenov
sweetluna Posted January 23 Posted January 23 On 1/16/2026 at 3:30 PM, Vladimir.Semenov said: Другое дело что я Вас сбил, retroreflection я повторить не пытаюсь. Задача другая, побороть муар в отдельном специфичном случае - на продольно повторяющейся геометрии. Буквально на заборе, забор который из досок или брусочков набит. В таком случае скорее всего вам не хватает разрешения рендера, надо попробовать увеличить Supersampling или включить SRAA. Quote PS: И отдельно спрошу здесь же: как можно в deferred pass писать в Auxiliary? В идеале подцепить бы её в MRT, но пока что-то мои эксперименты ни к чему не привели (ни MRT, ни RW_textures. не разобрался). В Deferred Pass нельзя писать в Auxiliary, в будущем может быть можно будет попробовать что-то такое организовать, но сейчас только если подписаться на эвент и вызвать свой шейдер который запишет в Auxiliary. On 1/16/2026 at 3:30 PM, Vladimir.Semenov said: PPS: И ещё - как я успел начитаться, один из минусов deferred рендеринга в том и состоит что поддержка разных материалов затруднена. Так что как мне видится в том числе для борьбы с сим недугом и нужны auxiliary + material_mask. В deferred pass их заполняем, а в освещениях по маске дёргаем нужный кастомный BRDF? Или я вижу неправильно? Ну и отдельно извините что я ещё не посмотрел новый retroreflection, возможно в нём ответы на свои вопросы и обнаружу. Но просвятите доходчиво по возможности? Спасибо! Можно конечно такое попробовать провернуть. Но надо встраиваться в сами шейдера внутри core. В целом там есть deferred_light.basemat, вполне можно попробовать там добавить использование Auxiliary и Material Mask текстур и в шейдере их читать и уже на основе этих масок выбирать какой BRDF нужен. Но нужно будет расширить ф-цию getBRDF, или сделать кастомную версию по месту. Еще это может не отработать на прозрачных материалах(с прозрачкой там отдельная головоломка это заводить), но вполне возможно что этого хватит. On 1/16/2026 at 3:30 PM, Vladimir.Semenov said: PPPS: Опять же не по теме топика, но по моей ситуации с муаром: Очевидно что решение получится более визуально правильным если применять его не одинаково по всей поверхности, а только на граничных пикселях, расчитывая коэфф для пикселя в зависимости от расстояния до края. Мои решения для этого и доп подгонку индивидуальную под геометрию подразумевают (отдельная текстура с разметкой), да и шейдер утяжеляют. Не хочется ещё больше в рантайме времени занимать, и моя замазка уже достаточно хорошо себя показывает по сравнению с тем, что было. Но спрошу: есть ли какое-то готовое/стандартное решение для определения расстояния до изгиба, или хотя бы полигона (если совсем ничего, то как хотя бы получить бароцентрические самого полигона каждого, не UV модели)? Слышал что у Nintendo3DS специально железно была реализована альфа на гранях, у нас ничего подобного нет? Посмотрите в сторону SRAA, TAA и Supersampling. Надеюсь поможет! May RenderDoc/Nsight Graphics/Intel GPA bless you
Vladimir.Semenov Posted January 23 Author Posted January 23 Спасибо, ветку можно помечать как resolved. По теме топика вроде всё освещено, ну а по моей беде если возникнут другие вопросы - уже специфично адресую. Спасибо ещё раз, помогает, не сомневайтесь)
Recommended Posts