当前位置: 首页 > 知识库问答 >
问题:

Mandelbrot使用LOVE2d通过GLSL中的着色器设置渲染圆,而不是分形

黄俊雄
2023-03-14

我试图渲染一个Mandelbrot设置使用GLSL,但我得到的是一个完整的圆...我已经检查了很多数学,但我根本找不到错误,所以我想也许问题是语义上的。

有人能看到出了什么问题吗?

还有,有人能给我一些关于组织、结构等方面的见解吗?我正在努力学习正确的编码,但很难找到关于样式的材料。

注意事项:着色器可以应用于任何图像

这个想法很简单(你可以跳过这个):

  • 如果z没有发散,则checkConvergence返回true(即abs(z)
GLSLShader = love.graphics.newShader[[
    vec2 c = vec2(1.0, 0.0);
    int tol = 100;

    vec4 black = vec4(0.0, 0.0, 0.0, 1.0);
    vec4 white = vec4(1.0, 1.0, 1.0, 1.0);

    bool checkConvergence(vec2 z) {
      return (z[0]*z[0] + z[1]*z[1] < 4);
    }

    vec2 sumSquare(vec2 z) {
      return vec2(z[0]*z[0] - z[1]*z[1] - c[0], 2 * z[0] * z[1] - c[1]);
    }

    int iterate(vec2 z) {
      int n = 0;
      while (checkConvergence(z) && (n < tol)) {
        vec2 z =  sumSquare(z);
        n = n + 1;
      }
      return n;
    }

    vec4 clr(int n){
      if(n == tol){return vec4(0.0,0.0,0.0,1.0);}

      int r, g, b;
      r = int(255*n + 47*(1-n));
      g = int(180*n + 136*(1-n));
      b = int(38*n + 255*(1-n));

      if (r > 255) {r = 255;}
      else{ 
        if(r<0){r = 0;}
      }

      if (g > 255) {g = 255;}
      else{
        if(g<0){g = 0;}
      }

      if (b > 255) {b = 255;}
      else{
        if(b<0){b = 0;}
      }

      return vec4(r, g, b, 1.0);

    }

    vec4 effect( vec4 color, Image texture, vec2 texture_coords, vec2 screen_coords){
      vec2 z = vec2(texture_coords.x*4-2, texture_coords.y*4-2);

      return clr(iterate(z));
    }
  ]]

使现代化

我尝试了@WeatherVane的一些建议:

  • 加C而不是减C

但都没有用,我还是得到了一个圆。我还尝试使用更多的迭代

我试图在不做太多改变的情况下简化编码。

我向clr函数添加了一个条件,如果n小于0或大于1,则返回绿色。奇怪的是圆圈是黑色的,屏幕的其余部分是白色的,但是我不知道这个白色是从哪里来的(因为clr从来不会为0返回白色

    vec2 c = vec2(0.0, 0.0);
    int tol = 1000;

    vec4 black = vec4(0.0, 0.0, 0.0, 1.0);
    vec4 white = vec4(1.0, 1.0, 1.0, 1.0);
    vec4 green = vec4(0.0, 1.0, 0.0, 1.0);

    int iterate(vec2 z) {
      int n = 0;

      while ( (z[0]*z[0] + z[1]*z[1] < 4) && (n < tol) ) {
        vec2 z =  vec2( z[0]*z[0] - z[1]*z[1]  + c[0], 2 * z[0] * z[1] + c[1] );
        n = n + 1;
      }

      return n;
    }

    vec4 clr(int n){
        n = n / tol;

        if(n == 1){return black;}
        if(n > 1 || n < 0){return green;}

        int r, g, b;
        r = int(255*n + 47*(1-n));
        g = int(180*n + 136*(1-n));
        b = int(38*n + 255*(1-n));

        return vec4(r, g, b, 1.0);

      }

    vec4 effect( vec4 color, Image texture, vec2 texture_coords, vec2 screen_coords){
      vec2 z = vec2(texture_coords.x*4-2, texture_coords.y*4-2);

      return clr(iterate(z));
    }

共有2个答案

慕云
2023-03-14
while ( ... ) {
    vec2 z = ...
}

摆脱vec2,您将在每次迭代中声明一个新变量。除此之外,请遵循@Bob__的一些建议(即,迭代(vec2c))。

南宫森
2023-03-14

迭代的起点应该作为向量c传递,而z从{0.0.0.0}开始。

正如你在https://en.wikipedia.org/wiki/Mandelbrot_set

如果从z=0开始并重复应用迭代z=z²c时,无论n变得多大,z的绝对值都保持有界,则复数c是Mandelbrot集的一部分。

您使用vec4来表示颜色,但在代码中,您使用整数值计算RGB组件,而不是使用浮点数。您应该转换为浮动,并将每个组件标准化到(0.0,1.0)范围。我试图纠正你的代码,但恐怕我真的不知道lua或love2d,我不能使用texture_coords,所以我使用screen_coords。我能做的最好的是:

function love.load()
    GLSLShader = love.graphics.newShader[[

        vec4 black = vec4(0.0, 0.0, 0.0, 1.0);
        vec4 white = vec4(1.0, 1.0, 1.0, 1.0);
        int max_iter = 1024;

        vec4 clr(int n){
            if(n == max_iter){return black;}

            float m = float(n)/float(max_iter);
            float r = float(mod(n,256))/32;
            float g = float(128 - mod(n+64,127))/255;
            float b = float(127 + mod(n,64))/255;

            if (r > 1.0) {r = 1.0;}
            else{ 
                if(r<0){r = 0;}
            }

            if (g > 1.0) {g = 1.0;}
            else{
                if(g<0){g = 0;}
            }

            if (b > 1.0) {b = 1.0;}
            else{
                if(b<0){b = 0;}
            }
            return vec4(r, g, b, 1.0);
        }

        vec4 effect( vec4 color, Image texture, vec2 texture_coords, vec2 screen_coords){

            vec2 c = vec2((screen_coords[0]-500)/200,(screen_coords[1]-300)/200);
            vec2 z = vec2(0.0,0.0);
            vec2 zn = vec2(0.0,0.0);
            int n_iter = 0;
            while ( (z[0]*z[0] + z[1]*z[1] < 4) &&  (n_iter < max_iter) ) {
                zn[0] = z[0]*z[0] - z[1]*z[1] + c[0];
                zn[1] = 2*z[0]*z[1] + c[1];
                z[0] = zn[0];
                z[1] = zn[1];
                n_iter++;
            }
            return clr(n_iter);
        }
    ]]
end

function love.draw()

    love.graphics.setShader(GLSLShader)
    love.graphics.rectangle('fill', 0,0,800,600)
    love.graphics.setShader()
end

这给了我这个输出:

 类似资料:
  • 我在Javascript上制作了一个程序,创建了mandelbrot分形,并在html画布上绘制了它。我的渲染方法是每行迭代,从0到500像素,然后简单地循环创建500行500像素。 我的问题是,当我渲染它的时候,(用更多的放大率刷新页面),它需要很多时间。300倍的放大率大约在30秒内工作,但5000倍需要一个多小时。请帮忙。我想有非常高的放大率和图像加载迅速。 我通过一个下载的文件运行我的程序

  • “渲染”(Rendering)是即使非计算机专业的都不会觉得陌生的词,虽然在很多人说这个词的时候,并不清楚“渲染”究竟意味着什么。相反,“着色器”(Shader)很可能是大家比较陌生的词,从名字看上去似乎是用来上色的,但它具体能做什么呢? 在解释着色器之前,我们先来聊聊渲染。 渲染 用通俗的话来说,渲染就是将模型数据在屏幕上显示出来的过程。 这听起来好像很简单呢!但正如你打开一个Word写文档一样

  • 所以我有一个非常简单的glsl着色器,可以用纹理和平行光渲染对象。 现在我有一个非常艰难的时间试图得到的纹理显示,其他一切工作,除此之外。 当我禁用着色器(glUseProgram(0))时,纹理以黑色和白色渲染,但当我启用它时,整个网格是单一颜色,没有纹理,当我尝试不同的纹理时,它会改变颜色。 这就是我加载纹理的方式 这就是我如何绑定我的纹理 这是我的顶点着色器 这是我的碎片着色器 最后但并非最

  • 我想在FBO中加载两个纹理,其中一个纹理包含HDR图像,我的第一个目标是将图像从第一个纹理“复制”到第二个纹理(该纹理为空),并称为“下采样纹理”。 所以我创建FBO,加载我想用颜色_附件_0书写的纹理,并绑定它;然后初始化我的着色器程序并渲染一个四边形,其中包含我要在GL\u texture\u 0中读取的纹理。 然后我解开FBO并绑定“DownSamplingTex”,然后画一个四元组。 我不

  • 我有一个非常简单的OpenGL应用程序,只渲染一个带纹理的四边形。这是我的代码,效果很好(带纹理的四边形看起来很好): 然后我想介绍一个简单的着色器。所以我稍微修改了我的代码: 顶点着色器: 片段着色器: 现在我得到的只是一个黑色的四边形:-( 我已经尝试并测试了很多东西: 着色器编译良好(无错误) 有人知道为什么我在使用着色器时看不到我的纹理吗?

  • 在一个教程之后,我将尝试使用FreeType在OpenGL中渲染文本。因此,灰度8位图像用作每个字符的纹理,使图像的每个字节对应于纹理的红色分量。 为了以其他颜色呈现文本,建议您使用着色器。但是,当使用提供的着色器时,我看到的不是彩色字母,而是彩色框,好像根本没有纹理。 以下是没有着色器时的效果: 这是它在着色器中的外观: (盒子的位置也会发生变化) 以下是顶点着色器代码: 这是片段着色器代码: