tesselation
[ld42_outofspace] / src / gamescr.cc
index d51c16a..032b3b9 100644 (file)
@@ -32,6 +32,16 @@ struct Rect {
        int width, height;
 };
 
        int width, height;
 };
 
+struct QuadMesh {
+       Vec3 *v;
+       Vec2 *uv;
+       uint16_t *idx;
+
+       int num_verts, num_idx, num_quads;
+
+       unsigned int vbo_v, vbo_uv, ibo;
+};
+
 #define SIM_DT         0.016
 
 #define GRID_SIZE      2048
 #define SIM_DT         0.016
 
 #define GRID_SIZE      2048
@@ -52,6 +62,10 @@ struct Rect {
 static int pos_to_grid(float x, float y);
 static Vec2 grid_to_pos(int gx, int gy);
 
 static int pos_to_grid(float x, float y);
 static Vec2 grid_to_pos(int gx, int gy);
 
+static void destroy_quadmesh(QuadMesh *m);
+static void draw_quadmesh(const QuadMesh *m, unsigned int prim = GL_QUADS);
+static void gen_quad_plane(QuadMesh *mesh, float width, float height, int usub, int vsub);
+
 static float grid[GRID_SIZE * GRID_SIZE];
 static Particle grid_part[GRID_SIZE * GRID_SIZE];
 static Texture *grid_tex;
 static float grid[GRID_SIZE * GRID_SIZE];
 static Particle grid_part[GRID_SIZE * GRID_SIZE];
 static Texture *grid_tex;
@@ -60,6 +74,10 @@ static std::vector<Emitter*> emitters;
 
 static Texture *gvis_tex;      // texture tile for visualizing a grid
 static unsigned int field_sdr;
 
 static Texture *gvis_tex;      // texture tile for visualizing a grid
 static unsigned int field_sdr;
+static int tess_level = 32;
+static float field_scale = 16.0f;
+
+static QuadMesh field_mesh;
 
 static float cam_theta;
 static float cam_dist = 100.0f;
 
 static float cam_theta;
 static float cam_dist = 100.0f;
@@ -97,18 +115,26 @@ bool GameScreen::init()
        }
        set_uniform_int(field_sdr, "gvis_tex", 0);
        set_uniform_int(field_sdr, "field_tex", 1);
        }
        set_uniform_int(field_sdr, "gvis_tex", 0);
        set_uniform_int(field_sdr, "field_tex", 1);
-       set_uniform_int(field_sdr, "tess_level", 2);
+       set_uniform_float(field_sdr, "gvis_scale", FIELD_SIZE / 32.0f);
+       set_uniform_int(field_sdr, "tess_level", tess_level);
+       set_uniform_float(field_sdr, "field_scale", field_scale);
+
+       gen_quad_plane(&field_mesh, FIELD_SIZE, FIELD_SIZE, 32, 32);
 
        // XXX DBG
        emit_place_pos = Vec2(0, 0);
        emit_place_pending = true;
 
 
        // XXX DBG
        emit_place_pos = Vec2(0, 0);
        emit_place_pending = true;
 
+       assert(glGetError() == GL_NO_ERROR);
        return true;
 }
 
 void GameScreen::destroy()
 {
        return true;
 }
 
 void GameScreen::destroy()
 {
+       free_program(field_sdr);
        delete gvis_tex;
        delete gvis_tex;
+       delete grid_tex;
+       destroy_quadmesh(&field_mesh);
 }
 
 static void calc_contrib_bounds(const Emitter *em, Rect *rect)
 }
 
 static void calc_contrib_bounds(const Emitter *em, Rect *rect)
@@ -242,34 +268,16 @@ void GameScreen::draw()
        bind_texture(grid_tex, 1);
 
        glUseProgram(field_sdr);
        bind_texture(grid_tex, 1);
 
        glUseProgram(field_sdr);
+       assert(glGetError() == GL_NO_ERROR);
 
 
-       float maxu = FIELD_SIZE / 32.0f;
-       float maxv = FIELD_SIZE / 32.0f;
-       float hsz = FIELD_SIZE * 0.5f;
-
-       glBegin(GL_QUADS);
-       glColor3f(1, 1, 1);
-
-       glMultiTexCoord2f(0, 0, 0);
-       glMultiTexCoord2f(1, 0, 0);
-       glVertex3f(-hsz, 0, -hsz);
-
-       glMultiTexCoord2f(0, maxu, 0);
-       glMultiTexCoord2f(1, 1, 0);
-       glVertex3f(hsz, 0, -hsz);
-
-       glMultiTexCoord2f(0, maxu, maxv);
-       glMultiTexCoord2f(1, 1, 1);
-       glVertex3f(hsz, 0, hsz);
-
-       glMultiTexCoord2f(0, 0, maxv);
-       glMultiTexCoord2f(1, 0, 1);
-       glVertex3f(-hsz, 0, hsz);
-       glEnd();
+       glPatchParameteri(GL_PATCH_VERTICES, 4);
+       draw_quadmesh(&field_mesh, GL_PATCHES);
 
        glUseProgram(0);
 
        glPopAttrib();
 
        glUseProgram(0);
 
        glPopAttrib();
+
+       assert(glGetError() == GL_NO_ERROR);
 }
 
 void GameScreen::reshape(int x, int y)
 }
 
 void GameScreen::reshape(int x, int y)
@@ -286,6 +294,39 @@ void GameScreen::keyboard(int key, bool pressed)
                        pop_screen();
                        break;
 
                        pop_screen();
                        break;
 
+               case ']':
+                       if(tess_level < glcaps.max_tess_level) {
+                               tess_level++;
+                               printf("tessellation level: %d\n", tess_level);
+                               set_uniform_int(field_sdr, "tess_level", tess_level);
+                               glUseProgram(0);
+                       }
+                       break;
+
+               case '[':
+                       if(tess_level > 1) {
+                               tess_level--;
+                               printf("tessellation level: %d\n", tess_level);
+                               set_uniform_int(field_sdr, "tess_level", tess_level);
+                               glUseProgram(0);
+                       }
+                       break;
+
+               case '=':
+                       field_scale += 0.5;
+                       printf("field scale: %f\n", field_scale);
+                       set_uniform_float(field_sdr, "field_scale", field_scale);
+                       break;
+
+               case '-':
+                       field_scale -= 0.5;
+                       if(field_scale < 0.0f) {
+                               field_scale = 0.0f;
+                       }
+                       printf("field scale: %f\n", field_scale);
+                       set_uniform_float(field_sdr, "field_scale", field_scale);
+                       break;
+
                default:
                        break;
                }
                default:
                        break;
                }
@@ -340,3 +381,97 @@ static Vec2 grid_to_pos(int gx, int gy)
 
        return Vec2(x, y);
 }
 
        return Vec2(x, y);
 }
+
+static void destroy_quadmesh(QuadMesh *m)
+{
+       glDeleteBuffers(1, &m->vbo_v);
+       glDeleteBuffers(1, &m->vbo_uv);
+       glDeleteBuffers(1, &m->ibo);
+
+       delete [] m->v;
+       delete [] m->uv;
+       delete [] m->idx;
+}
+
+static void draw_quadmesh(const QuadMesh *m, unsigned int prim)
+{
+       glEnableClientState(GL_VERTEX_ARRAY);
+       glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+
+       glBindBuffer(GL_ARRAY_BUFFER, m->vbo_v);
+       glVertexPointer(3, GL_FLOAT, 0, 0);
+
+       glBindBuffer(GL_ARRAY_BUFFER, m->vbo_uv);
+       glTexCoordPointer(2, GL_FLOAT, 0, 0);
+
+       glBindBuffer(GL_ARRAY_BUFFER, 0);
+
+       glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m->ibo);
+       glDrawElements(prim, m->num_idx, GL_UNSIGNED_SHORT, 0);
+       glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+
+       glDisableClientState(GL_VERTEX_ARRAY);
+       glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+}
+
+static void gen_quad_plane(QuadMesh *m, float width, float height, int usub, int vsub)
+{
+       Vec3 *vptr;
+       Vec2 *uvptr;
+       uint16_t *iptr;
+
+       if(usub < 1) usub = 1;
+       if(vsub < 1) vsub = 1;
+
+       int uverts = usub + 1;
+       int vverts = vsub + 1;
+       m->num_verts = uverts * vverts;
+       m->num_quads = usub * vsub;
+       m->num_idx = m->num_quads * 4;
+
+       vptr = m->v = new Vec3[m->num_verts];
+       uvptr = m->uv = new Vec2[m->num_verts];
+       iptr = m->idx = new uint16_t[m->num_idx];
+
+       float du = 1.0f / (float)usub;
+       float dv = 1.0f / (float)vsub;
+
+       float u = 0.0f;
+       for(int i=0; i<uverts; i++) {
+               float x = (u - 0.5f) * width;
+               float v = 0.0f;
+               for(int j=0; j<vverts; j++) {
+                       float y = (v - 0.5f) * height;
+
+                       *vptr++ = Vec3(x, 0, y);
+                       *uvptr++ = Vec2(u, v);
+
+                       if(i < usub && j < vsub) {
+                               int idx = i * vverts + j;
+
+                               *iptr++ = idx;
+                               *iptr++ = idx + vverts;
+                               *iptr++ = idx + vverts + 1;
+                               *iptr++ = idx + 1;
+                       }
+
+                       v += dv;
+               }
+               u += du;
+       }
+
+       glGenBuffers(1, &m->vbo_v);
+       glBindBuffer(GL_ARRAY_BUFFER, m->vbo_v);
+       glBufferData(GL_ARRAY_BUFFER, m->num_verts * 3 * sizeof(float), m->v, GL_STATIC_DRAW);
+
+       glGenBuffers(1, &m->vbo_uv);
+       glBindBuffer(GL_ARRAY_BUFFER, m->vbo_uv);
+       glBufferData(GL_ARRAY_BUFFER, m->num_verts * 2 * sizeof(float), m->uv, GL_STATIC_DRAW);
+
+       glGenBuffers(1, &m->ibo);
+       glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m->ibo);
+       glBufferData(GL_ELEMENT_ARRAY_BUFFER, m->num_idx * sizeof(uint16_t), m->idx, GL_STATIC_DRAW);
+
+       glBindBuffer(GL_ARRAY_BUFFER, 0);
+       glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+}