You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

254 lines
7.7 KiB

  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. #if defined HAVE_CONFIG_H
  11. # include "config.h"
  12. #endif
  13. #include <cstring>
  14. #include "core.h"
  15. #include "lolgl.h"
  16. #include "loldebug.h"
  17. using namespace std;
  18. using namespace lol;
  19. #if USE_SDL && defined __APPLE__
  20. # include <SDL_main.h>
  21. #endif
  22. #if defined _WIN32
  23. # undef main /* FIXME: still needed? */
  24. # include <direct.h>
  25. #endif
  26. class Fractal : public WorldEntity
  27. {
  28. public:
  29. Fractal(ivec2 const &size)
  30. {
  31. m_size = size;
  32. m_pixels = new u8vec4[size.x * size.y];
  33. m_angle = 0.0f;
  34. m_ready = false;
  35. }
  36. ~Fractal()
  37. {
  38. delete m_pixels;
  39. }
  40. virtual void TickGame(float deltams)
  41. {
  42. WorldEntity::TickGame(deltams);
  43. m_angle += deltams * 0.0005f;
  44. cmplx r0(cosf(m_angle), 0.8f * sinf(m_angle));
  45. for (int j = 0; j < m_size.y; j++)
  46. for (int i = 0; i < m_size.x; i++)
  47. {
  48. float const maxlen = 32.0f;
  49. int const colors = 16;
  50. int const maxiter = 30;
  51. cmplx x0(4.0f / m_size.x * i - 2.0f, 3.0f / m_size.y * j - 1.5f);
  52. cmplx r = x0 * r0;
  53. cmplx z;
  54. int iter = maxiter;
  55. for (z = r; iter && z.sqlen() < maxlen * maxlen; z = z * z + r)
  56. --iter;
  57. float f = iter % colors;
  58. float n = z.len();
  59. f += logf(logf(n) / logf(maxlen)) / logf(2.0f);
  60. if (iter)
  61. {
  62. uint8_t red = 255 - f * (255.0f / (colors + 1));
  63. uint8_t green = 255 - f * (255.0f / (colors + 1));
  64. uint8_t blue = (f * 512.0f / (colors + 1) > 255)
  65. ? 511 - (f * 512.0f / (colors + 1)) : 255;
  66. m_pixels[j * m_size.x + i] = u8vec4(red, green, blue, 0);
  67. }
  68. else
  69. {
  70. m_pixels[j * m_size.x + i] = u8vec4(0, 0, 0, 0);
  71. }
  72. }
  73. }
  74. virtual void TickDraw(float deltams)
  75. {
  76. WorldEntity::TickDraw(deltams);
  77. static float const vertices[] =
  78. {
  79. -1.0f, -1.0f,
  80. 1.0f, -1.0f,
  81. 1.0f, 1.0f,
  82. 1.0f, 1.0f,
  83. -1.0f, 1.0f,
  84. -1.0f, -1.0f,
  85. };
  86. static float const texcoords[] =
  87. {
  88. 0.0f, 0.0f,
  89. 1.0f, 0.0f,
  90. 1.0f, 1.0f,
  91. 1.0f, 1.0f,
  92. 0.0f, 1.0f,
  93. 0.0f, 0.0f,
  94. };
  95. if (!m_ready)
  96. {
  97. glGenTextures(1, &m_texid);
  98. glBindTexture(GL_TEXTURE_2D, m_texid);
  99. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_size.x, m_size.y, 0,
  100. GL_RGBA, GL_UNSIGNED_BYTE, m_pixels);
  101. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  102. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  103. m_shader = Shader::Create(
  104. #if !defined __CELLOS_LV2__
  105. "#version 120\n"
  106. "attribute vec2 in_TexCoord;\n"
  107. "attribute vec2 in_Vertex;"
  108. "void main(void) {"
  109. " gl_Position = vec4(in_Vertex, 0.0, 1.0);"
  110. " gl_TexCoord[0] = vec4(in_TexCoord, 0.0, 0.0);\n"
  111. "}",
  112. "#version 120\n"
  113. "uniform sampler2D in_Texture;\n"
  114. "void main(void) {"
  115. " gl_FragColor = texture2D(in_Texture, gl_TexCoord[0].xy);"
  116. "}"
  117. #else
  118. "void main(float4 in_Position : POSITION,"
  119. " float2 in_TexCoord : TEXCOORD0,"
  120. " out float4 out_Position : POSITION,"
  121. " out float2 out_TexCoord : TEXCOORD0)"
  122. "{"
  123. " out_TexCoord = in_TexCoord;"
  124. " out_Position = in_Position;"
  125. "}",
  126. "void main(float2 in_TexCoord : TEXCOORD0,"
  127. " uniform sampler2D tex,"
  128. " out float4 out_FragColor : COLOR)"
  129. "{"
  130. " out_FragColor = tex2D(tex, in_TexCoord);"
  131. "}"
  132. #endif
  133. );
  134. m_vertexattrib = m_shader->GetAttribLocation("in_Vertex");
  135. m_texattrib = m_shader->GetAttribLocation("in_TexCoord");
  136. m_ready = true;
  137. #if !defined __CELLOS_LV2__ && !defined __ANDROID__ && !defined __APPLE__
  138. /* Method 1: store vertex buffer on the GPU memory */
  139. glGenBuffers(1, &m_vbo);
  140. glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
  141. glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices,
  142. GL_STATIC_DRAW);
  143. glGenBuffers(1, &m_tbo);
  144. glBindBuffer(GL_ARRAY_BUFFER, m_tbo);
  145. glBufferData(GL_ARRAY_BUFFER, sizeof(texcoords), texcoords,
  146. GL_STATIC_DRAW);
  147. #elif !defined __CELLOS_LV2__ && !defined __ANDROID__ && !defined __APPLE__
  148. /* Method 2: upload vertex information at each frame */
  149. #else
  150. #endif
  151. /* FIXME: this object never cleans up */
  152. }
  153. glEnable(GL_TEXTURE_2D);
  154. glBindTexture(GL_TEXTURE_2D, m_texid);
  155. glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_size.x, m_size.y,
  156. #if !defined __CELLOS_LV2__
  157. GL_RGBA, GL_UNSIGNED_BYTE,
  158. #else
  159. /* The PS3 is big-endian */
  160. GL_RGBA, GL_UNSIGNED_INT_8_8_8_8,
  161. #endif
  162. m_pixels);
  163. m_shader->Bind();
  164. #if !defined __CELLOS_LV2__ && !defined __ANDROID__ && !defined __APPLE__
  165. glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
  166. glEnableVertexAttribArray(m_vertexattrib);
  167. glVertexAttribPointer(m_vertexattrib, 2, GL_FLOAT, GL_FALSE, 0, 0);
  168. glBindBuffer(GL_ARRAY_BUFFER, m_tbo);
  169. glEnableVertexAttribArray(m_texattrib);
  170. glVertexAttribPointer(m_texattrib, 2, GL_FLOAT, GL_FALSE, 0, 0);
  171. #elif !defined __CELLOS_LV2__ && !defined __ANDROID__ && !defined __APPLE__
  172. /* Never used for now */
  173. //glEnableVertexAttribArray(m_vertexattrib);
  174. //glVertexAttribPointer(m_vertexattrib, 2, GL_FLOAT, GL_FALSE, 0, vertices);
  175. #else
  176. glEnableClientState(GL_VERTEX_ARRAY);
  177. glVertexPointer(2, GL_FLOAT, 0, vertices);
  178. glEnableClientState(GL_TEXTURE_COORD_ARRAY);
  179. glTexCoordPointer(2, GL_FLOAT, 0, texcoords);
  180. #endif
  181. glDrawArrays(GL_TRIANGLES, 0, 6);
  182. #if !defined __CELLOS_LV2__ && !defined __ANDROID__ && !defined __APPLE__
  183. glDisableVertexAttribArray(m_vertexattrib);
  184. glDisableVertexAttribArray(m_texattrib);
  185. glBindBuffer(GL_ARRAY_BUFFER, 0);
  186. #elif !defined __CELLOS_LV2__ && !defined __ANDROID__ && !defined __APPLE__
  187. /* Never used for now */
  188. //glDisableVertexAttribArray(m_vertexattrib);
  189. //glDisableVertexAttribArray(m_texattrib);
  190. #else
  191. glDisableClientState(GL_VERTEX_ARRAY);
  192. glDisableClientState(GL_TEXTURE_COORD_ARRAY);
  193. #endif
  194. }
  195. private:
  196. ivec2 m_size;
  197. u8vec4 *m_pixels;
  198. Shader *m_shader;
  199. GLuint m_texid;
  200. #if !defined __CELLOS_LV2__ && !defined __ANDROID__ && !defined __APPLE__
  201. GLuint m_vbo, m_tbo;
  202. GLuint m_tco;
  203. #endif
  204. int m_vertexattrib, m_texattrib;
  205. float m_angle;
  206. bool m_ready;
  207. };
  208. int main()
  209. {
  210. #if defined _WIN32
  211. _chdir("../..");
  212. #endif
  213. Application app("Tutorial 3: Fractal", ivec2(640, 480), 60.0f);
  214. new DebugFps(5, 5);
  215. new Fractal(ivec2(640, 480));
  216. app.Run();
  217. return EXIT_SUCCESS;
  218. }