source: trunk/test/tutorial/tut03.cpp @ 1060

Last change on this file since 1060 was 1060, checked in by sam, 9 years ago

tutorial: zoom automatically in the fractal viewer.

  • Property svn:keywords set to Id
File size: 8.4 KB
Line 
1//
2// Lol Engine - Fractal tutorial
3//
4// Copyright: (c) 2011 Sam Hocevar <sam@hocevar.net>
5//   This program is free software; you can redistribute it and/or
6//   modify it under the terms of the Do What The Fuck You Want To
7//   Public License, Version 2, as published by Sam Hocevar. See
8//   http://sam.zoy.org/projects/COPYING.WTFPL for more details.
9//
10
11#if defined HAVE_CONFIG_H
12#   include "config.h"
13#endif
14
15#include <cstring>
16
17#include "core.h"
18#include "lolgl.h"
19#include "loldebug.h"
20
21using namespace std;
22using namespace lol;
23
24#if USE_SDL && defined __APPLE__
25#   include <SDL_main.h>
26#endif
27
28#if defined _WIN32
29#   undef main /* FIXME: still needed? */
30#   include <direct.h>
31#endif
32
33class Fractal : public WorldEntity
34{
35public:
36    Fractal(ivec2 const &size)
37    {
38        m_size = size;
39        m_pixels = new u8vec4[size.x * size.y];
40        m_time = 0.0f;
41        m_ready = false;
42    }
43
44    ~Fractal()
45    {
46        delete m_pixels;
47    }
48
49    virtual void TickGame(float deltams)
50    {
51        WorldEntity::TickGame(deltams);
52
53        m_time += deltams * 0.0005f;
54
55        f64cmplx center(0.001643721971153, 0.822467633298876);
56        //f64cmplx center(0.28693186889504513, 0.014286693904085048);
57        double radius = 8.0 * pow(2.0, -m_time);
58        double step = radius / (m_size.x > m_size.y ? m_size.x : m_size.y);
59
60        for (int j = 0; j < m_size.y; j++)
61        for (int i = 0; i < m_size.x; i++)
62        {
63            double const maxlen = 32;
64            int const colors = 16;
65            int const maxiter = 200;
66
67            f64cmplx delta(i - m_size.x / 2, j - m_size.y / 2);
68
69            f64cmplx z0 = center + step * delta;
70            f64cmplx r0 = z0;
71            //f64cmplx r0(0.28693186889504513, 0.014286693904085048);
72            //f64cmplx r0(-0.824,0.1711);
73            //f64cmplx r0(0.001643721971153, 0.822467633298876);
74            f64cmplx z;
75            int iter = maxiter;
76            for (z = z0; iter && z.sqlen() < maxlen * maxlen; z = z * z + r0)
77                --iter;
78
79            double f = iter;
80            double n = z.sqlen();
81
82            /* Approximate log2(x) with x-1 because x is in [1,2]. */
83            f += (log(n) * 0.5f / log(maxlen)) - 1.0f;
84
85            if (iter)
86            {
87                double r = fmod(f, (double)colors);
88                if (r > (double)colors / 2) r = (double)colors - r;
89                double g = fmod(f * 1.3 + 4.0f, (double)colors);
90                if (g > (double)colors / 2) g = (double)colors - g;
91                double b = fmod(f * 1.7 - 8.0f, (double)colors);
92                if (b > (double)colors / 2) b = (double)colors - b;
93
94                uint8_t red = 255 - r * (255.0f / (colors + 1));
95                uint8_t green = 255 - g * (255.0f / (colors + 1));
96                uint8_t blue = 255 - b * (255.0f / (colors + 1));
97                m_pixels[j * m_size.x + i] = u8vec4(red, green, blue, 0);
98            }
99            else
100            {
101                m_pixels[j * m_size.x + i] = u8vec4(0, 0, 0, 0);
102            }
103        }
104    }
105
106    virtual void TickDraw(float deltams)
107    {
108        WorldEntity::TickDraw(deltams);
109
110        static float const vertices[] =
111        {
112             1.0f,  1.0f,
113            -1.0f,  1.0f,
114            -1.0f, -1.0f,
115            -1.0f, -1.0f,
116             1.0f, -1.0f,
117             1.0f,  1.0f,
118        };
119
120        static float const texcoords[] =
121        {
122             0.0f,  0.0f,
123             1.0f,  0.0f,
124             1.0f,  1.0f,
125             1.0f,  1.0f,
126             0.0f,  1.0f,
127             0.0f,  0.0f,
128        };
129
130        if (!m_ready)
131        {
132            glGenTextures(1, &m_texid);
133            glBindTexture(GL_TEXTURE_2D, m_texid);
134            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_size.x, m_size.y, 0,
135                         GL_RGBA, GL_UNSIGNED_BYTE, m_pixels);
136            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
137            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
138
139            m_shader = Shader::Create(
140#if !defined __CELLOS_LV2__
141                "#version 120\n"
142                "attribute vec2 in_TexCoord;\n"
143                "attribute vec2 in_Vertex;"
144                "void main(void) {"
145                "    gl_Position = vec4(in_Vertex, 0.0, 1.0);"
146                "    gl_TexCoord[0] = vec4(in_TexCoord, 0.0, 0.0);\n"
147                "}",
148
149                "#version 120\n"
150                "uniform sampler2D in_Texture;\n"
151                "void main(void) {"
152                "    gl_FragColor = texture2D(in_Texture, gl_TexCoord[0].xy);"
153                "}"
154#else
155                "void main(float4 in_Position : POSITION,"
156                "          float2 in_TexCoord : TEXCOORD0,"
157                "          out float4 out_Position : POSITION,"
158                "          out float2 out_TexCoord : TEXCOORD0)"
159                "{"
160                "    out_TexCoord = in_TexCoord;"
161                "    out_Position = in_Position;"
162                "}",
163
164                "void main(float2 in_TexCoord : TEXCOORD0,"
165                "          uniform sampler2D tex,"
166                "          out float4 out_FragColor : COLOR)"
167                "{"
168                "    out_FragColor = tex2D(tex, in_TexCoord);"
169                "}"
170#endif
171            );
172            m_vertexattrib = m_shader->GetAttribLocation("in_Vertex");
173            m_texattrib = m_shader->GetAttribLocation("in_TexCoord");
174            m_ready = true;
175
176#if !defined __CELLOS_LV2__ && !defined __ANDROID__ && !defined __APPLE__
177            /* Method 1: store vertex buffer on the GPU memory */
178            glGenBuffers(1, &m_vbo);
179            glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
180            glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices,
181                         GL_STATIC_DRAW);
182            glGenBuffers(1, &m_tbo);
183            glBindBuffer(GL_ARRAY_BUFFER, m_tbo);
184            glBufferData(GL_ARRAY_BUFFER, sizeof(texcoords), texcoords,
185                         GL_STATIC_DRAW);
186#elif !defined __CELLOS_LV2__ && !defined __ANDROID__ && !defined __APPLE__
187            /* Method 2: upload vertex information at each frame */
188#else
189#endif
190
191            /* FIXME: this object never cleans up */
192        }
193
194        glEnable(GL_TEXTURE_2D);
195        glBindTexture(GL_TEXTURE_2D, m_texid);
196        glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_size.x, m_size.y,
197#if !defined __CELLOS_LV2__
198                        GL_RGBA, GL_UNSIGNED_BYTE,
199#else
200                        /* The PS3 is big-endian */
201                        GL_RGBA, GL_UNSIGNED_INT_8_8_8_8,
202#endif
203                        m_pixels);
204
205        m_shader->Bind();
206#if !defined __CELLOS_LV2__ && !defined __ANDROID__ && !defined __APPLE__
207        glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
208        glEnableVertexAttribArray(m_vertexattrib);
209        glVertexAttribPointer(m_vertexattrib, 2, GL_FLOAT, GL_FALSE, 0, 0);
210
211        glBindBuffer(GL_ARRAY_BUFFER, m_tbo);
212        glEnableVertexAttribArray(m_texattrib);
213        glVertexAttribPointer(m_texattrib, 2, GL_FLOAT, GL_FALSE, 0, 0);
214#elif !defined __CELLOS_LV2__ && !defined __ANDROID__ && !defined __APPLE__
215        /* Never used for now */
216        //glEnableVertexAttribArray(m_vertexattrib);
217        //glVertexAttribPointer(m_vertexattrib, 2, GL_FLOAT, GL_FALSE, 0, vertices);
218#else
219        glEnableClientState(GL_VERTEX_ARRAY);
220        glVertexPointer(2, GL_FLOAT, 0, vertices);
221        glEnableClientState(GL_TEXTURE_COORD_ARRAY);
222        glTexCoordPointer(2, GL_FLOAT, 0, texcoords);
223#endif
224
225        glDrawArrays(GL_TRIANGLES, 0, 6);
226
227#if !defined __CELLOS_LV2__ && !defined __ANDROID__ && !defined __APPLE__
228        glDisableVertexAttribArray(m_vertexattrib);
229        glDisableVertexAttribArray(m_texattrib);
230        glBindBuffer(GL_ARRAY_BUFFER, 0);
231#elif !defined __CELLOS_LV2__ && !defined __ANDROID__ && !defined __APPLE__
232        /* Never used for now */
233        //glDisableVertexAttribArray(m_vertexattrib);
234        //glDisableVertexAttribArray(m_texattrib);
235#else
236        glDisableClientState(GL_VERTEX_ARRAY);
237        glDisableClientState(GL_TEXTURE_COORD_ARRAY);
238#endif
239    }
240
241private:
242    ivec2 m_size;
243    u8vec4 *m_pixels;
244    Shader *m_shader;
245    GLuint m_texid;
246#if !defined __CELLOS_LV2__ && !defined __ANDROID__ && !defined __APPLE__
247    GLuint m_vbo, m_tbo;
248    GLuint m_tco;
249#endif
250    int m_vertexattrib, m_texattrib;
251    float m_time;
252    bool m_ready;
253};
254
255int main()
256{
257#if defined _WIN32
258    _chdir("../..");
259#endif
260
261    Application app("Tutorial 3: Fractal", ivec2(640, 480), 60.0f);
262
263    new DebugFps(5, 5);
264    new Fractal(ivec2(1280, 960));
265
266    app.Run();
267
268    return EXIT_SUCCESS;
269}
270
Note: See TracBrowser for help on using the repository browser.