tesselation as a function of distance
authorJohn Tsiombikas <nuclear@member.fsf.org>
Tue, 14 Aug 2018 19:09:05 +0000 (22:09 +0300)
committerJohn Tsiombikas <nuclear@member.fsf.org>
Tue, 14 Aug 2018 19:09:05 +0000 (22:09 +0300)
sdr/field.p.glsl
sdr/field.tc.glsl
sdr/field.v.glsl
src/gamescr.cc

index b021a55..84d2321 100644 (file)
@@ -10,6 +10,7 @@ void main()
 
        float foo = texture2D(field_tex, gl_TexCoord[0].st).x;
 
-       gl_FragColor.rgb = gridcol.rgb + vec3(0.0, foo, 0.0);
+       vec3 amb = gl_LightModel.ambient.rgb;
+       gl_FragColor.rgb = amb + gridcol.rgb + vec3(0.0, foo, 0.0);
        gl_FragColor.a = 1.0;
 }
index 71d6560..e742def 100644 (file)
@@ -4,17 +4,23 @@ layout(vertices = 4) out;
 
 uniform int tess_level;
 
+in float dist[gl_MaxPatchVertices];
+
 void main()
 {
        gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
        gl_out[gl_InvocationID].gl_TexCoord[0] = gl_in[gl_InvocationID].gl_TexCoord[0];
        gl_out[gl_InvocationID].gl_TexCoord[1] = gl_in[gl_InvocationID].gl_TexCoord[1];
 
-       gl_TessLevelInner[0] = tess_level;
-       gl_TessLevelInner[1] = tess_level;
+       const float min_tess_dist = 800.0;
+       float t = clamp(1.0 - dist[0] / min_tess_dist, 0.0, 1.0);
+       int tess = int(t * float(tess_level - 1.0)) + 1;
+
+       gl_TessLevelInner[0] = tess;
+       gl_TessLevelInner[1] = tess;
 
-       gl_TessLevelOuter[0] = tess_level;
-       gl_TessLevelOuter[1] = tess_level;
-       gl_TessLevelOuter[2] = tess_level;
-       gl_TessLevelOuter[3] = tess_level;
+       gl_TessLevelOuter[0] = tess;
+       gl_TessLevelOuter[1] = tess;
+       gl_TessLevelOuter[2] = tess;
+       gl_TessLevelOuter[3] = tess;
 }
index cecfabb..dbbbdfb 100644 (file)
@@ -1,7 +1,11 @@
 #version 410 compatibility
 
+out float dist;
+
 void main()
 {
+       dist = -(gl_ModelViewMatrix * gl_Vertex).z;
+
        gl_Position = gl_Vertex;
        gl_TexCoord[0] = gl_MultiTexCoord0;
 }
index 638032c..06b0429 100644 (file)
@@ -11,9 +11,7 @@
 
 /* NOTES:
  * - whistle hhgg music
- * - colliding particles merge
  * - select objects and center camera on them
- * - tesselate only where necessary
  */
 
 struct Particle {
@@ -71,6 +69,8 @@ struct QuadMesh {
 /* gravitational strength */
 #define GRAV_STR       16.0f
 
+static int pos_to_grid_x_noclamp(float x);
+static int pos_to_grid_y_noclamp(float y);
 static int pos_to_grid(float x, float y);
 static Vec2 grid_to_pos(int gx, int gy);
 
@@ -112,6 +112,8 @@ static float cam_dist = 100.0f;
 static Vec2 *targ_pos;
 static Mat4 view_matrix, proj_matrix;
 
+static bool wireframe;
+
 // emitter placement data (filled by event handlers, completed in update)
 static bool emit_place_pending;
 static Vec2 emit_place_pos;
@@ -185,6 +187,18 @@ static void simstep()
                p->vel += grad * SIM_DT;
                p->pos += p->vel * SIM_DT;
 
+               // if it moved outside of the simulation field, remove it
+               int gx = pos_to_grid_x_noclamp(p->pos.x);
+               int gy = pos_to_grid_y_noclamp(p->pos.y);
+               if(gx < 0 || gx >= GRID_SIZE || gy < 0 || gy >= GRID_SIZE) {
+                       Particle *next = p->next;
+                       grid_part[gidx] = 0;
+                       remove_particle(p);
+                       free_particle(p);
+                       p = next;
+                       continue;
+               }
+
                // find the grid cell it's moving to
                int gidx_next = pos_to_grid(p->pos.x, p->pos.y);
                p->vis_height = 0.0f;//-grid[gidx_next] * field_scale;
@@ -343,11 +357,17 @@ void GameScreen::draw()
        glMatrixMode(GL_MODELVIEW);
        glLoadMatrixf(view_matrix[0]);
 
-       glPushAttrib(GL_ENABLE_BIT);
-       glDisable(GL_CULL_FACE);
-
        // draw gravitational field
-       glEnable(GL_TEXTURE_2D);
+       if(wireframe) {
+               glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+
+               float amb[] = {0.5, 0.5, 0.5, 1.0};
+               glLightModelfv(GL_LIGHT_MODEL_AMBIENT, amb);
+       } else {
+               float amb[] = {0.01, 0.01, 0.01, 1.0};
+               glLightModelfv(GL_LIGHT_MODEL_AMBIENT, amb);
+       }
+
        bind_texture(gvis_tex, 0);
        bind_texture(grid_tex, 1);
 
@@ -355,6 +375,10 @@ void GameScreen::draw()
        glPatchParameteri(GL_PATCH_VERTICES, 4);
        draw_quadmesh(&field_mesh, GL_PATCHES);
 
+       if(wireframe) {
+               glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+       }
+
        // draw particles
        glUseProgram(particle_sdr);
 
@@ -374,8 +398,6 @@ void GameScreen::draw()
 
        glUseProgram(0);
 
-       glPopAttrib();
-
        assert(glGetError() == GL_NO_ERROR);
 }
 
@@ -426,6 +448,10 @@ void GameScreen::keyboard(int key, bool pressed)
                        set_uniform_float(field_sdr, "field_scale", field_scale);
                        break;
 
+               case 'w':
+                       wireframe = !wireframe;
+                       break;
+
                default:
                        break;
                }
@@ -459,11 +485,20 @@ void GameScreen::mwheel(int dir, int x, int y)
        if(cam_dist > MAX_CAM_DIST) cam_dist = MAX_CAM_DIST;
 }
 
+static int pos_to_grid_x_noclamp(float x)
+{
+       return ((x / (float)FIELD_SIZE) + 0.5f) * (float)GRID_SIZE;
+}
+
+static int pos_to_grid_y_noclamp(float y)
+{
+       return ((y / (float)FIELD_SIZE) + 0.5f) * (float)GRID_SIZE;
+}
 
 static int pos_to_grid(float x, float y)
 {
-       int gx = ((x / (float)FIELD_SIZE) + 0.5f) * (float)GRID_SIZE;
-       int gy = ((y / (float)FIELD_SIZE) + 0.5f) * (float)GRID_SIZE;
+       int gx = pos_to_grid_x_noclamp(x);
+       int gy = pos_to_grid_y_noclamp(y);
 
        if(gx < 0) gx = 0;
        if(gx >= GRID_SIZE) gx = GRID_SIZE - 1;
@@ -613,9 +648,9 @@ static void gen_quad_plane(QuadMesh *m, float width, float height, int usub, int
                                int idx = i * vverts + j;
 
                                *iptr++ = idx;
-                               *iptr++ = idx + vverts;
-                               *iptr++ = idx + vverts + 1;
                                *iptr++ = idx + 1;
+                               *iptr++ = idx + vverts + 1;
+                               *iptr++ = idx + vverts;
                        }
 
                        v += dv;