diff options
author | Clément Foucault <foucault.clem@gmail.com> | 2017-03-05 07:22:40 +0300 |
---|---|---|
committer | Clément Foucault <foucault.clem@gmail.com> | 2017-03-05 20:10:08 +0300 |
commit | 747ac668002497e4b2ca801c7629f27e0473f261 (patch) | |
tree | a08497fca2c2dba26cf433d8638443edd27b48c9 /source/blender/draw | |
parent | 45b42d3fb71d2b09e0781f22cb39f3d2677bd044 (diff) |
Clay Engine: More Lamp drawing work
Diffstat (limited to 'source/blender/draw')
-rw-r--r-- | source/blender/draw/intern/draw_cache.c | 245 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_cache.h | 5 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_mode_pass.c | 127 |
3 files changed, 373 insertions, 4 deletions
diff --git a/source/blender/draw/intern/draw_cache.c b/source/blender/draw/intern/draw_cache.c index 399ed1032cd..7514a0c806a 100644 --- a/source/blender/draw/intern/draw_cache.c +++ b/source/blender/draw/intern/draw_cache.c @@ -44,6 +44,7 @@ static struct DRWShapeCache { Batch *drw_single_arrow; Batch *drw_cube; Batch *drw_circle; + Batch *drw_square; Batch *drw_line; Batch *drw_line_endpoints; Batch *drw_empty_sphere; @@ -52,6 +53,10 @@ static struct DRWShapeCache { Batch *drw_axis_names; Batch *drw_lamp; Batch *drw_lamp_sunrays; + Batch *drw_lamp_area; + Batch *drw_lamp_hemi; + Batch *drw_lamp_spot; + Batch *drw_lamp_spot_square; Batch *drw_speaker; Batch *drw_bone_octahedral; Batch *drw_bone_octahedral_wire; @@ -77,6 +82,8 @@ void DRW_shape_cache_free(void) Batch_discard_all(SHC.drw_cube); if (SHC.drw_circle) Batch_discard_all(SHC.drw_circle); + if (SHC.drw_square) + Batch_discard_all(SHC.drw_square); if (SHC.drw_line) Batch_discard_all(SHC.drw_line); if (SHC.drw_line_endpoints) @@ -93,6 +100,14 @@ void DRW_shape_cache_free(void) Batch_discard_all(SHC.drw_lamp); if (SHC.drw_lamp_sunrays) Batch_discard_all(SHC.drw_lamp_sunrays); + if (SHC.drw_lamp_area) + Batch_discard_all(SHC.drw_lamp_area); + if (SHC.drw_lamp_hemi) + Batch_discard_all(SHC.drw_lamp_hemi); + if (SHC.drw_lamp_spot) + Batch_discard_all(SHC.drw_lamp_spot); + if (SHC.drw_lamp_spot_square) + Batch_discard_all(SHC.drw_lamp_spot_square); if (SHC.drw_speaker) Batch_discard_all(SHC.drw_speaker); if (SHC.drw_bone_octahedral) @@ -335,6 +350,34 @@ Batch *DRW_cache_circle_get(void) #undef CIRCLE_RESOL } +Batch *DRW_cache_square_get(void) +{ + if (!SHC.drw_square) { + float p[4][3] = {{ 1.0f, 0.0f, 1.0f}, + { 1.0f, 0.0f, -1.0f}, + {-1.0f, 0.0f, -1.0f}, + {-1.0f, 0.0f, 1.0f}}; + + /* Position Only 3D format */ + static VertexFormat format = { 0 }; + static unsigned pos_id; + if (format.attrib_ct == 0) { + pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT); + } + + VertexBuffer *vbo = VertexBuffer_create_with_format(&format); + VertexBuffer_allocate_data(vbo, 8); + + for (int i = 0; i < 4; i++) { + setAttrib(vbo, pos_id, i * 2, p[i % 4]); + setAttrib(vbo, pos_id, i * 2 + 1, p[(i+1) % 4]); + } + + SHC.drw_square = Batch_create(GL_LINES, vbo, NULL); + } + return SHC.drw_square; +} + Batch *DRW_cache_single_line_get(void) { /* Z axis line */ @@ -652,6 +695,208 @@ Batch *DRW_cache_lamp_sunrays_get(void) return SHC.drw_lamp_sunrays; } +Batch *DRW_cache_lamp_area_get(void) +{ + if (!SHC.drw_lamp_area) { + float v1[3] = {0.0f, 0.0f, 0.0f}; + + /* Position Only 3D format */ + static VertexFormat format = { 0 }; + static unsigned pos_id; + if (format.attrib_ct == 0) { + pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT); + } + + VertexBuffer *vbo = VertexBuffer_create_with_format(&format); + VertexBuffer_allocate_data(vbo, 8); + + v1[0] = v1[1] = 0.5f; + setAttrib(vbo, pos_id, 0, v1); + v1[0] = -0.5f; + setAttrib(vbo, pos_id, 1, v1); + setAttrib(vbo, pos_id, 2, v1); + v1[1] = -0.5f; + setAttrib(vbo, pos_id, 3, v1); + setAttrib(vbo, pos_id, 4, v1); + v1[0] = 0.5f; + setAttrib(vbo, pos_id, 5, v1); + setAttrib(vbo, pos_id, 6, v1); + v1[1] = 0.5f; + setAttrib(vbo, pos_id, 7, v1); + + SHC.drw_lamp_area = Batch_create(GL_LINES, vbo, NULL); + } + return SHC.drw_lamp_area; +} + +Batch *DRW_cache_lamp_hemi_get(void) +{ +#define CIRCLE_RESOL 32 + if (!SHC.drw_lamp_hemi) { + float v[3]; + int vidx = 0; + + /* Position Only 3D format */ + static VertexFormat format = { 0 }; + static unsigned pos_id; + if (format.attrib_ct == 0) { + pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT); + } + + VertexBuffer *vbo = VertexBuffer_create_with_format(&format); + VertexBuffer_allocate_data(vbo, CIRCLE_RESOL * 2 * 2 - 6 * 2 * 2); + + /* XZ plane */ + for (int a = 3; a < CIRCLE_RESOL / 2 - 3; a++) { + v[0] = sinf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL) - M_PI / 2); + v[2] = cosf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL) - M_PI / 2) - 1.0f; + v[1] = 0.0f; + setAttrib(vbo, pos_id, vidx++, v); + + v[0] = sinf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL) - M_PI / 2); + v[2] = cosf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL) - M_PI / 2) - 1.0f; + v[1] = 0.0f; + setAttrib(vbo, pos_id, vidx++, v); + } + + /* XY plane */ + for (int a = 3; a < CIRCLE_RESOL / 2 - 3; a++) { + v[2] = sinf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL)) - 1.0f; + v[1] = cosf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL)); + v[0] = 0.0f; + setAttrib(vbo, pos_id, vidx++, v); + + v[2] = sinf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL)) - 1.0f; + v[1] = cosf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL)); + v[0] = 0.0f; + setAttrib(vbo, pos_id, vidx++, v); + } + + /* YZ plane full circle */ + /* lease v[2] as it is */ + const float rad = cosf((2.0f * M_PI * 3) / ((float)CIRCLE_RESOL)); + for (int a = 0; a < CIRCLE_RESOL; a++) { + v[1] = rad * sinf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL)); + v[0] = rad * cosf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL)); + setAttrib(vbo, pos_id, vidx++, v); + + v[1] = rad * sinf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL)); + v[0] = rad * cosf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL)); + setAttrib(vbo, pos_id, vidx++, v); + } + + + SHC.drw_lamp_hemi = Batch_create(GL_LINES, vbo, NULL); + } + return SHC.drw_lamp_hemi; +#undef CIRCLE_RESOL +} + + +Batch *DRW_cache_lamp_spot_get(void) +{ +#define NSEGMENTS 32 + if (!SHC.drw_lamp_spot) { + /* a single ring of vertices */ + float p[NSEGMENTS][2]; + float n[NSEGMENTS][3]; + float neg[NSEGMENTS][3]; + float half_angle = 2 * M_PI / ((float)NSEGMENTS * 2); + for (int i = 0; i < NSEGMENTS; ++i) { + float angle = 2 * M_PI * ((float)i / (float)NSEGMENTS); + p[i][0] = cosf(angle); + p[i][1] = sinf(angle); + + n[i][0] = cosf(angle - half_angle); + n[i][1] = sinf(angle - half_angle); + n[i][2] = cosf(M_PI / 16.0f); /* slope of the cone */ + normalize_v3(n[i]); /* necessary ? */ + negate_v3_v3(neg[i], n[i]); + } + + /* Position Only 3D format */ + static VertexFormat format = { 0 }; + static unsigned int pos_id, n1_id, n2_id; + if (format.attrib_ct == 0) { + pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT); + n1_id = add_attrib(&format, "N1", GL_FLOAT, 3, KEEP_FLOAT); + n2_id = add_attrib(&format, "N2", GL_FLOAT, 3, KEEP_FLOAT); + } + + VertexBuffer *vbo = VertexBuffer_create_with_format(&format); + VertexBuffer_allocate_data(vbo, NSEGMENTS * 4); + + for (int i = 0; i < NSEGMENTS; ++i) { + float cv[2], v[3]; + cv[0] = p[i % NSEGMENTS][0]; + cv[1] = p[i % NSEGMENTS][1]; + + /* cone sides */ + v[0] = cv[0], v[1] = cv[1], v[2] = -1.0f; + setAttrib(vbo, pos_id, i * 4, v); + v[0] = 0.0f, v[1] = 0.0f, v[2] = 0.0f; + setAttrib(vbo, pos_id, i * 4 + 1, v); + + setAttrib(vbo, n1_id, i * 4, n[(i) % NSEGMENTS]); + setAttrib(vbo, n1_id, i * 4 + 1, n[(i) % NSEGMENTS]); + setAttrib(vbo, n2_id, i * 4, n[(i+1) % NSEGMENTS]); + setAttrib(vbo, n2_id, i * 4 + 1, n[(i+1) % NSEGMENTS]); + + /* end ring */ + v[0] = cv[0], v[1] = cv[1], v[2] = -1.0f; + setAttrib(vbo, pos_id, i * 4 + 2, v); + cv[0] = p[(i + 1) % NSEGMENTS][0]; + cv[1] = p[(i + 1) % NSEGMENTS][1]; + v[0] = cv[0], v[1] = cv[1], v[2] = -1.0f; + setAttrib(vbo, pos_id, i * 4 + 3, v); + + setAttrib(vbo, n1_id, i * 4 + 2, n[(i) % NSEGMENTS]); + setAttrib(vbo, n1_id, i * 4 + 3, n[(i) % NSEGMENTS]); + setAttrib(vbo, n2_id, i * 4 + 2, neg[(i) % NSEGMENTS]); + setAttrib(vbo, n2_id, i * 4 + 3, neg[(i) % NSEGMENTS]); + } + + SHC.drw_lamp_spot = Batch_create(GL_LINES, vbo, NULL); + } + return SHC.drw_lamp_spot; +#undef NSEGMENTS +} + +Batch *DRW_cache_lamp_spot_square_get(void) +{ + if (!SHC.drw_lamp_spot_square) { + float p[5][3] = {{ 0.0f, 0.0f, 0.0f}, + { 1.0f, 1.0f, -1.0f}, + { 1.0f, -1.0f, -1.0f}, + {-1.0f, -1.0f, -1.0f}, + {-1.0f, 1.0f, -1.0f}}; + + unsigned int v_idx = 0; + + /* Position Only 3D format */ + static VertexFormat format = { 0 }; + static unsigned int pos_id; + if (format.attrib_ct == 0) { + pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT); + } + + VertexBuffer *vbo = VertexBuffer_create_with_format(&format); + VertexBuffer_allocate_data(vbo, 16); + + /* piramid sides */ + for (int i = 1; i <= 4; ++i) { + setAttrib(vbo, pos_id, v_idx++, p[0]); + setAttrib(vbo, pos_id, v_idx++, p[i]); + + setAttrib(vbo, pos_id, v_idx++, p[(i % 4)+1]); + setAttrib(vbo, pos_id, v_idx++, p[((i+1) % 4)+1]); + } + + SHC.drw_lamp_spot_square = Batch_create(GL_LINES, vbo, NULL); + } + return SHC.drw_lamp_spot_square; +} + /* Speaker */ Batch *DRW_cache_speaker_get(void) { diff --git a/source/blender/draw/intern/draw_cache.h b/source/blender/draw/intern/draw_cache.h index bfab441bee6..66aa5400df5 100644 --- a/source/blender/draw/intern/draw_cache.h +++ b/source/blender/draw/intern/draw_cache.h @@ -42,6 +42,7 @@ struct Batch *DRW_cache_plain_axes_get(void); struct Batch *DRW_cache_single_arrow_get(void); struct Batch *DRW_cache_cube_get(void); struct Batch *DRW_cache_circle_get(void); +struct Batch *DRW_cache_square_get(void); struct Batch *DRW_cache_empty_sphere_get(void); struct Batch *DRW_cache_empty_cone_get(void); struct Batch *DRW_cache_arrows_get(void); @@ -50,6 +51,10 @@ struct Batch *DRW_cache_axis_names_get(void); /* Lamps */ struct Batch *DRW_cache_lamp_get(void); struct Batch *DRW_cache_lamp_sunrays_get(void); +struct Batch *DRW_cache_lamp_area_get(void); +struct Batch *DRW_cache_lamp_hemi_get(void); +struct Batch *DRW_cache_lamp_spot_get(void); +struct Batch *DRW_cache_lamp_spot_square_get(void); /* Camera */ struct Batch *DRW_cache_camera_get(void); diff --git a/source/blender/draw/intern/draw_mode_pass.c b/source/blender/draw/intern/draw_mode_pass.c index a066f8ce4f4..b21e6a23b72 100644 --- a/source/blender/draw/intern/draw_mode_pass.c +++ b/source/blender/draw/intern/draw_mode_pass.c @@ -65,6 +65,15 @@ static DRWShadingGroup *lamp_groundline; static DRWShadingGroup *lamp_circle; static DRWShadingGroup *lamp_circle_shadow; static DRWShadingGroup *lamp_sunrays; +static DRWShadingGroup *lamp_distance; +static DRWShadingGroup *lamp_buflimit; +static DRWShadingGroup *lamp_buflimit_points; +static DRWShadingGroup *lamp_area; +static DRWShadingGroup *lamp_hemi; +static DRWShadingGroup *lamp_spot_cone; +static DRWShadingGroup *lamp_spot_blend; +static DRWShadingGroup *lamp_spot_pyramid; +static DRWShadingGroup *lamp_spot_blend_rect; /* Helpers */ static DRWShadingGroup *relationship_lines; @@ -271,7 +280,6 @@ static DRWShadingGroup *shgroup_camera_instance(DRWPass *pass, struct Batch *geo return grp; } - static DRWShadingGroup *shgroup_distance_lines_instance(DRWPass *pass, struct Batch *geom) { GPUShader *sh_inst = GPU_shader_get_builtin_shader(GPU_SHADER_DISTANCE_LINES); @@ -287,6 +295,22 @@ static DRWShadingGroup *shgroup_distance_lines_instance(DRWPass *pass, struct Ba return grp; } +static DRWShadingGroup *shgroup_spot_instance(DRWPass *pass, struct Batch *geom) +{ + GPUShader *sh_inst = GPU_shader_get_builtin_shader(GPU_SHADER_INSTANCE_EDGES_VARIYING_COLOR); + static bool True = true; + static bool False = false; + + DRWShadingGroup *grp = DRW_shgroup_instance_create(sh_inst, pass, geom); + DRW_shgroup_attrib_float(grp, "color", 3); + DRW_shgroup_attrib_float(grp, "InstanceModelMatrix", 16); + DRW_shgroup_uniform_bool(grp, "drawFront", &False, 1); + DRW_shgroup_uniform_bool(grp, "drawBack", &False, 1); + DRW_shgroup_uniform_bool(grp, "drawSilhouette", &True, 1); + + return grp; +} + /* This Function setup the passes needed for the mode rendering. * The passes are populated by the rendering engines using the DRW_shgroup_* functions. * If a pass is not needed use NULL instead of the pass pointer */ @@ -392,8 +416,13 @@ void DRW_mode_passes_setup(DRWPass **psl_wire_overlay, /* Lamps */ /* TODO - * for now we create 3 times the same VBO with only lamp center coordinates + * for now we create multiple times the same VBO with only lamp center coordinates * but ideally we would only create it once */ + + /* start with buflimit because we don't want stipples */ + geom = DRW_cache_single_line_get(); + lamp_buflimit = shgroup_distance_lines_instance(*psl_non_meshes, geom); + lamp_center = shgroup_dynpoints_uniform_color(*psl_non_meshes, ts.colorLampNoAlpha, &ts.sizeLampCenter); lamp_center_group = shgroup_dynpoints_uniform_color(*psl_non_meshes, ts.colorGroup, &ts.sizeLampCenter); @@ -407,6 +436,30 @@ void DRW_mode_passes_setup(DRWPass **psl_wire_overlay, lamp_groundline = shgroup_groundlines_uniform_color(*psl_non_meshes, ts.colorLamp); lamp_groundpoint = shgroup_groundpoints_uniform_color(*psl_non_meshes, ts.colorLamp); + geom = DRW_cache_lamp_area_get(); + lamp_area = shgroup_instance(*psl_non_meshes, geom); + + geom = DRW_cache_lamp_hemi_get(); + lamp_hemi = shgroup_instance(*psl_non_meshes, geom); + + geom = DRW_cache_single_line_get(); + lamp_distance = shgroup_distance_lines_instance(*psl_non_meshes, geom); + + geom = DRW_cache_single_line_endpoints_get(); + lamp_buflimit_points = shgroup_distance_lines_instance(*psl_non_meshes, geom); + + geom = DRW_cache_lamp_spot_get(); + lamp_spot_cone = shgroup_spot_instance(*psl_non_meshes, geom); + + geom = DRW_cache_circle_get(); + lamp_spot_blend = shgroup_instance(*psl_non_meshes, geom); + + geom = DRW_cache_lamp_spot_square_get(); + lamp_spot_pyramid = shgroup_instance(*psl_non_meshes, geom); + + geom = DRW_cache_square_get(); + lamp_spot_blend_rect = shgroup_instance(*psl_non_meshes, geom); + /* Relationship Lines */ relationship_lines = shgroup_dynlines_uniform_color(*psl_non_meshes, ts.colorWire); DRW_shgroup_state_set(relationship_lines, DRW_STATE_STIPPLE_3); @@ -591,6 +644,7 @@ void DRW_shgroup_lamp(Object *ob) Lamp *la = ob->data; float *color; int theme_id = draw_object_wire_theme(ob, &color); + static float zero = 0.0f; /* Don't draw the center if it's selected or active */ if (theme_id == TH_GROUP) @@ -603,13 +657,78 @@ void DRW_shgroup_lamp(Object *ob) /* draw dashed outer circle if shadow is on. remember some lamps can't have certain shadows! */ if (la->type != LA_HEMI) { - DRW_shgroup_dynamic_call_add(lamp_circle_shadow, ob->obmat[3], color); + if ((la->mode & LA_SHAD_RAY) || ((la->mode & LA_SHAD_BUF) && (la->type == LA_SPOT))) { + DRW_shgroup_dynamic_call_add(lamp_circle_shadow, ob->obmat[3], color); + } + } + + /* Distance */ + if (ELEM(la->type, LA_HEMI, LA_SUN, LA_AREA)) { + DRW_shgroup_dynamic_call_add(lamp_distance, color, &zero, &la->dist, ob->obmat); } - /* Sunrays */ + copy_m4_m4(la->shapemat, ob->obmat); + if (la->type == LA_SUN) { DRW_shgroup_dynamic_call_add(lamp_sunrays, ob->obmat[3], color); } + else if (la->type == LA_SPOT) { + float size[3], sizemat[4][4]; + static float one = 1.0f; + float blend = 1.0f - pow2f(la->spotblend); + + size[0] = size[1] = sinf(la->spotsize * 0.5f) * la->dist; + size[2] = cosf(la->spotsize * 0.5f) * la->dist; + + size_to_mat4(sizemat, size); + mul_m4_m4m4(la->spotconemat, ob->obmat, sizemat); + + size[0] = size[1] = blend; size[2] = 1.0f; + size_to_mat4(sizemat, size); + translate_m4(sizemat, 0.0f, 0.0f, -1.0f); + rotate_m4(sizemat, 'X', M_PI / 2.0f); + mul_m4_m4m4(la->spotblendmat, la->spotconemat, sizemat); + + if (la->mode & LA_SQUARE) { + DRW_shgroup_dynamic_call_add(lamp_spot_pyramid, color, &one, la->spotconemat); + + /* hide line if it is zero size or overlaps with outer border, + * previously it adjusted to always to show it but that seems + * confusing because it doesn't show the actual blend size */ + if (blend != 0.0f && blend != 1.0f) { + DRW_shgroup_dynamic_call_add(lamp_spot_blend_rect, color, &one, la->spotblendmat); + } + } + else { + DRW_shgroup_dynamic_call_add(lamp_spot_cone, color, la->spotconemat); + + /* hide line if it is zero size or overlaps with outer border, + * previously it adjusted to always to show it but that seems + * confusing because it doesn't show the actual blend size */ + if (blend != 0.0f && blend != 1.0f) { + DRW_shgroup_dynamic_call_add(lamp_spot_blend, color, &one, la->spotblendmat); + } + } + + normalize_m4(la->shapemat); + DRW_shgroup_dynamic_call_add(lamp_buflimit, color, &la->clipsta, &la->clipend, ob->obmat); + DRW_shgroup_dynamic_call_add(lamp_buflimit_points, color, &la->clipsta, &la->clipend, ob->obmat); + } + else if (la->type == LA_HEMI) { + static float hemisize = 2.0f; + DRW_shgroup_dynamic_call_add(lamp_hemi, color, &hemisize, la->shapemat); + } + else if (la->type == LA_AREA) { + float size[3] = {1.0f, 1.0f, 1.0f}, sizemat[4][4]; + + if (la->area_shape == LA_AREA_RECT) { + size[1] = la->area_sizey / la->area_size; + size_to_mat4(sizemat, size); + mul_m4_m4m4(la->shapemat, la->shapemat, sizemat); + } + + DRW_shgroup_dynamic_call_add(lamp_area, color, &la->area_size, la->shapemat); + } /* Line and point going to the ground */ DRW_shgroup_dynamic_call_add(lamp_groundline, ob->obmat[3]); |