mightymandel v16

GPU-based Mandelbrot set explorer

slice.c
Go to the documentation of this file.
1 // mightymandel -- GPU-based Mandelbrot Set explorer
2 // Copyright (C) 2012,2013,2014,2015 Claude Heiland-Allen
3 // License GPL3+ http://www.gnu.org/licenses/gpl.html
4 
5 #include <assert.h>
6 #include <stdlib.h>
7 #include <GL/glew.h>
8 
9 #include "slice.h"
10 #include "texture.h"
11 #include "config.glsl"
12 
13 struct slice_coord {
14  GLubyte i;
15  GLubyte j;
16 };
17 
18 struct slice_table {
19  // coordinates to slice number
20  GLushort s0[1][1];
21  GLushort s1[2][2];
22  GLushort s2[4][4];
23  GLushort s3[8][8];
24  GLushort s4[16][16];
25  GLushort s5[32][32];
26  GLushort s6[64][64];
27  GLushort s7[128][128];
28  GLushort s8[256][256];
29  // slice number to coordinates
30  struct slice_coord c0[1][1];
31  struct slice_coord c1[2][2];
32  struct slice_coord c2[4][4];
33  struct slice_coord c3[8][8];
34  struct slice_coord c4[16][16];
35  struct slice_coord c5[32][32];
36  struct slice_coord c6[64][64];
37  struct slice_coord c7[128][128];
38  struct slice_coord c8[256][256];
39  // corresponding textures
40  GLuint s_tex;
41  GLuint c_tex;
42 };
43 
45  struct slice_table *t = malloc(sizeof(struct slice_table));
46  if (! t) { return 0; }
47 
48  t->s0[0][0] = 0;
49 
50  t->s1[0][0] = 0;
51  t->s1[0][1] = 2;
52  t->s1[1][0] = 3;
53  t->s1[1][1] = 1;
54 
55 #define FILL(next,from) do{ \
56  for (int i = 0; i < (1 << next); ++i) { \
57  for (int j = 0; j < (1 << next); ++j) { \
58  int k = t->s##from[i >> 1][j >> 1]; \
59  int n = t->s1[i & 1][j & 1]; \
60  t->s##next[i][j] = k + n * (1 << (from << 1)); \
61  } \
62  } \
63 }while(0)
64  FILL(2, 1);
65  FILL(3, 2);
66  FILL(4, 3);
67  FILL(5, 4);
68  FILL(6, 5);
69  FILL(7, 6);
70  FILL(8, 7);
71 #undef FILL
72 
73 #define INVERT(next) do{ \
74  for (int i = 0; i < (1 << next); ++i) { \
75  for (int j = 0; j < (1 << next); ++j) { \
76  int k = t->s##next[i][j]; \
77  int ii = k >> next; \
78  int jj = k - (ii << next); \
79  t->c##next[ii][jj].i = i; \
80  t->c##next[ii][jj].j = j; \
81  } \
82  } \
83 }while(0)
84  INVERT(0);
85  INVERT(1);
86  INVERT(2);
87  INVERT(3);
88  INVERT(4);
89  INVERT(5);
90  INVERT(6);
91  INVERT(7);
92  INVERT(8);
93 #undef INVERT
94 
95  glGenTextures(1, &t->s_tex);
96  glActiveTexture(GL_TEXTURE0 + TEX_SLICE_NUMBER);
97  glBindTexture(GL_TEXTURE_2D, t->s_tex);
98 #define UPLOAD(n) glTexImage2D(GL_TEXTURE_2D, SLICE_MAX - n, GL_R16UI, 1 << n, 1 << n, 0, GL_RED_INTEGER, GL_UNSIGNED_SHORT, &t->s##n[0][0])
99  UPLOAD(8);
100  UPLOAD(7);
101  UPLOAD(6);
102  UPLOAD(5);
103  UPLOAD(4);
104  UPLOAD(3);
105  UPLOAD(2);
106  UPLOAD(1);
107  UPLOAD(0);
108 #undef UPLOAD
109 
110  glGenTextures(1, &t->c_tex);
111  glActiveTexture(GL_TEXTURE0 + TEX_SLICE_COORDS);
112  glBindTexture(GL_TEXTURE_2D, t->c_tex);
113 #define UPLOAD(n) glTexImage2D(GL_TEXTURE_2D, SLICE_MAX - n, GL_RG8UI, 1 << n, 1 << n, 0, GL_RG_INTEGER, GL_UNSIGNED_BYTE, &t->c##n[0][0].i)
114  UPLOAD(8);
115  UPLOAD(7);
116  UPLOAD(6);
117  UPLOAD(5);
118  UPLOAD(4);
119  UPLOAD(3);
120  UPLOAD(2);
121  UPLOAD(1);
122  UPLOAD(0);
123 #undef UPLOAD
124  return t;
125 }
126 
128  assert(t);
129  glActiveTexture(GL_TEXTURE0 + TEX_SLICE_NUMBER);
130  glBindTexture(GL_TEXTURE_2D, 0);
131  glActiveTexture(GL_TEXTURE0 + TEX_SLICE_COORDS);
132  glBindTexture(GL_TEXTURE_2D, 0);
133  glDeleteTextures(1, &t->s_tex);
134  glDeleteTextures(1, &t->c_tex);
135  free(t);
136 }
137 
138 void slice_table_coords(struct slice_table *t, int slice, int n, int *i, int *j) {
139  assert(t);
140  assert(0 <= slice);
141  assert(slice <= SLICE_MAX);
142  assert(0 <= n);
143  assert(n < (1 << (slice << 1)));
144  assert(i);
145  assert(j);
146  int ii = n >> slice;
147  int jj = n - (ii << slice);
148  assert(0 <= ii);
149  assert(ii < (1 << slice));
150  assert(0 <= jj);
151  assert(jj < (1 << slice));
152  switch (slice) {
153 #define CASE(k) case k: *i = t->c##k[ii][jj].i; *j = t->c##k[ii][jj].j; break
154  CASE(0);
155  CASE(1);
156  CASE(2);
157  CASE(3);
158  CASE(4);
159  CASE(5);
160  CASE(6);
161  CASE(7);
162  CASE(8);
163 #undef CASE
164  default: assert(! "invalid slice"); break;
165  }
166 }