Как реализовать эффект 2D raycasting light в GLSL

Это было первоначально задано здесь @sydd. Мне было интересно, поэтому я пытаюсь закодировать его, но он был закрыт / удален, прежде чем я смог ответить, вот и все.

Вопрос: Как воспроизвести / реализовать этот эффект освещения в режиме 2D-луча в GLSL ?

Сам эффект отбрасывает лучи от положения мыши до каждого направления, накапливая альфа-карту фона и цвета, влияющие на силу пикселей.

Таким образом, вход должен быть:

  • положение мыши
  • фоновая текстура RGBA-карты

  1. Фоновая карта

    Хорошо, я создал тестовую RGBA- карту в виде двух изображений, содержащих RGB (слева), а второй с альфа-каналом (справа), чтобы вы могли видеть их обоих. Грубо они объединены, чтобы сформировать единую текстуру RGBA .

    Карта RGB альфа-карта

    Я немного их размыл, чтобы получить лучшие визуальные эффекты по краям.

  2. Литье под давлением

    Поскольку это должно выполняться в GLSL, нам нужно бросить лучи где-нибудь. Я решил сделать это с помощью fragmentарного шейдера . Итак, алгоритм выглядит так:

    1. На GL стороне формы, необходимые для шейдеров Здесь идет положение мыши как текстурная координата, максимальное разрешение текстуры и проницаемость света.
    2. На стороне GL нарисовать квадрат, покрывающий весь экран с текстурой фона (o blending)
    3. В Vertex shader просто передайте необходимые координаты текстуры и fragmentа
    4. По fragmentарным шейдерам на каждый fragment:

      • литой луч от положения мыши до фактического положения fragmentа (в координатах текстуры)
      • накапливать / интегрировать свойства света во время прохождения луча
      • остановитесь, если достигнута дальность света вблизи нуля или целевого положения fragmentа.

Вершинный шейдер

// Vertex #version 420 core layout(location=0) in vec2 pos; // glVertex2f <-1,+1> layout(location=8) in vec2 txr; // glTexCoord2f Unit0 <0,1> out smooth vec2 t1; // texture end point <0,1> void main() { t1=txr; gl_Position=vec4(pos,0.0,1.0); } 

Фрагментный шейдер

 // Fragment #version 420 core uniform float transmit=0.99;// light transmition coeficient <0,1> uniform int txrsiz=512; // max texture size [pixels] uniform sampler2D txrmap; // texture unit for light map uniform vec2 t0; // texture start point (mouse position) <0,1> in smooth vec2 t1; // texture end point, direction <0,1> out vec4 col; void main() { int i; vec2 t,dt; vec4 c0,c1; dt=normalize(t1-t0)/float(txrsiz); c0=vec4(1.0,1.0,1.0,1.0); // light ray strength t=t0; if (dot(t1-t,dt)>0.0) for (i=0;i 

И, наконец, результат:

вывод

Анимированные 256 цветов GIF:

анимация вывода

Цвета в GIF слегка искажены из-за 8-битного усечения. Также, если анимация перестает обновлять страницу или открывать в decend gfx viewer.

свет внутри полупрозрачного объекта

  • Получение истинного значения z из буфера глубины
  • Система координат OpenGL левая или правая?
  • Как использовать glOrtho () в OpenGL?
  • Интерполирование между matrixми вращения
  • Можно ли вращать объект вокруг своей оси, а не вокруг оси базовой оси?
  • Рисование сферы в OpenGL без использования gluSphere ()?
  • Нарисуйте прямоугольник на qglwidget в определенное время
  • Масштабирование изображения (KeepAspectRatioByExpanding) через OpenGL
  • Как визуализировать глубину линейно в современном OpenGL с gl_FragCoord.z ​​в флеш-шейдере?
  • OpenGL определяет положение вершин в пикселях
  • Использование мышиного прокрутки в GLUT
  • Давайте будем гением компьютера.