diff options
author | Eric Anholt <eric@anholt.net> | 2009-08-10 09:06:18 -0700 |
---|---|---|
committer | Eric Anholt <eric@anholt.net> | 2009-08-10 09:06:18 -0700 |
commit | 2f27b36a9a648d8f881f12e36594981eb5f17f81 (patch) | |
tree | 5e03237e0ed317fe672d75cfc31e951839ea332e /glass.c | |
parent | b41a892e194534d850861c934e9f257709ad2b6f (diff) |
Move the rings drawing code to a separate file.
Diffstat (limited to 'glass.c')
-rw-r--r-- | glass.c | 502 |
1 files changed, 6 insertions, 496 deletions
@@ -48,24 +48,12 @@ static int win_width, win_height; -enum uniform_list { - UNIFORM_MV, - UNIFORM_MVP, - UNIFORM_LIGHT_MVP, - UNIFORM_LIGHT_EYE, - UNIFORM_NORMAL_SAMPLER, - UNIFORM_HEIGHTMAP_SAMPLER, - UNIFORM_SHADOW_SAMPLER, - UNIFORM_NI, - UNIFORM_F0, -}; - enum shadowmap_display_uniform_list { SHADOWMAP_DISPLAY_UNIFORM_SHADOW_SAMPLER, SHADOWMAP_DISPLAY_UNIFORM_MAX }; -struct uniform_desc uniforms[] = { +struct uniform_desc uniforms[UNIFORM_MAX] = { [UNIFORM_MV] = { "mv" }, [UNIFORM_MVP] = { "mvp" }, [UNIFORM_LIGHT_MVP] = { "light_mvp" }, @@ -93,10 +81,8 @@ struct uniform_desc shadowmap_display_uniforms[SHADOWMAP_DISPLAY_UNIFORM_MAX] = [SHADOWMAP_DISPLAY_UNIFORM_SHADOW_SAMPLER] = { "shadow_sampler" }, }; -static GLuint glass_prog = 0, shadowmap_display_prog = 0; -GLuint ground_prog = 0, shadow_prog = 0; -struct revolved_object ring; -GLuint normalmap_tex, heightmap_tex; +static GLuint shadowmap_display_prog = 0; +GLuint glass_prog = 0, ground_prog = 0, shadow_prog = 0; static GLboolean display_shadow_map = GL_FALSE; static const GLUvec4 light_start_world = {{0.0, 10.0, 25.0, 1.0}}; @@ -111,8 +97,6 @@ GLUvec4 light_world; GLUmat4 projection; GLUmat4 world_to_eye; GLUmat4 ring_obj_to_world[NUM_RINGS]; -GLUvec4 ring_bounding_sphere_center_world; -float ring_bounding_sphere_radius; static time_t start_tv_sec = 0; static float start_time, cur_time, last_fps_time = 0; @@ -139,17 +123,6 @@ get_time_in_secs(void) } static void -update_brdf_constants(void) -{ - float ni = 1.5; /* index of refraction */ - /* Fresnel coefficient at normal (theta = 0) */ - float F0 = ((ni - 1) * (ni - 1)) / ((ni + 1) * (ni + 1)); - - glUniform1f(uniforms[UNIFORM_NI].location, ni); - glUniform1f(uniforms[UNIFORM_F0].location, F0); -} - -static void update_light_position(void) { GLUmat4 light_eye_matrix, light_world_matrix, temp; @@ -182,35 +155,6 @@ update_light_position(void) light_eye.values[3] = 1.0; } -void -do_ring_drawelements(void) -{ - GLvoid *indices[ring.num_verts]; - GLsizei count[ring.num_verts]; - int v; - - for (v = 0; v < ring.num_verts; v++) { - indices[v] = (void *)(uintptr_t)(ring.elements_offset + - ring.elements_vert_stride * v); - count[v] = ring.num_steps * 2 + 2; - } - - if (GLEW_EXT_multi_draw_arrays && !no_multi_draw_arrays) { - glMultiDrawElements(GL_TRIANGLE_STRIP, - count, - GL_UNSIGNED_INT, - (const GLvoid **)indices, - ring.num_verts); - } else { - for (v = 0; v < ring.num_verts; v++) { - glDrawElements(GL_TRIANGLE_STRIP, - ring.num_steps * 2 + 2, - GL_UNSIGNED_INT, - indices[v]); - } - } -} - static void calc_new_ring_transforms(int instance) { @@ -265,60 +209,8 @@ calc_new_ring_transforms(int instance) * So we're just making a bounding box and doing a bounding sphere * of it, really. */ - ring_bounding_sphere_radius = sqrt((5 + ring.radius) * (5 + ring.radius) * 3); -} - -static void -install_transform(int instance) -{ - GLUmat4 mv, mvp, light_mvp; - - /* Generate the whole mvp */ - gluMult4m_4m(&mv, &world_to_eye, &ring_obj_to_world[instance]); - gluMult4m_4m(&mvp, &projection, &mv); - gluMult4m_4m(&light_mvp, &world_to_shadow_texcoords, - &ring_obj_to_world[instance]); - glUniformMatrix4fv(uniforms[UNIFORM_MV].location, 1, 0, - (float *)&mv); - glUniformMatrix4fv(uniforms[UNIFORM_MVP].location, 1, 0, - (float *)&mvp); - glUniformMatrix4fv(uniforms[UNIFORM_LIGHT_MVP].location, 1, 0, - (float *)&light_mvp); -} - -static void -draw_rings(void) -{ - int instance; - - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, normalmap_tex); - glEnable(GL_TEXTURE_2D); - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, heightmap_tex); - glEnable(GL_TEXTURE_2D); - glActiveTexture(GL_TEXTURE2); - glBindTexture(GL_TEXTURE_2D, shadow_tex); - glEnable(GL_TEXTURE_2D); - - if (glass_prog != 0) { - glUseProgram(glass_prog); - glUniform3fv(uniforms[UNIFORM_LIGHT_EYE].location, 1, - light_eye.values); - - glBindVertexArray(ring.array_obj); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, ring.vbo); - for (instance = 0; instance < NUM_RINGS; instance++) { - install_transform(instance); - do_ring_drawelements(); - } - } - glActiveTexture(GL_TEXTURE0); - glDisable(GL_TEXTURE_2D); - glActiveTexture(GL_TEXTURE1); - glDisable(GL_TEXTURE_2D); - glActiveTexture(GL_TEXTURE2); - glDisable(GL_TEXTURE_2D); + ring_bounding_sphere_radius = sqrt((5 + ring.radius) * + (5 + ring.radius) * 3); } static void @@ -397,201 +289,6 @@ draw(void) } static void -revolve(const float *verts, unsigned int num_verts, - unsigned int steps, const float *translation_matrix, - float *pos, float *norm, float *tangent, float *tex_coord, - unsigned int *elements) -{ - int i, v, s; - float verts4[num_verts * 4]; - float normals4[num_verts * 4]; - float texcoord_y[num_verts]; - float unrotated_tangent4[4]; - float texcoord_len = 0; - - /* calculate the radius of the ring. */ - for (i = 0; i < num_verts; i++) { - } - - /* Calculate the 4-component vertex and normalized normal data - * that will be rotated around. - */ - ring.radius = 0; - for (i = 0; i < num_verts; i++) { - int v0; /* previous vertex */ - int v2; /* next vertex */ - float v0_v2[2], v1_v2[2], normal_len; - float position[4], this_radius; - - /* Expand vertex data out to 4f, so we can use the same - * matrix functions. - */ - verts4[i * 4 + 0] = verts[i * 2 + 0]; - verts4[i * 4 + 1] = verts[i * 2 + 1]; - verts4[i * 4 + 2] = 0.0; - verts4[i * 4 + 3] = 1.0; - - mult_m4_p4(position, - translation_matrix, - &verts4[i * 4]); - this_radius = sqrt(position[0] * position[0] + - position[1] * position[1] + - position[2] * position[2]); - if (this_radius > ring.radius) - ring.radius = this_radius; - - if (i == 0) - v0 = num_verts - 1; - else - v0 = i - 1; - if (i == num_verts - 1) - v2 = 0; - else - v2 = i + 1; - - v0_v2[0] = verts[v0 * 2 + 0] - verts[v2 * 2 + 0]; - v0_v2[1] = verts[v0 * 2 + 1] - verts[v2 * 2 + 1]; - v1_v2[0] = verts[i * 2 + 0] - verts[v2 * 2 + 0]; - v1_v2[1] = verts[i * 2 + 1] - verts[v2 * 2 + 1]; - - /* Make up a normal for this vector by taking the perpendicular - * of the neighboring two points, and normalizing it. - */ - normal_len = sqrt(v0_v2[0] * v0_v2[0] + v0_v2[1] * v0_v2[1]); - normals4[i * 4 + 0] = v0_v2[1]; - normals4[i * 4 + 1] = -v0_v2[0]; - normals4[i * 4 + 2] = 0.0; - normals4[i * 4 + 3] = normal_len; - - /* Sum the distance between this vertex and the next and store - * in the texcoord.y array. This way we get non-distorted - * mapping of texcoords to vertices even if they're unevenly - * distributed. - */ - texcoord_y[i] = texcoord_len; - texcoord_len += sqrt(v1_v2[0] * v1_v2[0] + v1_v2[1] * v1_v2[1]); - } - - /* Normalize texcoord.y to [0,1] range. */ - for (v = 0; v < num_verts; v++) { - texcoord_y[v] /= texcoord_len; - } - - /* Create a tangent vector pointing in the direction of the rotation. */ - unrotated_tangent4[0] = 0.0; - unrotated_tangent4[1] = 0.0; - unrotated_tangent4[2] = 1.0; - unrotated_tangent4[3] = 1.0; - - /* Calculate the positions and normals */ - for (i = 0; i <= steps; i++) { - int j; - float position[4], normal[4]; - float rotation_matrix[16]; - float translate_rotate_matrix[16]; - float rotation_rads = ((float)i / steps) * 2 * M_PI; - float tangent4[4]; - - /* Calculate the rotation matrix for this step: */ - init_m4_y_rotate(rotation_matrix, rotation_rads); - - /* Concatenate the translation matrix for the vertices with our - * rotation matrix. - */ - mult_m4_m4(translate_rotate_matrix, - rotation_matrix, - translation_matrix); - - /* print_m4(translate_rotate_matrix, "tr matrix"); */ - - mult_m4_p4(tangent4, rotation_matrix, unrotated_tangent4); - tangent4[0] /= tangent4[3]; - tangent4[1] /= tangent4[3]; - tangent4[2] /= tangent4[3]; - tangent4[3] = 1.0; - - /* Apply it to each of the vertices to get the verts for this - * step. - */ - for (j = 0; j < num_verts; j++) { - int vert_index = i * num_verts + j; - - mult_m4_p4(position, - translate_rotate_matrix, - &verts4[j * 4]); - pos[vert_index * 3 + 0] = position[0] / position[3]; - pos[vert_index * 3 + 1] = position[1] / position[3]; - pos[vert_index * 3 + 2] = position[2] / position[3]; - /* translated_point[3] should be 1.0. */ - - /* - printf("vert %2d@%2d: (%7.4f, %7.4f, %7.4f) -> " - "(%7.4f, %7.4f, %7.4f)\n", - j, i, - verts4[j * 4], - verts4[j * 4 + 1], - verts4[j * 4 + 1], - result[0], - result[1], - result[2]); - */ - - mult_m4_p4(normal, rotation_matrix, &normals4[j * 4]); - norm[vert_index * 3 + 0] = normal[0] / normal[3]; - norm[vert_index * 3 + 1] = normal[1] / normal[3]; - norm[vert_index * 3 + 2] = normal[2] / normal[3]; - /* - printf("norm: %7.4f %7.4f %7.4f %7.4f\n", - normal[0], normal[1], normal[2], normal[3]); - */ - - tangent[vert_index * 3 + 0] = tangent4[0]; - tangent[vert_index * 3 + 1] = tangent4[1]; - tangent[vert_index * 3 + 2] = tangent4[2]; - - tex_coord[vert_index * 2 + 0] = (float)i / steps * 4; - tex_coord[vert_index * 2 + 1] = texcoord_y[j]; - } - } - - /* Calculate the element data (indices). We'll emit num_verts strips - * going around the revolved object. - */ - i = 0; - for (v = 0; v < num_verts; v++) { - int v1 = (v + 1) % num_verts; - - for (s = 0; s <= steps; s++) { - elements[i++] = num_verts * s + v1; - elements[i++] = num_verts * s + v; - } - } - - glBindVertexArray(ring.array_obj); - glBindBuffer(GL_ARRAY_BUFFER_ARB, ring.vbo); - glVertexPointer(3, GL_FLOAT, 0, (void *)(uintptr_t)ring.pos_offset); - glEnable(GL_VERTEX_ARRAY); - glNormalPointer(GL_FLOAT, 0, (void *)(uintptr_t)ring.norm_offset); - glEnable(GL_NORMAL_ARRAY); - - glClientActiveTexture(GL_TEXTURE0); - glTexCoordPointer(2, GL_FLOAT, 0, (void *)(uintptr_t)ring.texcoord_offset); - glEnable(GL_TEXTURE_COORD_ARRAY); - - glClientActiveTexture(GL_TEXTURE1); - glTexCoordPointer(3, GL_FLOAT, 0, (void *)(uintptr_t)ring.tangent_offset); - glEnable(GL_TEXTURE_COORD_ARRAY); - - glNormalPointer(GL_FLOAT, 0, (void *)(uintptr_t)ring.norm_offset); - glEnable(GL_NORMAL_ARRAY); - - glBindVertexArray(ring.shadow_array_obj); - glBindBuffer(GL_ARRAY_BUFFER_ARB, ring.vbo); - glVertexPointer(3, GL_FLOAT, 0, (void *)(uintptr_t)ring.pos_offset); - glEnable(GL_VERTEX_ARRAY); -} - -static void reshape(int width, int height) { win_width = width; @@ -660,135 +357,6 @@ compile_program(GLenum type, const char *filename) return prog; } -/* Perform a sinusoidal weighting of v1 vs v2's components over steps, - * outputting to verts. - */ -static void -interp_corner_verts(float *verts, - float v1x, float v1y, - float v2x, float v2y, - int num_verts, int y_oriented) -{ - int i; - - for (i = 0; i < num_verts; i++) { - float smooth1 = 1 - cos((float)i / (num_verts - 1) * M_PI / 2); - float smooth2 = sin((float)i / (num_verts - 1) * M_PI / 2); - - if (y_oriented) { - verts[i * 2 + 0] = v1x + (v2x - v1x) * smooth1; - verts[i * 2 + 1] = v1y + (v2y - v1y) * smooth2; - } else { - verts[i * 2 + 0] = v1x + (v2x - v1x) * smooth2; - verts[i * 2 + 1] = v1y + (v2y - v1y) * smooth1; - } - /* - printf("%7.4f %7.4f\n", verts[i * 2 + 0], verts[i * 2 + 1]); - */ - } -} - - -/* Generate a rounded rectangle: - * |top_flat| - * _ __________ - * | / \ _ - * h| | | | side_flat. - * | | | _ - *0.0 _ \__________/ - * |-----w------| - * 0.0 - * The rounded bits are subdivided steps times. (steps = 0 means straight line - * between the vertices). The vertices are emitted in clockwise order. - * - * An additional vertex is generated along the flats near the corner - * transitions so that automatic normal generation produces actual flat sides. - */ -static void -generate_rounded_rect_verts(float w, float h, float top_flat, float side_flat, - int steps, float **out_verts, int *out_num_verts) -{ - float *verts; - int num_verts; - float corner_x = (w - top_flat) / 2; - float corner_y = (h - side_flat) / 2; - float top_epsilon = top_flat / 100; - float side_epsilon = side_flat / 100; - int v; - - assert(w > top_flat); - assert(h > side_flat); - assert(steps > 0); - - num_verts = steps * 4 + 4 * 4; - verts = malloc(num_verts * 2 * sizeof(float)); - if (verts == NULL) - errx(1, "out of memory\n"); - - v = 0; - -#define ADDVERT(x, y) do { \ - verts[v * 2 + 0] = x; \ - verts[v * 2 + 1] = y; \ - v++; \ -} while (0); - - /* left flat */ - ADDVERT(0, corner_y); - ADDVERT(0, corner_y + side_epsilon); - ADDVERT(0, h - corner_y - side_epsilon); - ADDVERT(0, h - corner_y); - - /* TL corner */ - interp_corner_verts(&verts[v * 2], - 0, h - corner_y, - corner_x, h, - steps, 1); - v+= steps; - - /* top flat */ - ADDVERT(corner_x, h); - ADDVERT(corner_x + top_epsilon, h); - ADDVERT(w - corner_x - top_epsilon, h); - ADDVERT(w - corner_x, h); - - /* TR corner */ - interp_corner_verts(&verts[v * 2], - w - corner_x, h, - w, h - corner_y, - steps, 0); - v+= steps; - - /* right flat */ - ADDVERT(w, h - corner_y); - ADDVERT(w, h - corner_y - side_epsilon); - ADDVERT(w, corner_y + side_epsilon); - ADDVERT(w, corner_y); - - /* BR corner */ - interp_corner_verts(&verts[v * 2], - w, corner_y, - w - corner_x, 0, - steps, 1); - v+= steps; - - /* bottom flat */ - ADDVERT(w - corner_x, 0); - ADDVERT(w - corner_x - top_epsilon, 0); - ADDVERT(corner_x + top_epsilon, 0); - ADDVERT(corner_x, 0); - - /* BL corner */ - interp_corner_verts(&verts[v * 2], - corner_x, 0, - 0, corner_y, - steps, 0); - v+= steps; - - *out_verts = verts; - *out_num_verts = num_verts; -} - static GLuint load_program(char *base_filename, struct uniform_desc *uniforms, int num_uniforms) @@ -891,16 +459,6 @@ load_programs(void) static void init(void) { - int size; - int num_steps = 100; - int corner_steps = 5; - float *verts; - int num_verts; - char *base; - float translation_matrix[16]; - GLuint vbo; - int sv; - reshape(DEFAULT_WIDTH, DEFAULT_HEIGHT); glewInit(); @@ -916,57 +474,9 @@ init(void) gluLookAt4v(&world_to_eye, &eye_world, &eye_center_world, &z_axis); setup_ground(); - - generate_rounded_rect_verts(0.2, 1.0, .02, 0.9, corner_steps, - &verts, &num_verts); - - memset(translation_matrix, 0, sizeof(translation_matrix)); - translation_matrix[0 * 4 + 0] = 1.0; - translation_matrix[1 * 4 + 1] = 1.0; - translation_matrix[3 * 4 + 0] = 1.9; - translation_matrix[3 * 4 + 1] = -0.5; - translation_matrix[2 * 4 + 2] = 1.0; - translation_matrix[3 * 4 + 3] = 1.0; - - sv = (num_steps + 1) * num_verts; - ring.num_steps = num_steps; - ring.num_verts = num_verts; - ring.pos_offset = 0; - ring.norm_offset = ring.pos_offset + 3 * 4 * sv; - ring.tangent_offset = ring.norm_offset + 3 * 4 * sv; - ring.texcoord_offset = ring.tangent_offset + 3 * 4 * sv; - ring.elements_offset = ring.texcoord_offset + 2 * 4 * sv; - ring.elements_vert_stride = (num_steps + 1) * 2 * 4; - size = ring.elements_offset + ring.elements_vert_stride * - ring.num_verts; - - glGenVertexArrays(1, &ring.array_obj); - glGenVertexArrays(1, &ring.shadow_array_obj); - - glGenBuffers(1, &vbo); - ring.vbo = vbo; - glBindBuffer(GL_ARRAY_BUFFER_ARB, vbo); - glBufferData(GL_ARRAY_BUFFER_ARB, size, NULL, GL_STATIC_DRAW_ARB); - - base = glMapBuffer(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB); - - revolve(verts, num_verts, num_steps, translation_matrix, - (float *)(base + ring.pos_offset), - (float *)(base + ring.norm_offset), - (float *)(base + ring.tangent_offset), - (float *)(base + ring.texcoord_offset), - (unsigned int *)(base + ring.elements_offset)); - - glUnmapBuffer(GL_ARRAY_BUFFER_ARB); - - free(verts); + setup_rings(); load_programs(); - - glActiveTexture(GL_TEXTURE0); - normalmap_tex = load_texture_rgb("normalmap.png"); - glActiveTexture(GL_TEXTURE1); - heightmap_tex = load_texture_rgb("heightmap.png"); } /** |