Фракталы и шейдеры. OpenGL 3.2+

Тема в разделе "WASM.OpenGL", создана пользователем ml64, 18 окт 2026 в 02:09.

  1. ml64

    ml64 Active Member

    Публикаций:
    0
    Регистрация:
    29 окт 2017
    Сообщения:
    140
    Вдохновлён примерами из книги Рэнди Дж. Роста "Трехмерная графика и язык программирования шейдеров".

    На движке RBMK64 построена плоскость, на плоскость натянута текстура.
    Всё просто:
    Код (C):
    1. #version 330 core
    2.  
    3. layout (location = 0) in vec3 aPos;
    4. layout (location = 1) in vec3 aNormal;   // unused by the fractal, kept for VAO compatibility
    5. layout (location = 2) in vec3 aColor;    // tint for the fractal
    6.  
    7. uniform mat4 uModel;
    8. uniform mat4 uView;
    9. uniform mat4 uProjection;
    10.  
    11. out vec2 vFractalUV;
    12. out vec3 vColor;
    13.  
    14. void main()
    15. {
    16.     vFractalUV = aPos.xy;
    17.     vColor    = aColor;
    18.     gl_Position = uProjection * uView * uModel * vec4(aPos, 1.0);
    19. }

    Код (C):
    1. #version 330 core
    2.  
    3. in vec2 vFractalUV;
    4. in vec3 vColor;
    5.  
    6. uniform vec2  uCenter;
    7. uniform float uZoom;
    8. uniform float uAspect;
    9.  
    10. out vec4 FragColor;
    11.  
    12. // IQ cosine palette — bright and continuous
    13. vec3 palette(float t)
    14. {
    15.     return 0.5 + 0.5 * cos(6.28318 * (vec3(1.0, 1.0, 1.0) * t +
    16.                                       vec3(0.0, 0.33, 0.67)));
    17. }
    18.  
    19. void main()
    20. {
    21.     vec2 p = vec2(vFractalUV.x * uAspect, vFractalUV.y) * uZoom + uCenter;
    22.  
    23.     float logScale = log2(max(1.0 / max(uZoom, 1e-6), 1.0));
    24.     float posTerm  = 0.5 * length(p - vec2(-0.75, 0.0));
    25.     int   maxIter  = int(64.0 + 32.0 * clamp(logScale + posTerm, 0.0, 12.0));
    26.     maxIter = min(maxIter, 512);
    27.  
    28.     vec2 z = vec2(0.0);
    29.     int i = 0;
    30.     for (; i < maxIter; ++i)
    31.     {
    32.         float zx2 = z.x * z.x;
    33.         float zy2 = z.y * z.y;
    34.         if (zx2 + zy2 > 4.0) break;
    35.         z = vec2(zx2 - zy2 + p.x, 2.0 * z.x * z.y + p.y);
    36.     }
    37.  
    38.     vec3 color;
    39.     if (i == maxIter)
    40.     {
    41.         // Interior: very dark purple instead of pure black
    42.         color = vec3(0.05, 0.0, 0.10);
    43.     }
    44.     else
    45.     {
    46.         float t = float(i) / float(maxIter);
    47.         t = pow(t, 0.4);             // log-ish spread: more range spent on small t
    48.         color = palette(t);
    49.     }
    50.  
    51.     FragColor = vec4(color * vColor, 1.0);
    52. }

    Все преимущества 3D-движка сохраняются (движение, вращение)

    Единственное, чего пока не сделал: фрактал - это самоподобие, для фрактала очень важен зум.
    нужен динамический пересчёт перспективы (near-far), ну и итеративный пересчёт геометрии, конечно.

    ...и для фракталов размер float - уже маловат. Но переписать движок ради фрактала я пока не готов.

    Mandelbrot.jpg
     

    Вложения:

    • Mandelbrot.7z
      Размер файла:
      33,4 КБ
      Просмотров:
      10
    Последнее редактирование: 18 окт 2026 в 03:48
    Mikl___ нравится это.
  2. Mikl___

    Mikl___ Супермодератор Команда форума

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    4.293
  3. Ahimov

    Ahimov Active Member

    Публикаций:
    0
    Регистрация:
    14 окт 2024
    Сообщения:
    908
    ml64,

    Похоже?

    _outfr.png

    z.ai собрал по исходному проекту, дипси упростил.
     

    Вложения:

    • _outfr.mp4
      Размер файла:
      12,9 МБ
      Просмотров:
      8
    • _fr.txt
      Размер файла:
      6,3 КБ
      Просмотров:
      8
    ml64 нравится это.
  4. Dmitry_Milk

    Dmitry_Milk Member

    Публикаций:
    0
    Регистрация:
    20 ноя 2007
    Сообщения:
    601
    Нафига? Мандельброт как раз тем и хорош, что у него каждая точка считается независимо. Он прям как будто предназначен, чтоб считать шейдером параллельно.
     
    ml64 нравится это.
  5. ml64

    ml64 Active Member

    Публикаций:
    0
    Регистрация:
    29 окт 2017
    Сообщения:
    140
    Да, LLM добавили итеративность. Я у себя тоже обязательно сделаю.

    Знаю, знаю. Но мне уже очень хотелось увидеть мой первый фрактал, построенный шейдером, поэтому сделал, как быстрее.
    Что дальше:
    1) я убираю из движка всё, что касается 3D-матриц;
    2) меняю размер на double;
    3) вставляю 2D-геометрию (full-screen quad или surface в терминологии Vulkan и Direct3D);
    4) получаю всё равно текстуру, натянутую на полигон (ну так это работает);
    5) вместо движения камеры вперёд-назад делаю зум с расчётом нужной глубины итераций. Шаг зума - не линейный, как при движении камеры, а логарифмический, но это не точно.
     
    Последнее редактирование: 18 окт 2026 в 14:58
    Mikl___ нравится это.
  6. GRAFik

    GRAFik Active Member

    Публикаций:
    0
    Регистрация:
    14 мар 2020
    Сообщения:
    571
    Предлагаю сброситься, выкупить этот сайт и оживить его. Всё равно хозяева его забросили, может отдадут задешево, а то и вообще, бесплатно подарят. :) :offtopic:
    https://www.demoscene.ru/forum/
     
    Application нравится это.
  7. Dmitry_Milk

    Dmitry_Milk Member

    Публикаций:
    0
    Регистрация:
    20 ноя 2007
    Сообщения:
    601
    Действительно мертвый, в "музыке" ни одной моей биперной демки за этот год.

    Правда непонятно, какое это имеет отношение к названию этой темы?

    Насчет хозяев - с этого года делегирование доменов в зоне ру возможно только с подтверждением через Госуслуги.
     
  8. GRAFik

    GRAFik Active Member

    Публикаций:
    0
    Регистрация:
    14 мар 2020
    Сообщения:
    571
    Ну как же, а фракталы, а шейдеры. Мне раньше иногда казалось, что Битл кроме терминов: ассемблер и шейдеры - больше никаких терминов и не знает. Ну и термин фракталы, он иногда в своих комментариях использовал. :)