diff --git a/.gitignore b/.gitignore index 308a9efd..792eb45f 100644 --- a/.gitignore +++ b/.gitignore @@ -58,6 +58,7 @@ monsterz/monsterz test/testsuite test/tutorial/tut01 test/tutorial/tut02 +test/tutorial/tut03 test/benchsuite test/quad test/sandbox diff --git a/test/tutorial/Makefile.am b/test/tutorial/Makefile.am index ae422f37..1146eac8 100644 --- a/test/tutorial/Makefile.am +++ b/test/tutorial/Makefile.am @@ -3,13 +3,14 @@ AM_CPPFLAGS = -I$(top_srcdir)/src all-local: $(noinst_PROGRAMS) test x$(MAKE_FSELF) = xno || make_fself tut01$(EXEEXT) tut01.self - test x$(MAKE_FSELF) = xno || make_fself tut02$(EXEEXT) tut01.self + test x$(MAKE_FSELF) = xno || make_fself tut02$(EXEEXT) tut02.self + test x$(MAKE_FSELF) = xno || make_fself tut03$(EXEEXT) tut03.self CLEANFILES = $(noinst_PROGRAMS:%$(EXEEXT)=%.self) \ $(noinst_PROGRAMS:%$(EXEEXT)=%.elf) \ $(noinst_PROGRAMS:%$(EXEEXT)=%.exe) -noinst_PROGRAMS = tut01 tut02 +noinst_PROGRAMS = tut01 tut02 tut03 tut01_SOURCES = tut01.cpp tut01_CPPFLAGS = @LOL_CFLAGS@ @PIPI_CFLAGS@ @@ -21,3 +22,8 @@ tut02_CPPFLAGS = @LOL_CFLAGS@ @PIPI_CFLAGS@ tut02_LDFLAGS = $(top_builddir)/src/liblol.a @LOL_LIBS@ @PIPI_LIBS@ tut02_DEPENDENCIES = $(top_builddir)/src/liblol.a +tut03_SOURCES = tut03.cpp +tut03_CPPFLAGS = @LOL_CFLAGS@ @PIPI_CFLAGS@ +tut03_LDFLAGS = $(top_builddir)/src/liblol.a @LOL_LIBS@ @PIPI_LIBS@ +tut03_DEPENDENCIES = $(top_builddir)/src/liblol.a + diff --git a/test/tutorial/tut03.cpp b/test/tutorial/tut03.cpp new file mode 100644 index 00000000..59b08192 --- /dev/null +++ b/test/tutorial/tut03.cpp @@ -0,0 +1,197 @@ +// +// Lol Engine - Fractal tutorial +// +// Copyright: (c) 2011 Sam Hocevar +// This program is free software; you can redistribute it and/or +// modify it under the terms of the Do What The Fuck You Want To +// Public License, Version 2, as published by Sam Hocevar. See +// http://sam.zoy.org/projects/COPYING.WTFPL for more details. +// + +#if defined HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +#include "core.h" +#include "lolgl.h" +#include "loldebug.h" + +using namespace std; +using namespace lol; + +#if USE_SDL && defined __APPLE__ +# include +#endif + +#if defined _WIN32 +# undef main /* FIXME: still needed? */ +#endif + +class Fractal : public WorldEntity +{ +public: + Fractal(ivec2 const &size) + { + m_size = size; + m_pixels = new u8vec4[size.x * size.y]; + m_angle = 0.0f; + m_ready = false; + } + + ~Fractal() + { + delete m_pixels; + } + + virtual void TickDraw(float deltams) + { + WorldEntity::TickDraw(deltams); + + static float const vertices[] = + { + -1.0f, -1.0f, + 1.0f, -1.0f, + 1.0f, 1.0f, + 1.0f, 1.0f, + -1.0f, 1.0f, + -1.0f, -1.0f, + }; + + static float const texcoords[] = + { + 0.0f, 0.0f, + 1.0f, 0.0f, + 1.0f, 1.0f, + 1.0f, 1.0f, + 0.0f, 1.0f, + 0.0f, 0.0f, + }; + + if (!m_ready) + { + glGenTextures(1, &m_texid); + glBindTexture(GL_TEXTURE_2D, m_texid); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_size.x, m_size.y, 0, + GL_RGBA, GL_UNSIGNED_BYTE, m_pixels); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + + m_shader = Shader::Create( + "#version 120\n" + "attribute vec2 in_TexCoord;\n" + "attribute vec2 in_Vertex;" + "void main(void) {" + " gl_Position = vec4(in_Vertex, 0.0, 1.0);" + " gl_TexCoord[0] = vec4(in_TexCoord, 0.0, 0.0);\n" + "}", + + "#version 120\n" + "uniform sampler2D in_Texture;\n" + "void main(void) {" + " gl_FragColor = texture2D(in_Texture, gl_TexCoord[0].xy);" + "}"); + m_vertexattrib = m_shader->GetAttribLocation("in_Vertex"); + m_texattrib = m_shader->GetAttribLocation("in_TexCoord"); + m_ready = true; + +#if !defined __CELLOS_LV2__ && !defined __ANDROID__ && !defined __APPLE__ + /* Method 1: store vertex buffer on the GPU memory */ + glGenBuffers(1, &m_vbo); + glBindBuffer(GL_ARRAY_BUFFER, m_vbo); + glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, + GL_STATIC_DRAW); + glGenBuffers(1, &m_tbo); + glBindBuffer(GL_ARRAY_BUFFER, m_tbo); + glBufferData(GL_ARRAY_BUFFER, sizeof(texcoords), texcoords, + GL_STATIC_DRAW); +#elif !defined __CELLOS_LV2__ && !defined __ANDROID__ && !defined __APPLE__ + /* Method 2: upload vertex information at each frame */ +#else +#endif + + /* FIXME: this object never cleans up */ + } + + m_angle += deltams * 0.001f; + + cmplx r0(cosf(m_angle), 0.3f * sinf(m_angle)); + for (int j = 0; j < m_size.y; j++) + for (int i = 0; i < m_size.x; i++) + { + cmplx x0(4.0f / m_size.x * i - 2.5f, 3.0f / m_size.y * j - 1.5f); + cmplx r = x0 * r0; + int iter = 20; + for (cmplx z = r; iter && z.sqlen() < 4.0f; z = z * z + r) + --iter; + m_pixels[j * m_size.x + i] = u8vec4(0, iter * 12, iter * 12, 0); + } + + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, m_texid); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_size.x, m_size.y, + GL_RGBA, GL_UNSIGNED_BYTE, m_pixels); + + m_shader->Bind(); +#if !defined __CELLOS_LV2__ && !defined __ANDROID__ && !defined __APPLE__ + glBindBuffer(GL_ARRAY_BUFFER, m_vbo); + glEnableVertexAttribArray(m_vertexattrib); + glVertexAttribPointer(m_vertexattrib, 2, GL_FLOAT, GL_FALSE, 0, 0); + + glBindBuffer(GL_ARRAY_BUFFER, m_tbo); + glEnableVertexAttribArray(m_texattrib); + glVertexAttribPointer(m_texattrib, 2, GL_FLOAT, GL_FALSE, 0, 0); +#elif !defined __CELLOS_LV2__ && !defined __ANDROID__ && !defined __APPLE__ + /* Never used for now */ + //glEnableVertexAttribArray(m_vertexattrib); + //glVertexAttribPointer(m_vertexattrib, 2, GL_FLOAT, GL_FALSE, 0, vertices); +#else + //glEnableClientState(GL_VERTEX_ARRAY); + //glVertexPointer(2, GL_FLOAT, 0, vertices); + //glEnableClientState(GL_VERTEX_ARRAY); + //glTexCoordPointer(2, GL_FLOAT, 0, texcoords); +#endif + + glDrawArrays(GL_TRIANGLES, 0, 6); + +#if !defined __CELLOS_LV2__ && !defined __ANDROID__ && !defined __APPLE__ + glDisableVertexAttribArray(m_vertexattrib); + glDisableVertexAttribArray(m_texattrib); + glBindBuffer(GL_ARRAY_BUFFER, 0); +#elif !defined __CELLOS_LV2__ && !defined __ANDROID__ && !defined __APPLE__ + /* Never used for now */ + //glDisableVertexAttribArray(m_vertexattrib); + //glDisableVertexAttribArray(m_texattrib); +#else + //glDisableClientState(GL_VERTEX_ARRAY); + //glDisableClientState(GL_TEXTURE_COORD_ARRAY); +#endif + } + +private: + ivec2 m_size; + u8vec4 *m_pixels; + Shader *m_shader; + GLuint m_texid; +#if !defined __CELLOS_LV2__ && !defined __ANDROID__ && !defined __APPLE__ + GLuint m_vbo, m_tbo; + GLuint m_tco; +#endif + int m_vertexattrib, m_texattrib; + float m_angle; + bool m_ready; +}; + +int main() +{ + Application app("Tutorial 3: Fractal", ivec2(640, 480), 60.0f); + + new DebugFps(5, 5); + new Fractal(ivec2(640, 480)); + + app.Run(); + + return EXIT_SUCCESS; +} +