Changeset 1078


Ignore:
Timestamp:
Nov 20, 2011, 12:34:25 AM (7 years ago)
Author:
sam
Message:

tutorial: look into previous frames for data when zooming in the Mandelbrot
viewer using only the shader.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/test/tutorial/tut03.cpp

    r1077 r1078  
    4747    Fractal(ivec2 const &size)
    4848    {
    49         /* Ensure size has even X and Y values */
     49        /* Ensure texture size is a multiple of 16 for better aligned
     50         * data access. Store the dimensions of a texel for our shader. */
    5051        m_size = size;
    51         m_size.x = (m_size.x + 1) & ~1;
    52         m_size.y = (m_size.y + 1) & ~1;
    53 
     52        m_size.x = (m_size.x + 15) & ~15;
     53        m_size.y = (m_size.y + 15) & ~15;
     54        m_texel_settings = vec4(vec2(1.0, 1.0) / (vec2)m_size, m_size);
     55
     56        /* Window size decides the world aspect ratio. For instance, 640×480
     57         * will be mapped to (-0.66,-0.5) - (0.66,0.5). */
    5458        m_window_size = Video::GetSize();
     59        if (m_window_size.y < m_window_size.x)
     60            m_window2world = 0.5 / m_window_size.y;
     61        else
     62            m_window2world = 0.5 / m_window_size.x;
     63        m_texel2world = (vec2)m_window_size / (vec2)m_size * m_window2world;
     64
    5565        m_pixels = new u8vec4[m_size.x * m_size.y];
    5666        m_tmppixels = new u8vec4[m_size.x / 2 * m_size.y / 2];
     
    6373        }
    6474        m_center = -0.75;
    65         m_radius = 1.5;
    66         m_texture_radius = 0.5 * (m_size.x < m_size.y ? m_size.x : m_size.y);
    67         m_window_radius = 0.5 * (m_window_size.x < m_window_size.y ? m_window_size.x : m_window_size.y);
    68         m_pixel_delta = vec4(vec2(1.0, 1.0) / (vec2)m_size, m_size);
     75        m_radius = 5.0;
    6976        m_ready = false;
    7077
     
    7279        for (int i = 0; i < (MAX_ITERATIONS + 1) * PALETTE_STEP; i++)
    7380        {
    74             float f = i / (double)PALETTE_STEP;
     81            double f = (double)i / PALETTE_STEP;
    7582
    7683            double r = 0.5 * sin(f * 0.27 - 2.5) + 0.5;
     
    7885            double b = 0.5 * sin(f * 0.21 + 0.4) + 0.5;
    7986
    80             uint8_t red = r * 255.0f;
    81             uint8_t green = g * 255.0f;
    82             uint8_t blue = b * 255.0f;
     87            if (f < 7.0)
     88            {
     89                f = f < 1.0 ? 0.0 : (f - 1.0) / 6.0;
     90                r *= f;
     91                g *= f;
     92                b *= f;
     93            }
     94
     95            uint8_t red = r * 255.99f;
     96            uint8_t green = g * 255.99f;
     97            uint8_t blue = b * 255.99f;
    8398            m_palette[i] = u8vec4(blue, green, red, 0);
    8499        }
     
    115130    inline f64cmplx TexelToWorldOffset(ivec2 texel)
    116131    {
    117         f64cmplx tmp = f64cmplx(0.5 + texel.x - m_size.x / 2,
    118                                 0.5 + m_size.y / 2 - texel.y);
    119         return tmp * (m_radius / m_texture_radius);
     132        double dx = (0.5 + texel.x - m_size.x / 2) * m_texel2world.x;
     133        double dy = (0.5 + m_size.y / 2 - texel.y) * m_texel2world.y;
     134        return m_radius * f64cmplx(dx, dy);
    120135    }
    121136
     
    124139        /* No 0.5 offset here, because we want to be able to position the
    125140         * mouse at (0,0) exactly. */
    126         f64cmplx tmp = f64cmplx(pixel.x - m_window_size.x / 2,
    127                                 m_window_size.y / 2 - pixel.y);
    128         return tmp * (m_radius / m_window_radius);
     141        double dx = pixel.x - m_window_size.x / 2;
     142        double dy = m_window_size.y / 2 - pixel.y;
     143        return m_radius * m_window2world * f64cmplx(dx, dy);
    129144    }
    130145
     
    133148        WorldEntity::TickGame(deltams);
    134149
     150        int prev_frame = m_frame;
    135151        m_frame = (m_frame + 1) % 4;
    136152
     
    161177#endif
    162178
    163             /* Store the transformation properties to go from m_frame-1
     179            /* Store the transformation properties to go from m_frame - 1
    164180             * to m_frame. */
    165             m_deltashift[m_frame] = (oldcenter - m_center) / m_radius;
    166             m_deltascale[m_frame] = oldradius / m_radius;
     181            m_deltashift[prev_frame] = (m_center - oldcenter) / oldradius;
     182            m_deltashift[prev_frame].x /= m_size.x * m_texel2world.x;
     183            m_deltashift[prev_frame].y /= m_size.y * m_texel2world.y;
     184            m_deltascale[prev_frame] = m_radius / oldradius;
    167185            m_dirty[0] = m_dirty[1] = m_dirty[2] = m_dirty[3] = 2;
    168186        }
     
    171189            /* If settings didn't change, set transformation from previous
    172190             * frame to identity. */
    173             m_deltashift[m_frame] = 0.0;
    174             m_deltascale[m_frame] = 1.0;
     191            m_deltashift[prev_frame] = 0.0;
     192            m_deltascale[prev_frame] = 1.0;
    175193        }
    176194
    177195        if (buttons[1])
    178196            m_dirty[0] = m_dirty[1] = m_dirty[2] = m_dirty[3] = 2;
     197
     198        /* Transformation from current frame to current frame is always
     199         * identity. */
     200        m_zoom_settings[m_frame][0] = 0.0f;
     201        m_zoom_settings[m_frame][1] = 0.0f;
     202        m_zoom_settings[m_frame][2] = 1.0f;
     203
     204        /* Compute transformation from other frames to current frame */
     205        for (int i = 0; i < 3; i++)
     206        {
     207            int prev_index = (m_frame + 4 - i) % 4;
     208            int cur_index = (m_frame + 3 - i) % 4;
     209
     210            m_zoom_settings[cur_index][0] = m_zoom_settings[prev_index][0] * m_deltascale[cur_index] + m_deltashift[cur_index].x;
     211            m_zoom_settings[cur_index][1] = m_zoom_settings[prev_index][1] * m_deltascale[cur_index] + m_deltashift[cur_index].y;
     212            m_zoom_settings[cur_index][2] = m_zoom_settings[prev_index][2] * m_deltascale[cur_index];
     213        }
    179214
    180215        char buf[128];
     
    292327                "#version 120\n"
    293328                ""
    294                 "uniform vec4 in_PixelDelta;"
     329                "uniform vec4 in_TexelSize;"
     330                "uniform mat4 in_ZoomSettings;"
    295331                "uniform sampler2D in_Texture;"
     332                ""
     333                "float mylen(vec2 p) {"
     334                //"    return abs(p.x) + abs(p.y);"
     335                //"    return p.x * p.x + p.y * p.y;"
     336                "    return length(p);"
     337                "}"
    296338                ""
    297339                /* Get the coordinate of the nearest point in slice 0 in xy,
     
    300342                 * return value has the 0.25 Y scaling. */
    301343                "vec3 nearest0(vec2 p) {"
    302                 "    vec2 q = p + 0.5 * in_PixelDelta.xy;"
    303                 "    q -= mod(q, 2.0 * in_PixelDelta.xy);"
    304                 "    q += 0.5 * in_PixelDelta.xy;"
    305                 "    return vec3(q * vec2(1.0, 0.25),"
    306                 "                length(q - p));"
     344                "    p -= vec2(0.5, 0.5);"
     345                "    p *= in_ZoomSettings[0][2];"
     346                "    p += vec2(in_ZoomSettings[0][0], -in_ZoomSettings[0][1]);"
     347                "    p += vec2(0.5, 0.5);"
     348                "    vec2 q = p + 0.5 * in_TexelSize.xy;"
     349                "    q -= mod(q, 2.0 * in_TexelSize.xy);"
     350                "    q += 0.5 * in_TexelSize.xy;"
     351                "    float l = (abs(q.x - 0.5) < 0.5 && abs(q.y - 0.5) < 0.5)"
     352                "             ? 1.0 / mylen(q - p) : 0.0;"
     353                "    return vec3(q * vec2(1.0, 0.25), l);"
    307354                "}"
    308355                ""
    309356                "vec3 nearest1(vec2 p) {"
    310                 "    vec2 q = p - 0.5 * in_PixelDelta.xy;"
    311                 "    q -= mod(q, 2.0 * in_PixelDelta.xy);"
    312                 "    q += 1.5 * in_PixelDelta.xy;"
    313                 "    return vec3(q * vec2(1.0, 0.25) + vec2(0.0, 0.25),"
    314                 "                length(q - p));"
     357                "    p -= vec2(0.5, 0.5);"
     358                "    p *= in_ZoomSettings[1][2];"
     359                "    p += vec2(in_ZoomSettings[1][0], -in_ZoomSettings[1][1]);"
     360                "    p += vec2(0.5, 0.5);"
     361                "    vec2 q = p + -0.5 * in_TexelSize.xy;"
     362                "    q -= mod(q, 2.0 * in_TexelSize.xy);"
     363                "    q += 1.5 * in_TexelSize.xy;"
     364                "    float l = (abs(q.x - 0.5) < 0.5 && abs(q.y - 0.5) < 0.5)"
     365                "             ? 1.0 / mylen(q - p) : 0.0;"
     366                "    return vec3(q * vec2(1.0, 0.25) + vec2(0.0, 0.25), l);"
    315367                "}"
    316368                ""
    317369                "vec3 nearest2(vec2 p) {"
    318                 "    vec2 q = p + vec2(0.5, -0.5) * in_PixelDelta.xy;"
    319                 "    q -= mod(q, 2.0 * in_PixelDelta.xy);"
    320                 "    q += vec2(0.5, 1.5) * in_PixelDelta.xy;"
    321                 "    return vec3(q * vec2(1.0, 0.25) + vec2(0.0, 0.50),"
    322                 "                length(q - p));"
     370                "    p -= vec2(0.5, 0.5);"
     371                "    p *= in_ZoomSettings[2][2];"
     372                "    p += vec2(in_ZoomSettings[2][0], -in_ZoomSettings[2][1]);"
     373                "    p += vec2(0.5, 0.5);"
     374                "    vec2 q = p + vec2(0.5, -0.5) * in_TexelSize.xy;"
     375                "    q -= mod(q, 2.0 * in_TexelSize.xy);"
     376                "    q += vec2(0.5, 1.5) * in_TexelSize.xy;"
     377                "    float l = (abs(q.x - 0.5) < 0.5 && abs(q.y - 0.5) < 0.5)"
     378                "             ? 1.0 / mylen(q - p) : 0.0;"
     379                "    return vec3(q * vec2(1.0, 0.25) + vec2(0.0, 0.50), l);"
    323380                "}"
    324381                ""
    325382                "vec3 nearest3(vec2 p) {"
    326                 "    vec2 q = p + vec2(-0.5, 0.5) * in_PixelDelta.xy;"
    327                 "    q -= mod(q, 2.0 * in_PixelDelta.xy);"
    328                 "    q += vec2(1.5, 0.5) * in_PixelDelta.xy;"
    329                 "    return vec3(q * vec2(1.0, 0.25) + vec2(0.0, 0.75),"
    330                 "                length(q - p));"
     383                "    p -= vec2(0.5, 0.5);"
     384                "    p *= in_ZoomSettings[3][2];"
     385                "    p += vec2(in_ZoomSettings[3][0], -in_ZoomSettings[3][1]);"
     386                "    p += vec2(0.5, 0.5);"
     387                "    vec2 q = p + vec2(-0.5, 0.5) * in_TexelSize.xy;"
     388                "    q -= mod(q, 2.0 * in_TexelSize.xy);"
     389                "    q += vec2(1.5, 0.5) * in_TexelSize.xy;"
     390                "    float l = (abs(q.x - 0.5) < 0.5 && abs(q.y - 0.5) < 0.5)"
     391                "             ? 1.0 / mylen(q - p) : 0.0;"
     392                "    return vec3(q * vec2(1.0, 0.25) + vec2(0.0, 0.75), l);"
    331393                "}"
    332394                ""
     
    336398                 * an exact texel boundary. This would lead to visual
    337399                 * artifacts. */
    338                 "    coord -= 0.1 * in_PixelDelta.xy;"
     400                "    coord -= 0.1 * in_TexelSize.xy;"
    339401                /* Get a pixel from each slice */
    340                 "    vec4 p0 = texture2D(in_Texture, nearest0(coord).xy);"
    341                 "    vec4 p1 = texture2D(in_Texture, nearest1(coord).xy);"
    342                 "    vec4 p2 = texture2D(in_Texture, nearest2(coord).xy);"
    343                 "    vec4 p3 = texture2D(in_Texture, nearest3(coord).xy);"
    344                 "    gl_FragColor = 0.25 * (p0 + p1 + p2 + p3);"
     402                "    vec3 k0 = nearest0(coord);"
     403                "    vec3 k1 = nearest1(coord);"
     404                "    vec3 k2 = nearest2(coord);"
     405                "    vec3 k3 = nearest3(coord);"
     406                "    vec4 p0 = texture2D(in_Texture, k0.xy);"
     407                "    vec4 p1 = texture2D(in_Texture, k1.xy);"
     408                "    vec4 p2 = texture2D(in_Texture, k2.xy);"
     409                "    vec4 p3 = texture2D(in_Texture, k3.xy);"
     410//"if (k0.z >= k1.z && k0.z >= k2.z && k0.z >= k3.z) gl_FragColor = p0;"
     411//"if (k1.z >= k0.z && k1.z >= k2.z && k1.z >= k3.z) gl_FragColor = p1;"
     412//"if (k2.z >= k0.z && k2.z >= k1.z && k2.z >= k3.z) gl_FragColor = p2;"
     413//"if (k3.z >= k0.z && k3.z >= k1.z && k3.z >= k2.z) gl_FragColor = p3;"
     414                "    gl_FragColor = 1.0 / (k0.z + k1.z + k2.z + k3.z)"
     415                "          * (k0.z * p0 + k1.z * p1 + k2.z * p2 + k3.z * p3);"
    345416                "}"
    346417#else
     
    354425                "}",
    355426
    356                 "float3 nearest0(float2 p, float4 in_PixelDelta) {"
    357                 "    float2 q = p + 0.5 * in_PixelDelta.xy;"
    358                 "    q -= fmod(q, 2.0 * in_PixelDelta.xy);"
    359                 "    q += 0.5 * in_PixelDelta.xy;"
     427                "float3 nearest0(float2 p, float4 in_TexelSize) {"
     428                "    float2 q = p + 0.5 * in_TexelSize.xy;"
     429                "    q -= fmod(q, 2.0 * in_TexelSize.xy);"
     430                "    q += 0.5 * in_TexelSize.xy;"
    360431                "    return float3(q * float2(1.0, 0.25),"
    361432                "                  length(q - p));"
    362433                "}"
    363434                ""
    364                 "float3 nearest1(float2 p, float4 in_PixelDelta) {"
    365                 "    float2 q = p - 0.5 * in_PixelDelta.xy;"
    366                 "    q -= fmod(q, 2.0 * in_PixelDelta.xy);"
    367                 "    q += 1.5 * in_PixelDelta.xy;"
     435                "float3 nearest1(float2 p, float4 in_TexelSize) {"
     436                "    float2 q = p - 0.5 * in_TexelSize.xy;"
     437                "    q -= fmod(q, 2.0 * in_TexelSize.xy);"
     438                "    q += 1.5 * in_TexelSize.xy;"
    368439                "    return float3(q * float2(1.0, 0.25) + float2(0.0, 0.25),"
    369440                "                  length(q - p));"
    370441                "}"
    371442                ""
    372                 "float3 nearest2(float2 p, float4 in_PixelDelta) {"
    373                 "    float2 q = p + float2(0.5, -0.5) * in_PixelDelta.xy;"
    374                 "    q -= fmod(q, 2.0 * in_PixelDelta.xy);"
    375                 "    q += float2(0.5, 1.5) * in_PixelDelta.xy;"
     443                "float3 nearest2(float2 p, float4 in_TexelSize) {"
     444                "    float2 q = p + float2(0.5, -0.5) * in_TexelSize.xy;"
     445                "    q -= fmod(q, 2.0 * in_TexelSize.xy);"
     446                "    q += float2(0.5, 1.5) * in_TexelSize.xy;"
    376447                "    return float3(q * float2(1.0, 0.25) + float2(0.0, 0.50),"
    377448                "                  length(q - p));"
    378449                "}"
    379450                ""
    380                 "float3 nearest3(float2 p, float4 in_PixelDelta) {"
    381                 "    float2 q = p + float2(-0.5, 0.5) * in_PixelDelta.xy;"
    382                 "    q -= fmod(q, 2.0 * in_PixelDelta.xy);"
    383                 "    q += float2(1.5, 0.5) * in_PixelDelta.xy;"
     451                "float3 nearest3(float2 p, float4 in_TexelSize) {"
     452                "    float2 q = p + float2(-0.5, 0.5) * in_TexelSize.xy;"
     453                "    q -= fmod(q, 2.0 * in_TexelSize.xy);"
     454                "    q += float2(1.5, 0.5) * in_TexelSize.xy;"
    384455                "    return float3(q * float2(1.0, 0.25) + float2(0.0, 0.75),"
    385456                "                  length(q - p));"
     
    387458                ""
    388459                "void main(float2 in_TexCoord : TEXCOORD0,"
    389                 "          uniform float4 in_PixelDelta,"
     460                "          uniform float4 in_TexelSize,"
    390461                "          uniform sampler2D in_Texture,"
    391462                "          out float4 out_FragColor : COLOR)"
    392463                "{"
    393464                "    float2 coord = in_TexCoord.xy;"
    394                 "    coord -= 0.1 * in_PixelDelta.xy;"
    395                 "    float4 p0 = tex2D(in_Texture, nearest0(coord, in_PixelDelta).xy);"
    396                 "    float4 p1 = tex2D(in_Texture, nearest1(coord, in_PixelDelta).xy);"
    397                 "    float4 p2 = tex2D(in_Texture, nearest2(coord, in_PixelDelta).xy);"
    398                 "    float4 p3 = tex2D(in_Texture, nearest3(coord, in_PixelDelta).xy);"
     465                "    coord -= 0.1 * in_TexelSize.xy;"
     466                "    float4 p0 = tex2D(in_Texture, nearest0(coord, in_TexelSize).xy);"
     467                "    float4 p1 = tex2D(in_Texture, nearest1(coord, in_TexelSize).xy);"
     468                "    float4 p2 = tex2D(in_Texture, nearest2(coord, in_TexelSize).xy);"
     469                "    float4 p3 = tex2D(in_Texture, nearest3(coord, in_TexelSize).xy);"
    399470                "    out_FragColor = 0.25 * (p0 + p1 + p2 + p3);"
    400471                "}"
     
    403474            m_vertexattrib = m_shader->GetAttribLocation("in_Vertex");
    404475            m_texattrib = m_shader->GetAttribLocation("in_TexCoord");
    405             m_pixeluni = m_shader->GetUniformLocation("in_PixelDelta");
     476            m_texeluni = m_shader->GetUniformLocation("in_TexelSize");
     477            m_zoomuni = m_shader->GetUniformLocation("in_ZoomSettings");
    406478            m_ready = true;
    407479
     
    446518
    447519        m_shader->Bind();
    448         m_shader->SetUniform(m_pixeluni, m_pixel_delta);
     520        m_shader->SetUniform(m_texeluni, m_texel_settings);
     521        m_shader->SetUniform(m_zoomuni, m_zoom_settings);
    449522#if !defined __CELLOS_LV2__ && !defined __ANDROID__
    450523        glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
     
    487560
    488561    ivec2 m_size, m_window_size;
     562    double m_window2world;
     563    f64vec2 m_texel2world;
    489564    u8vec4 *m_pixels, *m_tmppixels, *m_palette;
    490565    Shader *m_shader;
     
    494569    GLuint m_tco;
    495570#endif
    496     int m_vertexattrib, m_texattrib, m_pixeluni;
     571    int m_vertexattrib, m_texattrib, m_texeluni, m_zoomuni;
    497572    int m_frame, m_dirty[4];
    498573    bool m_ready;
    499574
    500575    f64cmplx m_center;
    501     double m_radius, m_texture_radius, m_window_radius;
    502     vec4 m_pixel_delta;
     576    double m_radius;
     577    vec4 m_texel_settings;
     578    mat4 m_zoom_settings;
    503579    f64cmplx m_deltashift[4];
    504580    double m_deltascale[4];
Note: See TracChangeset for help on using the changeset viewer.