TGViewer
🥒Код для приколов🥒 🥒Код для приколов🥒 @ogurchrik3228 · 107 subscribers
Post #90 96
Как вы можете заметить выше, я иногда беру код с ShaderToy для того, чтобы изменить его в той или иной степени или же переписать под Ren'Py для дальнейшего использования. Так вот о последнем вам и хочу рассказать: как взять (почти) любой шейдер с ShaderToy и перенести его в Ren'Py. Заранее предупрежу, что каждый шейдер на ShaderToy защищён авторским правом и их использование возможно лишь с разрешения автора или же в соответствии с CC BY-NC-SA 3.0.

Начну с базы: как сделать шейдер?

Для этого используется функция renpy.register_shader(), в аргументы которой вам нужно вписать как минимум название и фрагментный код, а при необходимости также переменные и вершинный код.
Простейший шейдер выглядит так:

init python:
renpy.register_shader("None", fragment_300="""gl_FragColor=gl_FragColor;""")


Тот просто присваивает каждому пикселю его текущий цвет, что эквивалентно отсутствию эффекта. fragment это обозначение того, какую часть шейдера мы пишем (кроме fragment есть vertex), _300 это то, с каким приоритетом будет применена эта часть кода относительно других шейдеров - чем больше, тем позже. Также есть префикс _functions и аргумент variables, про которые ниже.
Один из способов применения:

label kek:
show sprite:
shader "None"


Поскольку вышеописанное сильно отличается от любого другого шейдерного кода, что вы могли видеть, то я обязан пояснить: часть кода Ren'Py генерирует за вас.

Если вы в вашей новелле сделаете config.log_gl_shaders = True то у вас в log.txt будет чистый текст того, какой именно код Ren'Py сделал для вас. И по нему вы можете увидеть, что как минимум есть отдельный vertex None renpy.geometry и отдельный fragment None renpy.geometry, и что ни одну строку из vertex мы не писали, т.к. позиционированием картинок движок управляет сам и соответственно ставит каждому шейдеру своё позиционирование. В fragment же, в void main конкретно мы можем увидеть тот gl_FragColor=gl_FragColor; что и писали ранее.

Собственно в этом и вся связь между кодом шейдера на Ren'Py и ShaderToy: нужно перенести нужные части кода в нужные аргументы renpy.register_shader(). Потому далее расскажу на примере.

В указанном шейдере до void mainImage есть другой код, который относится к fragment_functions, потому можно его напрямую вставить в fragment_functions=""" """. Затем в void mainImage мы видим основной код, который соответствует fragment с любым приоритетом, соответственно передаём его туда.
Но так как ShaderToy и Ren'Py используют разные версии OpenGL и разные названия для базовых входных данных (uniforms), то нужно внести изменения.

Начнём с простейшего: коррекция разницы между версиями.

Достаточно изменить fragCoord на gl_FragCoord, fragColor на gl_FragColor, чтобы исправить разницу в версиях в том шейдере. Также в других шейдерах для работы с текстурами нужно поменять texture на texture2D.

Теперь надо изменить и прописать переменные (uniforms).

В ShaderToy чаще всего используются как переменные iTime, iResolution, iChannel0, ..., iChannel3, iMouse, но существуют и другие, которые используются реже.

Для того, чтобы прописать переменную необходимо писать в аргумент variables. Допустим хотим вписать переменную времени с момента текущего показа. Тогда пишем: variables="""uniform float u_time;"""", где float это тип переменной. Соответственно при адаптировании надо поменять iTime на u_time везде. Аналогом vec3 iResolution можно назвать vec2 u_virtual_size, т.к. первые два элемента векторов соответствуют друг другу, и его заменяем. И на этом всё в целом. Мы адаптировали тот пример под Ren'Py, но продолжу немного про другие аналоги.
Аналогами для названий текстур iChannel0 к tex0, ..., iChannel3 к tex3, и соответственно при использовании каждой надо добавлять sampler2D tex0 в variables. iMouse же отвечает за позицию курсора в момент нажатия, и т.к. мы можем получать позицию курсора из renpy.get_mouse_pos(), то создание аналога усложняется до того, что мы должны создать либо DynamicDisplayable либо screen, в котором мы будем каждый кадр через timer передавать координаты курсора в u_mouse_pos,
  • 🤯 4
  • ❤ 1
  • 👍 1
More from @ogurchrik3228
  1. Sep 22, 2026который уже пропишем сами в свойствах к transform, ведь значения для него не даются по умо…
  2. Sep 18, 2026Сидел в интернете как-то и заметил один весьма старый шейдер. Мне он естественно понравилс…
  3. Sep 17, 2026Экран, переключаемый на клавишу "-", позволяющий подобрать нужно выглядящую обводку под те…
  4. Sep 16, 2026В один момент вспомнил об одном своём оверлей-меню с динамичным подбором значений для матр…
  5. Sep 9, 2026Полазив в интернете я наткнулся на туториал по тому как сделать светящийся шарик. Подумав,…
  6. Aug 2, 2026Итак, прошло чуть больше трёх месяцев, так что самое время отчитаться о том, чего было, а…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →