Шейдер изогнутого матового стекла?

Хорошо сделать что-то прозрачным не так уж и сложно, но мне нужно, чтобы эта прозрачность отличалась в зависимости от кривой объекта, чтобы он выглядел не просто как плоский объект. Нечто подобное на картинке ниже.

Центр более прозрачен, чем стороны цилиндра, он более черный, что является фоновым цветом. Затем есть лицевая панель, которая, кажется, имеет какое-то зеркальное освещение сверху, чтобы сделать ее более блестящей, но я не представляю, как добиться такой прозрачности в этом случае. Используя нормали поверхности относительно положения глаза, чтобы определить значение прозрачности? Любая помощь будет оценена.

1 ответ

Решение

(переместил комментарии в ответ и добавил еще несколько деталей)

Используйте (Sub Surface) рассеивание вместо прозрачности.

Вы можете многое упростить, например, предполагая, что источник света постоянен по всей поверхности / объему... так что вам нужна только интеграция лучей обзора, а не интеграл всего объема по лучу... Я делаю это в своем Атмосферном шейдере, и это все еще выглядит довольно удивительно, почти неотличимо от реальных вещей, посмотрите некоторые новые скриншоты... сравнили их с фотографиями с Земли и Марса и результатами, которые довольно близки без ДЕЙСТВИТЕЛЬНО СЛОЖНОЙ МАТЫ.

Есть еще варианты, как этого добиться:

  1. Воксельная карта (объемный рендеринг)

    Легко реализовать рассеяние в движке объемного рендеринга, но требует много памяти и мощности.

  2. используйте 2 буфера глубины (передняя и задняя поверхность)

    для этого нужно 2 прохода с включенным Cull face и настройками CW/CCW. Это также легко реализовать, но это не может обрабатывать несколько объектов в одном и том же виде вдоль оси Z вида камеры. Идея состоит в том, чтобы передать оба буфера глубины в шейдер и интегрировать пиксельные лучи вдоль его пути, накапливая / поглощая свет от источника света. Что-то вроде этого:

    SSS 2 Буферы глубины

    1. рендерит геометрию в оба буфера глубины как 2 текстуры.
    2. рендеринг четырехугольника, охватывающего весь экран
    3. для каждого фрагмента вычисляют лучевую линию (зеленая)
    4. вычислить точки пересечения в буферах глубины кабины получить "длина, анг"
    5. интегрировать по длине, используя рассеяние, чтобы вычислить цвет пикселей

      Я использую что-то вроде этого:

         vec3 p,p0,p1; // p0 front and p1 back face ray/depth buffer intersection points
         int n=16; // integration steps
         dl=(p1-p0)/float(n); // integration step vector
         vec3 c=background color;
         float q=dot(normalize(p1-p0),light)=fabs(cos(ang)); // normal light shading
      
         for (p=p1,i=0;i<n;p1-=dp,i++)                // p = p1 -> p0 path through object
              {
              b=B0.rgb*dl;  // B0 is saturated color of object
              c.r*=1.0-b.r; // some light is absorbed
              c.g*=1.0-b.g;
              c.b*=1.0-b.b;
              c+=b*q;       // some light is scattered in
              } // here c is the final fragment color
      

    После / во время интеграции вы должны нормализовать цвет... так, чтобы результирующий цвет был насыщен по всей глубине видимого материала. для получения дополнительной информации см. ссылку на рассеяние в атмосфере ниже (этот фрагмент кода извлечен из него)

  3. представление аналитического объекта

    Если вы знаете уравнение поверхности, то вы можете вычислить пересечения пути света внутри шейдера без необходимости использовать буферы глубины или карту вокселей. Этот простой шейдер GLSL для атмосферы использует этот подход, поскольку с эллипсоидами действительно легко справиться.

  4. Луч трассировщик

    Если вам нужна точность и вы не можете использовать карты Voxel, тогда вы можете попробовать движки трассировки лучей. Но все средства визуализации / механизмы рассеяния (в том числе#1,#2,#3) в любом случае являются трассировщиками лучей... Как вы можете видеть, все обсуждаемые здесь методы одинаковы, единственное отличие состоит в способе получения точек пересечения границы луч / объект,

Другие вопросы по тегам