diff options
Diffstat (limited to 'source/blender/editors/space_view3d/drawobject.c')
-rw-r--r-- | source/blender/editors/space_view3d/drawobject.c | 4716 |
1 files changed, 3031 insertions, 1685 deletions
diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index 884bc6b83ba..126217057e5 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -62,6 +62,7 @@ #include "BKE_global.h" #include "BKE_image.h" #include "BKE_key.h" +#include "BKE_layer.h" #include "BKE_lattice.h" #include "BKE_main.h" #include "BKE_mesh.h" @@ -90,6 +91,10 @@ #include "GPU_select.h" #include "GPU_basic_shader.h" #include "GPU_shader.h" +#include "GPU_immediate.h" +#include "GPU_immediate_util.h" +#include "GPU_batch.h" +#include "GPU_matrix.h" #include "ED_mesh.h" #include "ED_particle.h" @@ -105,6 +110,11 @@ #include "view3d_intern.h" /* bad level include */ +#include "../../draw/intern/draw_cache_impl.h" /* bad level include (temporary) */ + +/* prototypes */ +static void imm_draw_box(const float vec[8][3], bool solid, unsigned pos); + /* Workaround for sequencer scene render mode. * * Strips doesn't use DAG to update objects or so, which @@ -129,6 +139,7 @@ typedef struct drawDMVerts_userData { BMVert *eve_act; char sel; + unsigned int pos, color; /* cached theme values */ unsigned char th_editmesh_active[4]; @@ -181,6 +192,7 @@ typedef struct drawDMFacesSel_userData { } drawDMFacesSel_userData; typedef struct drawDMNormal_userData { + unsigned int pos; BMesh *bm; int uniform_scale; float normalsize; @@ -189,6 +201,7 @@ typedef struct drawDMNormal_userData { } drawDMNormal_userData; typedef struct drawMVertOffset_userData { + unsigned int pos, col; MVert *mvert; int offset; } drawMVertOffset_userData; @@ -196,9 +209,11 @@ typedef struct drawMVertOffset_userData { typedef struct drawDMLayer_userData { BMesh *bm; int cd_layer_offset; + unsigned int pos, col; } drawDMLayer_userData; typedef struct drawBMOffset_userData { + unsigned int pos, col; BMesh *bm; int offset; } drawBMOffset_userData; @@ -206,25 +221,23 @@ typedef struct drawBMOffset_userData { typedef struct drawBMSelect_userData { BMesh *bm; bool select; + unsigned int pos; } drawBMSelect_userData; -static void draw_bounding_volume(Object *ob, char type); -static void drawcube_size(float size); -static void drawcircle_size(float size); -static void draw_empty_sphere(float size); -static void draw_empty_cone(float size); -static void draw_box(const float vec[8][3], bool solid); +static void drawcube_size(float size, unsigned pos); +static void drawcircle_size(float size, unsigned pos); +static void draw_empty_sphere(float size, unsigned pos); +static void draw_empty_cone(float size, unsigned pos); -static void ob_wire_color_blend_theme_id(const unsigned char ob_wire_col[4], const int theme_id, float fac) +static void ob_wire_color_blend_theme_id(const unsigned char ob_wire_col[4], const int theme_id, float fac, float r_col[3]) { - float col_wire[3], col_bg[3], col[3]; + float col_wire[3], col_bg[3]; rgb_uchar_to_float(col_wire, ob_wire_col); UI_GetThemeColor3fv(theme_id, col_bg); - interp_v3_v3v3(col, col_bg, col_wire, fac); - glColor3fv(col); + interp_v3_v3v3(r_col, col_bg, col_wire, fac); } int view3d_effective_drawtype(const struct View3D *v3d) @@ -296,13 +309,13 @@ static bool check_ob_drawface_dot(Scene *sce, View3D *vd, char dt) /* check for glsl drawing */ -bool draw_glsl_material(Scene *scene, Object *ob, View3D *v3d, const char dt) +bool draw_glsl_material(Scene *scene, SceneLayer *sl, Object *ob, View3D *v3d, const char dt) { if (G.f & G_PICKSEL) return false; if (!check_object_draw_texture(scene, v3d, dt)) return false; - if (ob == OBACT && (ob && ob->mode & OB_MODE_WEIGHT_PAINT)) + if (ob == OBACT_NEW && (ob && ob->mode & OB_MODE_WEIGHT_PAINT)) return false; if (v3d->flag2 & V3D_SHOW_SOLID_MATCAP) @@ -318,7 +331,7 @@ bool draw_glsl_material(Scene *scene, Object *ob, View3D *v3d, const char dt) static bool check_alpha_pass(Base *base) { - if (base->flag & OB_FROMDUPLI) + if (base->flag_legacy & OB_FROMDUPLI) return false; if (G.f & G_PICKSEL) @@ -414,9 +427,9 @@ static const float cosval[CIRCLE_RESOL] = { * \param viewmat_local_unit is typically the 'rv3d->viewmatob' * copied into a 3x3 matrix and normalized. */ -static void draw_xyz_wire(const float viewmat_local_unit[3][3], const float c[3], float size, int axis) +static void draw_xyz_wire(const float viewmat_local_unit[3][3], const float c[3], float size, int axis, unsigned pos) { - int line_type; + PrimitiveType line_type = PRIM_LINES; float buffer[4][3]; int n = 0; @@ -429,8 +442,6 @@ static void draw_xyz_wire(const float viewmat_local_unit[3][3], const float c[3] switch (axis) { case 0: /* x axis */ - line_type = GL_LINES; - /* bottom left to top right */ negate_v3_v3(v1, dx); sub_v3_v3(v1, dy); @@ -450,8 +461,6 @@ static void draw_xyz_wire(const float viewmat_local_unit[3][3], const float c[3] break; case 1: /* y axis */ - line_type = GL_LINES; - /* bottom left to top right */ mul_v3_fl(dx, 0.75f); negate_v3_v3(v1, dx); @@ -472,7 +481,7 @@ static void draw_xyz_wire(const float viewmat_local_unit[3][3], const float c[3] break; case 2: /* z axis */ - line_type = GL_LINE_STRIP; + line_type = PRIM_LINE_STRIP; /* start at top left */ negate_v3_v3(v1, dx); @@ -501,54 +510,60 @@ static void draw_xyz_wire(const float viewmat_local_unit[3][3], const float c[3] return; } + immBegin(line_type, n); for (int i = 0; i < n; i++) { mul_transposed_m3_v3((float (*)[3])viewmat_local_unit, buffer[i]); add_v3_v3(buffer[i], c); + immVertex3fv(pos, buffer[i]); } + immEnd(); - glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(3, GL_FLOAT, 0, buffer); - glDrawArrays(line_type, 0, n); - glDisableClientState(GL_VERTEX_ARRAY); + /* TODO: recode this function for clarity once we're not in a hurry to modernize GL usage */ } -void drawaxes(const float viewmat_local[4][4], float size, char drawtype) +void drawaxes(const float viewmat_local[4][4], float size, char drawtype, const unsigned char color[4]) { int axis; float v1[3] = {0.0, 0.0, 0.0}; float v2[3] = {0.0, 0.0, 0.0}; float v3[3] = {0.0, 0.0, 0.0}; - glLineWidth(1); + glLineWidth(1.0f); - switch (drawtype) { + unsigned int pos = VertexFormat_add_attrib(immVertexFormat(), "pos", COMP_F32, 3, KEEP_FLOAT); + if (color) { + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immUniformColor4ubv(color); + } + else { + immBindBuiltinProgram(GPU_SHADER_3D_DEPTH_ONLY); + } + switch (drawtype) { case OB_PLAINAXES: + immBegin(PRIM_LINES, 6); for (axis = 0; axis < 3; axis++) { - glBegin(GL_LINES); - v1[axis] = size; v2[axis] = -size; - glVertex3fv(v1); - glVertex3fv(v2); + immVertex3fv(pos, v1); + immVertex3fv(pos, v2); /* reset v1 & v2 to zero */ v1[axis] = v2[axis] = 0.0f; - - glEnd(); } + immEnd(); break; - case OB_SINGLE_ARROW: - glBegin(GL_LINES); + case OB_SINGLE_ARROW: + immBegin(PRIM_LINES, 2); /* in positive z direction only */ v1[2] = size; - glVertex3fv(v1); - glVertex3fv(v2); - glEnd(); + immVertex3fv(pos, v1); + immVertex3fv(pos, v2); + immEnd(); /* square pyramid */ - glBegin(GL_TRIANGLES); + immBegin(PRIM_TRIANGLES, 12); v2[0] = size * 0.035f; v2[1] = size * 0.035f; v3[0] = size * -0.035f; v3[1] = size * 0.035f; @@ -564,28 +579,27 @@ void drawaxes(const float viewmat_local[4][4], float size, char drawtype) v3[0] = -v3[0]; } - glVertex3fv(v1); - glVertex3fv(v2); - glVertex3fv(v3); - + immVertex3fv(pos, v1); + immVertex3fv(pos, v2); + immVertex3fv(pos, v3); } - glEnd(); - + immEnd(); break; + case OB_CUBE: - drawcube_size(size); + drawcube_size(size, pos); break; case OB_CIRCLE: - drawcircle_size(size); + drawcircle_size(size, pos); break; case OB_EMPTY_SPHERE: - draw_empty_sphere(size); + draw_empty_sphere(size, pos); break; case OB_EMPTY_CONE: - draw_empty_cone(size); + draw_empty_cone(size, pos); break; case OB_ARROWS: @@ -599,34 +613,34 @@ void drawaxes(const float viewmat_local[4][4], float size, char drawtype) for (axis = 0; axis < 3; axis++) { const int arrow_axis = (axis == 0) ? 1 : 0; - glBegin(GL_LINES); + immBegin(PRIM_LINES, 6); v2[axis] = size; - glVertex3fv(v1); - glVertex3fv(v2); - + immVertex3fv(pos, v1); + immVertex3fv(pos, v2); + v1[axis] = size * 0.85f; v1[arrow_axis] = -size * 0.08f; - glVertex3fv(v1); - glVertex3fv(v2); - + immVertex3fv(pos, v1); + immVertex3fv(pos, v2); + v1[arrow_axis] = size * 0.08f; - glVertex3fv(v1); - glVertex3fv(v2); + immVertex3fv(pos, v1); + immVertex3fv(pos, v2); - glEnd(); - - v2[axis] += size * 0.125f; + immEnd(); - draw_xyz_wire(viewmat_local_unit, v2, size, axis); + v2[axis] += size * 0.125f; + draw_xyz_wire(viewmat_local_unit, v2, size, axis, pos); /* reset v1 & v2 to zero */ v1[arrow_axis] = v1[axis] = v2[axis] = 0.0f; } - break; } } + + immUnbindProgram(); } @@ -634,38 +648,39 @@ void drawaxes(const float viewmat_local[4][4], float size, char drawtype) static void draw_empty_image(Object *ob, const short dflag, const unsigned char ob_wire_col[4], StereoViews sview) { Image *ima = ob->data; - ImBuf *ibuf; - ImageUser iuser = *ob->iuser; - /* Support multi-view */ - if (ima && (sview == STEREO_RIGHT_ID)) { - iuser.multiview_eye = sview; - iuser.flag |= IMA_SHOW_STEREO; - BKE_image_multiview_index(ima, &iuser); - } + const float ob_alpha = ob->col[3]; + float ima_x, ima_y; - ibuf = BKE_image_acquire_ibuf(ima, &iuser, NULL); + int bindcode = 0; - if (ibuf && (ibuf->rect == NULL) && (ibuf->rect_float != NULL)) { - IMB_rect_from_float(ibuf); - } + if (ima) { + ImageUser iuser = *ob->iuser; - int ima_x, ima_y; + /* Support multi-view */ + if (ima && (sview == STEREO_RIGHT_ID)) { + iuser.multiview_eye = sview; + iuser.flag |= IMA_SHOW_STEREO; + BKE_image_multiview_index(ima, &iuser); + } + + if (ob_alpha > 0.0f) { + bindcode = GPU_verify_image(ima, &iuser, GL_TEXTURE_2D, 0, false, false, false); + /* don't bother drawing the image if alpha = 0 */ + } - /* Get the buffer dimensions so we can fallback to fake ones */ - if (ibuf && ibuf->rect) { - ima_x = ibuf->x; - ima_y = ibuf->y; + int w, h; + BKE_image_get_size(ima, &iuser, &w, &h); + ima_x = w; + ima_y = h; } else { - ima_x = 1; - ima_y = 1; + /* if no image, make it a 1x1 empty square, honor scale & offset */ + ima_x = ima_y = 1.0f; } - float sca_x = 1.0f; - float sca_y = 1.0f; - /* Get the image aspect even if the buffer is invalid */ + float sca_x = 1.0f, sca_y = 1.0f; if (ima) { if (ima->aspx > ima->aspy) { sca_y = ima->aspy / ima->aspx; @@ -675,61 +690,98 @@ static void draw_empty_image(Object *ob, const short dflag, const unsigned char } } - /* Calculate the scale center based on object's origin */ - float ofs_x = ob->ima_ofs[0] * ima_x; - float ofs_y = ob->ima_ofs[1] * ima_y; + float scale_x; + float scale_y; + { + const float scale_x_inv = ima_x * sca_x; + const float scale_y_inv = ima_y * sca_y; + if (scale_x_inv > scale_y_inv) { + scale_x = ob->empty_drawsize; + scale_y = ob->empty_drawsize * (scale_y_inv / scale_x_inv); + } + else { + scale_x = ob->empty_drawsize * (scale_x_inv / scale_y_inv); + scale_y = ob->empty_drawsize; + } + } - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); + const float ofs_x = ob->ima_ofs[0] * scale_x; + const float ofs_y = ob->ima_ofs[1] * scale_y; - /* Calculate Image scale */ - float scale = ob->empty_drawsize / max_ff((float)ima_x * sca_x, (float)ima_y * sca_y); + const rctf rect = { + .xmin = ofs_x, + .xmax = ofs_x + scale_x, + .ymin = ofs_y, + .ymax = ofs_y + scale_y, + }; - /* Set the object scale */ - glScalef(scale * sca_x, scale * sca_y, 1.0f); + bool use_blend = false; - if (ibuf && ibuf->rect) { - const bool use_clip = (U.glalphaclip != 1.0f); - int zoomfilter = (U.gameflags & USER_DISABLE_MIPMAP) ? GL_NEAREST : GL_LINEAR; - /* Setup GL params */ - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + if (bindcode) { + use_blend = ob_alpha < 1.0f || BKE_image_has_alpha(ima); - if (use_clip) { - glEnable(GL_ALPHA_TEST); - glAlphaFunc(GL_GREATER, U.glalphaclip); + if (use_blend) { + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } - /* Use the object color and alpha */ - glColor4fv(ob->col); + VertexFormat *format = immVertexFormat(); + unsigned int pos = VertexFormat_add_attrib(format, "pos", COMP_F32, 2, KEEP_FLOAT); + unsigned int texCoord = VertexFormat_add_attrib(format, "texCoord", COMP_F32, 2, KEEP_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_IMAGE_MODULATE_ALPHA); + immUniform1f("alpha", ob_alpha); + immUniform1i("image", 0); /* default GL_TEXTURE0 unit */ - /* Draw the Image on the screen */ - glaDrawPixelsTex(ofs_x, ofs_y, ima_x, ima_y, GL_RGBA, GL_UNSIGNED_BYTE, zoomfilter, ibuf->rect); + immBegin(PRIM_TRIANGLE_FAN, 4); + immAttrib2f(texCoord, 0.0f, 0.0f); + immVertex2f(pos, rect.xmin, rect.ymin); - glDisable(GL_BLEND); + immAttrib2f(texCoord, 1.0f, 0.0f); + immVertex2f(pos, rect.xmax, rect.ymin); - if (use_clip) { - glDisable(GL_ALPHA_TEST); - glAlphaFunc(GL_ALWAYS, 0.0f); - } + immAttrib2f(texCoord, 1.0f, 1.0f); + immVertex2f(pos, rect.xmax, rect.ymax); + + immAttrib2f(texCoord, 0.0f, 1.0f); + immVertex2f(pos, rect.xmin, rect.ymax); + immEnd(); + + immUnbindProgram(); + + glBindTexture(GL_TEXTURE_2D, 0); /* necessary? */ } - if ((dflag & DRAW_CONSTCOLOR) == 0) { - glColor3ubv(ob_wire_col); + /* Draw the image outline */ + glLineWidth(1.5f); + unsigned int pos = VertexFormat_add_attrib(immVertexFormat(), "pos", COMP_F32, 2, KEEP_FLOAT); + + const bool picking = dflag & DRAW_CONSTCOLOR; + if (picking) { + /* TODO: deal with picking separately, use this function just to draw */ + immBindBuiltinProgram(GPU_SHADER_3D_DEPTH_ONLY); + if (use_blend) { + glDisable(GL_BLEND); + } + + imm_draw_line_box(pos, rect.xmin, rect.ymin, rect.xmax, rect.ymax); } + else { + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immUniformColor3ubv(ob_wire_col); + glEnable(GL_LINE_SMOOTH); - /* Calculate the outline vertex positions */ - glBegin(GL_LINE_LOOP); - glVertex2f(ofs_x, ofs_y); - glVertex2f(ofs_x + ima_x, ofs_y); - glVertex2f(ofs_x + ima_x, ofs_y + ima_y); - glVertex2f(ofs_x, ofs_y + ima_y); - glEnd(); + if (!use_blend) { + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } - /* Reset GL settings */ - glPopMatrix(); + imm_draw_line_box(pos, rect.xmin, rect.ymin, rect.xmax, rect.ymax); - BKE_image_release_ibuf(ima, ibuf, NULL); + glDisable(GL_LINE_SMOOTH); + glDisable(GL_BLEND); + } + + immUnbindProgram(); } static void circball_array_fill(float verts[CIRCLE_RESOL][3], const float cent[3], float rad, const float tmat[4][4]) @@ -747,62 +799,65 @@ static void circball_array_fill(float verts[CIRCLE_RESOL][3], const float cent[3 } } -void drawcircball(int mode, const float cent[3], float rad, const float tmat[4][4]) +void imm_drawcircball(const float cent[3], float rad, const float tmat[4][4], unsigned pos) { float verts[CIRCLE_RESOL][3]; circball_array_fill(verts, cent, rad, tmat); - glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(3, GL_FLOAT, 0, verts); - glDrawArrays(mode, 0, CIRCLE_RESOL); - glDisableClientState(GL_VERTEX_ARRAY); + immBegin(PRIM_LINE_LOOP, CIRCLE_RESOL); + for (int i = 0; i < CIRCLE_RESOL; ++i) { + immVertex3fv(pos, verts[i]); + } + immEnd(); } /* circle for object centers, special_color is for library or ob users */ -static void drawcentercircle(View3D *v3d, RegionView3D *rv3d, const float co[3], int selstate, bool special_color) +static void drawcentercircle(View3D *v3d, RegionView3D *UNUSED(rv3d), const float co[3], int selstate, bool special_color) { - const float size = ED_view3d_pixel_size(rv3d, co) * (float)U.obcenter_dia * 0.5f; - float verts[CIRCLE_RESOL][3]; + const float outlineWidth = 1.0f * U.pixelsize; + const float size = U.obcenter_dia * U.pixelsize + outlineWidth; + + if (v3d->zbuf) { + glDisable(GL_DEPTH_TEST); + /* TODO(merwin): fit things like this into plates/buffers design */ + } - /* using glDepthFunc guarantees that it does write z values, - * but not checks for it, so centers remain visible independent of draw order */ - if (v3d->zbuf) glDepthFunc(GL_ALWAYS); - /* write to near buffer always */ - glDepthRange(0.0, 0.0); glEnable(GL_BLEND); - + GPU_enable_program_point_size(); + + unsigned int pos = VertexFormat_add_attrib(immVertexFormat(), "pos", COMP_F32, 3, KEEP_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA); + immUniform1f("size", size); + if (special_color) { - if (selstate == ACTIVE || selstate == SELECT) glColor4ub(0x88, 0xFF, 0xFF, 155); - else glColor4ub(0x55, 0xCC, 0xCC, 155); + if (selstate == ACTIVE || selstate == SELECT) immUniformColor4ub(0x88, 0xFF, 0xFF, 155); + else immUniformColor4ub(0x55, 0xCC, 0xCC, 155); } else { - if (selstate == ACTIVE) UI_ThemeColorShadeAlpha(TH_ACTIVE, 0, -80); - else if (selstate == SELECT) UI_ThemeColorShadeAlpha(TH_SELECT, 0, -80); - else if (selstate == DESELECT) UI_ThemeColorShadeAlpha(TH_TRANSFORM, 0, -80); + if (selstate == ACTIVE) immUniformThemeColorShadeAlpha(TH_ACTIVE, 0, -80); + else if (selstate == SELECT) immUniformThemeColorShadeAlpha(TH_SELECT, 0, -80); + else if (selstate == DESELECT) immUniformThemeColorShadeAlpha(TH_TRANSFORM, 0, -80); } - circball_array_fill(verts, co, size, rv3d->viewinv); + /* set up outline */ + float outlineColor[4]; + UI_GetThemeColorShadeAlpha4fv(TH_WIRE, 0, -30, outlineColor); + immUniform4fv("outlineColor", outlineColor); + immUniform1f("outlineWidth", outlineWidth); - /* enable vertex array */ - glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(3, GL_FLOAT, 0, verts); + immBegin(PRIM_POINTS, 1); + immVertex3fv(pos, co); + immEnd(); - /* 1. draw filled, blended polygon */ - glDrawArrays(GL_POLYGON, 0, CIRCLE_RESOL); + immUnbindProgram(); - /* 2. draw outline */ - glLineWidth(1); - UI_ThemeColorShadeAlpha(TH_WIRE, 0, -30); - glDrawArrays(GL_LINE_LOOP, 0, CIRCLE_RESOL); - - /* finish up */ - glDisableClientState(GL_VERTEX_ARRAY); - - glDepthRange(0.0, 1.0); + GPU_disable_program_point_size(); glDisable(GL_BLEND); - if (v3d->zbuf) glDepthFunc(GL_LEQUAL); + if (v3d->zbuf) { + glEnable(GL_DEPTH_TEST); + } } /* *********** text drawing for object/particles/armature ************* */ @@ -893,36 +948,30 @@ void view3d_cached_text_draw_end(View3D *v3d, ARegion *ar, bool depth_write) if (tot) { int col_pack_prev = 0; -#if 0 - bglMats mats; /* ZBuffer depth vars */ - double ux, uy, uz; - float depth; - - if (v3d->zbuf) - bgl_get_mats(&mats); -#endif if (rv3d->rflag & RV3D_CLIPPING) { ED_view3d_clipping_disable(); } - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); + float original_proj[4][4]; + gpuGetProjectionMatrix(original_proj); wmOrtho2_region_pixelspace(ar); - glLoadIdentity(); + + gpuPushMatrix(); + gpuLoadIdentity(); if (depth_write) { if (v3d->zbuf) glDisable(GL_DEPTH_TEST); } else { - glDepthMask(0); + glDepthMask(GL_FALSE); } + const int font_id = BLF_default(); + for (vos = g_v3d_strings[g_v3d_string_level]; vos; vos = vos->next) { if (vos->sco[0] != IS_CLIPPED) { if (col_pack_prev != vos->col.pack) { - glColor3ubv(vos->col.ub); + BLF_color3ubv(font_id, vos->col.ub); col_pack_prev = vos->col.pack; } @@ -941,13 +990,11 @@ void view3d_cached_text_draw_end(View3D *v3d, ARegion *ar, bool depth_write) if (v3d->zbuf) glEnable(GL_DEPTH_TEST); } else { - glDepthMask(1); + glDepthMask(GL_TRUE); } - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - glMatrixMode(GL_MODELVIEW); - glPopMatrix(); + gpuPopMatrix(); + gpuLoadProjectionMatrix(original_proj); if (rv3d->rflag & RV3D_CLIPPING) { ED_view3d_clipping_enable(); @@ -971,9 +1018,9 @@ void view3d_cached_text_draw_end(View3D *v3d, ARegion *ar, bool depth_write) /* draws a cube given the scaling of the cube, assuming that * all required matrices have been set (used for drawing empties) */ -static void drawcube_size(float size) +static void drawcube_size(float size, unsigned pos) { - const GLfloat pos[8][3] = { + const float verts[8][3] = { {-size, -size, -size}, {-size, -size, size}, {-size, size, -size}, @@ -986,13 +1033,21 @@ static void drawcube_size(float size) const GLubyte indices[24] = {0,1,1,3,3,2,2,0,0,4,4,5,5,7,7,6,6,4,1,5,3,7,2,6}; +#if 0 glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(3, GL_FLOAT, 0, pos); + glVertexPointer(3, GL_FLOAT, 0, verts); glDrawRangeElements(GL_LINES, 0, 7, 24, GL_UNSIGNED_BYTE, indices); glDisableClientState(GL_VERTEX_ARRAY); +#else + immBegin(PRIM_LINES, 24); + for (int i = 0; i < 24; ++i) { + immVertex3fv(pos, verts[indices[i]]); + } + immEnd(); +#endif } -static void drawshadbuflimits(Lamp *la, float mat[4][4]) +static void drawshadbuflimits(const Lamp *la, const float mat[4][4], unsigned pos) { float sta[3], end[3], lavec[3]; @@ -1002,16 +1057,16 @@ static void drawshadbuflimits(Lamp *la, float mat[4][4]) madd_v3_v3v3fl(sta, mat[3], lavec, la->clipsta); madd_v3_v3v3fl(end, mat[3], lavec, la->clipend); - glBegin(GL_LINES); - glVertex3fv(sta); - glVertex3fv(end); - glEnd(); + immBegin(PRIM_LINES, 2); + immVertex3fv(pos, sta); + immVertex3fv(pos, end); + immEnd(); - glPointSize(3.0); - glBegin(GL_POINTS); - glVertex3fv(sta); - glVertex3fv(end); - glEnd(); + glPointSize(3.0f); + immBegin(PRIM_POINTS, 2); + immVertex3fv(pos, sta); + immVertex3fv(pos, end); + immEnd(); } static void spotvolume(float lvec[3], float vvec[3], const float inp) @@ -1077,62 +1132,63 @@ static void spotvolume(float lvec[3], float vvec[3], const float inp) mul_m3_v3(mat2, vvec); } -static void draw_spot_cone(Lamp *la, float x, float z) +static void draw_spot_cone(Lamp *la, float x, float z, unsigned pos) { z = fabsf(z); - glBegin(GL_TRIANGLE_FAN); - glVertex3f(0.0f, 0.0f, -x); + const bool square = (la->mode & LA_SQUARE); + + immBegin(PRIM_TRIANGLE_FAN, square ? 6 : 34); + immVertex3f(pos, 0.0f, 0.0f, -x); - if (la->mode & LA_SQUARE) { - glVertex3f(z, z, 0); - glVertex3f(-z, z, 0); - glVertex3f(-z, -z, 0); - glVertex3f(z, -z, 0); - glVertex3f(z, z, 0); + if (square) { + immVertex3f(pos, z, z, 0); + immVertex3f(pos, -z, z, 0); + immVertex3f(pos, -z, -z, 0); + immVertex3f(pos, z, -z, 0); + immVertex3f(pos, z, z, 0); } else { for (int a = 0; a < 33; a++) { float angle = a * M_PI * 2 / (33 - 1); - glVertex3f(z * cosf(angle), z * sinf(angle), 0); + immVertex3f(pos, z * cosf(angle), z * sinf(angle), 0.0f); } } - glEnd(); + immEnd(); } -static void draw_transp_spot_volume(Lamp *la, float x, float z) +static void draw_transp_spot_volume(Lamp *la, float x, float z, unsigned pos) { glEnable(GL_CULL_FACE); glEnable(GL_BLEND); - glDepthMask(0); + glDepthMask(GL_FALSE); /* draw backside darkening */ glCullFace(GL_FRONT); glBlendFunc(GL_ZERO, GL_SRC_ALPHA); - glColor4f(0.0f, 0.0f, 0.0f, 0.4f); + immUniformColor4f(0.0f, 0.0f, 0.0f, 0.4f); - draw_spot_cone(la, x, z); + draw_spot_cone(la, x, z, pos); /* draw front side lighting */ glCullFace(GL_BACK); glBlendFunc(GL_ONE, GL_ONE); - glColor4f(0.2f, 0.2f, 0.2f, 1.0f); + immUniformColor3f(0.2f, 0.2f, 0.2f); - draw_spot_cone(la, x, z); + draw_spot_cone(la, x, z, pos); /* restore state */ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glDisable(GL_BLEND); - glDepthMask(1); + glDepthMask(GL_TRUE); glDisable(GL_CULL_FACE); - glCullFace(GL_BACK); } #ifdef WITH_GAMEENGINE -static void draw_transp_sun_volume(Lamp *la) +static void draw_transp_sun_volume(Lamp *la, unsigned pos) { float box[8][3]; @@ -1145,50 +1201,46 @@ static void draw_transp_sun_volume(Lamp *la) box[1][2] = box[2][2] = box[5][2] = box[6][2] = -la->clipsta; /* draw edges */ - draw_box(box, false); + imm_draw_box(box, false, pos); /* draw faces */ glEnable(GL_CULL_FACE); glEnable(GL_BLEND); - glDepthMask(0); + glDepthMask(GL_FALSE); /* draw backside darkening */ glCullFace(GL_FRONT); glBlendFunc(GL_ZERO, GL_SRC_ALPHA); - glColor4f(0.0f, 0.0f, 0.0f, 0.4f); + immUniformColor4f(0.0f, 0.0f, 0.0f, 0.4f); - draw_box(box, true); + imm_draw_box(box, true, pos); /* draw front side lighting */ glCullFace(GL_BACK); glBlendFunc(GL_ONE, GL_ONE); - glColor4f(0.2f, 0.2f, 0.2f, 1.0f); + immUniformColor3f(0.2f, 0.2f, 0.2f); - draw_box(box, true); + imm_draw_box(box, true, pos); /* restore state */ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glDisable(GL_BLEND); - glDepthMask(1); + glDepthMask(GL_TRUE); glDisable(GL_CULL_FACE); - glCullFace(GL_BACK); } #endif -static void drawlamp(View3D *v3d, RegionView3D *rv3d, Base *base, - const char dt, const short dflag, const unsigned char ob_wire_col[4], const bool is_obact) +void drawlamp(View3D *v3d, RegionView3D *rv3d, Base *base, + const char dt, const short dflag, const unsigned char ob_wire_col[4], const bool is_obact) { Object *ob = base->object; const float pixsize = ED_view3d_pixel_size(rv3d, ob->obmat[3]); Lamp *la = ob->data; float vec[3], lvec[3], vvec[3], circrad; - float lampsize; float imat[4][4]; - unsigned char curcol[4]; - unsigned char col[4]; /* cone can't be drawn for duplicated lamps, because duplilist would be freed */ /* the moment of view3d_draw_transp() call */ const bool is_view = (rv3d->persp == RV3D_CAMOB && v3d->camera == base->object); @@ -1196,7 +1248,7 @@ static void drawlamp(View3D *v3d, RegionView3D *rv3d, Base *base, !(G.f & G_PICKSEL) && (la->type == LA_SPOT) && (la->mode & LA_SHOW_CONE) && - !(base->flag & OB_FROMDUPLI) && + !(base->flag_legacy & OB_FROMDUPLI) && !is_view); #ifdef WITH_GAMEENGINE @@ -1208,7 +1260,7 @@ static void drawlamp(View3D *v3d, RegionView3D *rv3d, Base *base, ((la->mode & LA_SHAD_BUF) || (la->mode & LA_SHAD_RAY)) && (la->mode & LA_SHOW_SHADOW_BOX) && - !(base->flag & OB_FROMDUPLI) && + !(base->flag_legacy & OB_FROMDUPLI) && !is_view); #else const bool drawshadowbox = false; @@ -1216,118 +1268,159 @@ static void drawlamp(View3D *v3d, RegionView3D *rv3d, Base *base, if ((drawcone || drawshadowbox) && !v3d->transp) { /* in this case we need to draw delayed */ - ED_view3d_after_add(v3d->xray ? &v3d->afterdraw_xraytransp : &v3d->afterdraw_transp, base, dflag); + ED_view3d_after_add(&v3d->afterdraw_transp, base, dflag); return; } - + /* we first draw only the screen aligned & fixed scale stuff */ - glPushMatrix(); - glLoadMatrixf(rv3d->viewmat); + gpuPushMatrix(); + gpuLoadMatrix(rv3d->viewmat); /* lets calculate the scale: */ - lampsize = pixsize * ((float)U.obcenter_dia * 0.5f); + const float lampsize_px = U.obcenter_dia; + const float lampsize = pixsize * lampsize_px * 0.5f; /* and view aligned matrix: */ copy_m4_m4(imat, rv3d->viewinv); normalize_v3(imat[0]); normalize_v3(imat[1]); + const unsigned int pos = VertexFormat_add_attrib(immVertexFormat(), "pos", COMP_F32, 3, KEEP_FLOAT); + /* lamp center */ copy_v3_v3(vec, ob->obmat[3]); + float curcol[4]; if ((dflag & DRAW_CONSTCOLOR) == 0) { /* for AA effects */ - curcol[0] = ob_wire_col[0]; - curcol[1] = ob_wire_col[1]; - curcol[2] = ob_wire_col[2]; - curcol[3] = 154; - glColor4ubv(curcol); + rgb_uchar_to_float(curcol, ob_wire_col); + curcol[3] = 0.6f; + /* TODO: pay attention to GL_BLEND */ } - glLineWidth(1); + glLineWidth(1.0f); + setlinestyle(3); if (lampsize > 0.0f) { + const float outlineWidth = 1.5f * U.pixelsize; + const float lampdot_size = lampsize_px * U.pixelsize + outlineWidth; + /* Inner Circle */ if ((dflag & DRAW_CONSTCOLOR) == 0) { + const float *color = curcol; if (ob->id.us > 1) { - if (is_obact || (ob->flag & SELECT)) { - glColor4ub(0x88, 0xFF, 0xFF, 155); + if (is_obact || ((base->flag & BASE_SELECTED) != 0)) { + static const float active_color[4] = {0.533f, 1.0f, 1.0f, 1.0f}; + color = active_color; } else { - glColor4ub(0x77, 0xCC, 0xCC, 155); + static const float inactive_color[4] = {0.467f, 0.8f, 0.8f, 1.0f}; + color = inactive_color; } } + + GPU_enable_program_point_size(); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + immBindBuiltinProgram(GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA); + immUniform1f("size", lampdot_size); + immUniform1f("outlineWidth", outlineWidth); + immUniformColor3fvAlpha(color, 0.3f); + immUniform4fv("outlineColor", color); + + immBegin(PRIM_POINTS, 1); + immVertex3fv(pos, vec); + immEnd(); + + immUnbindProgram(); + + glDisable(GL_BLEND); + GPU_disable_program_point_size(); } - - /* Inner Circle */ - glEnable(GL_BLEND); - drawcircball(GL_LINE_LOOP, vec, lampsize, imat); - glDisable(GL_BLEND); - drawcircball(GL_POLYGON, vec, lampsize, imat); - + else { + /* CONSTCOLOR in effect */ + /* TODO: separate picking from drawing */ + immBindBuiltinProgram(GPU_SHADER_3D_POINT_FIXED_SIZE_UNIFORM_COLOR); + /* color doesn't matter, so don't set */ + glPointSize(lampdot_size); + + immBegin(PRIM_POINTS, 1); + immVertex3fv(pos, vec); + immEnd(); + + immUnbindProgram(); + } + + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + /* TODO(merwin): short term, use DEPTH_ONLY for picking + * long term, separate picking from drawing + */ + /* restore */ if ((dflag & DRAW_CONSTCOLOR) == 0) { - if (ob->id.us > 1) - glColor4ubv(curcol); + immUniformColor4fv(curcol); } /* Outer circle */ circrad = 3.0f * lampsize; - setlinestyle(3); - drawcircball(GL_LINE_LOOP, vec, circrad, imat); + imm_drawcircball(vec, circrad, imat, pos); /* draw dashed outer circle if shadow is on. remember some lamps can't have certain shadows! */ if (la->type != LA_HEMI) { if ((la->mode & LA_SHAD_RAY) || ((la->mode & LA_SHAD_BUF) && (la->type == LA_SPOT))) { - drawcircball(GL_LINE_LOOP, vec, circrad + 3.0f * pixsize, imat); + imm_drawcircball(vec, circrad + 3.0f * pixsize, imat, pos); } } } else { - setlinestyle(3); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + if ((dflag & DRAW_CONSTCOLOR) == 0) { + immUniformColor4fv(curcol); + } circrad = 0.0f; } - + /* draw the pretty sun rays */ if (la->type == LA_SUN) { float v1[3], v2[3], mat[3][3]; short axis; - + /* setup a 45 degree rotation matrix */ axis_angle_normalized_to_mat3_ex(mat, imat[2], M_SQRT1_2, M_SQRT1_2); /* vectors */ mul_v3_v3fl(v1, imat[0], circrad * 1.2f); mul_v3_v3fl(v2, imat[0], circrad * 2.5f); - + /* center */ - glTranslate3fv(vec); - + gpuPushMatrix(); + gpuTranslate3fv(vec); + setlinestyle(3); - - glBegin(GL_LINES); + + immBegin(PRIM_LINES, 16); for (axis = 0; axis < 8; axis++) { - glVertex3fv(v1); - glVertex3fv(v2); + immVertex3fv(pos, v1); + immVertex3fv(pos, v2); mul_m3_v3(mat, v1); mul_m3_v3(mat, v2); } - glEnd(); - - glTranslatef(-vec[0], -vec[1], -vec[2]); + immEnd(); + gpuPopMatrix(); } - + if (la->type == LA_LOCAL) { if (la->mode & LA_SPHERE) { - drawcircball(GL_LINE_LOOP, vec, la->dist, imat); + imm_drawcircball(vec, la->dist, imat, pos); } } - - glPopMatrix(); /* back in object space */ + + gpuPopMatrix(); /* back in object space */ zero_v3(vec); - + if (is_view) { /* skip drawing extra info */ } @@ -1359,24 +1452,18 @@ static void drawlamp(View3D *v3d, RegionView3D *rv3d, Base *base, {z_abs, -z_abs, x}, {-z_abs, z_abs, x}, }; - const unsigned char indices[] = { - 0, 1, 3, - 0, 3, 2, - 0, 2, 4, - 0, 1, 4, - }; - - /* Draw call: - * activate and specify pointer to vertex array */ - glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(3, GL_FLOAT, 0, vertices); - /* draw the pyramid */ - glDrawElements(GL_LINE_STRIP, 12, GL_UNSIGNED_BYTE, indices); - /* deactivate vertex arrays after drawing */ - glDisableClientState(GL_VERTEX_ARRAY); + immBegin(PRIM_LINES, 16); + for (int i = 1; i <= 4; ++i) { + immVertex3fv(pos, vertices[0]); /* apex to corner */ + immVertex3fv(pos, vertices[i]); + int next_i = (i == 4) ? 1 : (i + 1); + immVertex3fv(pos, vertices[i]); /* corner to next corner */ + immVertex3fv(pos, vertices[next_i]); + } + immEnd(); - glTranslatef(0.0f, 0.0f, x); + gpuTranslate3f(0.0f, 0.0f, x); /* draw the square representing spotbl */ if (la->type == LA_SPOT) { @@ -1386,22 +1473,21 @@ static void drawlamp(View3D *v3d, RegionView3D *rv3d, Base *base, * 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 != z_abs) { - fdrawbox(blend, -blend, -blend, blend); + imm_draw_line_box_3d(pos, blend, -blend, -blend, blend); } } } else { - /* draw the angled sides of the cone */ - glBegin(GL_LINE_STRIP); - glVertex3fv(vvec); - glVertex3fv(vec); - glVertex3fv(lvec); - glEnd(); + immBegin(PRIM_LINE_STRIP, 3); + immVertex3fv(pos, vvec); + immVertex3fv(pos, vec); + immVertex3fv(pos, lvec); + immEnd(); /* draw the circle at the end of the cone */ - glTranslatef(0.0f, 0.0f, x); - circ(0.0f, 0.0f, z_abs); + gpuTranslate3f(0.0f, 0.0f, x); + imm_draw_circle_wire_3d(pos, 0.0f, 0.0f, z_abs, 32); /* draw the circle representing spotbl */ if (la->type == LA_SPOT) { @@ -1411,17 +1497,17 @@ static void drawlamp(View3D *v3d, RegionView3D *rv3d, Base *base, * 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 != z_abs) { - circ(0.0f, 0.0f, blend); + imm_draw_circle_wire_3d(pos, 0.0f, 0.0f, blend, 32); } } } if (drawcone) - draw_transp_spot_volume(la, x, z); + draw_transp_spot_volume(la, x, z, pos); /* draw clip start, useful for wide cones where its not obvious where the start is */ - glTranslatef(0.0, 0.0, -x); /* reverse translation above */ - glBegin(GL_LINES); + gpuTranslate3f(0.0f, 0.0f, -x); /* reverse translation above */ + immBegin(PRIM_LINES, 2); if (la->type == LA_SPOT && (la->mode & LA_SHAD_BUF)) { float lvec_clip[3]; float vvec_clip[3]; @@ -1430,41 +1516,40 @@ static void drawlamp(View3D *v3d, RegionView3D *rv3d, Base *base, interp_v3_v3v3(lvec_clip, vec, lvec, clipsta_fac); interp_v3_v3v3(vvec_clip, vec, vvec, clipsta_fac); - glVertex3fv(lvec_clip); - glVertex3fv(vvec_clip); + immVertex3fv(pos, lvec_clip); + immVertex3fv(pos, vvec_clip); } /* Else, draw spot direction (using distance as end limit, same as for Area lamp). */ else { - glVertex3f(0.0, 0.0, -circrad); - glVertex3f(0.0, 0.0, -la->dist); + immVertex3f(pos, 0.0f, 0.0f, -circrad); + immVertex3f(pos, 0.0f, 0.0f, -la->dist); } - glEnd(); + immEnd(); } else if (ELEM(la->type, LA_HEMI, LA_SUN)) { - /* draw the line from the circle along the dist */ - glBegin(GL_LINES); + immBegin(PRIM_LINES, 2); vec[2] = -circrad; - glVertex3fv(vec); + immVertex3fv(pos, vec); vec[2] = -la->dist; - glVertex3fv(vec); - glEnd(); - + immVertex3fv(pos, vec); + immEnd(); + if (la->type == LA_HEMI) { /* draw the hemisphere curves */ short axis, steps, dir; float outdist, zdist, mul; zero_v3(vec); - outdist = 0.14; mul = 1.4; dir = 1; - + outdist = 0.14f; mul = 1.4f; dir = 1; + setlinestyle(4); /* loop over the 4 compass points, and draw each arc as a LINE_STRIP */ for (axis = 0; axis < 4; axis++) { - float v[3] = {0.0, 0.0, 0.0}; - zdist = 0.02; - - glBegin(GL_LINE_STRIP); - + float v[3] = {0.0f, 0.0f, 0.0f}; + zdist = 0.02f; + + immBegin(PRIM_LINE_STRIP, 6); + for (steps = 0; steps < 6; steps++) { if (axis == 0 || axis == 1) { /* x axis up, x axis down */ /* make the arcs start at the edge of the energy circle */ @@ -1477,13 +1562,13 @@ static void drawlamp(View3D *v3d, RegionView3D *rv3d, Base *base, } v[2] = v[2] - steps * zdist; - - glVertex3fv(v); - + + immVertex3fv(pos, v); + zdist = zdist * mul; } - - glEnd(); + + immEnd(); /* flip the direction */ dir = -dir; } @@ -1491,96 +1576,92 @@ static void drawlamp(View3D *v3d, RegionView3D *rv3d, Base *base, #ifdef WITH_GAMEENGINE if (drawshadowbox) { - draw_transp_sun_volume(la); + draw_transp_sun_volume(la, pos); } #endif - } else if (la->type == LA_AREA) { setlinestyle(3); if (la->area_shape == LA_AREA_SQUARE) - fdrawbox(-la->area_size * 0.5f, -la->area_size * 0.5f, la->area_size * 0.5f, la->area_size * 0.5f); + imm_draw_line_box_3d(pos, -la->area_size * 0.5f, -la->area_size * 0.5f, la->area_size * 0.5f, la->area_size * 0.5f); else if (la->area_shape == LA_AREA_RECT) - fdrawbox(-la->area_size * 0.5f, -la->area_sizey * 0.5f, la->area_size * 0.5f, la->area_sizey * 0.5f); + imm_draw_line_box_3d(pos, -la->area_size * 0.5f, -la->area_sizey * 0.5f, la->area_size * 0.5f, la->area_sizey * 0.5f); - glBegin(GL_LINES); - glVertex3f(0.0, 0.0, -circrad); - glVertex3f(0.0, 0.0, -la->dist); - glEnd(); + immBegin(PRIM_LINES, 2); + immVertex3f(pos, 0.0f, 0.0f, -circrad); + immVertex3f(pos, 0.0f, 0.0f, -la->dist); + immEnd(); } - + /* and back to viewspace */ - glPushMatrix(); - glLoadMatrixf(rv3d->viewmat); + gpuPushMatrix(); + gpuLoadMatrix(rv3d->viewmat); copy_v3_v3(vec, ob->obmat[3]); setlinestyle(0); - + if ((la->type == LA_SPOT) && (la->mode & LA_SHAD_BUF) && (is_view == false)) { - drawshadbuflimits(la, ob->obmat); + drawshadbuflimits(la, ob->obmat, pos); } - + if ((dflag & DRAW_CONSTCOLOR) == 0) { - UI_GetThemeColor4ubv(TH_LAMP, col); - glColor4ubv(col); + immUniformThemeColor(TH_LAMP); } glEnable(GL_BLEND); - + if (vec[2] > 0) vec[2] -= circrad; else vec[2] += circrad; - - glBegin(GL_LINES); - glVertex3fv(vec); + + immBegin(PRIM_LINES, 2); + immVertex3fv(pos, vec); vec[2] = 0; - glVertex3fv(vec); - glEnd(); - - glPointSize(2.0); - glBegin(GL_POINTS); - glVertex3fv(vec); - glEnd(); - + immVertex3fv(pos, vec); + immEnd(); + + glPointSize(2.0f); + immBegin(PRIM_POINTS, 1); + immVertex3fv(pos, vec); + immEnd(); + glDisable(GL_BLEND); - - if ((dflag & DRAW_CONSTCOLOR) == 0) { - /* restore for drawing extra stuff */ - glColor3ubv(ob_wire_col); - } - /* and finally back to org object space! */ - glPopMatrix(); + + immUnbindProgram(); + gpuPopMatrix(); } -static void draw_limit_line(float sta, float end, const short dflag, const unsigned char col[3]) +static void draw_limit_line(float sta, float end, const short dflag, const unsigned char col[3], unsigned pos) { - glBegin(GL_LINES); - glVertex3f(0.0, 0.0, -sta); - glVertex3f(0.0, 0.0, -end); - glEnd(); + immBegin(PRIM_LINES, 2); + immVertex3f(pos, 0.0f, 0.0f, -sta); + immVertex3f(pos, 0.0f, 0.0f, -end); + immEnd(); if (!(dflag & DRAW_PICKING)) { - glPointSize(3.0); - glBegin(GL_POINTS); + glPointSize(3.0f); + /* would like smooth round points here, but that means binding another shader... + * if it's really desired, pull these points into their own function to be called after */ + immBegin(PRIM_POINTS, 2); if ((dflag & DRAW_CONSTCOLOR) == 0) { - glColor3ubv(col); + immUniformColor3ubv(col); } - glVertex3f(0.0, 0.0, -sta); - glVertex3f(0.0, 0.0, -end); - glEnd(); + immVertex3f(pos, 0.0f, 0.0f, -sta); + immVertex3f(pos, 0.0f, 0.0f, -end); + immEnd(); } } /* yafray: draw camera focus point (cross, similar to aqsis code in tuhopuu) */ /* qdn: now also enabled for Blender to set focus point for defocus composite node */ -static void draw_focus_cross(float dist, float size) +static void draw_focus_cross(float dist, float size, unsigned pos) { - glBegin(GL_LINES); - glVertex3f(-size, 0.0f, -dist); - glVertex3f(size, 0.0f, -dist); - glVertex3f(0.0f, -size, -dist); - glVertex3f(0.0f, size, -dist); - glEnd(); + immBegin(PRIM_LINES, 4); + immVertex3f(pos, -size, 0.0f, -dist); + immVertex3f(pos, size, 0.0f, -dist); + immVertex3f(pos, 0.0f, -size, -dist); + immVertex3f(pos, 0.0f, size, -dist); + immEnd(); } #ifdef VIEW3D_CAMERA_BORDER_HACK @@ -1590,28 +1671,8 @@ bool view3d_camera_border_hack_test = false; /* ****************** draw clip data *************** */ -static void draw_bundle_sphere(void) -{ - static GLuint displist = 0; - - if (displist == 0) { - GLUquadricObj *qobj; - - displist = glGenLists(1); - glNewList(displist, GL_COMPILE); - qobj = gluNewQuadric(); - gluQuadricDrawStyle(qobj, GLU_FILL); - gluSphere(qobj, 0.05, 8, 8); - gluDeleteQuadric(qobj); - - glEndList(); - } - - glCallList(displist); -} - static void draw_viewport_object_reconstruction( - Scene *scene, Base *base, const View3D *v3d, const RegionView3D *rv3d, + Scene *scene, BaseLegacy *base, const View3D *v3d, const RegionView3D *rv3d, MovieClip *clip, MovieTrackingObject *tracking_object, const short dflag, const unsigned char ob_wire_col[4], int *global_track_index, bool draw_selected) @@ -1635,7 +1696,7 @@ static void draw_viewport_object_reconstruction( if ((tracking_object->flag & TRACKING_OBJECT_CAMERA) == 0) mul_v3_fl(camera_size, tracking_object->scale); - glPushMatrix(); + gpuPushMatrix(); if (tracking_object->flag & TRACKING_OBJECT_CAMERA) { /* current ogl matrix is translated in camera space, bundles should @@ -1643,8 +1704,8 @@ static void draw_viewport_object_reconstruction( * from current ogl matrix */ invert_m4_m4(imat, base->object->obmat); - glMultMatrixf(imat); - glMultMatrixf(mat); + gpuMultMatrix(imat); + gpuMultMatrix(mat); } else { float obmat[4][4]; @@ -1653,7 +1714,7 @@ static void draw_viewport_object_reconstruction( BKE_tracking_camera_get_reconstructed_interpolate(tracking, tracking_object, framenr, obmat); invert_m4_m4(imat, obmat); - glMultMatrixf(imat); + gpuMultMatrix(imat); } for (track = tracksbase->first; track; track = track->next) { @@ -1666,66 +1727,93 @@ static void draw_viewport_object_reconstruction( continue; if (dflag & DRAW_PICKING) - GPU_select_load_id(base->selcol + (tracknr << 16)); + GPU_select_load_id(base->object->select_color + (tracknr << 16)); - glPushMatrix(); - glTranslate3fv(track->bundle_pos); - glScalef(v3d->bundle_size / 0.05f / camera_size[0], - v3d->bundle_size / 0.05f / camera_size[1], - v3d->bundle_size / 0.05f / camera_size[2]); + gpuPushMatrix(); + gpuTranslate3fv(track->bundle_pos); + gpuScale3f(v3d->bundle_size / 0.05f / camera_size[0], + v3d->bundle_size / 0.05f / camera_size[1], + v3d->bundle_size / 0.05f / camera_size[2]); const int v3d_drawtype = view3d_effective_drawtype(v3d); if (v3d_drawtype == OB_WIRE) { + unsigned char color[4]; + const unsigned char *color_ptr = NULL; if ((dflag & DRAW_CONSTCOLOR) == 0) { if (selected && (track->flag & TRACK_CUSTOMCOLOR) == 0) { - glColor3ubv(ob_wire_col); + color_ptr = ob_wire_col; } else { - glColor3fv(track->color); + rgba_float_to_uchar(color, track->color); + color_ptr = color; } } - drawaxes(rv3d->viewmatob, 0.05f, v3d->bundle_drawtype); + drawaxes(rv3d->viewmatob, 0.05f, v3d->bundle_drawtype, color_ptr); } else if (v3d_drawtype > OB_WIRE) { if (v3d->bundle_drawtype == OB_EMPTY_SPHERE) { + Batch *batch; + + gpuScaleUniform(0.05f); + /* selection outline */ if (selected) { + batch = Batch_get_sphere_wire(1); + if ((dflag & DRAW_CONSTCOLOR) == 0) { - glColor3ubv(ob_wire_col); + Batch_set_builtin_program(batch, GPU_SHADER_3D_UNIFORM_COLOR); + Batch_Uniform4f(batch, "color", + ob_wire_col[0]/255.f, + ob_wire_col[1]/255.f, + ob_wire_col[2]/255.f, 1.0f); + } + else { + Batch_set_builtin_program(batch, GPU_SHADER_3D_DEPTH_ONLY); } - glLineWidth(2.0f); - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - draw_bundle_sphere(); - - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + Batch_draw(batch); } + batch = Batch_get_sphere(0); + if ((dflag & DRAW_CONSTCOLOR) == 0) { - if (track->flag & TRACK_CUSTOMCOLOR) glColor3fv(track->color); - else UI_ThemeColor(TH_BUNDLE_SOLID); + const float light[3] = {0.0f, 0.0f, 1.0f}; + float col[3]; + Batch_set_builtin_program(batch, GPU_SHADER_SIMPLE_LIGHTING); + Batch_Uniform3fv(batch, "light", light); + + if (track->flag & TRACK_CUSTOMCOLOR) copy_v3_v3(col, track->color); + else UI_GetThemeColor3fv(TH_BUNDLE_SOLID, col); + Batch_Uniform4f(batch, "color", col[0], col[1], col[2], 1.0f); + } + else { + Batch_set_builtin_program(batch, GPU_SHADER_3D_DEPTH_ONLY); } - draw_bundle_sphere(); + Batch_draw(batch); } else { + unsigned char color[4]; + const unsigned char *color_ptr = NULL; if ((dflag & DRAW_CONSTCOLOR) == 0) { if (selected) { - glColor3ubv(ob_wire_col); + color_ptr = ob_wire_col; } else { - if (track->flag & TRACK_CUSTOMCOLOR) glColor3fv(track->color); - else UI_ThemeColor(TH_WIRE); + if (track->flag & TRACK_CUSTOMCOLOR) rgba_float_to_uchar(color, track->color); + else UI_GetThemeColor4ubv(TH_WIRE, color); + + color_ptr = color; } } - drawaxes(rv3d->viewmatob, 0.05f, v3d->bundle_drawtype); + drawaxes(rv3d->viewmatob, 0.05f, v3d->bundle_drawtype, color_ptr); } } - glPopMatrix(); + gpuPopMatrix(); if ((dflag & DRAW_PICKING) == 0 && (v3d->flag2 & V3D_SHOW_BUNDLENAME)) { float pos[3]; @@ -1745,28 +1833,33 @@ static void draw_viewport_object_reconstruction( MovieTrackingReconstruction *reconstruction; reconstruction = BKE_tracking_object_get_reconstruction(tracking, tracking_object); - if (reconstruction->camnr) { + if (reconstruction->camnr >= 2) { MovieReconstructedCamera *camera = reconstruction->cameras; + unsigned int pos = VertexFormat_add_attrib(immVertexFormat(), "pos", COMP_F32, 3, KEEP_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immUniformThemeColor(TH_CAMERA_PATH); - UI_ThemeColor(TH_CAMERA_PATH); glLineWidth(2.0f); - glBegin(GL_LINE_STRIP); + immBegin(PRIM_LINE_STRIP, reconstruction->camnr); for (int a = 0; a < reconstruction->camnr; a++, camera++) { - glVertex3fv(camera->mat[3]); + immVertex3fv(pos, camera->mat[3]); } - glEnd(); + immEnd(); + + immUnbindProgram(); } } } - glPopMatrix(); + gpuPopMatrix(); *global_track_index = tracknr; } static void draw_viewport_reconstruction( - Scene *scene, Base *base, const View3D *v3d, const RegionView3D *rv3d, MovieClip *clip, + Scene *scene, BaseLegacy *base, const View3D *v3d, const RegionView3D *rv3d, MovieClip *clip, const short dflag, const unsigned char ob_wire_col[4], const bool draw_selected) { @@ -1795,67 +1888,65 @@ static void draw_viewport_reconstruction( /* restore */ GPU_basic_shader_bind(GPU_SHADER_USE_COLOR); - if ((dflag & DRAW_CONSTCOLOR) == 0) { - glColor3ubv(ob_wire_col); - } - if (dflag & DRAW_PICKING) - GPU_select_load_id(base->selcol); + GPU_select_load_id(base->object->select_color); } -static void drawcamera_volume(float near_plane[4][3], float far_plane[4][3], const GLenum mode) +/* camera frame */ +static void drawcamera_frame(float vec[4][3], bool filled, unsigned pos) { - glBegin(mode); - glVertex3fv(near_plane[0]); - glVertex3fv(far_plane[0]); - glVertex3fv(far_plane[1]); - glVertex3fv(near_plane[1]); - glEnd(); - - glBegin(mode); - glVertex3fv(near_plane[1]); - glVertex3fv(far_plane[1]); - glVertex3fv(far_plane[2]); - glVertex3fv(near_plane[2]); - glEnd(); - - glBegin(mode); - glVertex3fv(near_plane[2]); - glVertex3fv(far_plane[2]); - glVertex3fv(far_plane[3]); - glVertex3fv(near_plane[3]); - glEnd(); - - glBegin(mode); - glVertex3fv(far_plane[3]); - glVertex3fv(near_plane[3]); - glVertex3fv(near_plane[0]); - glVertex3fv(far_plane[0]); - glEnd(); + immBegin(filled ? PRIM_TRIANGLE_FAN : PRIM_LINE_LOOP, 4); + immVertex3fv(pos, vec[0]); + immVertex3fv(pos, vec[1]); + immVertex3fv(pos, vec[2]); + immVertex3fv(pos, vec[3]); + immEnd(); } -/* camera frame */ -static void drawcamera_frame(float vec[4][3], const GLenum mode) +/* center point to camera frame */ +static void drawcamera_framelines(float vec[4][3], float origin[3], unsigned pos) { - glBegin(mode); - glVertex3fv(vec[0]); - glVertex3fv(vec[1]); - glVertex3fv(vec[2]); - glVertex3fv(vec[3]); - glEnd(); + immBegin(PRIM_LINES, 8); + immVertex3fv(pos, origin); + immVertex3fv(pos, vec[0]); + immVertex3fv(pos, origin); + immVertex3fv(pos, vec[1]); + immVertex3fv(pos, origin); + immVertex3fv(pos, vec[2]); + immVertex3fv(pos, origin); + immVertex3fv(pos, vec[3]); + immEnd(); } -/* center point to camera frame */ -static void drawcamera_framelines(float vec[4][3], float origin[3]) +static void drawcamera_volume(float near_plane[4][3], float far_plane[4][3], bool filled, unsigned pos) { - glBegin(GL_LINE_STRIP); - glVertex3fv(vec[1]); - glVertex3fv(origin); - glVertex3fv(vec[0]); - glVertex3fv(vec[3]); - glVertex3fv(origin); - glVertex3fv(vec[2]); - glEnd(); + drawcamera_frame(near_plane, filled, pos); + drawcamera_frame(far_plane, filled, pos); + + if (filled) { + immBegin(PRIM_TRIANGLE_STRIP, 10); + + immVertex3fv(pos, near_plane[0]); + immVertex3fv(pos, far_plane[0]); + immVertex3fv(pos, near_plane[1]); + immVertex3fv(pos, far_plane[1]); + immVertex3fv(pos, near_plane[2]); + immVertex3fv(pos, far_plane[2]); + immVertex3fv(pos, near_plane[3]); + immVertex3fv(pos, far_plane[3]); + immVertex3fv(pos, near_plane[0]); + immVertex3fv(pos, far_plane[0]); + + immEnd(); + } + else { + immBegin(PRIM_LINES, 8); + for (int i = 0; i < 4; ++i) { + immVertex3fv(pos, near_plane[i]); + immVertex3fv(pos, far_plane[i]); + } + immEnd(); + } } static bool drawcamera_is_stereo3d(Scene *scene, View3D *v3d, Object *ob) @@ -1867,7 +1958,7 @@ static bool drawcamera_is_stereo3d(Scene *scene, View3D *v3d, Object *ob) static void drawcamera_stereo3d( Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, const Camera *cam, - float vec[4][3], float drawsize, const float scale[3]) + float vec[4][3], float drawsize, const float scale[3], unsigned pos) { float obmat[4][4]; float vec_lr[2][4][3]; @@ -1883,15 +1974,15 @@ static void drawcamera_stereo3d( zero_v3(tvec); - glPushMatrix(); + /* caller bound GPU_SHADER_3D_UNIFORM_COLOR, passed in pos attribute ID */ for (int i = 0; i < 2; i++) { ob = BKE_camera_multiview_render(scene, ob, names[i]); cam_lr[i] = ob->data; - glLoadMatrixf(rv3d->viewmat); + gpuLoadMatrix(rv3d->viewmat); BKE_camera_multiview_model_matrix(&scene->r, ob, names[i], obmat); - glMultMatrixf(obmat); + gpuMultMatrix(obmat); copy_m3_m3(vec_lr[i], vec); copy_v3_v3(vec_lr[i][3], vec[3]); @@ -1908,10 +1999,10 @@ static void drawcamera_stereo3d( if (is_stereo3d_cameras) { /* camera frame */ - drawcamera_frame(vec_lr[i], GL_LINE_LOOP); + drawcamera_frame(vec_lr[i], false, pos); /* center point to camera frame */ - drawcamera_framelines(vec_lr[i], tvec); + drawcamera_framelines(vec_lr[i], tvec, pos); } /* connecting line */ @@ -1925,21 +2016,20 @@ static void drawcamera_stereo3d( } } - /* the remaining drawing takes place in the view space */ - glLoadMatrixf(rv3d->viewmat); + gpuLoadMatrix(rv3d->viewmat); if (is_stereo3d_cameras) { /* draw connecting lines */ - GPU_basic_shader_bind_enable(GPU_SHADER_LINE | GPU_SHADER_STIPPLE); - GPU_basic_shader_line_stipple(2, 0xAAAA); + glLineStipple(2, 0xAAAA); + glEnable(GL_LINE_STIPPLE); - glBegin(GL_LINES); - glVertex3fv(origin[0]); - glVertex3fv(origin[1]); - glEnd(); + immBegin(PRIM_LINES, 2); + immVertex3fv(pos, origin[0]); + immVertex3fv(pos, origin[1]); + immEnd(); - GPU_basic_shader_bind_disable(GPU_SHADER_LINE | GPU_SHADER_STIPPLE); + glDisable(GL_LINE_STIPPLE); } /* draw convergence plane */ @@ -1964,21 +2054,21 @@ static void drawcamera_stereo3d( add_v3_v3(local_plane[i], axis_center); } - glColor3f(0.0f, 0.0f, 0.0f); + immUniformColor3f(0.0f, 0.0f, 0.0f); /* camera frame */ - drawcamera_frame(local_plane, GL_LINE_LOOP); + drawcamera_frame(local_plane, false, pos); if (v3d->stereo3d_convergence_alpha > 0.0f) { glEnable(GL_BLEND); - glDepthMask(0); /* disable write in zbuffer, needed for nice transp */ + glDepthMask(GL_FALSE); /* disable write in zbuffer, needed for nice transp */ - glColor4f(0.0f, 0.0f, 0.0f, v3d->stereo3d_convergence_alpha); + immUniformColor4f(0.0f, 0.0f, 0.0f, v3d->stereo3d_convergence_alpha); - drawcamera_frame(local_plane, GL_QUADS); + drawcamera_frame(local_plane, true, pos); glDisable(GL_BLEND); - glDepthMask(1); /* restore write in zbuffer */ + glDepthMask(GL_TRUE); /* restore write in zbuffer */ } } @@ -2003,37 +2093,31 @@ static void drawcamera_stereo3d( } /* camera frame */ - glColor3f(0.0f, 0.0f, 0.0f); + immUniformColor3f(0.0f, 0.0f, 0.0f); - drawcamera_frame(near_plane, GL_LINE_LOOP); - drawcamera_frame(far_plane, GL_LINE_LOOP); - drawcamera_volume(near_plane, far_plane, GL_LINE_LOOP); + drawcamera_volume(near_plane, far_plane, false, pos); if (v3d->stereo3d_volume_alpha > 0.0f) { glEnable(GL_BLEND); - glDepthMask(0); /* disable write in zbuffer, needed for nice transp */ + glDepthMask(GL_FALSE); /* disable write in zbuffer, needed for nice transp */ if (i == 0) - glColor4f(0.0f, 1.0f, 1.0f, v3d->stereo3d_volume_alpha); + immUniformColor4f(0.0f, 1.0f, 1.0f, v3d->stereo3d_volume_alpha); else - glColor4f(1.0f, 0.0f, 0.0f, v3d->stereo3d_volume_alpha); + immUniformColor4f(1.0f, 0.0f, 0.0f, v3d->stereo3d_volume_alpha); - drawcamera_frame(near_plane, GL_QUADS); - drawcamera_frame(far_plane, GL_QUADS); - drawcamera_volume(near_plane, far_plane, GL_QUADS); + drawcamera_volume(near_plane, far_plane, true, pos); glDisable(GL_BLEND); - glDepthMask(1); /* restore write in zbuffer */ + glDepthMask(GL_TRUE); /* restore write in zbuffer */ } } } - - glPopMatrix(); } /* flag similar to draw_object() */ -static void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, - const short dflag, const unsigned char ob_wire_col[4]) +void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, + const short dflag, const unsigned char ob_wire_col[4]) { /* a standing up pyramid with (0,0,0) as top */ Camera *cam; @@ -2096,8 +2180,12 @@ static void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base BKE_camera_view_frame_ex(scene, cam, cam->drawsize, is_view, scale, asp, shift, &drawsize, vec); - glDisable(GL_CULL_FACE); - glLineWidth(1); + unsigned int pos = VertexFormat_add_attrib(immVertexFormat(), "pos", COMP_F32, 3, KEEP_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + if (ob_wire_col) { + immUniformColor3ubv(ob_wire_col); + } + glLineWidth(1.0f); /* camera frame */ if (!is_stereo3d_cameras) { @@ -2106,27 +2194,29 @@ static void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base float obmat[4][4]; bool is_left = v3d->multiview_eye == STEREO_LEFT_ID; - glPushMatrix(); - glLoadMatrixf(rv3d->viewmat); + gpuPushMatrix(); + gpuLoadMatrix(rv3d->viewmat); BKE_camera_multiview_model_matrix(&scene->r, ob, is_left ? STEREO_LEFT_NAME : STEREO_RIGHT_NAME, obmat); - glMultMatrixf(obmat); + gpuMultMatrix(obmat); - drawcamera_frame(vec, GL_LINE_LOOP); - glPopMatrix(); + drawcamera_frame(vec, false, pos); + gpuPopMatrix(); } else { - drawcamera_frame(vec, GL_LINE_LOOP); + drawcamera_frame(vec, false, pos); } } - if (is_view) + if (is_view) { + immUnbindProgram(); return; + } zero_v3(tvec); /* center point to camera frame */ if (!is_stereo3d_cameras) - drawcamera_framelines(vec, tvec); + drawcamera_framelines(vec, tvec, pos); /* arrow on top */ tvec[2] = vec[1][2]; /* copy the depth */ @@ -2135,22 +2225,25 @@ static void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base * for active cameras. We actually draw both outline+filled * for active cameras so the wire can be seen side-on */ for (int i = 0; i < 2; i++) { - if (i == 0) glBegin(GL_LINE_LOOP); - else if (i == 1 && is_active) glBegin(GL_TRIANGLES); + if (i == 0) immBegin(PRIM_LINE_LOOP, 3); + else if (i == 1 && is_active) { + glDisable(GL_CULL_FACE); /* TODO: declarative state tracking */ + immBegin(PRIM_TRIANGLES, 3); + } else break; tvec[0] = shift[0] + ((-0.7f * drawsize) * scale[0]); tvec[1] = shift[1] + ((drawsize * (asp[1] + 0.1f)) * scale[1]); - glVertex3fv(tvec); /* left */ + immVertex3fv(pos, tvec); /* left */ tvec[0] = shift[0] + ((0.7f * drawsize) * scale[0]); - glVertex3fv(tvec); /* right */ + immVertex3fv(pos, tvec); /* right */ tvec[0] = shift[0]; tvec[1] = shift[1] + ((1.1f * drawsize * (asp[1] + 0.7f)) * scale[1]); - glVertex3fv(tvec); /* top */ + immVertex3fv(pos, tvec); /* top */ - glEnd(); + immEnd(); } if ((dflag & DRAW_SCENESET) == 0) { @@ -2161,16 +2254,15 @@ static void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base copy_m4_m4(nobmat, ob->obmat); normalize_m4(nobmat); - glPushMatrix(); - glLoadMatrixf(rv3d->viewmat); - glMultMatrixf(nobmat); + gpuLoadMatrix(rv3d->viewmat); + gpuMultMatrix(nobmat); if (cam->flag & CAM_SHOWLIMITS) { const unsigned char col[3] = {128, 128, 60}, col_hi[3] = {255, 255, 120}; - draw_limit_line(cam->clipsta, cam->clipend, dflag, (is_active ? col_hi : col)); + draw_limit_line(cam->clipsta, cam->clipend, dflag, (is_active ? col_hi : col), pos); /* qdn: was yafray only, now also enabled for Blender to be used with defocus composite node */ - draw_focus_cross(BKE_camera_object_dof_distance(ob), cam->drawsize); + draw_focus_cross(BKE_camera_object_dof_distance(ob), cam->drawsize, pos); } if (cam->flag & CAM_SHOWMIST) { @@ -2179,69 +2271,79 @@ static void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base if (world) { draw_limit_line(world->miststa, world->miststa + world->mistdist, - dflag, (is_active ? col_hi : col)); + dflag, (is_active ? col_hi : col), pos); } } - glPopMatrix(); } } /* stereo cameras drawing */ if (is_stereo3d) { - drawcamera_stereo3d(scene, v3d, rv3d, ob, cam, vec, drawsize, scale); + drawcamera_stereo3d(scene, v3d, rv3d, ob, cam, vec, drawsize, scale, pos); } + + immUnbindProgram(); } /* flag similar to draw_object() */ -static void drawspeaker(Scene *UNUSED(scene), View3D *UNUSED(v3d), RegionView3D *UNUSED(rv3d), - Object *UNUSED(ob), int UNUSED(flag)) +void drawspeaker(const unsigned char ob_wire_col[3]) { - float vec[3]; + VertexFormat *format = immVertexFormat(); + unsigned int pos = VertexFormat_add_attrib(format, "pos", COMP_F32, 3, KEEP_FLOAT); - glEnable(GL_BLEND); - glLineWidth(1); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + + if (ob_wire_col) { + immUniformColor3ubv(ob_wire_col); + } + + glLineWidth(1.0f); + + const int segments = 16; for (int j = 0; j < 3; j++) { - vec[2] = 0.25f * j - 0.125f; + float z = 0.25f * j - 0.125f; - glBegin(GL_LINE_LOOP); - for (int i = 0; i < 16; i++) { - vec[0] = cosf((float)M_PI * i / 8.0f) * (j == 0 ? 0.5f : 0.25f); - vec[1] = sinf((float)M_PI * i / 8.0f) * (j == 0 ? 0.5f : 0.25f); - glVertex3fv(vec); + immBegin(PRIM_LINE_LOOP, segments); + for (int i = 0; i < segments; i++) { + float x = cosf((float)M_PI * i / 8.0f) * (j == 0 ? 0.5f : 0.25f); + float y = sinf((float)M_PI * i / 8.0f) * (j == 0 ? 0.5f : 0.25f); + immVertex3f(pos, x, y, z); } - glEnd(); + immEnd(); } for (int j = 0; j < 4; j++) { - vec[0] = (((j + 1) % 2) * (j - 1)) * 0.5f; - vec[1] = ((j % 2) * (j - 2)) * 0.5f; - glBegin(GL_LINE_STRIP); + float x = (((j + 1) % 2) * (j - 1)) * 0.5f; + float y = ((j % 2) * (j - 2)) * 0.5f; + immBegin(PRIM_LINE_STRIP, 3); for (int i = 0; i < 3; i++) { if (i == 1) { - vec[0] *= 0.5f; - vec[1] *= 0.5f; + x *= 0.5f; + y *= 0.5f; } - vec[2] = 0.25f * i - 0.125f; - glVertex3fv(vec); + float z = 0.25f * i - 0.125f; + immVertex3f(pos, x, y, z); } - glEnd(); + immEnd(); } - glDisable(GL_BLEND); + immUnbindProgram(); } -static void lattice_draw_verts(Lattice *lt, DispList *dl, BPoint *actbp, short sel) +static void lattice_draw_verts(Lattice *lt, DispList *dl, BPoint *actbp, short sel, + unsigned int pos, unsigned int color) { BPoint *bp = lt->def; const float *co = dl ? dl->verts : NULL; + float active_color[4], draw_color[4]; - const int color = sel ? TH_VERTEX_SELECT : TH_VERTEX; - UI_ThemeColor(color); + UI_GetThemeColor4fv(sel ? TH_VERTEX_SELECT : TH_VERTEX, draw_color); + UI_GetThemeColor4fv(TH_ACTIVE_VERT, active_color); glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE)); - glBegin(GL_POINTS); + immBeginAtMost(PRIM_POINTS, lt->pntsw * lt->pntsv * lt->pntsu); for (int w = 0; w < lt->pntsw; w++) { int wxt = (w == 0 || w == lt->pntsw - 1); @@ -2253,12 +2355,12 @@ static void lattice_draw_verts(Lattice *lt, DispList *dl, BPoint *actbp, short s if (bp->hide == 0) { /* check for active BPoint and ensure selected */ if ((bp == actbp) && (bp->f1 & SELECT)) { - UI_ThemeColor(TH_ACTIVE_VERT); - glVertex3fv(dl ? co : bp->vec); - UI_ThemeColor(color); + immAttrib4fv(color, active_color); + immVertex3fv(pos, dl ? co : bp->vec); } else if ((bp->f1 & SELECT) == sel) { - glVertex3fv(dl ? co : bp->vec); + immAttrib4fv(color, draw_color); + immVertex3fv(pos, dl ? co : bp->vec); } } } @@ -2266,27 +2368,26 @@ static void lattice_draw_verts(Lattice *lt, DispList *dl, BPoint *actbp, short s } } - glEnd(); + immEnd(); } -static void drawlattice__point(Lattice *lt, DispList *dl, int u, int v, int w, int actdef_wcol) +static void drawlattice__point(Lattice *lt, DispList *dl, int u, int v, int w, int actdef_wcol, + unsigned int pos, unsigned int color) { int index = ((w * lt->pntsv + v) * lt->pntsu) + u; if (actdef_wcol) { float col[3]; MDeformWeight *mdw = defvert_find_index(lt->dvert + index, actdef_wcol - 1); - weight_to_rgb(col, mdw ? mdw->weight : 0.0f); - glColor3fv(col); - + immAttrib3fv(color, col); } if (dl) { - glVertex3fv(&dl->verts[index * 3]); + immVertex3fv(pos, &dl->verts[index * 3]); } else { - glVertex3fv(lt->def[index].vec); + immVertex3fv(pos, lt->def[index].vec); } } @@ -2334,7 +2435,7 @@ static void ensure_curve_cache(Scene *scene, Object *object) #endif /* lattice color is hardcoded, now also shows weightgroup values in edit mode */ -static void drawlattice(View3D *v3d, Object *ob) +static void drawlattice(View3D *v3d, Object *ob, const short dflag, const unsigned char ob_wire_col[4]) { Lattice *lt = ob->data; DispList *dl; @@ -2347,15 +2448,37 @@ static void drawlattice(View3D *v3d, Object *ob) if (is_edit) { lt = lt->editlatt->latt; - UI_ThemeColor(TH_WIRE_EDIT); - if (ob->defbase.first && lt->dvert) { actdef_wcol = ob->actdef; } } - glLineWidth(1); - glBegin(GL_LINES); + VertexFormat *format = immVertexFormat(); + unsigned int color, pos = VertexFormat_add_attrib(format, "pos", COMP_F32, 3, KEEP_FLOAT); + + if (actdef_wcol) { + color = VertexFormat_add_attrib(format, "color", COMP_F32, 3, KEEP_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_SMOOTH_COLOR); + } + else { + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + + if (is_edit) { + immUniformThemeColor(TH_WIRE_EDIT); + } + else { + if ((dflag & DRAW_CONSTCOLOR) == 0) { + immUniformColor3ubv(ob_wire_col); + } + else { + immUniformColor3f(0.0f, 0.0f, 0.0f); + } + } + } + + glLineWidth(1.0f); + immBeginAtMost(PRIM_LINES, lt->pntsw * lt->pntsv * lt->pntsu * 6); + for (w = 0; w < lt->pntsw; w++) { int wxt = (w == 0 || w == lt->pntsw - 1); for (v = 0; v < lt->pntsv; v++) { @@ -2364,30 +2487,40 @@ static void drawlattice(View3D *v3d, Object *ob) int uxt = (u == 0 || u == lt->pntsu - 1); if (w && ((uxt || vxt) || !(lt->flag & LT_OUTSIDE))) { - drawlattice__point(lt, dl, u, v, w - 1, actdef_wcol); - drawlattice__point(lt, dl, u, v, w, actdef_wcol); + drawlattice__point(lt, dl, u, v, w - 1, actdef_wcol, pos, color); + drawlattice__point(lt, dl, u, v, w, actdef_wcol, pos, color); } if (v && ((uxt || wxt) || !(lt->flag & LT_OUTSIDE))) { - drawlattice__point(lt, dl, u, v - 1, w, actdef_wcol); - drawlattice__point(lt, dl, u, v, w, actdef_wcol); + drawlattice__point(lt, dl, u, v - 1, w, actdef_wcol, pos, color); + drawlattice__point(lt, dl, u, v, w, actdef_wcol, pos, color); } if (u && ((vxt || wxt) || !(lt->flag & LT_OUTSIDE))) { - drawlattice__point(lt, dl, u - 1, v, w, actdef_wcol); - drawlattice__point(lt, dl, u, v, w, actdef_wcol); + drawlattice__point(lt, dl, u - 1, v, w, actdef_wcol, pos, color); + drawlattice__point(lt, dl, u, v, w, actdef_wcol, pos, color); } } } } - glEnd(); + + immEnd(); + immUnbindProgram(); if (is_edit) { BPoint *actbp = BKE_lattice_active_point_get(lt); if (v3d->zbuf) glDisable(GL_DEPTH_TEST); - - lattice_draw_verts(lt, dl, actbp, 0); - lattice_draw_verts(lt, dl, actbp, 1); - + + VertexFormat *v_format = immVertexFormat(); + unsigned int v_pos = VertexFormat_add_attrib(v_format, "pos", COMP_F32, 3, KEEP_FLOAT); + unsigned int v_color = VertexFormat_add_attrib(v_format, "color", COMP_F32, 4, KEEP_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_3D_POINT_FIXED_SIZE_VARYING_COLOR); + + lattice_draw_verts(lt, dl, actbp, 0, v_pos, v_color); + lattice_draw_verts(lt, dl, actbp, 1, v_pos, v_color); + + immUnbindProgram(); + if (v3d->zbuf) glEnable(GL_DEPTH_TEST); } } @@ -2401,6 +2534,7 @@ typedef struct drawDMVertSel_userData { int active; unsigned char *col[3]; /* (base, sel, act) */ char sel_prev; + unsigned int pos, color; } drawDMVertSel_userData; static void drawSelectedVertices__mapFunc(void *userData, int index, const float co[3], @@ -2412,17 +2546,18 @@ static void drawSelectedVertices__mapFunc(void *userData, int index, const float if (!(mv->flag & ME_HIDE)) { const char sel = (index == data->active) ? 2 : (mv->flag & SELECT); if (sel != data->sel_prev) { - glColor3ubv(data->col[sel]); + immAttrib3ubv(data->color, data->col[sel]); data->sel_prev = sel; } - glVertex3fv(co); + immVertex3fv(data->pos, co); } } static void drawSelectedVertices(DerivedMesh *dm, Mesh *me) { drawDMVertSel_userData data; + VertexFormat *format = immVertexFormat(); /* TODO define selected color */ unsigned char base_col[3] = {0x0, 0x0, 0x0}; @@ -2437,9 +2572,18 @@ static void drawSelectedVertices(DerivedMesh *dm, Mesh *me) data.col[1] = sel_col; data.col[2] = act_col; - glBegin(GL_POINTS); + data.color = VertexFormat_add_attrib(format, "color", COMP_U8, 3, NORMALIZE_INT_TO_FLOAT); + data.pos = VertexFormat_add_attrib(format, "pos", COMP_F32, 3, KEEP_FLOAT); + + if (dm->getNumVerts(dm) == 0) return; + + immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR); + + immBeginAtMost(PRIM_POINTS, dm->getNumVerts(dm)); dm->foreachMappedVert(dm, drawSelectedVertices__mapFunc, &data, DM_FOREACH_NOP); - glEnd(); + immEnd(); + + immUnbindProgram(); } /* ************** DRAW MESH ****************** */ @@ -2486,25 +2630,34 @@ static void draw_dm_face_normals__mapFunc(void *userData, int index, const float copy_v3_v3(n, no); } - glVertex3fv(cent); - glVertex3f(cent[0] + n[0] * data->normalsize, - cent[1] + n[1] * data->normalsize, - cent[2] + n[2] * data->normalsize); + immVertex3fv(data->pos, cent); + immVertex3f(data->pos, cent[0] + n[0] * data->normalsize, + cent[1] + n[1] * data->normalsize, + cent[2] + n[2] * data->normalsize); } } -static void draw_dm_face_normals(BMEditMesh *em, Scene *scene, Object *ob, DerivedMesh *dm) +static void draw_dm_face_normals(BMEditMesh *em, Scene *scene, Object *ob, DerivedMesh *dm, int theme_id) { + VertexFormat *format = immVertexFormat(); drawDMNormal_userData data; data.bm = em->bm; data.normalsize = scene->toolsettings->normalsize; + data.pos = VertexFormat_add_attrib(format, "pos", COMP_F32, 3, KEEP_FLOAT); calcDrawDMNormalScale(ob, &data); - glBegin(GL_LINES); + if (dm->getNumPolys(dm) == 0) return; + + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immUniformThemeColor(theme_id); + + immBeginAtMost(PRIM_LINES, dm->getNumPolys(dm) * 2); dm->foreachMappedFaceCenter(dm, draw_dm_face_normals__mapFunc, &data, DM_FOREACH_USE_NORMAL); - glEnd(); + immEnd(); + + immUnbindProgram(); } static void draw_dm_face_centers__mapFunc(void *userData, int index, const float cent[3], const float UNUSED(no[3])) @@ -2515,16 +2668,28 @@ static void draw_dm_face_centers__mapFunc(void *userData, int index, const float if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN) && (BM_elem_flag_test(efa, BM_ELEM_SELECT) == data->select)) { - glVertex3fv(cent); + immVertex3fv(data->pos, cent); } } -static void draw_dm_face_centers(BMEditMesh *em, DerivedMesh *dm, bool select) +static void draw_dm_face_centers(BMEditMesh *em, DerivedMesh *dm, bool select, const unsigned char fcol[3]) { - drawBMSelect_userData data = {em->bm, select}; + VertexFormat *format = immVertexFormat(); + + drawBMSelect_userData data; + data.bm = em->bm; + data.select = select; + data.pos = VertexFormat_add_attrib(format, "pos", COMP_F32, 3, KEEP_FLOAT); - glBegin(GL_POINTS); + if (dm->getNumPolys(dm) == 0) return; + + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immUniformColor3ubv(fcol); + + immBeginAtMost(PRIM_POINTS, dm->getNumPolys(dm)); dm->foreachMappedFaceCenter(dm, draw_dm_face_centers__mapFunc, &data, DM_FOREACH_NOP); - glEnd(); + immEnd(); + + immUnbindProgram(); } static void draw_dm_vert_normals__mapFunc(void *userData, int index, const float co[3], const float no_f[3], const short no_s[3]) @@ -2551,71 +2716,83 @@ static void draw_dm_vert_normals__mapFunc(void *userData, int index, const float copy_v3_v3(n, no); } - glVertex3fv(co); - glVertex3f(co[0] + n[0] * data->normalsize, - co[1] + n[1] * data->normalsize, - co[2] + n[2] * data->normalsize); + immVertex3fv(data->pos, co); + immVertex3f(data->pos, co[0] + n[0] * data->normalsize, + co[1] + n[1] * data->normalsize, + co[2] + n[2] * data->normalsize); } } -static void draw_dm_vert_normals(BMEditMesh *em, Scene *scene, Object *ob, DerivedMesh *dm) +static void draw_dm_vert_normals(BMEditMesh *em, Scene *scene, Object *ob, DerivedMesh *dm, int theme_id) { drawDMNormal_userData data; + VertexFormat *format = immVertexFormat(); data.bm = em->bm; data.normalsize = scene->toolsettings->normalsize; + data.pos = VertexFormat_add_attrib(format, "pos", COMP_F32, 3, KEEP_FLOAT); calcDrawDMNormalScale(ob, &data); - glBegin(GL_LINES); + if (dm->getNumVerts(dm) == 0) return; + + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immUniformThemeColor(theme_id); + + immBeginAtMost(PRIM_LINES, dm->getNumVerts(dm) * 2); dm->foreachMappedVert(dm, draw_dm_vert_normals__mapFunc, &data, DM_FOREACH_USE_NORMAL); - glEnd(); + immEnd(); + + immUnbindProgram(); } -/* Draw verts with color set based on selection */ -static void draw_dm_verts__mapFunc(void *userData, int index, const float co[3], - const float UNUSED(no_f[3]), const short UNUSED(no_s[3])) +static void draw_dm_verts_skin_root__mapFunc(void *userData, int index, const float co[3], + const float UNUSED(no_f[3]), const short UNUSED(no_s[3])) { drawDMVerts_userData *data = userData; BMVert *eve = BM_vert_at_index(data->bm, index); if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN) && BM_elem_flag_test(eve, BM_ELEM_SELECT) == data->sel) { /* skin nodes: draw a red circle around the root node(s) */ - if (data->cd_vskin_offset != -1) { - const MVertSkin *vs = BM_ELEM_CD_GET_VOID_P(eve, data->cd_vskin_offset); - if (vs->flag & MVERT_SKIN_ROOT) { - float radius = (vs->radius[0] + vs->radius[1]) * 0.5f; - glEnd(); - - glColor4ubv(data->th_skin_root); - drawcircball(GL_LINES, co, radius, data->imat); - - glColor4ubv(data->sel ? data->th_vertex_select : data->th_vertex); - glBegin(GL_POINTS); - } + const MVertSkin *vs = BM_ELEM_CD_GET_VOID_P(eve, data->cd_vskin_offset); + if (vs->flag & MVERT_SKIN_ROOT) { + float radius = (vs->radius[0] + vs->radius[1]) * 0.5f; + imm_drawcircball(co, radius, data->imat, data->pos); } + } +} +/* Draw verts with color set based on selection */ +static void draw_dm_verts__mapFunc(void *userData, int index, const float co[3], + const float UNUSED(no_f[3]), const short UNUSED(no_s[3])) +{ + drawDMVerts_userData *data = userData; + BMVert *eve = BM_vert_at_index(data->bm, index); + + if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN) && BM_elem_flag_test(eve, BM_ELEM_SELECT) == data->sel) { /* draw active in a different color - no need to stop/start point drawing for this :D */ if (eve == data->eve_act) { - glColor4ubv(data->th_editmesh_active); - glVertex3fv(co); - - /* back to regular vertex color */ - glColor4ubv(data->sel ? data->th_vertex_select : data->th_vertex); + immAttrib4ubv(data->color, data->th_editmesh_active); + immVertex3fv(data->pos, co); } else { - glVertex3fv(co); + immAttrib4ubv(data->color, data->sel ? data->th_vertex_select : data->th_vertex); + immVertex3fv(data->pos, co); } } } static void draw_dm_verts(BMEditMesh *em, DerivedMesh *dm, const char sel, BMVert *eve_act, - RegionView3D *rv3d) + RegionView3D *rv3d, const unsigned char col[4]) { + VertexFormat *format = immVertexFormat(); + drawDMVerts_userData data; data.sel = sel; data.eve_act = eve_act; data.bm = em->bm; + data.pos = VertexFormat_add_attrib(format, "pos", COMP_F32, 3, KEEP_FLOAT); + data.color = VertexFormat_add_attrib(format, "color", COMP_U8, 4, NORMALIZE_INT_TO_FLOAT); /* Cache theme values */ UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, data.th_editmesh_active); @@ -2623,16 +2800,37 @@ static void draw_dm_verts(BMEditMesh *em, DerivedMesh *dm, const char sel, BMVer UI_GetThemeColor4ubv(TH_VERTEX, data.th_vertex); UI_GetThemeColor4ubv(TH_SKIN_ROOT, data.th_skin_root); - /* For skin root drawing */ - data.cd_vskin_offset = CustomData_get_offset(&em->bm->vdata, CD_MVERT_SKIN); + /* Set correct alpha */ + data.th_editmesh_active[3] = data.th_vertex_select[3] = data.th_vertex[3] = data.th_skin_root[3] = col[3]; + /* view-aligned matrix */ mul_m4_m4m4(data.imat, rv3d->viewmat, em->ob->obmat); invert_m4(data.imat); + if (dm->getNumVerts(dm) == 0) return; + + immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR); + glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE)); - glBegin(GL_POINTS); + + immBeginAtMost(PRIM_POINTS, dm->getNumVerts(dm)); dm->foreachMappedVert(dm, draw_dm_verts__mapFunc, &data, DM_FOREACH_NOP); - glEnd(); + immEnd(); + + immUnbindProgram(); + + /* For skin root drawing */ + data.cd_vskin_offset = CustomData_get_offset(&em->bm->vdata, CD_MVERT_SKIN); + + if (data.cd_vskin_offset != -1) { + data.pos = VertexFormat_add_attrib(immVertexFormat(), "pos", COMP_F32, 3, KEEP_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immUniformColor4ubv(data.th_skin_root); + + dm->foreachMappedVert(dm, draw_dm_verts_skin_root__mapFunc, &data, DM_FOREACH_NOP); + + immUnbindProgram(); + } } /* Draw edges with color set based on selection */ @@ -2938,24 +3136,32 @@ static void draw_dm_loop_normals__mapFunc(void *userData, int vertex_index, int } mul_v3_fl(vec, data->normalsize); add_v3_v3(vec, co); - glVertex3fv(co); - glVertex3fv(vec); + immVertex3fv(data->pos, co); + immVertex3fv(data->pos, vec); } } } -static void draw_dm_loop_normals(BMEditMesh *em, Scene *scene, Object *ob, DerivedMesh *dm) +static void draw_dm_loop_normals(BMEditMesh *em, Scene *scene, Object *ob, DerivedMesh *dm, int theme_id) { drawDMNormal_userData data; data.bm = em->bm; data.normalsize = scene->toolsettings->normalsize; + data.pos = VertexFormat_add_attrib(immVertexFormat(), "pos", COMP_F32, 3, KEEP_FLOAT); + + if (dm->getNumLoops(dm) == 0) return; + + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immUniformThemeColor(theme_id); calcDrawDMNormalScale(ob, &data); - glBegin(GL_LINES); + immBeginAtMost(PRIM_LINES, dm->getNumLoops(dm) * 2); dm->foreachMappedLoop(dm, draw_dm_loop_normals__mapFunc, &data, DM_FOREACH_USE_NORMAL); - glEnd(); + immEnd(); + + immUnbindProgram(); } /* Draw faces with color set based on selection @@ -3072,7 +3278,7 @@ static void draw_dm_creases(BMEditMesh *em, DerivedMesh *dm) data.cd_layer_offset = CustomData_get_offset(&em->bm->edata, CD_CREASE); if (data.cd_layer_offset != -1) { - glLineWidth(3.0); + glLineWidth(3.0f); dm->drawMappedEdges(dm, draw_dm_creases__setDrawOptions, &data); } } @@ -3102,8 +3308,10 @@ static void draw_dm_bweights__mapFunc(void *userData, int index, const float co[ if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) { const float bweight = BM_ELEM_CD_GET_FLOAT(eve, data->cd_layer_offset); if (bweight != 0.0f) { - UI_ThemeColorBlend(TH_VERTEX, TH_VERTEX_BEVEL, bweight); - glVertex3fv(co); + unsigned char col[3]; + UI_GetThemeColorBlend3ubv(TH_VERTEX, TH_VERTEX_BEVEL, bweight, col); + immAttrib3ubv(data->col, col); + immVertex3fv(data->pos, co); } } } @@ -3117,11 +3325,21 @@ static void draw_dm_bweights(BMEditMesh *em, Scene *scene, DerivedMesh *dm) data.bm = em->bm; data.cd_layer_offset = CustomData_get_offset(&em->bm->vdata, CD_BWEIGHT); + /* is that ever true? */ if (data.cd_layer_offset != -1) { - glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE) + 2); - glBegin(GL_POINTS); + VertexFormat *format = immVertexFormat(); + data.pos = VertexFormat_add_attrib(format, "pos", COMP_F32, 3, KEEP_FLOAT); + data.col = VertexFormat_add_attrib(format, "color", COMP_U8, 4, NORMALIZE_INT_TO_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR); + + glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE) + 2.0f); + + immBeginAtMost(PRIM_POINTS, dm->getNumVerts(dm)); dm->foreachMappedVert(dm, draw_dm_bweights__mapFunc, &data, DM_FOREACH_NOP); - glEnd(); + immEnd(); + + immUnbindProgram(); } } else { @@ -3131,7 +3349,7 @@ static void draw_dm_bweights(BMEditMesh *em, Scene *scene, DerivedMesh *dm) data.cd_layer_offset = CustomData_get_offset(&em->bm->edata, CD_BWEIGHT); if (data.cd_layer_offset != -1) { - glLineWidth(3.0); + glLineWidth(3.0f); dm->drawMappedEdges(dm, draw_dm_bweights__setDrawOptions, &data); } } @@ -3152,7 +3370,7 @@ static void draw_em_fancy_verts(Scene *scene, View3D *v3d, Object *obedit, { ToolSettings *ts = scene->toolsettings; - if (v3d->zbuf) glDepthMask(0); /* disable write in zbuffer, zbuf select */ + if (v3d->zbuf) glDepthMask(GL_FALSE); /* disable write in zbuffer, zbuf select */ for (int sel = 0; sel < 2; sel++) { unsigned char col[4], fcol[4]; @@ -3182,15 +3400,12 @@ static void draw_em_fancy_verts(Scene *scene, View3D *v3d, Object *obedit, } if (ts->selectmode & SCE_SELECT_VERTEX) { - glPointSize(size); - glColor4ubv(col); - draw_dm_verts(em, cageDM, sel, eve_act, rv3d); + draw_dm_verts(em, cageDM, sel, eve_act, rv3d, col); } if (check_ob_drawface_dot(scene, v3d, obedit->dt)) { glPointSize(fsize); - glColor4ubv(fcol); - draw_dm_face_centers(em, cageDM, sel); + draw_dm_face_centers(em, cageDM, sel, fcol); } if (pass == 0) { @@ -3200,7 +3415,7 @@ static void draw_em_fancy_verts(Scene *scene, View3D *v3d, Object *obedit, } } - if (v3d->zbuf) glDepthMask(1); + if (v3d->zbuf) glDepthMask(GL_TRUE); } static void draw_em_fancy_edges(BMEditMesh *em, Scene *scene, View3D *v3d, @@ -3307,11 +3522,9 @@ static void draw_em_measure_stats(ARegion *ar, View3D *v3d, Object *ob, BMEditMe if (me->drawflag & (ME_DRAWEXTRA_EDGELEN | ME_DRAWEXTRA_EDGEANG)) { BoundBox bb; - bglMats mats = {{0}}; const rcti rect = {0, ar->winx, 0, ar->winy}; - view3d_get_transformation(ar, ar->regiondata, em->ob, &mats); - ED_view3d_clipping_calc(&bb, clip_planes, &mats, &rect); + ED_view3d_clipping_calc(&bb, clip_planes, ar, em->ob, &rect); } if (me->drawflag & ME_DRAWEXTRA_EDGELEN) { @@ -3675,7 +3888,7 @@ static DMDrawOption draw_em_fancy__setGLSLFaceOpts(void *userData, int index) } } -static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d, +static void draw_em_fancy(Scene *scene, SceneLayer *sl, ARegion *ar, View3D *v3d, Object *ob, BMEditMesh *em, DerivedMesh *cageDM, DerivedMesh *finalDM, const char dt) { @@ -3684,7 +3897,7 @@ static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d, const bool use_occlude_wire = (dt > OB_WIRE) && (v3d->flag2 & V3D_OCCLUDE_WIRE); bool use_depth_offset = false; - glLineWidth(1); + glLineWidth(1.0f); BM_mesh_elem_table_ensure(em->bm, BM_VERT | BM_EDGE | BM_FACE); @@ -3693,7 +3906,7 @@ static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d, draw_mesh_paint_weight_faces(finalDM, true, draw_em_fancy__setFaceOpts, me->edit_btmesh); ED_view3d_polygon_offset(rv3d, 1.0); - glDepthMask(0); + glDepthMask(GL_FALSE); use_depth_offset = true; } else { @@ -3713,7 +3926,7 @@ static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d, glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); } else if (check_object_draw_texture(scene, v3d, dt)) { - if (draw_glsl_material(scene, ob, v3d, dt)) { + if (draw_glsl_material(scene, sl, ob, v3d, dt)) { glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW); finalDM->drawMappedFacesGLSL(finalDM, GPU_object_material_bind, @@ -3723,7 +3936,7 @@ static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d, glFrontFace(GL_CCW); } else { - draw_mesh_textured(scene, v3d, rv3d, ob, finalDM, 0); + draw_mesh_textured(scene, sl, v3d, rv3d, ob, finalDM, 0); } } else { @@ -3740,7 +3953,7 @@ static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d, UI_ThemeColor(TH_WIRE_EDIT); ED_view3d_polygon_offset(rv3d, 1.0); - glDepthMask(0); + glDepthMask(GL_FALSE); use_depth_offset = true; } else { @@ -3790,7 +4003,7 @@ static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d, #endif glEnable(GL_BLEND); - glDepthMask(0); /* disable write in zbuffer, needed for nice transp */ + glDepthMask(GL_FALSE); /* disable write in zbuffer, needed for nice transp */ /* don't draw unselected faces, only selected, this is MUCH nicer when texturing */ if (check_object_draw_texture(scene, v3d, dt)) @@ -3806,7 +4019,7 @@ static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d, #endif glDisable(GL_BLEND); - glDepthMask(1); /* restore write in zbuffer */ + glDepthMask(GL_TRUE); /* restore write in zbuffer */ } else if (efa_act) { /* even if draw faces is off it would be nice to draw the stipple face @@ -3821,7 +4034,7 @@ static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d, UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, col3); glEnable(GL_BLEND); - glDepthMask(0); /* disable write in zbuffer, needed for nice transp */ + glDepthMask(GL_FALSE); /* disable write in zbuffer, needed for nice transp */ #ifdef WITH_FREESTYLE draw_dm_faces_sel(em, cageDM, col1, col2, col3, col4, efa_act); @@ -3830,7 +4043,7 @@ static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d, #endif glDisable(GL_BLEND); - glDepthMask(1); /* restore write in zbuffer */ + glDepthMask(GL_TRUE); /* restore write in zbuffer */ } /* here starts all fancy draw-extra over */ @@ -3844,7 +4057,7 @@ static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d, else { if (me->drawflag & ME_DRAWSEAMS) { UI_ThemeColor(TH_EDGE_SEAM); - glLineWidth(2); + glLineWidth(2.0f); draw_dm_edges_seams(em, cageDM); @@ -3853,7 +4066,7 @@ static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d, if (me->drawflag & ME_DRAWSHARP) { UI_ThemeColor(TH_EDGE_SHARP); - glLineWidth(2); + glLineWidth(2.0f); draw_dm_edges_sharp(em, cageDM); @@ -3863,7 +4076,7 @@ static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d, #ifdef WITH_FREESTYLE if (me->drawflag & ME_DRAW_FREESTYLE_EDGE && CustomData_has_layer(&em->bm->edata, CD_FREESTYLE_EDGE)) { UI_ThemeColor(TH_FREESTYLE_EDGE_MARK); - glLineWidth(2); + glLineWidth(2.0f); draw_dm_edges_freestyle(em, cageDM); @@ -3878,7 +4091,7 @@ static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d, draw_dm_bweights(em, scene, cageDM); } - glLineWidth(1); + glLineWidth(1.0f); draw_em_fancy_edges(em, scene, v3d, me, cageDM, 0, eed_act); } @@ -3886,16 +4099,13 @@ static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d, draw_em_fancy_verts(scene, v3d, ob, em, cageDM, eve_act, rv3d); if (me->drawflag & ME_DRAWNORMALS) { - UI_ThemeColor(TH_NORMAL); - draw_dm_face_normals(em, scene, ob, cageDM); + draw_dm_face_normals(em, scene, ob, cageDM, TH_NORMAL); } if (me->drawflag & ME_DRAW_VNORMALS) { - UI_ThemeColor(TH_VNORMAL); - draw_dm_vert_normals(em, scene, ob, cageDM); + draw_dm_vert_normals(em, scene, ob, cageDM, TH_VNORMAL); } if (me->drawflag & ME_DRAW_LNORMALS) { - UI_ThemeColor(TH_LNORMAL); - draw_dm_loop_normals(em, scene, ob, cageDM); + draw_dm_loop_normals(em, scene, ob, cageDM, TH_LNORMAL); } if ((me->drawflag & (ME_DRAWEXTRA_EDGELEN | @@ -3916,7 +4126,7 @@ static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d, } if (use_depth_offset) { - glDepthMask(1); + glDepthMask(GL_TRUE); ED_view3d_polygon_offset(rv3d, 0.0); GPU_object_material_unbind(); } @@ -3927,15 +4137,97 @@ static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d, #endif } +static void draw_em_fancy_new(Scene *UNUSED(scene), ARegion *UNUSED(ar), View3D *UNUSED(v3d), + Object *UNUSED(ob), Mesh *me, BMEditMesh *UNUSED(em), DerivedMesh *UNUSED(cageDM), DerivedMesh *UNUSED(finalDM), const char UNUSED(dt)) +{ + /* for now... something simple! */ + Batch *surface = DRW_mesh_batch_cache_get_all_triangles(me); + + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_LEQUAL); + + glEnable(GL_BLEND); + + /* disable depth writes for transparent surface, so it doesn't interfere with itself */ + glDepthMask(GL_FALSE); + + Batch_set_builtin_program(surface, GPU_SHADER_3D_UNIFORM_COLOR); + Batch_Uniform4f(surface, "color", 1.0f, 0.5f, 0.0f, 0.5f); + Batch_draw(surface); + +#if 0 /* until I understand finalDM better */ + if (finalDM != cageDM) { + puts("finalDM != cageDM"); + Batch *finalSurface = MBC_get_all_triangles(finalDM); + Batch_set_builtin_program(finalSurface, GPU_SHADER_3D_UNIFORM_COLOR); + Batch_Uniform4f(finalSurface, "color", 0.0f, 0.0f, 0.0f, 0.05f); + Batch_draw(finalSurface); + } +#endif + + glDepthMask(GL_TRUE); + + /* now write surface depth so other objects won't poke through + * NOTE: does not help as much as desired + * TODO: draw edit object last to avoid this mess + */ + Batch_set_builtin_program(surface, GPU_SHADER_3D_DEPTH_ONLY); + Batch_draw(surface); + + if (GLEW_VERSION_3_2) { +#if 0 + Batch *overlay = DRW_mesh_batch_cache_get_overlay_edges(me); + Batch_set_builtin_program(overlay, GPU_SHADER_EDGES_OVERLAY); + Batch_Uniform2f(overlay, "viewportSize", ar->winx, ar->winy); + Batch_draw(overlay); +#endif + +#if 0 /* TODO: use this SIMPLE variant for pure triangle meshes */ + Batch_set_builtin_program(surface, GPU_SHADER_EDGES_OVERLAY_SIMPLE); + /* use these defaults: + * const float edgeColor[4] = { 0.0f, 0.0f, 0.0f, 1.0f }; + * Batch_Uniform4f(surface, "fillColor", edgeColor[0], edgeColor[1], edgeColor[2], 0.0f); + * Batch_Uniform4fv(surface, "outlineColor", edgeColor); + * Batch_Uniform1f(surface, "outlineWidth", 1.0f); + */ + Batch_Uniform2f(surface, "viewportSize", ar->winx, ar->winy); + Batch_draw(surface); +#endif + } + else { + Batch *edges = DRW_mesh_batch_cache_get_all_edges(me); + Batch_set_builtin_program(edges, GPU_SHADER_3D_UNIFORM_COLOR); + Batch_Uniform4f(edges, "color", 0.0f, 0.0f, 0.0f, 1.0f); + glEnable(GL_LINE_SMOOTH); + glLineWidth(1.5f); + Batch_draw(edges); + glDisable(GL_LINE_SMOOTH); + } + +#if 0 /* looks good even without points */ + Batch *verts = MBC_get_all_verts(me); + glEnable(GL_BLEND); + + Batch_set_builtin_program(verts, GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA); + Batch_Uniform4f(verts, "color", 0.0f, 0.0f, 0.0f, 1.0f); + Batch_Uniform1f(verts, "size", UI_GetThemeValuef(TH_VERTEX_SIZE) * 1.5f); + Batch_draw(verts); + + glDisable(GL_BLEND); +#endif +} + /* Mesh drawing routines */ -static void draw_mesh_object_outline(View3D *v3d, Object *ob, DerivedMesh *dm) +void draw_mesh_object_outline(View3D *v3d, Object *ob, DerivedMesh *dm, const unsigned char ob_wire_col[4]) /* LEGACY */ { if ((v3d->transp == false) && /* not when we draw the transparent pass */ (ob->mode & OB_MODE_ALL_PAINT) == false) /* not when painting (its distracting) - campbell */ { glLineWidth(UI_GetThemeValuef(TH_OUTLINE_WIDTH) * 2.0f); - glDepthMask(0); + glDepthMask(GL_FALSE); + + if (ob_wire_col) glColor4ubv(ob_wire_col); /* if transparent, we cannot draw the edges for solid select... edges * have no material info. GPU_object_material_visible will skip the @@ -3949,7 +4241,49 @@ static void draw_mesh_object_outline(View3D *v3d, Object *ob, DerivedMesh *dm) dm->drawEdges(dm, 0, 1); } - glDepthMask(1); + glDepthMask(GL_TRUE); + } +} + +static void draw_mesh_object_outline_new(View3D *v3d, RegionView3D *rv3d, Object *ob, Mesh *me, const bool is_active) +{ + if ((v3d->transp == false) && /* not when we draw the transparent pass */ + (ob->mode & OB_MODE_ALL_PAINT) == false) /* not when painting (its distracting) - campbell */ + { + glLineWidth(UI_GetThemeValuef(TH_OUTLINE_WIDTH) * 2.0f); + glDepthMask(GL_FALSE); + + float outline_color[4]; + UI_GetThemeColor4fv((is_active ? TH_ACTIVE : TH_SELECT), outline_color); + +#if 1 /* new version that draws only silhouette edges */ + Batch *fancy_edges = DRW_mesh_batch_cache_get_fancy_edges(me); + + if (rv3d->persp == RV3D_ORTHO) { + Batch_set_builtin_program(fancy_edges, GPU_SHADER_EDGES_FRONT_BACK_ORTHO); + /* set eye vector, transformed to object coords */ + float eye[3] = { 0.0f, 0.0f, 1.0f }; /* looking into the screen */ + mul_m3_v3(gpuGetNormalMatrixInverse(NULL), eye); + Batch_Uniform3fv(fancy_edges, "eye", eye); + } + else { + Batch_set_builtin_program(fancy_edges, GPU_SHADER_EDGES_FRONT_BACK_PERSP); + } + + Batch_Uniform1b(fancy_edges, "drawFront", false); + Batch_Uniform1b(fancy_edges, "drawBack", false); + Batch_Uniform1b(fancy_edges, "drawSilhouette", true); + Batch_Uniform4fv(fancy_edges, "silhouetteColor", outline_color); + + Batch_draw(fancy_edges); +#else /* alternate version that matches look of old viewport (but more efficient) */ + Batch *batch = MBC_get_all_edges(dm); + Batch_set_builtin_program(batch, GPU_SHADER_3D_UNIFORM_COLOR); + Batch_Uniform4fv(batch, "color", outline_color); + Batch_draw(batch); +#endif + + glDepthMask(GL_TRUE); } } @@ -3959,11 +4293,11 @@ static bool object_is_halo(Scene *scene, Object *ob) return (ma && (ma->material_type == MA_TYPE_HALO) && !BKE_scene_use_new_shading_nodes(scene)); } -static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, Base *base, +static void draw_mesh_fancy(Scene *scene, SceneLayer *sl, ARegion *ar, View3D *v3d, RegionView3D *rv3d, Base *base, const char dt, const unsigned char ob_wire_col[4], const short dflag) { #ifdef WITH_GAMEENGINE - Object *ob = (rv3d->rflag & RV3D_IS_GAME_ENGINE) ? BKE_object_lod_meshob_get(base->object, scene) : base->object; + Object *ob = (rv3d->rflag & RV3D_IS_GAME_ENGINE) ? BKE_object_lod_meshob_get(base->object, sl) : base->object; #else Object *ob = base->object; #endif @@ -3971,7 +4305,7 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D eWireDrawMode draw_wire = OBDRAW_WIRE_OFF; bool /* no_verts,*/ no_edges, no_faces; DerivedMesh *dm = mesh_get_derived_final(scene, ob, scene->customdata_mask); - const bool is_obact = (ob == OBACT); + const bool is_obact = (ob == OBACT_NEW); int draw_flags = (is_obact && BKE_paint_select_face_test(ob)) ? DRAW_FACE_SELECT : 0; if (!dm) @@ -4007,12 +4341,12 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D if (dt == OB_BOUNDBOX) { if (((v3d->flag2 & V3D_RENDER_OVERRIDE) && v3d->drawtype >= OB_WIRE) == 0) - draw_bounding_volume(ob, ob->boundtype); + draw_bounding_volume(ob, ob->boundtype, ob_wire_col); } else if ((no_faces && no_edges) || ((!is_obact || (ob->mode == OB_MODE_OBJECT)) && object_is_halo(scene, ob))) { - glPointSize(1.5); + glPointSize(1.5f); dm->drawVerts(dm); } else if ((dt == OB_WIRE) || no_faces) { @@ -4025,19 +4359,19 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D if ((v3d->flag & V3D_SELECT_OUTLINE) && ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) && - (base->flag & SELECT) && + (base->flag & BASE_SELECTED) && !(G.f & G_PICKSEL || (draw_flags & DRAW_FACE_SELECT)) && (draw_wire == OBDRAW_WIRE_OFF)) { - draw_mesh_object_outline(v3d, ob, dm); + draw_mesh_object_outline(v3d, ob, dm, ob_wire_col); } - if (draw_glsl_material(scene, ob, v3d, dt) && !(draw_flags & DRAW_MODIFIERS_PREVIEW)) { + if (draw_glsl_material(scene, sl, ob, v3d, dt) && !(draw_flags & DRAW_MODIFIERS_PREVIEW)) { Paint *p; glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW); - if ((v3d->flag2 & V3D_SHOW_SOLID_MATCAP) && ob->sculpt && (p = BKE_paint_get_active(scene))) { + if ((v3d->flag2 & V3D_SHOW_SOLID_MATCAP) && ob->sculpt && (p = BKE_paint_get_active(scene, sl))) { GPUVertexAttribs gattribs; float planes[4][4]; float (*fpl)[4] = NULL; @@ -4045,7 +4379,7 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D if (ob->sculpt->partial_redraw) { if (ar->do_draw & RGN_DRAW_PARTIAL) { - ED_sculpt_redraw_planes_get(planes, ar, rv3d, ob); + ED_sculpt_redraw_planes_get(planes, ar, ob); fpl = planes; ob->sculpt->partial_redraw = 0; } @@ -4070,7 +4404,7 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D draw_mesh_face_select(rv3d, me, dm, false); } else { - draw_mesh_textured(scene, v3d, rv3d, ob, dm, draw_flags); + draw_mesh_textured(scene, sl, v3d, rv3d, ob, dm, draw_flags); } if (draw_loose && !(draw_flags & DRAW_FACE_SELECT)) { @@ -4096,11 +4430,11 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D /* draw outline */ if ((v3d->flag & V3D_SELECT_OUTLINE) && ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) && - (base->flag & SELECT) && + (base->flag & BASE_SELECTED) && (draw_wire == OBDRAW_WIRE_OFF) && (ob->sculpt == NULL)) { - draw_mesh_object_outline(v3d, ob, dm); + draw_mesh_object_outline(v3d, ob, dm, ob_wire_col); } /* materials arent compatible with vertex colors */ @@ -4120,23 +4454,23 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D if ((v3d->flag & V3D_SELECT_OUTLINE) && ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) && - (base->flag & SELECT) && + (base->flag & BASE_SELECTED) && (draw_wire == OBDRAW_WIRE_OFF) && (ob->sculpt == NULL)) { - draw_mesh_object_outline(v3d, ob, dm); + draw_mesh_object_outline(v3d, ob, dm, ob_wire_col); } glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW); - if (ob->sculpt && (p = BKE_paint_get_active(scene))) { + if (ob->sculpt && (p = BKE_paint_get_active(scene, sl))) { float planes[4][4]; float (*fpl)[4] = NULL; const bool fast = (p->flags & PAINT_FAST_NAVIGATE) && (rv3d->rflag & RV3D_NAVIGATING); if (ob->sculpt->partial_redraw) { if (ar->do_draw & RGN_DRAW_PARTIAL) { - ED_sculpt_redraw_planes_get(planes, ar, rv3d, ob); + ED_sculpt_redraw_planes_get(planes, ar, ob); fpl = planes; ob->sculpt->partial_redraw = 0; } @@ -4177,7 +4511,9 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D if ((dflag & DRAW_CONSTCOLOR) == 0) { if (is_obact && (ob->mode & OB_MODE_PARTICLE_EDIT)) { - ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.15f); + float color[3]; + ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.15f, color); + glColor3fv(color); } else { glColor3ubv(ob_wire_col); @@ -4195,14 +4531,14 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D */ if (dt != OB_WIRE && (draw_wire == OBDRAW_WIRE_ON_DEPTH)) { ED_view3d_polygon_offset(rv3d, 1.0); - glDepthMask(0); /* disable write in zbuffer, selected edge wires show better */ + glDepthMask(GL_FALSE); /* disable write in zbuffer, selected edge wires show better */ } glLineWidth(1.0f); dm->drawEdges(dm, ((dt == OB_WIRE) || no_faces), (ob->dtx & OB_DRAW_ALL_EDGES) != 0); if (dt != OB_WIRE && (draw_wire == OBDRAW_WIRE_ON_DEPTH)) { - glDepthMask(1); + glDepthMask(GL_TRUE); ED_view3d_polygon_offset(rv3d, 0.0); } } @@ -4221,7 +4557,7 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D } /* returns true if nothing was drawn, for detecting to draw an object center */ -static bool draw_mesh_object(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, Base *base, +static bool draw_mesh_object(Scene *scene, SceneLayer *sl, ARegion *ar, View3D *v3d, RegionView3D *rv3d, BaseLegacy *base, const char dt, const unsigned char ob_wire_col[4], const short dflag) { Object *ob = base->object; @@ -4233,7 +4569,7 @@ static bool draw_mesh_object(Scene *scene, ARegion *ar, View3D *v3d, RegionView3 /* If we are drawing shadows and any of the materials don't cast a shadow, * then don't draw the object */ if (v3d->flag2 & V3D_RENDER_SHADOW) { - for (int i = 1; i <= ob->totcol; ++i) { + for (int i = 0; i < ob->totcol; ++i) { Material *ma = give_current_material(ob, i); if (ma && !(ma->mode2 & MA_CASTSHADOW)) { return true; @@ -4275,13 +4611,13 @@ static bool draw_mesh_object(Scene *scene, ARegion *ar, View3D *v3d, RegionView3 if (use_material) { if (dt > OB_WIRE) { - const bool glsl = draw_glsl_material(scene, ob, v3d, dt); + const bool glsl = draw_glsl_material(scene, sl, ob, v3d, dt); - GPU_begin_object_materials(v3d, rv3d, scene, ob, glsl, NULL); + GPU_begin_object_materials(v3d, rv3d, scene, sl, ob, glsl, NULL); } } - draw_em_fancy(scene, ar, v3d, ob, em, cageDM, finalDM, dt); + draw_em_fancy(scene, sl, ar, v3d, ob, em, cageDM, finalDM, dt); if (use_material) { GPU_end_object_materials(); @@ -4294,16 +4630,16 @@ static bool draw_mesh_object(Scene *scene, ARegion *ar, View3D *v3d, RegionView3 /* ob->bb was set by derived mesh system, do NULL check just to be sure */ if (me->totpoly <= 4 || (!ob->bb || ED_view3d_boundbox_clip(rv3d, ob->bb))) { if (dt > OB_WIRE) { - const bool glsl = draw_glsl_material(scene, ob, v3d, dt); + const bool glsl = draw_glsl_material(scene, sl, ob, v3d, dt); if (dt == OB_SOLID || glsl) { const bool check_alpha = check_alpha_pass(base); - GPU_begin_object_materials(v3d, rv3d, scene, ob, glsl, + GPU_begin_object_materials(v3d, rv3d, scene, sl, ob, glsl, (check_alpha) ? &do_alpha_after : NULL); } } - draw_mesh_fancy(scene, ar, v3d, rv3d, base, dt, ob_wire_col, dflag); + draw_mesh_fancy(scene, sl, ar, v3d, rv3d, base, dt, ob_wire_col, dflag); GPU_end_object_materials(); @@ -4311,7 +4647,7 @@ static bool draw_mesh_object(Scene *scene, ARegion *ar, View3D *v3d, RegionView3 } } - if ((dflag & DRAW_PICKING) == 0 && (base->flag & OB_FROMDUPLI) == 0 && (v3d->flag2 & V3D_RENDER_SHADOW) == 0) { + if ((dflag & DRAW_PICKING) == 0 && (base->flag_legacy & OB_FROMDUPLI) == 0 && (v3d->flag2 & V3D_RENDER_SHADOW) == 0) { /* GPU_begin_object_materials checked if this is needed */ if (do_alpha_after) { if (ob->dtx & OB_DRAWXRAY) { @@ -4335,18 +4671,547 @@ static bool draw_mesh_object(Scene *scene, ARegion *ar, View3D *v3d, RegionView3 return retval; } +static void make_color_variations(const unsigned char base_ubyte[4], float low[4], float med[4], float high[4], const bool other_obedit) +{ + /* original idea: nice variations (lighter & darker shades) of base color + * current implementation uses input color as high; med & low get closer to background color + */ + + float bg[3]; + UI_GetThemeColor3fv(TH_BACK, bg); + + float base[4]; + rgba_uchar_to_float(base, base_ubyte); + + if (other_obedit) { + /* this object should fade away so user can focus on the object being edited */ + interp_v3_v3v3(low, bg, base, 0.1f); + interp_v3_v3v3(med, bg, base, 0.2f); + interp_v3_v3v3(high, bg, base, 0.25f); + } + else { + interp_v3_v3v3(low, bg, base, 0.333f); + interp_v3_v3v3(med, bg, base, 0.667f); + copy_v3_v3(high, base); + } + + /* use original alpha */ + low[3] = base[3]; + med[3] = base[3]; + high[3] = base[3]; +} + +static void draw_mesh_fancy_new(Scene *scene, SceneLayer *sl, ARegion *ar, View3D *v3d, RegionView3D *rv3d, Base *base, + const char dt, const unsigned char ob_wire_col[4], const short dflag, const bool other_obedit) +{ + if (dflag & (DRAW_PICKING | DRAW_CONSTCOLOR)) { + /* too complicated! use existing methods */ + /* TODO: move this into a separate depth pre-pass */ + draw_mesh_fancy(scene, sl, ar, v3d, rv3d, base, dt, ob_wire_col, dflag); + return; + } + +#ifdef WITH_GAMEENGINE + Object *ob = (rv3d->rflag & RV3D_IS_GAME_ENGINE) ? BKE_object_lod_meshob_get(base->object, sl) : base->object; +#else + Object *ob = base->object; +#endif + Mesh *me = ob->data; + eWireDrawMode draw_wire = OBDRAW_WIRE_OFF; /* could be bool draw_wire_overlay */ + bool no_edges, no_faces; + DerivedMesh *dm = mesh_get_derived_final(scene, ob, scene->customdata_mask); + const bool is_obact = (ob == OBACT_NEW); + int draw_flags = (is_obact && BKE_paint_select_face_test(ob)) ? DRAW_FACE_SELECT : 0; + + if (!dm) + return; + + const bool solid = dt >= OB_SOLID; + if (solid) { + DM_update_materials(dm, ob); + } + + /* Check to draw dynamic paint colors (or weights from WeightVG modifiers). + * Note: Last "preview-active" modifier in stack will win! */ + if (DM_get_loop_data_layer(dm, CD_PREVIEW_MLOOPCOL) && modifiers_isPreview(ob)) + draw_flags |= DRAW_MODIFIERS_PREVIEW; + + /* Unwanted combination */ + if (draw_flags & DRAW_FACE_SELECT) { + draw_wire = OBDRAW_WIRE_OFF; + } + else if (ob->dtx & OB_DRAWWIRE) { + draw_wire = OBDRAW_WIRE_ON; + } + + /* check polys instead of tessfaces because of dyntopo where tessfaces don't exist */ + if (dm->type == DM_TYPE_CCGDM) { + no_edges = !subsurf_has_edges(dm); + no_faces = !subsurf_has_faces(dm); + } + else { + no_edges = (dm->getNumEdges(dm) == 0); + no_faces = (dm->getNumPolys(dm) == 0); + } + + if (solid) { + /* vertexpaint, faceselect wants this, but it doesnt work for shaded? */ + glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW); + } + + if (dt == OB_BOUNDBOX) { + if (((v3d->flag2 & V3D_RENDER_OVERRIDE) && v3d->drawtype >= OB_WIRE) == 0) + draw_bounding_volume(ob, ob->boundtype, ob_wire_col); + } + else if ((no_faces && no_edges) || + ((!is_obact || (ob->mode == OB_MODE_OBJECT)) && object_is_halo(scene, ob))) + { + glPointSize(1.5f); + // dm->drawVerts(dm); + // TODO: draw smooth round points as a batch + } + else if ((dt == OB_WIRE) || no_faces) { + draw_wire = OBDRAW_WIRE_ON; + + /* enable depth for wireframes */ + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_LESS); + + glLineWidth(1.0f); + +#if 1 /* fancy wireframes */ + + Batch *fancy_edges = DRW_mesh_batch_cache_get_fancy_edges(me); + + if (rv3d->persp == RV3D_ORTHO) { + Batch_set_builtin_program(fancy_edges, GPU_SHADER_EDGES_FRONT_BACK_ORTHO); + /* set eye vector, transformed to object coords */ + float eye[3] = { 0.0f, 0.0f, 1.0f }; /* looking into the screen */ + mul_m3_v3(gpuGetNormalMatrixInverse(NULL), eye); + Batch_Uniform3fv(fancy_edges, "eye", eye); + } + else { + Batch_set_builtin_program(fancy_edges, GPU_SHADER_EDGES_FRONT_BACK_PERSP); + } + + float frontColor[4]; + float backColor[4]; + float outlineColor[4]; + make_color_variations(ob_wire_col, backColor, frontColor, outlineColor, other_obedit); + + Batch_Uniform4fv(fancy_edges, "frontColor", frontColor); + Batch_Uniform4fv(fancy_edges, "backColor", backColor); + Batch_Uniform1b(fancy_edges, "drawFront", true); + Batch_Uniform1b(fancy_edges, "drawBack", true); /* false here = backface cull */ + Batch_Uniform1b(fancy_edges, "drawSilhouette", false); + + Batch_draw(fancy_edges); + + /* extra oomph for the silhouette contours */ + glLineWidth(2.0f); + Batch_use_program(fancy_edges); /* hack to make the following uniforms stick */ + Batch_Uniform1b(fancy_edges, "drawFront", false); + Batch_Uniform1b(fancy_edges, "drawBack", false); + Batch_Uniform1b(fancy_edges, "drawSilhouette", true); + Batch_Uniform4fv(fancy_edges, "silhouetteColor", outlineColor); + + Batch_draw(fancy_edges); + +#else /* simple wireframes */ + + Batch *batch = MBC_get_all_edges(dm); + Batch_set_builtin_program(batch, GPU_SHADER_3D_UNIFORM_COLOR); + + float color[4]; + rgba_uchar_to_float(color, ob_wire_col); + + Batch_Uniform4fv(batch, "color", color); + + Batch_draw(batch); +#endif + } + else if (((is_obact && ob->mode & OB_MODE_TEXTURE_PAINT)) || + check_object_draw_texture(scene, v3d, dt)) + { + bool draw_loose = true; + + if ((v3d->flag & V3D_SELECT_OUTLINE) && + ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) && + (base->flag & BASE_SELECTED) && + !(G.f & G_PICKSEL || (draw_flags & DRAW_FACE_SELECT)) && + (draw_wire == OBDRAW_WIRE_OFF)) + { + draw_mesh_object_outline_new(v3d, rv3d, ob, me, (ob == OBACT_NEW)); + } + + if (draw_glsl_material(scene, sl, ob, v3d, dt) && !(draw_flags & DRAW_MODIFIERS_PREVIEW)) { + Paint *p; + + glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW); + + if ((v3d->flag2 & V3D_SHOW_SOLID_MATCAP) && ob->sculpt && (p = BKE_paint_get_active(scene, sl))) { + GPUVertexAttribs gattribs; + float planes[4][4]; + float (*fpl)[4] = NULL; + const bool fast = (p->flags & PAINT_FAST_NAVIGATE) && (rv3d->rflag & RV3D_NAVIGATING); + + if (ob->sculpt->partial_redraw) { + if (ar->do_draw & RGN_DRAW_PARTIAL) { + ED_sculpt_redraw_planes_get(planes, ar, ob); + fpl = planes; + ob->sculpt->partial_redraw = 0; + } + } + + GPU_object_material_bind(1, &gattribs); + dm->drawFacesSolid(dm, fpl, fast, NULL); + draw_loose = false; + } + else + dm->drawFacesGLSL(dm, GPU_object_material_bind); + + GPU_object_material_unbind(); + + glFrontFace(GL_CCW); + + if (draw_flags & DRAW_FACE_SELECT) + draw_mesh_face_select(rv3d, me, dm, false); + } + else { + draw_mesh_textured(scene, sl, v3d, rv3d, ob, dm, draw_flags); + } + + if (draw_loose && !(draw_flags & DRAW_FACE_SELECT)) { + if ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) { + if ((dflag & DRAW_CONSTCOLOR) == 0) { + glColor3ubv(ob_wire_col); + } + glLineWidth(1.0f); + dm->drawLooseEdges(dm); + } + } + } + else if (dt == OB_SOLID) { + if (draw_flags & DRAW_MODIFIERS_PREVIEW) { + /* for object selection draws no shade */ + if (dflag & (DRAW_PICKING | DRAW_CONSTCOLOR)) { + /* TODO: draw basic faces with GPU_SHADER_3D_DEPTH_ONLY */ + } + else { + const float specular[3] = {0.47f, 0.47f, 0.47f}; + + /* draw outline */ + /* TODO: move this into a separate pass */ + if ((v3d->flag & V3D_SELECT_OUTLINE) && + ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) && + (base->flag & BASE_SELECTED) && + (draw_wire == OBDRAW_WIRE_OFF) && + (ob->sculpt == NULL)) + { + draw_mesh_object_outline_new(v3d, rv3d, ob, me, (ob == OBACT_NEW)); + } + + /* materials arent compatible with vertex colors */ + GPU_end_object_materials(); + + /* set default specular */ + GPU_basic_shader_colors(NULL, specular, 35, 1.0f); + GPU_basic_shader_bind(GPU_SHADER_LIGHTING | GPU_SHADER_USE_COLOR); + + dm->drawMappedFaces(dm, NULL, NULL, NULL, NULL, DM_DRAW_USE_COLORS | DM_DRAW_NEED_NORMALS); + + GPU_basic_shader_bind(GPU_SHADER_USE_COLOR); + } + } + else { + Paint *p; + + if ((v3d->flag & V3D_SELECT_OUTLINE) && + ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) && + (base->flag & BASE_SELECTED) && + (draw_wire == OBDRAW_WIRE_OFF) && + (ob->sculpt == NULL)) + { + /* TODO: move this into a separate pass */ + draw_mesh_object_outline_new(v3d, rv3d, ob, me, (ob == OBACT_NEW)); + } + + glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW); + + if (ob->sculpt && (p = BKE_paint_get_active(scene, sl))) { + float planes[4][4]; + float (*fpl)[4] = NULL; + const bool fast = (p->flags & PAINT_FAST_NAVIGATE) && (rv3d->rflag & RV3D_NAVIGATING); + + if (ob->sculpt->partial_redraw) { + if (ar->do_draw & RGN_DRAW_PARTIAL) { + ED_sculpt_redraw_planes_get(planes, ar, ob); + fpl = planes; + ob->sculpt->partial_redraw = 0; + } + } + + dm->drawFacesSolid(dm, fpl, fast, GPU_object_material_bind); + } + else + dm->drawFacesSolid(dm, NULL, 0, GPU_object_material_bind); + + glFrontFace(GL_CCW); + + GPU_object_material_unbind(); + + if (!ob->sculpt && (v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) { + if ((dflag & DRAW_CONSTCOLOR) == 0) { + glColor3ubv(ob_wire_col); + } + glLineWidth(1.0f); + dm->drawLooseEdges(dm); + } + } + } + else if (dt == OB_PAINT) { + draw_mesh_paint(v3d, rv3d, ob, dm, draw_flags); + + /* since we already draw wire as wp guide, don't draw over the top */ + draw_wire = OBDRAW_WIRE_OFF; + } + + if ((draw_wire != OBDRAW_WIRE_OFF) && /* draw extra wire */ + /* when overriding with render only, don't bother */ + (((v3d->flag2 & V3D_RENDER_OVERRIDE) && v3d->drawtype >= OB_SOLID) == 0)) // <-- is this "== 0" in the right spot??? + { + /* When using wireframe object draw in particle edit mode + * the mesh gets in the way of seeing the particles, fade the wire color + * with the background. */ + + if ((dflag & DRAW_CONSTCOLOR) == 0) { + /* TODO: + * Batch_UniformColor4ubv(ob_wire_col); + */ + } + + /* If drawing wire and drawtype is not OB_WIRE then we are + * overlaying the wires. + * + * No need for polygon offset because new technique is AWESOME. + */ +#if 0 + glLineWidth(1.0f); + dm->drawEdges(dm, ((dt == OB_WIRE) || no_faces), (ob->dtx & OB_DRAW_ALL_EDGES) != 0); +#else + /* something */ +#endif + } + +#if 0 // (merwin) what is this for? + if (is_obact && BKE_paint_select_vert_test(ob)) { + const bool use_depth = (v3d->flag & V3D_ZBUF_SELECT) != 0; + glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE)); + + if (!use_depth) glDisable(GL_DEPTH_TEST); + else ED_view3d_polygon_offset(rv3d, 1.0); + drawSelectedVertices(dm, ob->data); + if (!use_depth) glEnable(GL_DEPTH_TEST); + else ED_view3d_polygon_offset(rv3d, 0.0); + } +#endif + + dm->release(dm); +} + +static bool UNUSED_FUNCTION(draw_mesh_object_new)(Scene *scene, SceneLayer *sl, ARegion *ar, View3D *v3d, RegionView3D *rv3d, BaseLegacy *base, + const char dt, const unsigned char ob_wire_col[4], const short dflag) +{ + Object *ob = base->object; + Object *obedit = scene->obedit; + Mesh *me = ob->data; + BMEditMesh *em = me->edit_btmesh; + bool do_alpha_after = false, drawlinked = false, retval = false; + + if (v3d->flag2 & V3D_RENDER_SHADOW) { + /* TODO: handle shadow pass separately */ + return true; + } + + if (obedit && ob != obedit && ob->data == obedit->data) { + if (BKE_key_from_object(ob) || BKE_key_from_object(obedit)) {} + else if (ob->modifiers.first || obedit->modifiers.first) {} + else drawlinked = true; + } + + /* backface culling */ + const bool solid = dt > OB_WIRE; + const bool cullBackface = solid && (v3d->flag2 & V3D_BACKFACE_CULLING); + if (cullBackface) { + glEnable(GL_CULL_FACE); + glCullFace(GL_BACK); + } + + if (ob == obedit || drawlinked) { + DerivedMesh *finalDM, *cageDM; + + if (obedit != ob) { + /* linked to the edit object */ + finalDM = cageDM = editbmesh_get_derived_base( + ob, em, scene->customdata_mask); + } + else { + cageDM = editbmesh_get_derived_cage_and_final( + scene, ob, em, scene->customdata_mask, + &finalDM); + } + + const bool use_material = solid && ((me->drawflag & ME_DRAWEIGHT) == 0); + +#if 0 // why update if not being used? + DM_update_materials(finalDM, ob); + if (cageDM != finalDM) { + DM_update_materials(cageDM, ob); + } +#endif // moved to below + + if (use_material) { + DM_update_materials(finalDM, ob); + if (cageDM != finalDM) { + DM_update_materials(cageDM, ob); + } + + const bool glsl = draw_glsl_material(scene, sl, ob, v3d, dt); + + GPU_begin_object_materials(v3d, rv3d, scene, sl, ob, glsl, NULL); + } + + draw_em_fancy_new(scene, ar, v3d, ob, me, em, cageDM, finalDM, dt); + + if (use_material) { + GPU_end_object_materials(); + } + + if (obedit != ob) + finalDM->release(finalDM); + } + else { + /* ob->bb was set by derived mesh system, do NULL check just to be sure */ + if (me->totpoly <= 4 || (!ob->bb || ED_view3d_boundbox_clip(rv3d, ob->bb))) { + if (solid) { + const bool glsl = draw_glsl_material(scene, sl, ob, v3d, dt); + + if (dt == OB_SOLID || glsl) { + const bool check_alpha = check_alpha_pass(base); + GPU_begin_object_materials(v3d, rv3d, scene, sl, ob, glsl, + (check_alpha) ? &do_alpha_after : NULL); + } + } + + const bool other_obedit = obedit && (obedit != ob); + + draw_mesh_fancy_new(scene, sl, ar, v3d, rv3d, base, dt, ob_wire_col, dflag, other_obedit); + + GPU_end_object_materials(); + + if (me->totvert == 0) retval = true; + } + } + + if (cullBackface) + glDisable(GL_CULL_FACE); + + return retval; +} + /* ************** DRAW DISPLIST ****************** */ +static void drawDispListVerts(PrimitiveType prim_type, const void *data, unsigned int vert_ct, const unsigned char wire_col[3]) +{ + VertexFormat format = {0}; + unsigned int pos_id = VertexFormat_add_attrib(&format, "pos", COMP_F32, 3, KEEP_FLOAT); + + VertexBuffer *vbo = VertexBuffer_create_with_format(&format); + VertexBuffer_allocate_data(vbo, vert_ct); + + VertexBuffer_fill_attrib(vbo, pos_id, data); + + Batch *batch = Batch_create(prim_type, vbo, NULL); + Batch_set_builtin_program(batch, GPU_SHADER_3D_UNIFORM_COLOR); + if (wire_col) { + Batch_Uniform4f(batch, "color", wire_col[0]/255.0f, wire_col[1]/255.0f, wire_col[2]/255.0f, 1.0f); + } + Batch_draw(batch); + Batch_discard_all(batch); +} + +/* convert dispList with elem indices to batch, only support triangles and quads + * XXX : This is a huge perf issue. We should cache the resulting batches inside the object instead. + * But new viewport will do it anyway + * TODO implement flat drawing */ +static void drawDispListElem( + bool quads, bool UNUSED(smooth), bool ndata_is_single, + const float *data, const float *ndata, unsigned int data_len, + const int *elem, unsigned int elem_len, const unsigned char wire_col[3]) +{ + VertexFormat format = {0}; + int i; + const int *idx = elem; + unsigned int pos_id, nor_id; + + pos_id = VertexFormat_add_attrib(&format, "pos", COMP_F32, 3, KEEP_FLOAT); + if (ndata) { + if (ndata_is_single) { + /* pass */ + } + else { + nor_id = VertexFormat_add_attrib(&format, "nor", COMP_F32, 3, KEEP_FLOAT); + } + } + + ElementListBuilder elb; + ElementListBuilder_init(&elb, PRIM_TRIANGLES, (quads) ? elem_len * 2 : elem_len, 0xffffffff); + + if (quads) { + for (i = elem_len; i; --i, idx += 4) { + add_triangle_vertices(&elb, idx[0], idx[1], idx[2]); + add_triangle_vertices(&elb, idx[0], idx[2], idx[3]); + } + } + else { + for (i = elem_len; i; --i, idx += 3) { + add_triangle_vertices(&elb, idx[0], idx[1], idx[2]); + } + } + + VertexBuffer *vbo = VertexBuffer_create_with_format(&format); + VertexBuffer_allocate_data(vbo, data_len); + + VertexBuffer_fill_attrib(vbo, pos_id, data); + + if (ndata) { + if (ndata_is_single) { + /* TODO: something like glNormal for a single value */ + } + else { + VertexBuffer_fill_attrib(vbo, nor_id, ndata); + } + } + + Batch *batch = Batch_create(PRIM_TRIANGLES, vbo, ElementList_build(&elb)); + Batch_set_builtin_program(batch, GPU_SHADER_SIMPLE_LIGHTING); + if (wire_col) { + Batch_Uniform4f(batch, "color", wire_col[0]/255.0f, wire_col[1]/255.0f, wire_col[2]/255.0f, 1.0f); + } + Batch_Uniform4f(batch, "color", 0.8f, 0.8f, 0.8f, 1.0f); + Batch_Uniform3f(batch, "light", 0.0f, 0.0f, 1.0f); + Batch_draw(batch); + Batch_discard_all(batch); +} /** * \param dl_type_mask Only draw types matching this mask. * \return true when nothing was drawn */ -static bool drawDispListwire_ex(ListBase *dlbase, unsigned int dl_type_mask) +static bool drawDispListwire_ex(ListBase *dlbase, unsigned int dl_type_mask, const unsigned char wire_col[3]) { if (dlbase == NULL) return true; - glEnableClientState(GL_VERTEX_ARRAY); glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); for (DispList *dl = dlbase->first; dl; dl = dl->next) { @@ -4357,83 +5222,76 @@ static bool drawDispListwire_ex(ListBase *dlbase, unsigned int dl_type_mask) if ((dl_type_mask & (1 << dl->type)) == 0) { continue; } - + const float *data = dl->verts; int parts; switch (dl->type) { case DL_SEGM: - - glVertexPointer(3, GL_FLOAT, 0, data); - for (parts = 0; parts < dl->parts; parts++) - glDrawArrays(GL_LINE_STRIP, parts * dl->nr, dl->nr); - + drawDispListVerts(PRIM_LINE_STRIP, data + (parts * dl->nr * 3), dl->nr, wire_col); break; - case DL_POLY: - - glVertexPointer(3, GL_FLOAT, 0, data); + case DL_POLY: for (parts = 0; parts < dl->parts; parts++) - glDrawArrays(GL_LINE_LOOP, parts * dl->nr, dl->nr); - + drawDispListVerts(PRIM_LINE_LOOP, data + (parts * dl->nr * 3), dl->nr, wire_col); break; - case DL_SURF: - - glVertexPointer(3, GL_FLOAT, 0, data); + case DL_SURF: for (parts = 0; parts < dl->parts; parts++) { if (dl->flag & DL_CYCL_U) - glDrawArrays(GL_LINE_LOOP, parts * dl->nr, dl->nr); + drawDispListVerts(PRIM_LINE_LOOP, data + (parts * dl->nr * 3), dl->nr, wire_col); else - glDrawArrays(GL_LINE_STRIP, parts * dl->nr, dl->nr); + drawDispListVerts(PRIM_LINE_STRIP, data + (parts * dl->nr * 3), dl->nr, wire_col); } + float *data_aligned = MEM_mallocN(sizeof(float) * 3 * dl->parts, "aligned data"); for (int nr = 0; nr < dl->nr; nr++) { int ofs = 3 * dl->nr; + int idx = 0; data = (dl->verts) + 3 * nr; parts = dl->parts; - if (dl->flag & DL_CYCL_V) glBegin(GL_LINE_LOOP); - else glBegin(GL_LINE_STRIP); - while (parts--) { - glVertex3fv(data); + copy_v3_v3(data_aligned + idx, data); data += ofs; + idx += 3; } - glEnd(); -#if 0 - /* (ton) this code crashes for me when resolv is 86 or higher... no clue */ - glVertexPointer(3, GL_FLOAT, sizeof(float) * 3 * dl->nr, data + 3 * nr); - if (dl->flag & DL_CYCL_V) - glDrawArrays(GL_LINE_LOOP, 0, dl->parts); - else - glDrawArrays(GL_LINE_STRIP, 0, dl->parts); -#endif + if (dl->flag & DL_CYCL_V) + drawDispListVerts(PRIM_LINE_LOOP, data_aligned, dl->parts, wire_col); + else + drawDispListVerts(PRIM_LINE_STRIP, data_aligned, dl->parts, wire_col); } + + if (data_aligned) + MEM_freeN(data_aligned); + break; case DL_INDEX3: - glVertexPointer(3, GL_FLOAT, 0, dl->verts); - glDrawElements(GL_TRIANGLES, 3 * dl->parts, GL_UNSIGNED_INT, dl->index); + drawDispListElem( + false, true, false, + dl->verts, NULL, dl->nr, + dl->index, dl->parts, wire_col); break; case DL_INDEX4: - glVertexPointer(3, GL_FLOAT, 0, dl->verts); - glDrawElements(GL_QUADS, 4 * dl->parts, GL_UNSIGNED_INT, dl->index); + drawDispListElem( + true, true, false, + dl->verts, NULL, dl->nr, + dl->index, dl->parts, wire_col); break; } } - glDisableClientState(GL_VERTEX_ARRAY); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); return false; } -static bool drawDispListwire(ListBase *dlbase, const short ob_type) +static bool drawDispListwire(ListBase *dlbase, const short ob_type, const unsigned char wire_col[3]) { unsigned int dl_mask = 0xffffffff; @@ -4442,27 +5300,25 @@ static bool drawDispListwire(ListBase *dlbase, const short ob_type) dl_mask &= ~((1 << DL_INDEX3) | (1 << DL_INDEX4)); } - return drawDispListwire_ex(dlbase, dl_mask); + return drawDispListwire_ex(dlbase, dl_mask, wire_col); } static bool index3_nors_incr = true; -static void drawDispListsolid(ListBase *lb, Object *ob, const short dflag, +static void drawDispListsolid(ListBase *lb, Object *ob, const short UNUSED(dflag), const unsigned char ob_wire_col[4], const bool use_glsl) { GPUVertexAttribs gattribs; if (lb == NULL) return; - glEnableClientState(GL_VERTEX_ARRAY); - /* track current material, -1 for none (needed for lines) */ short col = -1; DispList *dl = lb->first; while (dl) { const float *data = dl->verts; - const float *ndata = dl->nors; + //const float *ndata = dl->nors; switch (dl->type) { case DL_SEGM: @@ -4472,15 +5328,7 @@ static void drawDispListsolid(ListBase *lb, Object *ob, const short dflag, col = -1; } - if ((dflag & DRAW_CONSTCOLOR) == 0) - glColor3ubv(ob_wire_col); - - // glVertexPointer(3, GL_FLOAT, 0, dl->verts); - // glDrawArrays(GL_LINE_STRIP, 0, dl->nr); - glBegin(GL_LINE_STRIP); - for (int nr = dl->nr; nr; nr--, data += 3) - glVertex3fv(data); - glEnd(); + drawDispListVerts(PRIM_LINE_STRIP, data, dl->nr, ob_wire_col); } break; case DL_POLY: @@ -4490,14 +5338,7 @@ static void drawDispListsolid(ListBase *lb, Object *ob, const short dflag, col = -1; } - /* for some reason glDrawArrays crashes here in half of the platforms (not osx) */ - //glVertexPointer(3, GL_FLOAT, 0, dl->verts); - //glDrawArrays(GL_LINE_LOOP, 0, dl->nr); - - glBegin(GL_LINE_LOOP); - for (int nr = dl->nr; nr; nr--, data += 3) - glVertex3fv(data); - glEnd(); + drawDispListVerts(PRIM_LINE_LOOP, data, dl->nr, ob_wire_col); } break; case DL_SURF: @@ -4507,15 +5348,12 @@ static void drawDispListsolid(ListBase *lb, Object *ob, const short dflag, GPU_object_material_bind(dl->col + 1, use_glsl ? &gattribs : NULL); col = dl->col; } - /* FLAT/SMOOTH shading for surfaces */ - glShadeModel((dl->rt & CU_SMOOTH) ? GL_SMOOTH : GL_FLAT); + const unsigned int verts_len = dl->nr * dl->parts; - glEnableClientState(GL_NORMAL_ARRAY); - glVertexPointer(3, GL_FLOAT, 0, dl->verts); - glNormalPointer(GL_FLOAT, 0, dl->nors); - glDrawElements(GL_QUADS, 4 * dl->totindex, GL_UNSIGNED_INT, dl->index); - glDisableClientState(GL_NORMAL_ARRAY); - glShadeModel(GL_SMOOTH); + drawDispListElem( + true, (dl->rt & CU_SMOOTH) != 0, false, + dl->verts, dl->nors, verts_len, + dl->index, dl->totindex, ob_wire_col); } break; @@ -4525,8 +5363,7 @@ static void drawDispListsolid(ListBase *lb, Object *ob, const short dflag, col = dl->col; } - glVertexPointer(3, GL_FLOAT, 0, dl->verts); - +#if 0 /* for polys only one normal needed */ if (index3_nors_incr) { glEnableClientState(GL_NORMAL_ARRAY); @@ -4534,11 +5371,17 @@ static void drawDispListsolid(ListBase *lb, Object *ob, const short dflag, } else glNormal3fv(ndata); +#endif + /* special case, 'nors' is a single value */ + drawDispListElem( + false, (dl->rt & CU_SMOOTH) != 0, true, + dl->verts, dl->nors, dl->nr, + dl->index, dl->parts, ob_wire_col); - glDrawElements(GL_TRIANGLES, 3 * dl->parts, GL_UNSIGNED_INT, dl->index); - +#if 0 if (index3_nors_incr) glDisableClientState(GL_NORMAL_ARRAY); +#endif break; @@ -4548,18 +5391,16 @@ static void drawDispListsolid(ListBase *lb, Object *ob, const short dflag, col = dl->col; } - glEnableClientState(GL_NORMAL_ARRAY); - glVertexPointer(3, GL_FLOAT, 0, dl->verts); - glNormalPointer(GL_FLOAT, 0, dl->nors); - glDrawElements(GL_QUADS, 4 * dl->parts, GL_UNSIGNED_INT, dl->index); - glDisableClientState(GL_NORMAL_ARRAY); + drawDispListElem( + true, true, false, + dl->verts, dl->nors, dl->nr, + dl->index, dl->parts, ob_wire_col); break; } dl = dl->next; } - glDisableClientState(GL_VERTEX_ARRAY); glFrontFace(GL_CCW); if (col != -1) { @@ -4574,7 +5415,7 @@ static void drawCurveDMWired(Object *ob) } /* return true when nothing was drawn */ -static bool drawCurveDerivedMesh(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, const char dt) +static bool drawCurveDerivedMesh(Scene *scene, SceneLayer *sl, View3D *v3d, RegionView3D *rv3d, BaseLegacy *base, const char dt) { Object *ob = base->object; DerivedMesh *dm = ob->derivedFinal; @@ -4588,8 +5429,8 @@ static bool drawCurveDerivedMesh(Scene *scene, View3D *v3d, RegionView3D *rv3d, glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW); if (dt > OB_WIRE && dm->getNumPolys(dm)) { - bool glsl = draw_glsl_material(scene, ob, v3d, dt); - GPU_begin_object_materials(v3d, rv3d, scene, ob, glsl, NULL); + bool glsl = draw_glsl_material(scene, sl, ob, v3d, dt); + GPU_begin_object_materials(v3d, rv3d, scene, sl, ob, glsl, NULL); if (!glsl) dm->drawFacesSolid(dm, NULL, 0, GPU_object_material_bind); @@ -4610,7 +5451,7 @@ static bool drawCurveDerivedMesh(Scene *scene, View3D *v3d, RegionView3D *rv3d, * Only called by #drawDispList * \return true when nothing was drawn */ -static bool drawDispList_nobackface(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, +static bool drawDispList_nobackface(Scene *scene, SceneLayer *sl, View3D *v3d, RegionView3D *rv3d, Base *base, const char dt, const short dflag, const unsigned char ob_wire_col[4]) { Object *ob = base->object; @@ -4640,10 +5481,10 @@ static bool drawDispList_nobackface(Scene *scene, View3D *v3d, RegionView3D *rv3 if (!render_only) { /* when we have faces, only draw loose-wire */ if (has_faces) { - drawDispListwire_ex(lb, (1 << DL_SEGM)); + drawDispListwire_ex(lb, (1 << DL_SEGM), ob_wire_col); } else { - drawDispListwire(lb, ob->type); + drawDispListwire(lb, ob->type, ob_wire_col); } } @@ -4651,26 +5492,26 @@ static bool drawDispList_nobackface(Scene *scene, View3D *v3d, RegionView3D *rv3 /* pass */ } else { - if (draw_glsl_material(scene, ob, v3d, dt)) { - GPU_begin_object_materials(v3d, rv3d, scene, ob, 1, NULL); + if (draw_glsl_material(scene, sl, ob, v3d, dt)) { + GPU_begin_object_materials(v3d, rv3d, scene, sl, ob, 1, NULL); drawDispListsolid(lb, ob, dflag, ob_wire_col, true); GPU_end_object_materials(); } else { - GPU_begin_object_materials(v3d, rv3d, scene, ob, 0, NULL); + GPU_begin_object_materials(v3d, rv3d, scene, sl, ob, 0, NULL); drawDispListsolid(lb, ob, dflag, ob_wire_col, false); GPU_end_object_materials(); } if (cu->editnurb && cu->bevobj == NULL && cu->taperobj == NULL && cu->ext1 == 0.0f && cu->ext2 == 0.0f) { - cpack(0); - drawDispListwire(lb, ob->type); + unsigned char col[4] = {0, 0, 0, 0}; + drawDispListwire(lb, ob->type, col); } } index3_nors_incr = true; } else { if (!render_only || BKE_displist_has_faces(lb)) { - return drawDispListwire(lb, ob->type); + return drawDispListwire(lb, ob->type, ob_wire_col); } } break; @@ -4686,19 +5527,19 @@ static bool drawDispList_nobackface(Scene *scene, View3D *v3d, RegionView3D *rv3 if (dl->nors == NULL) BKE_displist_normals_add(lb); - if (draw_glsl_material(scene, ob, v3d, dt)) { - GPU_begin_object_materials(v3d, rv3d, scene, ob, 1, NULL); + if (draw_glsl_material(scene, sl, ob, v3d, dt)) { + GPU_begin_object_materials(v3d, rv3d, scene, sl, ob, 1, NULL); drawDispListsolid(lb, ob, dflag, ob_wire_col, true); GPU_end_object_materials(); } else { - GPU_begin_object_materials(v3d, rv3d, scene, ob, 0, NULL); + GPU_begin_object_materials(v3d, rv3d, scene, sl, ob, 0, NULL); drawDispListsolid(lb, ob, dflag, ob_wire_col, false); GPU_end_object_materials(); } } else { - return drawDispListwire(lb, ob->type); + return drawDispListwire(lb, ob->type, ob_wire_col); } break; case OB_MBALL: @@ -4711,19 +5552,19 @@ static bool drawDispList_nobackface(Scene *scene, View3D *v3d, RegionView3D *rv3 if (solid) { - if (draw_glsl_material(scene, ob, v3d, dt)) { - GPU_begin_object_materials(v3d, rv3d, scene, ob, 1, NULL); + if (draw_glsl_material(scene, sl, ob, v3d, dt)) { + GPU_begin_object_materials(v3d, rv3d, scene, sl, ob, 1, NULL); drawDispListsolid(lb, ob, dflag, ob_wire_col, true); GPU_end_object_materials(); } else { - GPU_begin_object_materials(v3d, rv3d, scene, ob, 0, NULL); + GPU_begin_object_materials(v3d, rv3d, scene, sl, ob, 0, NULL); drawDispListsolid(lb, ob, dflag, ob_wire_col, false); GPU_end_object_materials(); } } else { - return drawDispListwire(lb, ob->type); + return drawDispListwire(lb, ob->type, ob_wire_col); } } break; @@ -4731,7 +5572,7 @@ static bool drawDispList_nobackface(Scene *scene, View3D *v3d, RegionView3D *rv3 return false; } -static bool drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, +static bool drawDispList(Scene *scene, SceneLayer *sl, View3D *v3d, RegionView3D *rv3d, Base *base, const char dt, const short dflag, const unsigned char ob_wire_col[4]) { bool retval; @@ -4747,7 +5588,7 @@ static bool drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *ba ensure_curve_cache(scene, base->object); #endif - if (drawCurveDerivedMesh(scene, v3d, rv3d, base, dt) == false) { + if (drawCurveDerivedMesh(scene, sl, v3d, rv3d, base, dt) == false) { retval = false; } else { @@ -4763,7 +5604,7 @@ static bool drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *ba glFrontFace(mode); - retval = drawDispList_nobackface(scene, v3d, rv3d, base, dt, dflag, ob_wire_col); + retval = drawDispList_nobackface(scene, sl, v3d, rv3d, base, dt, dflag, ob_wire_col); if (mode != GL_CCW) { glFrontFace(GL_CCW); @@ -4778,16 +5619,63 @@ static bool drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *ba } /* *********** drawing for particles ************* */ -static void draw_particle_arrays(int draw_as, int totpoint, int ob_dt, int select) +/* stride : offset size in bytes + * col[4] : the color to use when *color is NULL, can be also NULL */ +static void draw_vertex_array(PrimitiveType prim_type, const float *vert, const float *nor, const float *color, int stride, int vert_ct, float col[4]) +{ + VertexFormat format = {0}; + unsigned int pos_id, nor_id, col_id; + pos_id = VertexFormat_add_attrib(&format, "pos", COMP_F32, 3, KEEP_FLOAT); + if (nor) nor_id = VertexFormat_add_attrib(&format, "nor", COMP_F32, 3, KEEP_FLOAT); + if (color) col_id = VertexFormat_add_attrib(&format, "color", COMP_F32, 3, KEEP_FLOAT); + + VertexBuffer *vbo = VertexBuffer_create_with_format(&format); + VertexBuffer_allocate_data(vbo, vert_ct); + + if (stride == 0) { + VertexBuffer_fill_attrib(vbo, pos_id, vert); + if (nor) VertexBuffer_fill_attrib(vbo, nor_id, nor); + if (color) VertexBuffer_fill_attrib(vbo, col_id, color); + } + else { + VertexBuffer_fill_attrib_stride(vbo, pos_id, stride, vert); + if (nor) VertexBuffer_fill_attrib_stride(vbo, nor_id, stride, nor); + if (color) VertexBuffer_fill_attrib_stride(vbo, col_id, stride, color); + } + + Batch *batch = Batch_create(prim_type, vbo, NULL); + if (nor && color) { + Batch_set_builtin_program(batch, GPU_SHADER_SIMPLE_LIGHTING_SMOOTH_COLOR); + Batch_Uniform3f(batch, "light", 0.0f, 0.0f, 1.0f); + } + else if (nor) { + Batch_set_builtin_program(batch, GPU_SHADER_SIMPLE_LIGHTING); + Batch_Uniform3f(batch, "light", 0.0f, 0.0f, 1.0f); + if (col) Batch_Uniform4fv(batch, "color", col); + } + else if (color) { + Batch_set_builtin_program(batch, GPU_SHADER_3D_SMOOTH_COLOR); + } + else { + Batch_set_builtin_program(batch, GPU_SHADER_3D_UNIFORM_COLOR); + if (col) Batch_Uniform4fv(batch, "color", col); + } + Batch_draw(batch); + Batch_discard_all(batch); +} + +static void draw_particle_arrays_new(int draw_as, int ob_dt, int select, + const float *vert, const float *nor, const float *color, + int totpoint, float col[4]) { /* draw created data arrays */ switch (draw_as) { case PART_DRAW_AXIS: case PART_DRAW_CROSS: - glDrawArrays(GL_LINES, 0, 6 * totpoint); + draw_vertex_array(PRIM_LINES, vert, nor, color, 0, 6 * totpoint, col); break; case PART_DRAW_LINE: - glDrawArrays(GL_LINES, 0, 2 * totpoint); + draw_vertex_array(PRIM_LINES, vert, nor, color, 0, 2 * totpoint, col); break; case PART_DRAW_BB: if (ob_dt <= OB_WIRE || select) @@ -4795,15 +5683,16 @@ static void draw_particle_arrays(int draw_as, int totpoint, int ob_dt, int selec else glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - glDrawArrays(GL_QUADS, 0, 4 * totpoint); + draw_vertex_array(PRIM_TRIANGLES, vert, nor, color, 0, 6 * totpoint, col); break; default: - glDrawArrays(GL_POINTS, 0, totpoint); + draw_vertex_array(PRIM_POINTS, vert, nor, color, 0, totpoint, col); break; } } static void draw_particle(ParticleKey *state, int draw_as, short draw, float pixsize, - float imat[4][4], const float draw_line[2], ParticleBillboardData *bb, ParticleDrawData *pdd) + float imat[4][4], const float draw_line[2], ParticleBillboardData *bb, ParticleDrawData *pdd, + unsigned int pos) { float vec[3], vec2[3]; float *vd = NULL; @@ -4913,24 +5802,19 @@ static void draw_particle(ParticleKey *state, int draw_as, short draw, float pix } case PART_DRAW_CIRC: { - drawcircball(GL_LINE_LOOP, state->co, pixsize, imat); + imm_drawcircball(state->co, pixsize, imat, pos); break; } case PART_DRAW_BB: { float xvec[3], yvec[3], zvec[3], bb_center[3]; - if (cd) { - cd[0] = cd[3] = cd[6] = cd[9] = ma_col[0]; - cd[1] = cd[4] = cd[7] = cd[10] = ma_col[1]; - cd[2] = cd[5] = cd[8] = cd[11] = ma_col[2]; - pdd->cd += 12; - } copy_v3_v3(bb->vec, state->co); copy_v3_v3(bb->vel, state->vel); psys_make_billboard(bb, xvec, yvec, zvec, bb_center); - + + /* First tri */ add_v3_v3v3(pdd->vd, bb_center, xvec); add_v3_v3(pdd->vd, yvec); pdd->vd += 3; @@ -4940,13 +5824,24 @@ static void draw_particle(ParticleKey *state, int draw_as, short draw, float pix sub_v3_v3v3(pdd->vd, bb_center, xvec); sub_v3_v3v3(pdd->vd, pdd->vd, yvec); pdd->vd += 3; + /* Second tri */ + add_v3_v3v3(pdd->vd, bb_center, xvec); + add_v3_v3(pdd->vd, yvec); pdd->vd += 3; + + sub_v3_v3v3(pdd->vd, bb_center, xvec); + sub_v3_v3v3(pdd->vd, pdd->vd, yvec); pdd->vd += 3; + add_v3_v3v3(pdd->vd, bb_center, xvec); sub_v3_v3v3(pdd->vd, pdd->vd, yvec); pdd->vd += 3; - copy_v3_v3(pdd->nd, zvec); pdd->nd += 3; - copy_v3_v3(pdd->nd, zvec); pdd->nd += 3; - copy_v3_v3(pdd->nd, zvec); pdd->nd += 3; - copy_v3_v3(pdd->nd, zvec); pdd->nd += 3; + if (cd) { + for (int i = 0; i < 6; i++, cd += 3, pdd->cd += 3) { + copy_v3_v3(cd, ma_col); + } + } + for (int i = 0; i < 6; i++, pdd->nd += 3) { + copy_v3_v3(pdd->nd, zvec); + } break; } } @@ -4954,7 +5849,8 @@ static void draw_particle(ParticleKey *state, int draw_as, short draw, float pix static void draw_particle_data(ParticleSystem *psys, RegionView3D *rv3d, ParticleKey *state, int draw_as, float imat[4][4], ParticleBillboardData *bb, ParticleDrawData *pdd, - const float ct, const float pa_size, const float r_tilt, const float pixsize_scale) + const float ct, const float pa_size, const float r_tilt, const float pixsize_scale, + unsigned int pos) { ParticleSettings *part = psys->part; float pixsize; @@ -4985,7 +5881,7 @@ static void draw_particle_data(ParticleSystem *psys, RegionView3D *rv3d, pixsize = ED_view3d_pixel_size(rv3d, state->co) * pixsize_scale; - draw_particle(state, draw_as, part->draw, pixsize, imat, part->draw_line, bb, pdd); + draw_particle(state, draw_as, part->draw, pixsize, imat, part->draw_line, bb, pdd, pos); } /* unified drawing of all new particle systems draw types except dupli ob & group * mostly tries to use vertex arrays for speed @@ -5018,10 +5914,11 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv float cfra; float ma_col[3] = {0.0f, 0.0f, 0.0f}; int a, totpart, totpoint = 0, totve = 0, drawn, draw_as, totchild = 0; - bool select = (ob->flag & SELECT) != 0, create_cdata = false, need_v = false; + bool select = (base->flag & BASE_SELECTED) != 0, create_cdata = false, need_v = false; GLint polygonmode[2]; char numstr[32]; unsigned char tcol[4] = {0, 0, 0, 255}; + unsigned int pos; /* 1. */ if (part == NULL || !psys_check_enabled(ob, psys, G.is_rendering)) @@ -5083,16 +5980,12 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv copy_v3_v3(ma_col, &ma->r); } - if ((dflag & DRAW_CONSTCOLOR) == 0) { - glColor3ubv(tcol); - } - timestep = psys_get_timestep(&sim); - if ((base->flag & OB_FROMDUPLI) && (ob->flag & OB_FROMGROUP)) { + if ((ob->flag & OB_FROMGROUP) != 0) { float mat[4][4]; mul_m4_m4m4(mat, ob->obmat, psys->imat); - glMultMatrixf(mat); + gpuMultMatrix(mat); } /* needed for text display */ @@ -5212,7 +6105,7 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv tot_vec_size *= 2; break; case PART_DRAW_BB: - tot_vec_size *= 4; + tot_vec_size *= 6; /* New OGL only understands tris, no choice here. */ create_ndata = 1; break; } @@ -5266,6 +6159,11 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv totpoint = pdd->totpoint; /* draw data is up to date */ } else { + if ((draw_as == PART_DRAW_CIRC) || (part->draw & PART_DRAW_SIZE)) { + pos = VertexFormat_add_attrib(immVertexFormat(), "pos", COMP_F32, 3, KEEP_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + imm_cpack(0xFFFFFF); + } for (a = 0, pa = pars; a < totpart + totchild; a++, pa++) { /* setup per particle individual stuff */ if (a < totpart) { @@ -5336,7 +6234,7 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv draw_particle_data(psys, rv3d, &state, draw_as, imat, &bb, psys->pdd, - ct, pa_size, r_tilt, pixsize_scale); + ct, pa_size, r_tilt, pixsize_scale, pos); totpoint++; drawn = 1; @@ -5348,7 +6246,7 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv draw_particle_data(psys, rv3d, &state, draw_as, imat, &bb, psys->pdd, - pa_time, pa_size, r_tilt, pixsize_scale); + pa_time, pa_size, r_tilt, pixsize_scale, pos); totpoint++; drawn = 1; @@ -5370,7 +6268,7 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv if (part->draw & PART_DRAW_SIZE) { setlinestyle(3); - drawcircball(GL_LINE_LOOP, state.co, pa_size, imat); + imm_drawcircball(state.co, pa_size, imat, pos); setlinestyle(0); } @@ -5407,31 +6305,19 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv } } } + if ((draw_as == PART_DRAW_CIRC) || (part->draw & PART_DRAW_SIZE)) { + immUnbindProgram(); + } } } /* 6. */ glGetIntegerv(GL_POLYGON_MODE, polygonmode); - glEnableClientState(GL_VERTEX_ARRAY); if (draw_as == PART_DRAW_PATH) { ParticleCacheKey **cache, *path; float *cdata2 = NULL; - /* setup gl flags */ - if (1) { //ob_dt > OB_WIRE) { - glEnableClientState(GL_NORMAL_ARRAY); - - if ((dflag & DRAW_CONSTCOLOR) == 0) { - if (part->draw_col == PART_DRAW_COL_MAT) - glEnableClientState(GL_COLOR_ARRAY); - } - - // XXX test - GPU_basic_shader_colors(NULL, NULL, 0.0f, 1.0f); - GPU_basic_shader_bind(GPU_SHADER_LIGHTING | GPU_SHADER_USE_COLOR); - } - if (totchild && (part->draw & PART_DRAW_PARENT) == 0) totpart = 0; else if (psys->pathcache == NULL) @@ -5442,41 +6328,28 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv for (a = 0, pa = psys->particles; a < totpart; a++, pa++) { path = cache[a]; if (path->segments > 0) { - glVertexPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->co); - - if (1) { //ob_dt > OB_WIRE) { - glNormalPointer(GL_FLOAT, sizeof(ParticleCacheKey), path->vel); - if ((dflag & DRAW_CONSTCOLOR) == 0) { - if (part->draw_col == PART_DRAW_COL_MAT) { - glColorPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->col); - } - } + if (((dflag & DRAW_CONSTCOLOR) == 0) && (part->draw_col == PART_DRAW_COL_MAT)) { + draw_vertex_array(PRIM_LINE_STRIP, path->co, path->vel, path->col, sizeof(ParticleCacheKey), path->segments + 1, NULL); + } + else { + float color[4]; + rgba_uchar_to_float(color, tcol); + draw_vertex_array(PRIM_LINE_STRIP, path->co, path->vel, NULL, sizeof(ParticleCacheKey), path->segments + 1, color); } - - glDrawArrays(GL_LINE_STRIP, 0, path->segments + 1); } } if (part->type == PART_HAIR) { if (part->draw & PART_DRAW_GUIDE_HAIRS) { DerivedMesh *hair_dm = psys->hair_out_dm; - - glDisableClientState(GL_NORMAL_ARRAY); - glDisableClientState(GL_COLOR_ARRAY); - + for (a = 0, pa = psys->particles; a < totpart; a++, pa++) { if (pa->totkey > 1) { HairKey *hkey = pa->hair; - glVertexPointer(3, GL_FLOAT, sizeof(HairKey), hkey->world_co); - -#if 0 /* XXX use proper theme color here */ - UI_ThemeColor(TH_NORMAL); -#else - glColor3f(0.58f, 0.67f, 1.0f); -#endif - - glDrawArrays(GL_LINE_STRIP, 0, pa->totkey); + /* XXX use proper theme color here */ + float color[4] = {0.58f, 0.67f, 1.0f, 1.0f}; + draw_vertex_array(PRIM_LINE_STRIP, hkey->world_co, NULL, NULL, sizeof(HairKey), pa->totkey, color); } } @@ -5484,30 +6357,36 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv MVert *mvert = hair_dm->getVertArray(hair_dm); int i; - glColor3f(0.9f, 0.4f, 0.4f); - - glBegin(GL_LINES); + unsigned int pos_id = VertexFormat_add_attrib(immVertexFormat(), "pos", COMP_F32, 3, KEEP_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immUniformColor3f(0.9f, 0.4f, 0.4f); + + unsigned int count = 0; for (a = 0, pa = psys->particles; a < totpart; a++, pa++) { - for (i = 1; i < pa->totkey; ++i) { - float v1[3], v2[3]; - - copy_v3_v3(v1, mvert[pa->hair_index + i - 1].co); - copy_v3_v3(v2, mvert[pa->hair_index + i].co); - - mul_m4_v3(ob->obmat, v1); - mul_m4_v3(ob->obmat, v2); - - glVertex3fv(v1); - glVertex3fv(v2); + count += MAX2(pa->totkey - 1, 0); + } + + if (count > 0) { + immBegin(PRIM_LINES, count * 2); + for (a = 0, pa = psys->particles; a < totpart; a++, pa++) { + for (i = 1; i < pa->totkey; ++i) { + float v1[3], v2[3]; + + copy_v3_v3(v1, mvert[pa->hair_index + i - 1].co); + copy_v3_v3(v2, mvert[pa->hair_index + i].co); + + mul_m4_v3(ob->obmat, v1); + mul_m4_v3(ob->obmat, v2); + + immVertex3fv(pos_id, v1); + immVertex3fv(pos_id, v2); + } } + immEnd(); } - glEnd(); + + immUnbindProgram(); } - - glEnableClientState(GL_NORMAL_ARRAY); - if ((dflag & DRAW_CONSTCOLOR) == 0) - if (part->draw_col == PART_DRAW_COL_MAT) - glEnableClientState(GL_COLOR_ARRAY); } if (part->draw & PART_DRAW_HAIR_GRID) { @@ -5518,64 +6397,69 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv int *res = clmd->hair_grid_res; int i; - glDisableClientState(GL_NORMAL_ARRAY); - glDisableClientState(GL_COLOR_ARRAY); - + unsigned int pos_id = VertexFormat_add_attrib(immVertexFormat(), "pos", COMP_F32, 3, KEEP_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); if (select) - UI_ThemeColor(TH_ACTIVE); + immUniformThemeColor(TH_ACTIVE); else - UI_ThemeColor(TH_WIRE); - glBegin(GL_LINES); - glVertex3f(gmin[0], gmin[1], gmin[2]); glVertex3f(gmax[0], gmin[1], gmin[2]); - glVertex3f(gmax[0], gmin[1], gmin[2]); glVertex3f(gmax[0], gmax[1], gmin[2]); - glVertex3f(gmax[0], gmax[1], gmin[2]); glVertex3f(gmin[0], gmax[1], gmin[2]); - glVertex3f(gmin[0], gmax[1], gmin[2]); glVertex3f(gmin[0], gmin[1], gmin[2]); + immUniformThemeColor(TH_WIRE); + + immBegin(PRIM_LINES, 24); + immVertex3f(pos_id, gmin[0], gmin[1], gmin[2]); immVertex3f(pos_id, gmax[0], gmin[1], gmin[2]); + immVertex3f(pos_id, gmax[0], gmin[1], gmin[2]); immVertex3f(pos_id, gmax[0], gmax[1], gmin[2]); + immVertex3f(pos_id, gmax[0], gmax[1], gmin[2]); immVertex3f(pos_id, gmin[0], gmax[1], gmin[2]); + immVertex3f(pos_id, gmin[0], gmax[1], gmin[2]); immVertex3f(pos_id, gmin[0], gmin[1], gmin[2]); - glVertex3f(gmin[0], gmin[1], gmax[2]); glVertex3f(gmax[0], gmin[1], gmax[2]); - glVertex3f(gmax[0], gmin[1], gmax[2]); glVertex3f(gmax[0], gmax[1], gmax[2]); - glVertex3f(gmax[0], gmax[1], gmax[2]); glVertex3f(gmin[0], gmax[1], gmax[2]); - glVertex3f(gmin[0], gmax[1], gmax[2]); glVertex3f(gmin[0], gmin[1], gmax[2]); + immVertex3f(pos_id, gmin[0], gmin[1], gmax[2]); immVertex3f(pos_id, gmax[0], gmin[1], gmax[2]); + immVertex3f(pos_id, gmax[0], gmin[1], gmax[2]); immVertex3f(pos_id, gmax[0], gmax[1], gmax[2]); + immVertex3f(pos_id, gmax[0], gmax[1], gmax[2]); immVertex3f(pos_id, gmin[0], gmax[1], gmax[2]); + immVertex3f(pos_id, gmin[0], gmax[1], gmax[2]); immVertex3f(pos_id, gmin[0], gmin[1], gmax[2]); - glVertex3f(gmin[0], gmin[1], gmin[2]); glVertex3f(gmin[0], gmin[1], gmax[2]); - glVertex3f(gmax[0], gmin[1], gmin[2]); glVertex3f(gmax[0], gmin[1], gmax[2]); - glVertex3f(gmin[0], gmax[1], gmin[2]); glVertex3f(gmin[0], gmax[1], gmax[2]); - glVertex3f(gmax[0], gmax[1], gmin[2]); glVertex3f(gmax[0], gmax[1], gmax[2]); - glEnd(); + immVertex3f(pos_id, gmin[0], gmin[1], gmin[2]); immVertex3f(pos_id, gmin[0], gmin[1], gmax[2]); + immVertex3f(pos_id, gmax[0], gmin[1], gmin[2]); immVertex3f(pos_id, gmax[0], gmin[1], gmax[2]); + immVertex3f(pos_id, gmin[0], gmax[1], gmin[2]); immVertex3f(pos_id, gmin[0], gmax[1], gmax[2]); + immVertex3f(pos_id, gmax[0], gmax[1], gmin[2]); immVertex3f(pos_id, gmax[0], gmax[1], gmax[2]); + immEnd(); if (select) - UI_ThemeColorShadeAlpha(TH_ACTIVE, 0, -100); + immUniformThemeColorShadeAlpha(TH_ACTIVE, 0, -100); else - UI_ThemeColorShadeAlpha(TH_WIRE, 0, -100); - glEnable(GL_BLEND); - glBegin(GL_LINES); - for (i = 1; i < res[0] - 1; ++i) { - float f = interpf(gmax[0], gmin[0], (float)i / (float)(res[0] - 1)); - glVertex3f(f, gmin[1], gmin[2]); glVertex3f(f, gmax[1], gmin[2]); - glVertex3f(f, gmax[1], gmin[2]); glVertex3f(f, gmax[1], gmax[2]); - glVertex3f(f, gmax[1], gmax[2]); glVertex3f(f, gmin[1], gmax[2]); - glVertex3f(f, gmin[1], gmax[2]); glVertex3f(f, gmin[1], gmin[2]); - } - for (i = 1; i < res[1] - 1; ++i) { - float f = interpf(gmax[1], gmin[1], (float)i / (float)(res[1] - 1)); - glVertex3f(gmin[0], f, gmin[2]); glVertex3f(gmax[0], f, gmin[2]); - glVertex3f(gmax[0], f, gmin[2]); glVertex3f(gmax[0], f, gmax[2]); - glVertex3f(gmax[0], f, gmax[2]); glVertex3f(gmin[0], f, gmax[2]); - glVertex3f(gmin[0], f, gmax[2]); glVertex3f(gmin[0], f, gmin[2]); - } - for (i = 1; i < res[2] - 1; ++i) { - float f = interpf(gmax[2], gmin[2], (float)i / (float)(res[2] - 1)); - glVertex3f(gmin[0], gmin[1], f); glVertex3f(gmax[0], gmin[1], f); - glVertex3f(gmax[0], gmin[1], f); glVertex3f(gmax[0], gmax[1], f); - glVertex3f(gmax[0], gmax[1], f); glVertex3f(gmin[0], gmax[1], f); - glVertex3f(gmin[0], gmax[1], f); glVertex3f(gmin[0], gmin[1], f); + immUniformThemeColorShadeAlpha(TH_WIRE, 0, -100); + + int count = 0; + count += MAX2(0, res[0] - 2) * 8; + count += MAX2(0, res[1] - 2) * 8; + count += MAX2(0, res[2] - 2) * 8; + + if (count >= 2) { + glEnable(GL_BLEND); + immBegin(PRIM_LINES, count); + for (i = 1; i < res[0] - 1; ++i) { + float f = interpf(gmax[0], gmin[0], (float)i / (float)(res[0] - 1)); + immVertex3f(pos_id, f, gmin[1], gmin[2]); immVertex3f(pos_id, f, gmax[1], gmin[2]); + immVertex3f(pos_id, f, gmax[1], gmin[2]); immVertex3f(pos_id, f, gmax[1], gmax[2]); + immVertex3f(pos_id, f, gmax[1], gmax[2]); immVertex3f(pos_id, f, gmin[1], gmax[2]); + immVertex3f(pos_id, f, gmin[1], gmax[2]); immVertex3f(pos_id, f, gmin[1], gmin[2]); + } + for (i = 1; i < res[1] - 1; ++i) { + float f = interpf(gmax[1], gmin[1], (float)i / (float)(res[1] - 1)); + immVertex3f(pos_id, gmin[0], f, gmin[2]); immVertex3f(pos_id, gmax[0], f, gmin[2]); + immVertex3f(pos_id, gmax[0], f, gmin[2]); immVertex3f(pos_id, gmax[0], f, gmax[2]); + immVertex3f(pos_id, gmax[0], f, gmax[2]); immVertex3f(pos_id, gmin[0], f, gmax[2]); + immVertex3f(pos_id, gmin[0], f, gmax[2]); immVertex3f(pos_id, gmin[0], f, gmin[2]); + } + for (i = 1; i < res[2] - 1; ++i) { + float f = interpf(gmax[2], gmin[2], (float)i / (float)(res[2] - 1)); + immVertex3f(pos_id, gmin[0], gmin[1], f); immVertex3f(pos_id, gmax[0], gmin[1], f); + immVertex3f(pos_id, gmax[0], gmin[1], f); immVertex3f(pos_id, gmax[0], gmax[1], f); + immVertex3f(pos_id, gmax[0], gmax[1], f); immVertex3f(pos_id, gmin[0], gmax[1], f); + immVertex3f(pos_id, gmin[0], gmax[1], f); immVertex3f(pos_id, gmin[0], gmin[1], f); + } + immEnd(); + glDisable(GL_BLEND); } - glEnd(); - glDisable(GL_BLEND); - - glEnableClientState(GL_NORMAL_ARRAY); - if ((dflag & DRAW_CONSTCOLOR) == 0) - if (part->draw_col == PART_DRAW_COL_MAT) - glEnableClientState(GL_COLOR_ARRAY); + + immUnbindProgram(); } } } @@ -5584,27 +6468,17 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv cache = psys->childcache; for (a = 0; a < totchild; a++) { path = cache[a]; - glVertexPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->co); - if (1) { //ob_dt > OB_WIRE) { - glNormalPointer(GL_FLOAT, sizeof(ParticleCacheKey), path->vel); - if ((dflag & DRAW_CONSTCOLOR) == 0) { - if (part->draw_col == PART_DRAW_COL_MAT) { - glColorPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->col); - } - } + if (((dflag & DRAW_CONSTCOLOR) == 0) && (part->draw_col == PART_DRAW_COL_MAT)) { + draw_vertex_array(PRIM_LINE_STRIP, path->co, path->vel, path->col, sizeof(ParticleCacheKey), path->segments + 1, NULL); + } + else { + float color[4] = {0.0f, 0.0f, 0.0f, 1.0f}; + draw_vertex_array(PRIM_LINE_STRIP, path->co, path->vel, NULL, sizeof(ParticleCacheKey), path->segments + 1, color); } - - glDrawArrays(GL_LINE_STRIP, 0, path->segments + 1); } /* restore & clean up */ - if (1) { //ob_dt > OB_WIRE) { - if (part->draw_col == PART_DRAW_COL_MAT) - glDisableClientState(GL_COLOR_ARRAY); - GPU_basic_shader_bind(GPU_SHADER_USE_COLOR); - } - if (cdata2) { MEM_freeN(cdata2); cdata2 = NULL; @@ -5624,19 +6498,11 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv } } else if (pdd && ELEM(draw_as, 0, PART_DRAW_CIRC) == 0) { - glDisableClientState(GL_COLOR_ARRAY); - /* enable point data array */ if (pdd->vdata) { - glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(3, GL_FLOAT, 0, pdd->vdata); - } - else - glDisableClientState(GL_VERTEX_ARRAY); - - if ((dflag & DRAW_CONSTCOLOR) == 0) { if (select) { - UI_ThemeColor(TH_ACTIVE); + float color[4]; + UI_GetThemeColor4fv(TH_ACTIVE, color); if (part->draw_size) glPointSize(part->draw_size + 2); @@ -5645,48 +6511,39 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv glLineWidth(3.0); - draw_particle_arrays(draw_as, totpoint, ob_dt, 1); + draw_particle_arrays_new(draw_as, ob_dt, 1, pdd->vdata, NULL, NULL, totpoint, color); } - /* restore from select */ - glColor3fv(ma_col); - } - - glPointSize(part->draw_size ? part->draw_size : 2.0); - glLineWidth(1.0); + glPointSize(part->draw_size ? part->draw_size : 2.0); + glLineWidth(1.0); - /* enable other data arrays */ - - /* billboards are drawn this way */ - if (pdd->ndata && ob_dt > OB_WIRE) { - glEnableClientState(GL_NORMAL_ARRAY); - glNormalPointer(GL_FLOAT, 0, pdd->ndata); - GPU_basic_shader_colors(NULL, NULL, 0.0f, 1.0f); - GPU_basic_shader_bind(GPU_SHADER_LIGHTING | GPU_SHADER_USE_COLOR); - } - if ((dflag & DRAW_CONSTCOLOR) == 0) { - if (pdd->cdata) { - glEnableClientState(GL_COLOR_ARRAY); - glColorPointer(3, GL_FLOAT, 0, pdd->cdata); +#if 0 + /* enable other data arrays */ + /* billboards are drawn this way */ + if (pdd->ndata && ob_dt > OB_WIRE) { + GPU_basic_shader_colors(NULL, NULL, 0.0f, 1.0f); + GPU_basic_shader_bind(GPU_SHADER_LIGHTING | GPU_SHADER_USE_COLOR); } + if ((dflag & DRAW_CONSTCOLOR) == 0) { + if (pdd->cdata) { + glEnableClientState(GL_COLOR_ARRAY); + glColorPointer(3, GL_FLOAT, 0, pdd->cdata); + } + } +#endif + + draw_particle_arrays_new(draw_as, ob_dt, 0, pdd->vdata, pdd->ndata, pdd->cdata, totpoint, NULL); } - draw_particle_arrays(draw_as, totpoint, ob_dt, 0); pdd->flag |= PARTICLE_DRAW_DATA_UPDATED; pdd->totpoint = totpoint; } if (pdd && pdd->vedata) { - if ((dflag & DRAW_CONSTCOLOR) == 0) { - glDisableClientState(GL_COLOR_ARRAY); - cpack(0xC0C0C0); - } - - glVertexPointer(3, GL_FLOAT, 0, pdd->vedata); - - glDrawArrays(GL_LINES, 0, 2 * totve); + float color[4] = {0.75f, 0.75f, 0.75f, 1.0f}; + draw_vertex_array(PRIM_LINES, pdd->vedata, NULL, NULL, 0, 2 * totve, color); } glPolygonMode(GL_FRONT, polygonmode[0]); @@ -5695,9 +6552,6 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv /* 7. */ GPU_basic_shader_bind(GPU_SHADER_USE_COLOR); - glDisableClientState(GL_COLOR_ARRAY); - glDisableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_NORMAL_ARRAY); if (states) MEM_freeN(states); @@ -5720,15 +6574,15 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv pdd->ma_col = NULL; } - if ((base->flag & OB_FROMDUPLI) && (ob->flag & OB_FROMGROUP)) { - glLoadMatrixf(rv3d->viewmat); + if ((ob->flag & OB_FROMGROUP) != 0) { + gpuLoadMatrix(rv3d->viewmat); } } -static void draw_update_ptcache_edit(Scene *scene, Object *ob, PTCacheEdit *edit) +static void draw_update_ptcache_edit(Scene *scene, SceneLayer *sl, Object *ob, PTCacheEdit *edit) { if (edit->psys && edit->psys->flag & PSYS_HAIR_UPDATED) - PE_update_object(scene, ob, 0); + PE_update_object(scene, sl, ob, 0); /* create path and child path cache if it doesn't exist already */ if (edit->pathcache == NULL) @@ -5737,15 +6591,9 @@ static void draw_update_ptcache_edit(Scene *scene, Object *ob, PTCacheEdit *edit static void draw_ptcache_edit(Scene *scene, View3D *v3d, PTCacheEdit *edit) { - ParticleCacheKey **cache, *path, *pkey; - PTCacheEditPoint *point; - PTCacheEditKey *key; ParticleEditSettings *pset = PE_settings(scene); - int i, k, totpoint = edit->totpoint, timed = (pset->flag & PE_FADE_TIME) ? pset->fade_frames : 0; - int totkeys = 1; - float sel_col[3]; - float nosel_col[3]; - float *pathcol = NULL, *pcol; + const int totpoint = edit->totpoint; + const bool timed = (pset->flag & PE_FADE_TIME) ? pset->fade_frames : false; if (edit->pathcache == NULL) return; @@ -5757,50 +6605,71 @@ static void draw_ptcache_edit(Scene *scene, View3D *v3d, PTCacheEdit *edit) glDisable(GL_DEPTH_TEST); /* get selection theme colors */ + float sel_col[3], nosel_col[3]; UI_GetThemeColor3fv(TH_VERTEX_SELECT, sel_col); UI_GetThemeColor3fv(TH_VERTEX, nosel_col); /* draw paths */ - totkeys = (*edit->pathcache)->segments + 1; + const int totkeys = (*edit->pathcache)->segments + 1; glEnable(GL_BLEND); - pathcol = MEM_callocN(totkeys * 4 * sizeof(float), "particle path color data"); - - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_COLOR_ARRAY); + float *pathcol = MEM_callocN(totkeys * 4 * sizeof(float), "particle path color data"); if (pset->brushtype == PE_BRUSH_WEIGHT) glLineWidth(2.0f); - cache = edit->pathcache; + ParticleCacheKey **cache = edit->pathcache; + PTCacheEditPoint *point; + int i; + for (i = 0, point = edit->points; i < totpoint; i++, point++) { - path = cache[i]; - glVertexPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->co); + ParticleCacheKey *path = cache[i]; + + VertexFormat format = {0}; + unsigned int pos_id, col_id, col_comp; + + col_comp = ((point->flag & PEP_HIDE) || timed) ? 4 : 3; + + pos_id = VertexFormat_add_attrib(&format, "pos", COMP_F32, 3, KEEP_FLOAT); + col_id = VertexFormat_add_attrib(&format, "color", COMP_F32, col_comp, KEEP_FLOAT); + + VertexBuffer *vbo = VertexBuffer_create_with_format(&format); + VertexBuffer_allocate_data(vbo, path->segments + 1); + + VertexBuffer_fill_attrib_stride(vbo, pos_id, sizeof(ParticleCacheKey), path->co); + + float *pcol = pathcol; if (point->flag & PEP_HIDE) { - for (k = 0, pcol = pathcol; k < totkeys; k++, pcol += 4) { + for (int k = 0; k < totkeys; k++, pcol += 4) { copy_v3_v3(pcol, path->col); pcol[3] = 0.25f; } - glColorPointer(4, GL_FLOAT, 4 * sizeof(float), pathcol); + VertexBuffer_fill_attrib(vbo, col_id, pathcol); } else if (timed) { - for (k = 0, pcol = pathcol, pkey = path; k < totkeys; k++, pkey++, pcol += 4) { + ParticleCacheKey *pkey = path; + for (int k = 0; k < totkeys; k++, pkey++, pcol += 4) { copy_v3_v3(pcol, pkey->col); pcol[3] = 1.0f - fabsf((float)(CFRA) -pkey->time) / (float)pset->fade_frames; } - glColorPointer(4, GL_FLOAT, 4 * sizeof(float), pathcol); + VertexBuffer_fill_attrib(vbo, col_id, pathcol); + } + else { + /* FIXME: shader wants 4 color components but the cache only contains ParticleCacheKey + * So alpha is random */ + VertexBuffer_fill_attrib_stride(vbo, col_id, sizeof(ParticleCacheKey), path->col); } - else - glColorPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->col); - glDrawArrays(GL_LINE_STRIP, 0, path->segments + 1); + Batch *batch = Batch_create(PRIM_LINE_STRIP, vbo, NULL); + Batch_set_builtin_program(batch, GPU_SHADER_3D_SMOOTH_COLOR); + Batch_draw(batch); + Batch_discard_all(batch); } - if (pathcol) { MEM_freeN(pathcol); pathcol = pcol = NULL; } - + if (pathcol) { MEM_freeN(pathcol); pathcol = NULL; } /* draw edit vertices */ if (pset->selectmode != SCE_SELECT_PATH) { @@ -5811,6 +6680,10 @@ static void draw_ptcache_edit(Scene *scene, View3D *v3d, PTCacheEdit *edit) float *cd = NULL, *cdata = NULL; int totkeys_visible = 0; + VertexFormat format = {0}; + unsigned int pos_id = VertexFormat_add_attrib(&format, "pos", COMP_F32, 3, KEEP_FLOAT); + unsigned int col_id = VertexFormat_add_attrib(&format, "color", COMP_F32, (timed ? 4 : 3), KEEP_FLOAT); + for (i = 0, point = edit->points; i < totpoint; i++, point++) if (!(point->flag & PEP_HIDE)) totkeys_visible += point->totkey; @@ -5825,7 +6698,8 @@ static void draw_ptcache_edit(Scene *scene, View3D *v3d, PTCacheEdit *edit) if (point->flag & PEP_HIDE) continue; - for (k = 0, key = point->keys; k < point->totkey; k++, key++) { + PTCacheEditKey *key = point->keys; + for (int k = 0; k < point->totkey; k++, key++) { if (pd) { copy_v3_v3(pd, key->co); pd += 3; @@ -5850,14 +6724,20 @@ static void draw_ptcache_edit(Scene *scene, View3D *v3d, PTCacheEdit *edit) if (point->flag & PEP_HIDE || point->totkey == 0) continue; + VertexBuffer *vbo = VertexBuffer_create_with_format(&format); + VertexBuffer_allocate_data(vbo, point->totkey); + if (point->keys->flag & PEK_USE_WCO) - glVertexPointer(3, GL_FLOAT, sizeof(PTCacheEditKey), point->keys->world_co); + VertexBuffer_fill_attrib_stride(vbo, pos_id, sizeof(PTCacheEditKey), point->keys->world_co); else - glVertexPointer(3, GL_FLOAT, 3 * sizeof(float), pd); + VertexBuffer_fill_attrib(vbo, pos_id, pd); - glColorPointer((timed ? 4 : 3), GL_FLOAT, (timed ? 4 : 3) * sizeof(float), cd); + VertexBuffer_fill_attrib(vbo, col_id, cd); - glDrawArrays(GL_POINTS, 0, point->totkey); + Batch *batch = Batch_create(PRIM_POINTS, vbo, NULL); + Batch_set_builtin_program(batch, GPU_SHADER_3D_SMOOTH_COLOR); + Batch_draw(batch); + Batch_discard_all(batch); pd += pd ? 3 * point->totkey : 0; cd += (timed ? 4 : 3) * point->totkey; @@ -5866,23 +6746,30 @@ static void draw_ptcache_edit(Scene *scene, View3D *v3d, PTCacheEdit *edit) if (cdata) { MEM_freeN(cdata); cd = cdata = NULL; } } else if (pset->selectmode == SCE_SELECT_END) { - glBegin(GL_POINTS); + VertexFormat *format = immVertexFormat(); + unsigned int pos_id = VertexFormat_add_attrib(format, "pos", COMP_F32, 3, KEEP_FLOAT); + unsigned int col_id = VertexFormat_add_attrib(format, "color", COMP_F32, 3, KEEP_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR); + immBeginAtMost(PRIM_POINTS, totpoint); for (i = 0, point = edit->points; i < totpoint; i++, point++) { if ((point->flag & PEP_HIDE) == 0 && point->totkey) { - key = point->keys + point->totkey - 1; - glColor3fv((key->flag & PEK_SELECT) ? sel_col : nosel_col); + PTCacheEditKey *key = point->keys + point->totkey - 1; + if ((key->flag & PEK_SELECT) != 0) { + immAttrib3fv(col_id, sel_col); + } + else { + immAttrib3fv(col_id, nosel_col); + } /* has to be like this.. otherwise selection won't work, have try glArrayElement later..*/ - glVertex3fv((key->flag & PEK_USE_WCO) ? key->world_co : key->co); + immVertex3fv(pos_id, (key->flag & PEK_USE_WCO) ? key->world_co : key->co); } } - glEnd(); + immEnd(); + immUnbindProgram(); } } glDisable(GL_BLEND); - glDisableClientState(GL_COLOR_ARRAY); - glDisableClientState(GL_NORMAL_ARRAY); - glDisableClientState(GL_VERTEX_ARRAY); if (v3d->zbuf) glEnable(GL_DEPTH_TEST); } @@ -5895,130 +6782,137 @@ static void ob_draw_RE_motion(float com[3], float rotscale[3][3], float itw, flo float tw = itw * drw_size; float th = ith * drw_size; - glBegin(GL_LINES); + VertexFormat *format = immVertexFormat(); + unsigned int pos = VertexFormat_add_attrib(format, "pos", COMP_F32, 3, KEEP_FLOAT); + unsigned int col = VertexFormat_add_attrib(format, "color", COMP_U8, 4, NORMALIZE_INT_TO_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR); + + immBegin(PRIM_LINES, 30); - glColor4ub(0x7F, 0x00, 0x00, 155); + immAttrib4ub(col, 0x7F, 0x00, 0x00, 155); root[1] = root[2] = 0.0f; root[0] = -drw_size; mul_m3_v3(tr, root); add_v3_v3(root, com); - glVertex3fv(root); + immVertex3fv(pos, root); tip[1] = tip[2] = 0.0f; tip[0] = drw_size; mul_m3_v3(tr, tip); add_v3_v3(tip, com); - glVertex3fv(tip); + immVertex3fv(pos, tip); root[1] = 0.0f; root[2] = tw; root[0] = th; mul_m3_v3(tr, root); add_v3_v3(root, com); - glVertex3fv(root); - glVertex3fv(tip); + immVertex3fv(pos, root); + immVertex3fv(pos, tip); root[1] = 0.0f; root[2] = -tw; root[0] = th; mul_m3_v3(tr, root); add_v3_v3(root, com); - glVertex3fv(root); - glVertex3fv(tip); + immVertex3fv(pos, root); + immVertex3fv(pos, tip); root[1] = tw; root[2] = 0.0f; root[0] = th; mul_m3_v3(tr, root); add_v3_v3(root, com); - glVertex3fv(root); - glVertex3fv(tip); + immVertex3fv(pos, root); + immVertex3fv(pos, tip); root[1] = -tw; root[2] = 0.0f; root[0] = th; mul_m3_v3(tr, root); add_v3_v3(root, com); - glVertex3fv(root); - glVertex3fv(tip); + immVertex3fv(pos, root); + immVertex3fv(pos, tip); - glColor4ub(0x00, 0x7F, 0x00, 155); + immAttrib4ub(col, 0x00, 0x7F, 0x00, 155); root[0] = root[2] = 0.0f; root[1] = -drw_size; mul_m3_v3(tr, root); add_v3_v3(root, com); - glVertex3fv(root); + immVertex3fv(pos, root); tip[0] = tip[2] = 0.0f; tip[1] = drw_size; mul_m3_v3(tr, tip); add_v3_v3(tip, com); - glVertex3fv(tip); + immVertex3fv(pos, tip); root[0] = 0.0f; root[2] = tw; root[1] = th; mul_m3_v3(tr, root); add_v3_v3(root, com); - glVertex3fv(root); - glVertex3fv(tip); + immVertex3fv(pos, root); + immVertex3fv(pos, tip); root[0] = 0.0f; root[2] = -tw; root[1] = th; mul_m3_v3(tr, root); add_v3_v3(root, com); - glVertex3fv(root); - glVertex3fv(tip); + immVertex3fv(pos, root); + immVertex3fv(pos, tip); root[0] = tw; root[2] = 0.0f; root[1] = th; mul_m3_v3(tr, root); add_v3_v3(root, com); - glVertex3fv(root); - glVertex3fv(tip); + immVertex3fv(pos, root); + immVertex3fv(pos, tip); root[0] = -tw; root[2] = 0.0f; root[1] = th; mul_m3_v3(tr, root); add_v3_v3(root, com); - glVertex3fv(root); - glVertex3fv(tip); + immVertex3fv(pos, root); + immVertex3fv(pos, tip); - glColor4ub(0x00, 0x00, 0x7F, 155); + immAttrib4ub(col, 0x00, 0x00, 0x7F, 155); root[0] = root[1] = 0.0f; root[2] = -drw_size; mul_m3_v3(tr, root); add_v3_v3(root, com); - glVertex3fv(root); + immVertex3fv(pos, root); tip[0] = tip[1] = 0.0f; tip[2] = drw_size; mul_m3_v3(tr, tip); add_v3_v3(tip, com); - glVertex3fv(tip); + immVertex3fv(pos, tip); root[0] = 0.0f; root[1] = tw; root[2] = th; mul_m3_v3(tr, root); add_v3_v3(root, com); - glVertex3fv(root); - glVertex3fv(tip); + immVertex3fv(pos, root); + immVertex3fv(pos, tip); root[0] = 0.0f; root[1] = -tw; root[2] = th; mul_m3_v3(tr, root); add_v3_v3(root, com); - glVertex3fv(root); - glVertex3fv(tip); + immVertex3fv(pos, root); + immVertex3fv(pos, tip); root[0] = tw; root[1] = 0.0f; root[2] = th; mul_m3_v3(tr, root); add_v3_v3(root, com); - glVertex3fv(root); - glVertex3fv(tip); + immVertex3fv(pos, root); + immVertex3fv(pos, tip); root[0] = -tw; root[1] = 0.0f; root[2] = th; mul_m3_v3(tr, root); add_v3_v3(root, com); - glVertex3fv(root); - glVertex3fv(tip); + immVertex3fv(pos, root); + immVertex3fv(pos, tip); - glEnd(); + immEnd(); + + immUnbindProgram(); } /* place to add drawers */ @@ -6027,7 +6921,7 @@ static void drawhandlesN(Nurb *nu, const char sel, const bool hide_handles) { if (nu->hide || hide_handles) return; - if (nu->type == CU_BEZIER) { + if (nu->type == CU_BEZIER && nu->pntsu > 0) { const float *fp; @@ -6040,9 +6934,14 @@ static void drawhandlesN(Nurb *nu, const char sel, const bool hide_handles) UI_GetThemeColor3ubv(basecol + a, handle_cols[a]); } + VertexFormat *format = immVertexFormat(); + unsigned int pos = VertexFormat_add_attrib(format, "pos", COMP_F32, 3, KEEP_FLOAT); + unsigned int col = VertexFormat_add_attrib(format, "color", COMP_U8, 3, NORMALIZE_INT_TO_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR); + glLineWidth(1.0f); - glBegin(GL_LINES); + immBeginAtMost(PRIM_LINES, nu->pntsu * 4); BezTriple *bezt = nu->bezt; int a = nu->pntsu; @@ -6051,33 +6950,35 @@ static void drawhandlesN(Nurb *nu, const char sel, const bool hide_handles) if ((bezt->f2 & SELECT) == sel) { fp = bezt->vec[0]; - glColor3ubv(handle_cols[MIN2(bezt->h1, TH_HANDLE_COL_TOT - 1)]); - glVertex3fv(fp); - glVertex3fv(fp + 3); + immAttrib3ubv(col, handle_cols[MIN2(bezt->h1, TH_HANDLE_COL_TOT - 1)]); + immVertex3fv(pos, fp); + immVertex3fv(pos, fp + 3); - glColor3ubv(handle_cols[MIN2(bezt->h2, TH_HANDLE_COL_TOT - 1)]); - glVertex3fv(fp + 3); - glVertex3fv(fp + 6); + immAttrib3ubv(col, handle_cols[MIN2(bezt->h2, TH_HANDLE_COL_TOT - 1)]); + immVertex3fv(pos, fp + 3); + immVertex3fv(pos, fp + 6); } else if ((bezt->f1 & SELECT) == sel) { fp = bezt->vec[0]; - glColor3ubv(handle_cols[MIN2(bezt->h1, TH_HANDLE_COL_TOT - 1)]); - glVertex3fv(fp); - glVertex3fv(fp + 3); + immAttrib3ubv(col, handle_cols[MIN2(bezt->h1, TH_HANDLE_COL_TOT - 1)]); + immVertex3fv(pos, fp); + immVertex3fv(pos, fp + 3); } else if ((bezt->f3 & SELECT) == sel) { fp = bezt->vec[1]; - glColor3ubv(handle_cols[MIN2(bezt->h2, TH_HANDLE_COL_TOT - 1)]); - glVertex3fv(fp); - glVertex3fv(fp + 3); + immAttrib3ubv(col, handle_cols[MIN2(bezt->h2, TH_HANDLE_COL_TOT - 1)]); + immVertex3fv(pos, fp); + immVertex3fv(pos, fp + 3); } } bezt++; } - glEnd(); + immEnd(); + + immUnbindProgram(); #undef TH_HANDLE_COL_TOT @@ -6088,153 +6989,196 @@ static void drawhandlesN_active(Nurb *nu) { if (nu->hide) return; - UI_ThemeColor(TH_ACTIVE_SPLINE); - glLineWidth(2); - - glBegin(GL_LINES); + if (nu->type == CU_BEZIER && nu->pntsu > 0) { + unsigned int pos = VertexFormat_add_attrib(immVertexFormat(), "pos", COMP_F32, 3, KEEP_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immUniformThemeColor(TH_ACTIVE_SPLINE); + glLineWidth(2.0f); - if (nu->type == CU_BEZIER) { + immBeginAtMost(PRIM_LINES, nu->pntsu * 4); BezTriple *bezt = nu->bezt; int a = nu->pntsu; while (a--) { if (bezt->hide == 0) { const float *fp = bezt->vec[0]; - glVertex3fv(fp); - glVertex3fv(fp + 3); + immVertex3fv(pos, fp); + immVertex3fv(pos, fp + 3); - glVertex3fv(fp + 3); - glVertex3fv(fp + 6); + immVertex3fv(pos, fp + 3); + immVertex3fv(pos, fp + 6); } bezt++; } + immEnd(); + immUnbindProgram(); } - glEnd(); - - glColor3ub(0, 0, 0); } -static void drawvertsN(Nurb *nu, const char sel, const bool hide_handles, const void *vert) +static void drawvertsN(const Nurb *nurb, const bool hide_handles, const void *vert) { - if (nu->hide) return; + const Nurb *nu; + + // just quick guesstimate of how many verts to draw + int count = 0; + for (nu = nurb; nu; nu = nu->next) { + if (!nu->hide) { + if (nu->type == CU_BEZIER) { + count += nu->pntsu * 3; + } + else { + count += nu->pntsu * nu->pntsv; + } + } + } + if (count == 0) return; - const int color = sel ? TH_VERTEX_SELECT : TH_VERTEX; + VertexFormat *format = immVertexFormat(); + unsigned int pos = VertexFormat_add_attrib(format, "pos", COMP_F32, 3, KEEP_FLOAT); + unsigned int color = VertexFormat_add_attrib(format, "color", COMP_U8, 3, NORMALIZE_INT_TO_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR); - UI_ThemeColor(color); + unsigned char vert_color[3]; + unsigned char vert_color_select[3]; + unsigned char vert_color_active[3]; + UI_GetThemeColor3ubv(TH_VERTEX, vert_color); + UI_GetThemeColor3ubv(TH_VERTEX_SELECT, vert_color_select); + UI_GetThemeColor3ubv(TH_ACTIVE_VERT, vert_color_active); glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE)); + + immBeginAtMost(PRIM_POINTS, count); - glBegin(GL_POINTS); - - if (nu->type == CU_BEZIER) { + for (nu = nurb; nu; nu = nu->next) { - BezTriple *bezt = nu->bezt; - int a = nu->pntsu; - while (a--) { - if (bezt->hide == 0) { - if (sel == 1 && bezt == vert) { - UI_ThemeColor(TH_ACTIVE_VERT); + if (nu->hide) continue; - if (bezt->f2 & SELECT) glVertex3fv(bezt->vec[1]); - if (!hide_handles) { - if (bezt->f1 & SELECT) glVertex3fv(bezt->vec[0]); - if (bezt->f3 & SELECT) glVertex3fv(bezt->vec[2]); - } + if (nu->type == CU_BEZIER) { - UI_ThemeColor(color); - } - else if (hide_handles) { - if ((bezt->f2 & SELECT) == sel) glVertex3fv(bezt->vec[1]); - } - else { - if ((bezt->f1 & SELECT) == sel) glVertex3fv(bezt->vec[0]); - if ((bezt->f2 & SELECT) == sel) glVertex3fv(bezt->vec[1]); - if ((bezt->f3 & SELECT) == sel) glVertex3fv(bezt->vec[2]); + const BezTriple *bezt = nu->bezt; + int a = nu->pntsu; + while (a--) { + if (bezt->hide == 0) { + if (bezt == vert) { + immAttrib3ubv(color, bezt->f2 & SELECT ? vert_color_active : vert_color); + immVertex3fv(pos, bezt->vec[1]); + if (!hide_handles) { + immAttrib3ubv(color, bezt->f1 & SELECT ? vert_color_active : vert_color); + immVertex3fv(pos, bezt->vec[0]); + immAttrib3ubv(color, bezt->f3 & SELECT ? vert_color_active : vert_color); + immVertex3fv(pos, bezt->vec[2]); + } + } + else { + immAttrib3ubv(color, bezt->f2 & SELECT ? vert_color_select : vert_color); + immVertex3fv(pos, bezt->vec[1]); + if (!hide_handles) { + immAttrib3ubv(color, bezt->f1 & SELECT ? vert_color_select : vert_color); + immVertex3fv(pos, bezt->vec[0]); + immAttrib3ubv(color, bezt->f3 & SELECT ? vert_color_select : vert_color); + immVertex3fv(pos, bezt->vec[2]); + } + } } + bezt++; } - bezt++; } - } - else { - BPoint *bp = nu->bp; - int a = nu->pntsu * nu->pntsv; - while (a--) { - if (bp->hide == 0) { - if (bp == vert) { - UI_ThemeColor(TH_ACTIVE_VERT); - glVertex3fv(bp->vec); - UI_ThemeColor(color); - } - else { - if ((bp->f1 & SELECT) == sel) glVertex3fv(bp->vec); + else { + const BPoint *bp = nu->bp; + int a = nu->pntsu * nu->pntsv; + while (a--) { + if (bp->hide == 0) { + if (bp == vert) { + immAttrib3ubv(color, vert_color_active); + } + else { + immAttrib3ubv(color, bp->f1 & SELECT ? vert_color_select : vert_color); + } + immVertex3fv(pos, bp->vec); } + bp++; } - bp++; } } - - glEnd(); + + immEnd(); + immUnbindProgram(); } static void editnurb_draw_active_poly(Nurb *nu) { - UI_ThemeColor(TH_ACTIVE_SPLINE); - glLineWidth(2); + VertexFormat *format = immVertexFormat(); + unsigned int pos = VertexFormat_add_attrib(format, "pos", COMP_F32, 3, KEEP_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immUniformThemeColor(TH_ACTIVE_SPLINE); + + glLineWidth(2.0f); BPoint *bp = nu->bp; for (int b = 0; b < nu->pntsv; b++) { - if (nu->flagu & 1) glBegin(GL_LINE_LOOP); - else glBegin(GL_LINE_STRIP); + if (nu->pntsu >= 2) { + if (nu->flagu & 1) immBegin(PRIM_LINE_LOOP, nu->pntsu); + else immBegin(PRIM_LINE_STRIP, nu->pntsu); - for (int a = 0; a < nu->pntsu; a++, bp++) { - glVertex3fv(bp->vec); - } + for (int a = 0; a < nu->pntsu; a++, bp++) { + immVertex3fv(pos, bp->vec); + } - glEnd(); + immEnd(); + } } - glColor3ub(0, 0, 0); + immUnbindProgram(); } static void editnurb_draw_active_nurbs(Nurb *nu) { - UI_ThemeColor(TH_ACTIVE_SPLINE); - glLineWidth(2); - - glBegin(GL_LINES); - BPoint *bp = nu->bp; - for (int b = 0; b < nu->pntsv; b++) { - BPoint *bp1 = bp; - bp++; + if (nu->pntsv > 0) { + VertexFormat *format = immVertexFormat(); + unsigned int pos = VertexFormat_add_attrib(format, "pos", COMP_F32, 3, KEEP_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immUniformThemeColor(TH_ACTIVE_SPLINE); - for (int a = nu->pntsu - 1; a > 0; a--, bp++) { - if (bp->hide == 0 && bp1->hide == 0) { - glVertex3fv(bp->vec); - glVertex3fv(bp1->vec); - } - bp1 = bp; - } - } + glLineWidth(2.0f); + // just quick guesstimate of how many verts to draw + int count = (nu->pntsu - 1) * nu->pntsv * 2; + if (nu->pntsv > 1) count += (nu->pntsv - 1) * nu->pntsu * 2; + if (count < 2) return; - if (nu->pntsv > 1) { /* surface */ + immBeginAtMost(PRIM_LINES, count); + BPoint *bp = nu->bp; + for (int b = 0; b < nu->pntsv; b++) { + BPoint *bp1 = bp; + bp++; - int ofs = nu->pntsu; - for (int b = 0; b < nu->pntsu; b++) { - BPoint *bp1 = nu->bp + b; - bp = bp1 + ofs; - for (int a = nu->pntsv - 1; a > 0; a--, bp += ofs) { + for (int a = nu->pntsu - 1; a > 0; a--, bp++) { if (bp->hide == 0 && bp1->hide == 0) { - glVertex3fv(bp->vec); - glVertex3fv(bp1->vec); + immVertex3fv(pos, bp->vec); + immVertex3fv(pos, bp1->vec); } bp1 = bp; } } - } - glEnd(); + if (nu->pntsv > 1) { /* surface */ + int ofs = nu->pntsu; + for (int b = 0; b < nu->pntsu; b++) { + BPoint *bp1 = nu->bp + b; + bp = bp1 + ofs; + for (int a = nu->pntsv - 1; a > 0; a--, bp += ofs) { + if (bp->hide == 0 && bp1->hide == 0) { + immVertex3fv(pos, bp->vec); + immVertex3fv(pos, bp1->vec); + } + bp1 = bp; + } + } + } + + immEnd(); - glColor3ub(0, 0, 0); + immUnbindProgram(); + } } static void draw_editnurb_splines(Object *ob, Nurb *nurb, const bool sel) @@ -6242,6 +7186,9 @@ static void draw_editnurb_splines(Object *ob, Nurb *nurb, const bool sel) BPoint *bp, *bp1; int a, b; Curve *cu = ob->data; + VertexFormat *format; + unsigned int pos, col; + unsigned char color[3]; int index = 0; Nurb *nu = nurb; @@ -6249,35 +7196,55 @@ static void draw_editnurb_splines(Object *ob, Nurb *nurb, const bool sel) if (nu->hide == 0) { switch (nu->type) { case CU_POLY: + { if (!sel && index == cu->actnu) { /* we should draw active spline highlight below everything */ editnurb_draw_active_poly(nu); } - glLineWidth(1); + format = immVertexFormat(); + pos = VertexFormat_add_attrib(format, "pos", COMP_F32, 3, KEEP_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + + glLineWidth(1.0f); - UI_ThemeColor(TH_NURB_ULINE); + immUniformThemeColor(TH_NURB_ULINE); bp = nu->bp; for (b = 0; b < nu->pntsv; b++) { - if (nu->flagu & 1) glBegin(GL_LINE_LOOP); - else glBegin(GL_LINE_STRIP); + if (nu->pntsu >= 2) { + if (nu->flagu & 1) immBegin(PRIM_LINE_LOOP, nu->pntsu); + else immBegin(PRIM_LINE_STRIP, nu->pntsu); - for (a = 0; a < nu->pntsu; a++, bp++) { - glVertex3fv(bp->vec); - } + for (a = 0; a < nu->pntsu; a++, bp++) { + immVertex3fv(pos, bp->vec); + } - glEnd(); + immEnd(); + } } + immUnbindProgram(); break; + } case CU_NURBS: + { if (!sel && index == cu->actnu) { /* we should draw active spline highlight below everything */ editnurb_draw_active_nurbs(nu); } - glLineWidth(1); + format = immVertexFormat(); + pos = VertexFormat_add_attrib(format, "pos", COMP_F32, 3, KEEP_FLOAT); + col = VertexFormat_add_attrib(format, "color", COMP_U8, 3, NORMALIZE_INT_TO_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR); + + // just quick guesstimate of how many verts to draw + int count = (nu->pntsu - 1) * nu->pntsv * 2; + if (nu->pntsv > 1) count += (nu->pntsv - 1) * nu->pntsu * 2; + if (count < 2) return; - glBegin(GL_LINES); + glLineWidth(1.0f); + + immBeginAtMost(PRIM_LINES, count); bp = nu->bp; for (b = 0; b < nu->pntsv; b++) { @@ -6287,10 +7254,10 @@ static void draw_editnurb_splines(Object *ob, Nurb *nurb, const bool sel) if (bp->hide == 0 && bp1->hide == 0) { if (sel) { if ((bp->f1 & SELECT) && (bp1->f1 & SELECT)) { - UI_ThemeColor(TH_NURB_SEL_ULINE); - - glVertex3fv(bp->vec); - glVertex3fv(bp1->vec); + UI_GetThemeColor3ubv(TH_NURB_SEL_ULINE, color); + immAttrib3ubv(col, color); + immVertex3fv(pos, bp->vec); + immVertex3fv(pos, bp1->vec); } } else { @@ -6298,10 +7265,10 @@ static void draw_editnurb_splines(Object *ob, Nurb *nurb, const bool sel) /* pass */ } else { - UI_ThemeColor(TH_NURB_ULINE); - - glVertex3fv(bp->vec); - glVertex3fv(bp1->vec); + UI_GetThemeColor3ubv(TH_NURB_ULINE, color); + immAttrib3ubv(col, color); + immVertex3fv(pos, bp->vec); + immVertex3fv(pos, bp1->vec); } } } @@ -6318,10 +7285,10 @@ static void draw_editnurb_splines(Object *ob, Nurb *nurb, const bool sel) if (bp->hide == 0 && bp1->hide == 0) { if (sel) { if ((bp->f1 & SELECT) && (bp1->f1 & SELECT)) { - UI_ThemeColor(TH_NURB_SEL_VLINE); - - glVertex3fv(bp->vec); - glVertex3fv(bp1->vec); + UI_GetThemeColor3ubv(TH_NURB_SEL_VLINE, color); + immAttrib3ubv(col, color); + immVertex3fv(pos, bp->vec); + immVertex3fv(pos, bp1->vec); } } else { @@ -6329,10 +7296,10 @@ static void draw_editnurb_splines(Object *ob, Nurb *nurb, const bool sel) /* pass */ } else { - UI_ThemeColor(TH_NURB_VLINE); - - glVertex3fv(bp->vec); - glVertex3fv(bp1->vec); + UI_GetThemeColor3ubv(TH_NURB_VLINE, color); + immAttrib3ubv(col, color); + immVertex3fv(pos, bp->vec); + immVertex3fv(pos, bp1->vec); } } } @@ -6340,9 +7307,10 @@ static void draw_editnurb_splines(Object *ob, Nurb *nurb, const bool sel) } } } - - glEnd(); + immEnd(); + immUnbindProgram(); break; + } } } @@ -6352,8 +7320,8 @@ static void draw_editnurb_splines(Object *ob, Nurb *nurb, const bool sel) } static void draw_editnurb( - Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, Nurb *nurb, - const char dt, const short dflag, const unsigned char ob_wire_col[4]) + Scene *scene, SceneLayer *sl, View3D *v3d, RegionView3D *rv3d, Base *base, Nurb *nurb, + const char dt, const short dflag, const unsigned char UNUSED(ob_wire_col[4])) { ToolSettings *ts = scene->toolsettings; Object *ob = base->object; @@ -6365,9 +7333,8 @@ static void draw_editnurb( /* DispList */ UI_GetThemeColor3ubv(TH_WIRE_EDIT, wire_col); - glColor3ubv(wire_col); - drawDispList(scene, v3d, rv3d, base, dt, dflag, ob_wire_col); + drawDispList(scene, sl, v3d, rv3d, base, dt, dflag, wire_col); /* for shadows only show solid faces */ if (v3d->flag2 & V3D_RENDER_SHADOW) @@ -6391,78 +7358,108 @@ static void draw_editnurb( for (nu = nurb; nu; nu = nu->next) { if (nu->type == CU_BEZIER && (cu->drawflag & CU_HIDE_HANDLES) == 0) drawhandlesN(nu, 1, hide_handles); - drawvertsN(nu, 0, hide_handles, NULL); } if (v3d->zbuf) glDepthFunc(GL_LEQUAL); - glColor3ubv(wire_col); - /* direction vectors for 3d curve paths * when at its lowest, don't render normals */ if ((cu->flag & CU_3D) && (ts->normalsize > 0.0015f) && (cu->drawflag & CU_HIDE_NORMALS) == 0) { BevList *bl; + + VertexFormat *format = immVertexFormat(); + unsigned int pos = VertexFormat_add_attrib(format, "pos", COMP_F32, 3, KEEP_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immUniformThemeColor(TH_WIRE_EDIT); + glLineWidth(1.0f); + + int count = 0; + int count_used = 0; for (bl = ob->curve_cache->bev.first, nu = nurb; nu && bl; bl = bl->next, nu = nu->next) { - BevPoint *bevp = bl->bevpoints; int nr = bl->nr; int skip = nu->resolu / 16; - + +#if 0 while (nr-- > 0) { /* accounts for empty bevel lists */ - const float fac = bevp->radius * ts->normalsize; - float vec_a[3]; /* Offset perpendicular to the curve */ - float vec_b[3]; /* Delta along the curve */ + count += 4; + nr -= skip; + } +#else + /* Same as loop above */ + count += 4 * max_ii((nr + max_ii(skip - 1, 0)) / (skip + 1), 0); +#endif + } - vec_a[0] = fac; - vec_a[1] = 0.0f; - vec_a[2] = 0.0f; - - mul_qt_v3(bevp->quat, vec_a); - madd_v3_v3fl(vec_a, bevp->dir, -fac); + if (count > 2) { + immBegin(PRIM_LINES, count); + for (bl = ob->curve_cache->bev.first, nu = nurb; nu && bl; bl = bl->next, nu = nu->next) { + BevPoint *bevp = bl->bevpoints; + int nr = bl->nr; + int skip = nu->resolu / 16; - reflect_v3_v3v3(vec_b, vec_a, bevp->dir); - negate_v3(vec_b); + while (nr-- > 0) { /* accounts for empty bevel lists */ + const float fac = bevp->radius * ts->normalsize; + float vec_a[3]; /* Offset perpendicular to the curve */ + float vec_b[3]; /* Delta along the curve */ - add_v3_v3(vec_a, bevp->vec); - add_v3_v3(vec_b, bevp->vec); + vec_a[0] = fac; + vec_a[1] = 0.0f; + vec_a[2] = 0.0f; + + mul_qt_v3(bevp->quat, vec_a); + madd_v3_v3fl(vec_a, bevp->dir, -fac); - glBegin(GL_LINE_STRIP); - glVertex3fv(vec_a); - glVertex3fv(bevp->vec); - glVertex3fv(vec_b); - glEnd(); - - bevp += skip + 1; - nr -= skip; + reflect_v3_v3v3(vec_b, vec_a, bevp->dir); + negate_v3(vec_b); + + add_v3_v3(vec_a, bevp->vec); + add_v3_v3(vec_b, bevp->vec); + + immVertex3fv(pos, vec_a); + immVertex3fv(pos, bevp->vec); + immVertex3fv(pos, bevp->vec); + immVertex3fv(pos, vec_b); + + bevp += skip + 1; + nr -= skip; + count_used += 4; + } } + BLI_assert(count == count_used); + UNUSED_VARS_NDEBUG(count_used); + + immEnd(); } + immUnbindProgram(); } - if (v3d->zbuf) glDepthFunc(GL_ALWAYS); - - for (nu = nurb; nu; nu = nu->next) { - drawvertsN(nu, 1, hide_handles, vert); - } - - if (v3d->zbuf) glDepthFunc(GL_LEQUAL); + if (v3d->zbuf) glDisable(GL_DEPTH_TEST); + + drawvertsN(nurb, hide_handles, vert); + + if (v3d->zbuf) glEnable(GL_DEPTH_TEST); } static void draw_editfont_textcurs(RegionView3D *rv3d, float textcurs[4][2]) { - cpack(0); + unsigned int pos = VertexFormat_add_attrib(immVertexFormat(), "pos", COMP_F32, 2, KEEP_FLOAT); ED_view3d_polygon_offset(rv3d, -1.0); set_inverted_drawing(1); - glBegin(GL_QUADS); - glVertex2fv(textcurs[0]); - glVertex2fv(textcurs[1]); - glVertex2fv(textcurs[2]); - glVertex2fv(textcurs[3]); - glEnd(); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + imm_cpack(0); + immBegin(PRIM_TRIANGLE_FAN, 4); + immVertex2fv(pos, textcurs[0]); + immVertex2fv(pos, textcurs[1]); + immVertex2fv(pos, textcurs[2]); + immVertex2fv(pos, textcurs[3]); + immEnd(); set_inverted_drawing(0); ED_view3d_polygon_offset(rv3d, 0.0); + immUnbindProgram(); } -static void draw_editfont(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, +static void draw_editfont(Scene *scene, SceneLayer *sl, View3D *v3d, RegionView3D *rv3d, Base *base, const char dt, const short dflag, const unsigned char ob_wire_col[4]) { Object *ob = base->object; @@ -6473,17 +7470,19 @@ static void draw_editfont(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *b draw_editfont_textcurs(rv3d, ef->textcurs); if (cu->flag & CU_FAST) { - cpack(0xFFFFFF); + imm_cpack(0xFFFFFF); set_inverted_drawing(1); - drawDispList(scene, v3d, rv3d, base, OB_WIRE, dflag, ob_wire_col); + drawDispList(scene, sl, v3d, rv3d, base, OB_WIRE, dflag, ob_wire_col); set_inverted_drawing(0); } else { - drawDispList(scene, v3d, rv3d, base, dt, dflag, ob_wire_col); + drawDispList(scene, sl, v3d, rv3d, base, dt, dflag, ob_wire_col); } if (cu->linewidth != 0.0f) { - UI_ThemeColor(TH_WIRE_EDIT); + unsigned int pos = VertexFormat_add_attrib(immVertexFormat(), "pos", COMP_F32, 2, KEEP_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immUniformThemeColor(TH_WIRE_EDIT); copy_v3_v3(vec1, ob->orig); copy_v3_v3(vec2, ob->orig); vec1[0] += cu->linewidth; @@ -6491,31 +7490,35 @@ static void draw_editfont(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *b vec1[1] += cu->linedist * cu->fsize; vec2[1] -= cu->lines * cu->linedist * cu->fsize; setlinestyle(3); - glBegin(GL_LINES); - glVertex2fv(vec1); - glVertex2fv(vec2); - glEnd(); + immBegin(PRIM_LINES, 2); + immVertex2fv(pos, vec1); + immVertex2fv(pos, vec2); + immEnd(); setlinestyle(0); + immUnbindProgram(); } setlinestyle(3); for (int i = 0; i < cu->totbox; i++) { if (cu->tb[i].w != 0.0f) { - UI_ThemeColor(i == (cu->actbox - 1) ? TH_ACTIVE : TH_WIRE); + unsigned int pos = VertexFormat_add_attrib(immVertexFormat(), "pos", COMP_F32, 3, KEEP_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immUniformThemeColor(i == (cu->actbox - 1) ? TH_ACTIVE : TH_WIRE); vec1[0] = cu->xof + cu->tb[i].x; vec1[1] = cu->yof + cu->tb[i].y + cu->fsize; vec1[2] = 0.001; - glBegin(GL_LINE_STRIP); - glVertex3fv(vec1); + immBegin(PRIM_LINE_STRIP, 5); + immVertex3fv(pos, vec1); vec1[0] += cu->tb[i].w; - glVertex3fv(vec1); + immVertex3fv(pos, vec1); vec1[1] -= cu->tb[i].h; - glVertex3fv(vec1); + immVertex3fv(pos, vec1); vec1[0] -= cu->tb[i].w; - glVertex3fv(vec1); + immVertex3fv(pos, vec1); vec1[1] += cu->tb[i].h; - glVertex3fv(vec1); - glEnd(); + immVertex3fv(pos, vec1); + immEnd(); + immUnbindProgram(); } } setlinestyle(0); @@ -6524,7 +7527,9 @@ static void draw_editfont(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *b if (ef->selboxes && ef->selboxes_len) { float selboxw; - cpack(0xffffff); + unsigned int pos = VertexFormat_add_attrib(immVertexFormat(), "pos", COMP_F32, 3, KEEP_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + imm_cpack(0xffffff); set_inverted_drawing(1); for (int i = 0; i < ef->selboxes_len; i++) { EditFontSelBox *sb = &ef->selboxes[i]; @@ -6543,20 +7548,20 @@ static void draw_editfont(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *b /* fill in xy below */ tvec[2] = 0.001; - glBegin(GL_QUADS); + immBegin(PRIM_TRIANGLE_FAN, 4); if (sb->rot == 0.0f) { copy_v2_fl2(tvec, sb->x, sb->y); - glVertex3fv(tvec); + immVertex3fv(pos, tvec); copy_v2_fl2(tvec, sb->x + selboxw, sb->y); - glVertex3fv(tvec); + immVertex3fv(pos, tvec); copy_v2_fl2(tvec, sb->x + selboxw, sb->y + sb->h); - glVertex3fv(tvec); + immVertex3fv(pos, tvec); copy_v2_fl2(tvec, sb->x, sb->y + sb->h); - glVertex3fv(tvec); + immVertex3fv(pos, tvec); } else { float mat[2][2]; @@ -6564,84 +7569,87 @@ static void draw_editfont(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *b angle_to_mat2(mat, sb->rot); copy_v2_fl2(tvec, sb->x, sb->y); - glVertex3fv(tvec); + immVertex3fv(pos, tvec); copy_v2_fl2(tvec, selboxw, 0.0f); mul_m2v2(mat, tvec); add_v2_v2(tvec, &sb->x); - glVertex3fv(tvec); + immVertex3fv(pos, tvec); copy_v2_fl2(tvec, selboxw, sb->h); mul_m2v2(mat, tvec); add_v2_v2(tvec, &sb->x); - glVertex3fv(tvec); + immVertex3fv(pos, tvec); copy_v2_fl2(tvec, 0.0f, sb->h); mul_m2v2(mat, tvec); add_v2_v2(tvec, &sb->x); - glVertex3fv(tvec); + immVertex3fv(pos, tvec); } - glEnd(); + immEnd(); } set_inverted_drawing(0); + immUnbindProgram(); } } /* draw a sphere for use as an empty drawtype */ -static void draw_empty_sphere(float size) -{ - static GLuint displist = 0; - - if (displist == 0) { - GLUquadricObj *qobj; - - displist = glGenLists(1); - glNewList(displist, GL_COMPILE); - - glPushMatrix(); - - qobj = gluNewQuadric(); - gluQuadricDrawStyle(qobj, GLU_SILHOUETTE); - gluDisk(qobj, 0.0, 1, 16, 1); - - glRotatef(90, 0, 1, 0); - gluDisk(qobj, 0.0, 1, 16, 1); - - glRotatef(90, 1, 0, 0); - gluDisk(qobj, 0.0, 1, 16, 1); - - gluDeleteQuadric(qobj); - - glPopMatrix(); - glEndList(); - } - - glScalef(size, size, size); - glCallList(displist); - glScalef(1.0f / size, 1.0f / size, 1.0f / size); +static void draw_empty_sphere(float size, unsigned pos) +{ +#define NSEGMENTS 16 + /* a single ring of vertices */ + float p[NSEGMENTS][2]; + for (int i = 0; i < NSEGMENTS; ++i) { + float angle = 2 * M_PI * ((float)i / (float)NSEGMENTS); + p[i][0] = size * cosf(angle); + p[i][1] = size * sinf(angle); + } + + immBegin(PRIM_LINE_LOOP, NSEGMENTS); + for (int i = 0; i < NSEGMENTS; ++i) + immVertex3f(pos, p[i][0], p[i][1], 0.0f); + immEnd(); + immBegin(PRIM_LINE_LOOP, NSEGMENTS); + for (int i = 0; i < NSEGMENTS; ++i) + immVertex3f(pos, p[i][0], 0.0f, p[i][1]); + immEnd(); + immBegin(PRIM_LINE_LOOP, NSEGMENTS); + for (int i = 0; i < NSEGMENTS; ++i) + immVertex3f(pos, 0.0f, p[i][0], p[i][1]); + immEnd(); +#undef NSEGMENTS } /* draw a cone for use as an empty drawtype */ -static void draw_empty_cone(float size) +static void draw_empty_cone(float size, unsigned pos) { - const float radius = size; +#define NSEGMENTS 8 + /* a single ring of vertices */ + float p[NSEGMENTS][2]; + for (int i = 0; i < NSEGMENTS; ++i) { + float angle = 2 * M_PI * ((float)i / (float)NSEGMENTS); + p[i][0] = size * cosf(angle); + p[i][1] = size * sinf(angle); + } - GLUquadricObj *qobj = gluNewQuadric(); - gluQuadricDrawStyle(qobj, GLU_SILHOUETTE); - - glPushMatrix(); - - glScalef(radius, size * 2.0f, radius); - glRotatef(-90.0, 1.0, 0.0, 0.0); - gluCylinder(qobj, 1.0, 0.0, 1.0, 8, 1); + /* cone sides */ + immBegin(PRIM_LINES, NSEGMENTS * 2); + for (int i = 0; i < NSEGMENTS; ++i) { + immVertex3f(pos, 0.0f, 2.0f * size, 0.0f); + immVertex3f(pos, p[i][0], 0.0f, p[i][1]); + } + immEnd(); - glPopMatrix(); - - gluDeleteQuadric(qobj); + /* end ring */ + immBegin(PRIM_LINE_LOOP, NSEGMENTS); + for (int i = 0; i < NSEGMENTS; ++i) + immVertex3f(pos, p[i][0], 0.0f, p[i][1]); + immEnd(); +#undef NSEGMENTS } -static void drawspiral(const float cent[3], float rad, float tmat[4][4], int start) +static void drawspiral(unsigned int pos, const float cent[3], float rad, float tmat[4][4], int start) { float vec[3], vx[3], vy[3]; const float tot_inv = 1.0f / (float)CIRCLE_RESOL; @@ -6657,11 +7665,11 @@ static void drawspiral(const float cent[3], float rad, float tmat[4][4], int sta mul_v3_v3fl(vx, tmat[0], rad); mul_v3_v3fl(vy, tmat[1], rad); - glBegin(GL_LINE_STRIP); + immBegin(PRIM_LINE_STRIP, CIRCLE_RESOL + 1); if (inverse == 0) { copy_v3_v3(vec, cent); - glVertex3fv(vec); + immVertex3fv(pos, vec); for (a = 0; a < CIRCLE_RESOL; a++) { if (a + start >= CIRCLE_RESOL) @@ -6675,7 +7683,7 @@ static void drawspiral(const float cent[3], float rad, float tmat[4][4], int sta vec[1] = cent[1] + (x * vx[1] + y * vy[1]); vec[2] = cent[2] + (x * vx[2] + y * vy[2]); - glVertex3fv(vec); + immVertex3fv(pos, vec); } } else { @@ -6687,7 +7695,7 @@ static void drawspiral(const float cent[3], float rad, float tmat[4][4], int sta vec[1] = cent[1] + (x * vx[1] + y * vy[1]); vec[2] = cent[2] + (x * vx[2] + y * vy[2]); - glVertex3fv(vec); + immVertex3fv(pos, vec); for (a = 0; a < CIRCLE_RESOL; a++) { if (a + start >= CIRCLE_RESOL) @@ -6700,78 +7708,77 @@ static void drawspiral(const float cent[3], float rad, float tmat[4][4], int sta vec[0] = cent[0] + (x * vx[0] + y * vy[0]); vec[1] = cent[1] + (x * vx[1] + y * vy[1]); vec[2] = cent[2] + (x * vx[2] + y * vy[2]); - glVertex3fv(vec); + immVertex3fv(pos, vec); } } - glEnd(); + immEnd(); } /* draws a circle on x-z plane given the scaling of the circle, assuming that * all required matrices have been set (used for drawing empties) */ -static void drawcircle_size(float size) +static void drawcircle_size(float size, unsigned pos) { - glBegin(GL_LINE_LOOP); + immBegin(PRIM_LINE_LOOP, CIRCLE_RESOL); /* coordinates are: cos(degrees * 11.25) = x, sin(degrees * 11.25) = y, 0.0f = z */ for (short degrees = 0; degrees < CIRCLE_RESOL; degrees++) { float x = cosval[degrees]; float y = sinval[degrees]; - - glVertex3f(x * size, 0.0f, y * size); + + immVertex3f(pos, x * size, 0.0f, y * size); } - - glEnd(); + immEnd(); } /* needs fixing if non-identity matrix used */ -static void drawtube(const float vec[3], float radius, float height, float tmat[4][4]) +static void imm_drawtube(const float vec[3], float radius, float height, float tmat[4][4], unsigned pos) { float cur[3]; - drawcircball(GL_LINE_LOOP, vec, radius, tmat); + imm_drawcircball(vec, radius, tmat, pos); copy_v3_v3(cur, vec); cur[2] += height; - drawcircball(GL_LINE_LOOP, cur, radius, tmat); + imm_drawcircball(cur, radius, tmat, pos); - glBegin(GL_LINES); - glVertex3f(vec[0] + radius, vec[1], vec[2]); - glVertex3f(cur[0] + radius, cur[1], cur[2]); - glVertex3f(vec[0] - radius, vec[1], vec[2]); - glVertex3f(cur[0] - radius, cur[1], cur[2]); - glVertex3f(vec[0], vec[1] + radius, vec[2]); - glVertex3f(cur[0], cur[1] + radius, cur[2]); - glVertex3f(vec[0], vec[1] - radius, vec[2]); - glVertex3f(cur[0], cur[1] - radius, cur[2]); - glEnd(); + immBegin(PRIM_LINES, 8); + immVertex3f(pos, vec[0] + radius, vec[1], vec[2]); + immVertex3f(pos, cur[0] + radius, cur[1], cur[2]); + immVertex3f(pos, vec[0] - radius, vec[1], vec[2]); + immVertex3f(pos, cur[0] - radius, cur[1], cur[2]); + immVertex3f(pos, vec[0], vec[1] + radius, vec[2]); + immVertex3f(pos, cur[0], cur[1] + radius, cur[2]); + immVertex3f(pos, vec[0], vec[1] - radius, vec[2]); + immVertex3f(pos, cur[0], cur[1] - radius, cur[2]); + immEnd(); } /* needs fixing if non-identity matrix used */ -static void drawcone(const float vec[3], float radius, float height, float tmat[4][4]) +static void imm_drawcone(const float vec[3], float radius, float height, float tmat[4][4], unsigned pos) { float cur[3]; copy_v3_v3(cur, vec); cur[2] += height; - drawcircball(GL_LINE_LOOP, cur, radius, tmat); + imm_drawcircball(cur, radius, tmat, pos); - glBegin(GL_LINES); - glVertex3f(vec[0], vec[1], vec[2]); - glVertex3f(cur[0] + radius, cur[1], cur[2]); - glVertex3f(vec[0], vec[1], vec[2]); - glVertex3f(cur[0] - radius, cur[1], cur[2]); - glVertex3f(vec[0], vec[1], vec[2]); - glVertex3f(cur[0], cur[1] + radius, cur[2]); - glVertex3f(vec[0], vec[1], vec[2]); - glVertex3f(cur[0], cur[1] - radius, cur[2]); - glEnd(); + immBegin(PRIM_LINES, 8); + immVertex3f(pos, vec[0], vec[1], vec[2]); + immVertex3f(pos, cur[0] + radius, cur[1], cur[2]); + immVertex3f(pos, vec[0], vec[1], vec[2]); + immVertex3f(pos, cur[0] - radius, cur[1], cur[2]); + immVertex3f(pos, vec[0], vec[1], vec[2]); + immVertex3f(pos, cur[0], cur[1] + radius, cur[2]); + immVertex3f(pos, vec[0], vec[1], vec[2]); + immVertex3f(pos, cur[0], cur[1] - radius, cur[2]); + immEnd(); } /* return true if nothing was drawn */ -static bool drawmball(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, +static bool drawmball(Scene *scene, SceneLayer *sl, View3D *v3d, RegionView3D *rv3d, Base *base, const char dt, const short dflag, const unsigned char ob_wire_col[4]) { Object *ob = base->object; @@ -6785,15 +7792,13 @@ static bool drawmball(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, if ((G.f & G_PICKSEL) == 0) { unsigned char wire_col[4]; UI_GetThemeColor4ubv(TH_WIRE_EDIT, wire_col); - glColor3ubv(wire_col); - - drawDispList(scene, v3d, rv3d, base, dt, dflag, wire_col); + drawDispList(scene, sl, v3d, rv3d, base, dt, dflag, wire_col); } ml = mb->editelems->first; } else { - if ((base->flag & OB_FROMDUPLI) == 0) { - drawDispList(scene, v3d, rv3d, base, dt, dflag, ob_wire_col); + if ((base->flag_legacy & OB_FROMDUPLI) == 0) { + drawDispList(scene, sl, v3d, rv3d, base, dt, dflag, ob_wire_col); } ml = mb->elems.first; } @@ -6810,20 +7815,25 @@ static bool drawmball(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, normalize_v3(imat[0]); normalize_v3(imat[1]); +#if 0 /* no purpose? */ if (mb->editelems == NULL) { if ((dflag & DRAW_CONSTCOLOR) == 0) { glColor3ubv(ob_wire_col); } } - +#endif + glLineWidth(1.0f); + const unsigned int pos = VertexFormat_add_attrib(immVertexFormat(), "pos", COMP_F32, 3, KEEP_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + while (ml) { /* draw radius */ if (mb->editelems) { if ((dflag & DRAW_CONSTCOLOR) == 0) { - if ((ml->flag & SELECT) && (ml->flag & MB_SCALE_RAD)) cpack(0xA0A0F0); - else cpack(0x3030A0); + if ((ml->flag & SELECT) && (ml->flag & MB_SCALE_RAD)) imm_cpack(0xA0A0F0); + else imm_cpack(0x3030A0); } if (G.f & G_PICKSEL) { @@ -6831,24 +7841,26 @@ static bool drawmball(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, GPU_select_load_id(code++); } } - drawcircball(GL_LINE_LOOP, &(ml->x), ml->rad, imat); + imm_drawcircball(&(ml->x), ml->rad, imat, pos); /* draw stiffness */ if (mb->editelems) { if ((dflag & DRAW_CONSTCOLOR) == 0) { - if ((ml->flag & SELECT) && !(ml->flag & MB_SCALE_RAD)) cpack(0xA0F0A0); - else cpack(0x30A030); + if ((ml->flag & SELECT) && !(ml->flag & MB_SCALE_RAD)) imm_cpack(0xA0F0A0); + else imm_cpack(0x30A030); } if (G.f & G_PICKSEL) { ml->selcol2 = code; GPU_select_load_id(code++); } - drawcircball(GL_LINE_LOOP, &(ml->x), ml->rad * atanf(ml->s) / (float)M_PI_2, imat); + imm_drawcircball(&(ml->x), ml->rad * atanf(ml->s) / (float)M_PI_2, imat, pos); } ml = ml->next; } + + immUnbindProgram(); return false; } @@ -6858,6 +7870,7 @@ static void draw_forcefield(Object *ob, RegionView3D *rv3d, PartDeflect *pd = ob->pd; float imat[4][4], tmat[4][4]; float vec[3] = {0.0, 0.0, 0.0}; + float draw_color[3] = {0.0f, 0.0f, 0.0f}; /* scale size of circle etc with the empty drawsize */ const float size = (ob->type == OB_EMPTY) ? ob->empty_drawsize : 1.0f; @@ -6867,35 +7880,53 @@ static void draw_forcefield(Object *ob, RegionView3D *rv3d, normalize_v3(imat[0]); /* we don't do this because field doesnt scale either... apart from wind! */ normalize_v3(imat[1]); #endif + + const unsigned int pos = VertexFormat_add_attrib(immVertexFormat(), "pos", COMP_F32, 3, KEEP_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immUniformColor3fv(draw_color); if (pd->forcefield == PFIELD_WIND) { float force_val = pd->f_strength; if ((dflag & DRAW_CONSTCOLOR) == 0) { - ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.5f); + ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.5f, draw_color); + immUniformColor3fv(draw_color); } unit_m4(tmat); force_val *= 0.1f; - drawcircball(GL_LINE_LOOP, vec, size, tmat); + imm_drawcircball(vec, size, tmat, pos); vec[2] = 0.5f * force_val; - drawcircball(GL_LINE_LOOP, vec, size, tmat); + imm_drawcircball(vec, size, tmat, pos); vec[2] = 1.0f * force_val; - drawcircball(GL_LINE_LOOP, vec, size, tmat); + imm_drawcircball(vec, size, tmat, pos); vec[2] = 1.5f * force_val; - drawcircball(GL_LINE_LOOP, vec, size, tmat); + imm_drawcircball(vec, size, tmat, pos); vec[2] = 0.0f; /* reset vec for max dist circle */ - } else if (pd->forcefield == PFIELD_FORCE) { float ffall_val = pd->f_power; - if ((dflag & DRAW_CONSTCOLOR) == 0) ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.5f); - drawcircball(GL_LINE_LOOP, vec, size, imat); - if ((dflag & DRAW_CONSTCOLOR) == 0) ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.9f - 0.4f / powf(1.5f, ffall_val)); - drawcircball(GL_LINE_LOOP, vec, size * 1.5f, imat); - if ((dflag & DRAW_CONSTCOLOR) == 0) ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.9f - 0.4f / powf(2.0f, ffall_val)); - drawcircball(GL_LINE_LOOP, vec, size * 2.0f, imat); + if ((dflag & DRAW_CONSTCOLOR) == 0) { + ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.5f, draw_color); + immUniformColor3fv(draw_color); + } + + imm_drawcircball(vec, size, imat, pos); + + if ((dflag & DRAW_CONSTCOLOR) == 0) { + ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.9f - 0.4f / powf(1.5f, ffall_val), draw_color); + immUniformColor3fv(draw_color); + } + + imm_drawcircball(vec, size * 1.5f, imat, pos); + + if ((dflag & DRAW_CONSTCOLOR) == 0) { + ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.9f - 0.4f / powf(2.0f, ffall_val), draw_color); + immUniformColor3fv(draw_color); + } + + imm_drawcircball(vec, size * 2.0f, imat, pos); } else if (pd->forcefield == PFIELD_VORTEX) { float force_val = pd->f_strength; @@ -6903,16 +7934,17 @@ static void draw_forcefield(Object *ob, RegionView3D *rv3d, unit_m4(tmat); if ((dflag & DRAW_CONSTCOLOR) == 0) { - ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.7f); + ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.7f, draw_color); + immUniformColor3fv(draw_color); } if (force_val < 0) { - drawspiral(vec, size, tmat, 1); - drawspiral(vec, size, tmat, 16); + drawspiral(pos, vec, size, tmat, 1); + drawspiral(pos, vec, size, tmat, 16); } else { - drawspiral(vec, size, tmat, -1); - drawspiral(vec, size, tmat, -16); + drawspiral(pos, vec, size, tmat, -1); + drawspiral(pos, vec, size, tmat, -16); } } else if (pd->forcefield == PFIELD_GUIDE && ob->type == OB_CURVE) { @@ -6922,18 +7954,19 @@ static void draw_forcefield(Object *ob, RegionView3D *rv3d, float mindist = pd->f_strength; if ((dflag & DRAW_CONSTCOLOR) == 0) { - ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.5f); + ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.5f, draw_color); + immUniformColor3fv(draw_color); } /* path end */ setlinestyle(3); where_on_path(ob, 1.0f, guidevec1, guidevec2, NULL, NULL, NULL); - drawcircball(GL_LINE_LOOP, guidevec1, mindist, imat); + imm_drawcircball(guidevec1, mindist, imat, pos); /* path beginning */ setlinestyle(0); where_on_path(ob, 0.0f, guidevec1, guidevec2, NULL, NULL, NULL); - drawcircball(GL_LINE_LOOP, guidevec1, mindist, imat); + imm_drawcircball(guidevec1, mindist, imat, pos); copy_v3_v3(vec, guidevec1); /* max center */ } @@ -6942,16 +7975,19 @@ static void draw_forcefield(Object *ob, RegionView3D *rv3d, setlinestyle(3); if ((dflag & DRAW_CONSTCOLOR) == 0) { - ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.5f); + ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.5f, draw_color); + immUniformColor3fv(draw_color); } if (pd->falloff == PFIELD_FALL_SPHERE) { /* as last, guide curve alters it */ - if (pd->flag & PFIELD_USEMAX) - drawcircball(GL_LINE_LOOP, vec, pd->maxdist, imat); + if ((pd->flag & PFIELD_USEMAX) != 0) { + imm_drawcircball(vec, pd->maxdist, imat, pos); + } - if (pd->flag & PFIELD_USEMIN) - drawcircball(GL_LINE_LOOP, vec, pd->mindist, imat); + if ((pd->flag & PFIELD_USEMIN) != 0) { + imm_drawcircball(vec, pd->mindist, imat, pos); + } } else if (pd->falloff == PFIELD_FALL_TUBE) { float radius, distance; @@ -6964,16 +8000,18 @@ static void draw_forcefield(Object *ob, RegionView3D *rv3d, vec[2] = distance; distance = (pd->flag & PFIELD_POSZ) ? -distance : -2.0f * distance; - if (pd->flag & (PFIELD_USEMAX | PFIELD_USEMAXR)) - drawtube(vec, radius, distance, tmat); + if (pd->flag & (PFIELD_USEMAX | PFIELD_USEMAXR)) { + imm_drawtube(vec, radius, distance, tmat, pos); + } radius = (pd->flag & PFIELD_USEMINR) ? pd->minrad : 1.0f; distance = (pd->flag & PFIELD_USEMIN) ? pd->mindist : 0.0f; vec[2] = distance; distance = (pd->flag & PFIELD_POSZ) ? -distance : -2.0f * distance; - if (pd->flag & (PFIELD_USEMIN | PFIELD_USEMINR)) - drawtube(vec, radius, distance, tmat); + if (pd->flag & (PFIELD_USEMIN | PFIELD_USEMINR)) { + imm_drawtube(vec, radius, distance, tmat, pos); + } } else if (pd->falloff == PFIELD_FALL_CONE) { float radius, distance; @@ -6984,46 +8022,54 @@ static void draw_forcefield(Object *ob, RegionView3D *rv3d, distance = (pd->flag & PFIELD_USEMAX) ? pd->maxdist : 0.0f; if (pd->flag & (PFIELD_USEMAX | PFIELD_USEMAXR)) { - drawcone(vec, distance * sinf(radius), distance * cosf(radius), tmat); + imm_drawcone(vec, distance * sinf(radius), distance * cosf(radius), tmat, pos); if ((pd->flag & PFIELD_POSZ) == 0) - drawcone(vec, distance * sinf(radius), -distance * cosf(radius), tmat); + imm_drawcone(vec, distance * sinf(radius), -distance * cosf(radius), tmat, pos); } radius = DEG2RADF((pd->flag & PFIELD_USEMINR) ? pd->minrad : 1.0f); distance = (pd->flag & PFIELD_USEMIN) ? pd->mindist : 0.0f; if (pd->flag & (PFIELD_USEMIN | PFIELD_USEMINR)) { - drawcone(vec, distance * sinf(radius), distance * cosf(radius), tmat); + imm_drawcone(vec, distance * sinf(radius), distance * cosf(radius), tmat, pos); if ((pd->flag & PFIELD_POSZ) == 0) - drawcone(vec, distance * sinf(radius), -distance * cosf(radius), tmat); + imm_drawcone(vec, distance * sinf(radius), -distance * cosf(radius), tmat, pos); } } setlinestyle(0); + + immUnbindProgram(); } -static void draw_box(const float vec[8][3], bool solid) +static void imm_draw_box(const float vec[8][3], bool solid, unsigned pos) { - glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(3, GL_FLOAT, 0, vec); - if (solid) { - const GLubyte indices[24] = {0,1,2,3,7,6,5,4,4,5,1,0,3,2,6,7,3,7,4,0,1,5,6,2}; - glDrawRangeElements(GL_QUADS, 0, 7, 24, GL_UNSIGNED_BYTE, indices); + /* Adpated from "Optimizing Triangle Strips for Fast Rendering" by F. Evans, S. Skiena and A. Varshney + * (http://www.cs.umd.edu/gvil/papers/av_ts.pdf). */ + static const GLubyte tris_strip_indices[14] = {0,1,3,2,6,1,5,0,4,3,7,6,4,5}; + immBegin(PRIM_TRIANGLE_STRIP, 14); + for (int i = 0; i < 14; ++i) { + immVertex3fv(pos, vec[tris_strip_indices[i]]); + } + immEnd(); } else { - const GLubyte indices[24] = {0,1,1,2,2,3,3,0,0,4,4,5,5,6,6,7,7,4,1,5,2,6,3,7}; - glDrawRangeElements(GL_LINES, 0, 7, 24, GL_UNSIGNED_BYTE, indices); + static const GLubyte line_indices[24] = {0,1,1,2,2,3,3,0,0,4,4,5,5,6,6,7,7,4,1,5,2,6,3,7}; + immBegin(PRIM_LINES, 24); + for (int i = 0; i < 24; ++i) { + immVertex3fv(pos, vec[line_indices[i]]); + } + immEnd(); } - glDisableClientState(GL_VERTEX_ARRAY); } -static void draw_bb_quadric(BoundBox *bb, char type, bool around_origin) +static void imm_draw_bb(BoundBox *bb, char type, bool around_origin, const unsigned char ob_wire_col[4]) { float size[3], cent[3]; - GLUquadricObj *qobj = gluNewQuadric(); - - gluQuadricDrawStyle(qobj, GLU_SILHOUETTE); + Batch *sphere = Batch_get_sphere_wire(0); + Batch_set_builtin_program(sphere, GPU_SHADER_3D_UNIFORM_COLOR); + if (ob_wire_col) Batch_Uniform4f(sphere, "color", ob_wire_col[0]/255.0f, ob_wire_col[1]/255.0f, ob_wire_col[2]/255.0f, 1.0f); BKE_boundbox_calc_size_aabb(bb, size); @@ -7034,40 +8080,51 @@ static void draw_bb_quadric(BoundBox *bb, char type, bool around_origin) BKE_boundbox_calc_center_aabb(bb, cent); } - glPushMatrix(); + gpuPushMatrix(); + + unsigned int pos = VertexFormat_add_attrib(immVertexFormat(), "pos", COMP_F32, 3, KEEP_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + if (ob_wire_col) immUniformColor3ubv(ob_wire_col); + if (type == OB_BOUND_SPHERE) { float scale = MAX3(size[0], size[1], size[2]); - glTranslate3fv(cent); - glScalef(scale, scale, scale); - gluSphere(qobj, 1.0, 8, 5); + gpuTranslate3fv(cent); + gpuRotateAxis(90, 'X'); + gpuScaleUniform(scale); + Batch_draw(sphere); } else if (type == OB_BOUND_CYLINDER) { float radius = size[0] > size[1] ? size[0] : size[1]; - glTranslatef(cent[0], cent[1], cent[2] - size[2]); - glScalef(radius, radius, 2.0f * size[2]); - gluCylinder(qobj, 1.0, 1.0, 1.0, 8, 1); + gpuTranslate3f(cent[0], cent[1], cent[2] - size[2]); + gpuScale3f(radius, radius, 2.0f * size[2]); + imm_draw_cylinder_wire_3d(pos, 1.0f, 1.0f, 1.0f, 8, 1); } else if (type == OB_BOUND_CONE) { float radius = size[0] > size[1] ? size[0] : size[1]; - glTranslatef(cent[0], cent[1], cent[2] - size[2]); - glScalef(radius, radius, 2.0f * size[2]); - gluCylinder(qobj, 1.0, 0.0, 1.0, 8, 1); + gpuTranslate3f(cent[0], cent[1], cent[2] - size[2]); + gpuScale3f(radius, radius, 2.0f * size[2]); + imm_draw_cylinder_wire_3d(pos, 1.0f, 0.0f, 1.0f, 8, 1); + } else if (type == OB_BOUND_CAPSULE) { float radius = size[0] > size[1] ? size[0] : size[1]; float length = size[2] > radius ? 2.0f * (size[2] - radius) : 0.0f; - glTranslatef(cent[0], cent[1], cent[2] - length * 0.5f); - gluCylinder(qobj, radius, radius, length, 8, 1); - gluSphere(qobj, radius, 8, 4); - glTranslatef(0.0, 0.0, length); - gluSphere(qobj, radius, 8, 4); + gpuTranslate3f(cent[0], cent[1], cent[2] - length * 0.5f); + imm_draw_cylinder_wire_3d(pos, radius, radius, length, 8, 1); + + gpuRotateAxis(90, 'X'); + gpuScaleUniform(radius); + Batch_draw(sphere); + + gpuTranslate3f(0.0f, length / radius, 0.0f); + Batch_draw(sphere); } - glPopMatrix(); - - gluDeleteQuadric(qobj); + + gpuPopMatrix(); + immUnbindProgram(); } -static void draw_bounding_volume(Object *ob, char type) +void draw_bounding_volume(Object *ob, char type, const unsigned char ob_wire_col[4]) { BoundBox bb_local; BoundBox *bb = NULL; @@ -7097,12 +8154,16 @@ static void draw_bounding_volume(Object *ob, char type) if (bb == NULL) return; - + if (ob->gameflag & OB_BOUNDS) { /* bounds need to be drawn around origin for game engine */ if (type == OB_BOUND_BOX) { float vec[8][3], size[3]; - + + unsigned int pos = VertexFormat_add_attrib(immVertexFormat(), "pos", COMP_F32, 3, KEEP_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + if (ob_wire_col) immUniformColor3ubv(ob_wire_col); + BKE_boundbox_calc_size_aabb(bb, size); vec[0][0] = vec[1][0] = vec[2][0] = vec[3][0] = -size[0]; @@ -7112,21 +8173,31 @@ static void draw_bounding_volume(Object *ob, char type) vec[0][2] = vec[3][2] = vec[4][2] = vec[7][2] = -size[2]; vec[1][2] = vec[2][2] = vec[5][2] = vec[6][2] = +size[2]; - draw_box(vec, false); + imm_draw_box(vec, false, pos); + + immUnbindProgram(); } else { - draw_bb_quadric(bb, type, true); + imm_draw_bb(bb, type, true, ob_wire_col); } } else { - if (type == OB_BOUND_BOX) - draw_box(bb->vec, false); + if (type == OB_BOUND_BOX) { + unsigned int pos = VertexFormat_add_attrib(immVertexFormat(), "pos", COMP_F32, 3, KEEP_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + if (ob_wire_col) immUniformColor3ubv(ob_wire_col); + + imm_draw_box(bb->vec, false, pos); + + immUnbindProgram(); + } else - draw_bb_quadric(bb, type, false); + imm_draw_bb(bb, type, false, ob_wire_col); } + } -static void drawtexspace(Object *ob) +static void drawtexspace(Object *ob, const unsigned char ob_wire_col[3]) { float vec[8][3], loc[3], size[3]; @@ -7156,20 +8227,32 @@ static void drawtexspace(Object *ob) setlinestyle(2); - draw_box(vec, false); + unsigned int pos = VertexFormat_add_attrib(immVertexFormat(), "pos", COMP_F32, 3, KEEP_FLOAT); + + if (ob_wire_col) { + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immUniformColor3ubv(ob_wire_col); + } + else { + immBindBuiltinProgram(GPU_SHADER_3D_DEPTH_ONLY); + } + + imm_draw_box(vec, false, pos); + + immUnbindProgram(); setlinestyle(0); } /* draws wire outline */ static void draw_object_selected_outline( - Scene *scene, View3D *v3d, ARegion *ar, Base *base, + Scene *scene, SceneLayer *sl, View3D *v3d, ARegion *ar, Base *base, const unsigned char ob_wire_col[4]) { RegionView3D *rv3d = ar->regiondata; Object *ob = base->object; - glDepthMask(0); + glDepthMask(GL_FALSE); if (ELEM(ob->type, OB_FONT, OB_CURVE, OB_SURF)) { bool has_faces = false; @@ -7193,46 +8276,41 @@ static void draw_object_selected_outline( if (has_faces && ED_view3d_boundbox_clip(rv3d, ob->bb)) { glLineWidth(UI_GetThemeValuef(TH_OUTLINE_WIDTH) * 2.0f); if (dm) { - draw_mesh_object_outline(v3d, ob, dm); + draw_mesh_object_outline(v3d, ob, dm, ob_wire_col); } else { /* only draw 'solid' parts of the display list as wire. */ - drawDispListwire_ex(&ob->curve_cache->disp, (DL_INDEX3 | DL_INDEX4 | DL_SURF)); + drawDispListwire_ex(&ob->curve_cache->disp, (DL_INDEX3 | DL_INDEX4 | DL_SURF), ob_wire_col); } } } else if (ob->type == OB_MBALL) { if (BKE_mball_is_basis(ob)) { - if ((base->flag & OB_FROMDUPLI) == 0) { + if ((base->flag_legacy & OB_FROMDUPLI) == 0) { glLineWidth(UI_GetThemeValuef(TH_OUTLINE_WIDTH) * 2.0f); - drawDispListwire(&ob->curve_cache->disp, ob->type); + drawDispListwire(&ob->curve_cache->disp, ob->type, ob_wire_col); } } } else if (ob->type == OB_ARMATURE) { - if (!(ob->mode & OB_MODE_POSE && base == scene->basact)) { + if (!(ob->mode & OB_MODE_POSE && base == sl->basact)) { glLineWidth(UI_GetThemeValuef(TH_OUTLINE_WIDTH) * 2.0f); - draw_armature(scene, v3d, ar, base, OB_WIRE, 0, ob_wire_col, true); + draw_armature(scene, sl, v3d, ar, base, OB_WIRE, 0, ob_wire_col, true); } } - glDepthMask(1); + glDepthMask(GL_TRUE); } static void draw_wire_extra(Scene *scene, RegionView3D *rv3d, Object *ob, const unsigned char ob_wire_col[4]) { if (ELEM(ob->type, OB_FONT, OB_CURVE, OB_SURF, OB_MBALL)) { - - if (scene->obedit == ob) { - UI_ThemeColor(TH_WIRE_EDIT); - } - else { - glColor3ubv(ob_wire_col); - } + unsigned char wire_edit_col[4]; + UI_GetThemeColor4ubv(TH_WIRE_EDIT, wire_edit_col); ED_view3d_polygon_offset(rv3d, 1.0); - glDepthMask(0); /* disable write in zbuffer, selected edge wires show better */ - glLineWidth(1); + glDepthMask(GL_FALSE); /* disable write in zbuffer, selected edge wires show better */ + glLineWidth(1.0f); if (ELEM(ob->type, OB_FONT, OB_CURVE, OB_SURF)) { if (ED_view3d_boundbox_clip(rv3d, ob->bb)) { @@ -7241,23 +8319,23 @@ static void draw_wire_extra(Scene *scene, RegionView3D *rv3d, Object *ob, const drawCurveDMWired(ob); } else { - drawDispListwire(&ob->curve_cache->disp, ob->type); + drawDispListwire(&ob->curve_cache->disp, ob->type, (scene->obedit == ob) ? wire_edit_col : ob_wire_col); } } } else if (ob->type == OB_MBALL) { if (BKE_mball_is_basis(ob)) { - drawDispListwire(&ob->curve_cache->disp, ob->type); + drawDispListwire(&ob->curve_cache->disp, ob->type, (scene->obedit == ob) ? wire_edit_col : ob_wire_col); } } - glDepthMask(1); + glDepthMask(GL_TRUE); ED_view3d_polygon_offset(rv3d, 0.0); } } /* should be called in view space */ -static void draw_hooks(Object *ob) +static void draw_hooks(Object *ob, unsigned int pos) { for (ModifierData *md = ob->modifiers.first; md; md = md->next) { if (md->type == eModifierType_Hook) { @@ -7268,17 +8346,17 @@ static void draw_hooks(Object *ob) if (hmd->object) { setlinestyle(3); - glBegin(GL_LINES); - glVertex3fv(hmd->object->obmat[3]); - glVertex3fv(vec); - glEnd(); + immBegin(PRIM_LINES, 2); + immVertex3fv(pos, hmd->object->obmat[3]); + immVertex3fv(pos, vec); + immEnd(); setlinestyle(0); } - glPointSize(3.0); - glBegin(GL_POINTS); - glVertex3fv(vec); - glEnd(); + glPointSize(3.0f); + immBegin(PRIM_POINTS, 1); + immVertex3fv(pos, vec); + immEnd(); } } } @@ -7289,9 +8367,16 @@ static void draw_rigid_body_pivot(bRigidBodyJointConstraint *data, const char *axis_str[3] = {"px", "py", "pz"}; float mat[4][4]; + unsigned int pos = VertexFormat_add_attrib(immVertexFormat(), "pos", COMP_F32, 3, KEEP_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + + if (ob_wire_col) immUniformColor3ubv(ob_wire_col); + eul_to_mat4(mat, &data->axX); glLineWidth(4.0f); setlinestyle(2); + + immBegin(PRIM_LINES, 6); for (int axis = 0; axis < 3; axis++) { float dir[3] = {0, 0, 0}; float v[3]; @@ -7299,12 +8384,10 @@ static void draw_rigid_body_pivot(bRigidBodyJointConstraint *data, copy_v3_v3(v, &data->pivX); dir[axis] = 1.0f; - glBegin(GL_LINES); mul_m4_v3(mat, dir); add_v3_v3(v, dir); - glVertex3fv(&data->pivX); - glVertex3fv(v); - glEnd(); + immVertex3fv(pos, &data->pivX); + immVertex3fv(pos, v); /* when const color is set wirecolor is NULL - we could get the current color but * with selection and group instancing its not needed to draw the text */ @@ -7312,11 +8395,15 @@ static void draw_rigid_body_pivot(bRigidBodyJointConstraint *data, view3d_cached_text_draw_add(v, axis_str[axis], 2, 0, V3D_CACHE_TEXT_ASCII, ob_wire_col); } } + immEnd(); setlinestyle(0); + glLineWidth(1.0f); + + immUnbindProgram(); } -static void draw_object_wire_color(Scene *scene, Base *base, unsigned char r_ob_wire_col[4]) +void draw_object_wire_color(Scene *scene, SceneLayer *sl, Base *base, unsigned char r_ob_wire_col[4]) { Object *ob = base->object; int colindex = 0; @@ -7330,23 +8417,23 @@ static void draw_object_wire_color(Scene *scene, Base *base, unsigned char r_ob_ if ((scene->obedit == NULL) && (G.moving & G_TRANSFORM_OBJ) && - (base->flag & (SELECT + BA_WAS_SEL))) + ((base->flag & BASE_SELECTED) || (base->flag_legacy & BA_WAS_SEL))) { theme_id = TH_TRANSFORM; } else { /* Sets the 'colindex' */ if (ID_IS_LINKED_DATABLOCK(ob)) { - colindex = (base->flag & (SELECT + BA_WAS_SEL)) ? 2 : 1; + colindex = ((base->flag & BASE_SELECTED) || (base->flag_legacy & BA_WAS_SEL)) ? 2 : 1; } /* Sets the 'theme_id' or fallback to wire */ else { - if (ob->flag & OB_FROMGROUP) { - if (base->flag & (SELECT + BA_WAS_SEL)) { + if ((ob->flag & OB_FROMGROUP) != 0) { + if ((base->flag & BASE_SELECTED) || (base->flag_legacy & BA_WAS_SEL)) { /* uses darker active color for non-active + selected */ theme_id = TH_GROUP_ACTIVE; - if (scene->basact != base) { + if (sl->basact != base) { theme_shade = -16; } } @@ -7355,8 +8442,8 @@ static void draw_object_wire_color(Scene *scene, Base *base, unsigned char r_ob_ } } else { - if (base->flag & (SELECT + BA_WAS_SEL)) { - theme_id = scene->basact == base ? TH_ACTIVE : TH_SELECT; + if ((base->flag & BASE_SELECTED) || (base->flag_legacy & BA_WAS_SEL)) { + theme_id = sl->basact == base ? TH_ACTIVE : TH_SELECT; } else { if (ob->type == OB_LAMP) theme_id = TH_LAMP; @@ -7410,10 +8497,11 @@ static void draw_object_matcap_check(View3D *v3d, Object *ob) v3d->flag2 |= V3D_SHOW_SOLID_MATCAP; } -static void draw_rigidbody_shape(Object *ob) +void draw_rigidbody_shape(Object *ob, const unsigned char ob_wire_col[4]) { BoundBox *bb = NULL; float size[3], vec[8][3]; + unsigned int pos; if (ob->type == OB_MESH) { bb = BKE_mesh_boundbox_get(ob); @@ -7426,6 +8514,10 @@ static void draw_rigidbody_shape(Object *ob) case RB_SHAPE_BOX: BKE_boundbox_calc_size_aabb(bb, size); + pos = VertexFormat_add_attrib(immVertexFormat(), "pos", COMP_F32, 3, KEEP_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + if (ob_wire_col) immUniformColor3ubv(ob_wire_col); + vec[0][0] = vec[1][0] = vec[2][0] = vec[3][0] = -size[0]; vec[4][0] = vec[5][0] = vec[6][0] = vec[7][0] = +size[0]; vec[0][1] = vec[1][1] = vec[4][1] = vec[5][1] = -size[1]; @@ -7433,19 +8525,20 @@ static void draw_rigidbody_shape(Object *ob) vec[0][2] = vec[3][2] = vec[4][2] = vec[7][2] = -size[2]; vec[1][2] = vec[2][2] = vec[5][2] = vec[6][2] = +size[2]; - draw_box(vec, false); + imm_draw_box(vec, false, pos); + immUnbindProgram(); break; case RB_SHAPE_SPHERE: - draw_bb_quadric(bb, OB_BOUND_SPHERE, true); + imm_draw_bb(bb, OB_BOUND_SPHERE, true, ob_wire_col); break; case RB_SHAPE_CONE: - draw_bb_quadric(bb, OB_BOUND_CONE, true); + imm_draw_bb(bb, OB_BOUND_CONE, true, ob_wire_col); break; case RB_SHAPE_CYLINDER: - draw_bb_quadric(bb, OB_BOUND_CYLINDER, true); + imm_draw_bb(bb, OB_BOUND_CYLINDER, true, ob_wire_col); break; case RB_SHAPE_CAPSULE: - draw_bb_quadric(bb, OB_BOUND_CAPSULE, true); + imm_draw_bb(bb, OB_BOUND_CAPSULE, true, ob_wire_col); break; } } @@ -7454,17 +8547,16 @@ static void draw_rigidbody_shape(Object *ob) * main object drawing function, draws in selection * \param dflag (draw flag) can be DRAW_PICKING and/or DRAW_CONSTCOLOR, DRAW_SCENESET */ -void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short dflag) +void draw_object(Scene *scene, SceneLayer *sl, ARegion *ar, View3D *v3d, Base *base, const short dflag) { ModifierData *md = NULL; Object *ob = base->object; Curve *cu; RegionView3D *rv3d = ar->regiondata; - unsigned int col = 0; unsigned char _ob_wire_col[4]; /* dont initialize this */ const unsigned char *ob_wire_col = NULL; /* dont initialize this, use NULL crashes as a way to find invalid use */ bool zbufoff = false, is_paint = false, empty_object = false; - const bool is_obact = (ob == OBACT); + const bool is_obact = (ob == OBACT_NEW); const bool render_override = (v3d->flag2 & V3D_RENDER_OVERRIDE) != 0; const bool is_picking = (G.f & G_PICKSEL) != 0; const bool has_particles = (ob->particlesystem.first != NULL); @@ -7504,7 +8596,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short } } - if (((base->flag & OB_FROMDUPLI) == 0) && + if (((base->flag_legacy & OB_FROMDUPLI) == 0) && (md = modifiers_findByType(ob, eModifierType_Smoke)) && (modifier_isEnabled(scene, md, eModifierMode_Realtime))) { @@ -7528,7 +8620,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short /* xray delay? */ - if ((dflag & DRAW_PICKING) == 0 && (base->flag & OB_FROMDUPLI) == 0 && (v3d->flag2 & V3D_RENDER_SHADOW) == 0) { + if ((dflag & DRAW_PICKING) == 0 && (base->flag_legacy & OB_FROMDUPLI) == 0 && (v3d->flag2 & V3D_RENDER_SHADOW) == 0) { /* don't do xray in particle mode, need the z-buffer */ if (!(ob->mode & OB_MODE_PARTICLE_EDIT)) { /* xray and transp are set when it is drawing the 2nd/3rd pass */ @@ -7581,10 +8673,10 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short ED_view3d_project_base(ar, base); - draw_object_wire_color(scene, base, _ob_wire_col); + draw_object_wire_color(scene, sl, base, _ob_wire_col); ob_wire_col = _ob_wire_col; - glColor3ubv(ob_wire_col); + //glColor3ubv(ob_wire_col); } /* maximum drawtype */ @@ -7636,15 +8728,22 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short /* draw outline for selected objects, mesh does itself */ if ((v3d->flag & V3D_SELECT_OUTLINE) && !render_override && ob->type != OB_MESH) { if (dt > OB_WIRE && (ob->mode & OB_MODE_EDIT) == 0 && (dflag & DRAW_SCENESET) == 0) { - if (!(ob->dtx & OB_DRAWWIRE) && (ob->flag & SELECT) && !(dflag & (DRAW_PICKING | DRAW_CONSTCOLOR))) { - draw_object_selected_outline(scene, v3d, ar, base, ob_wire_col); + if (!(ob->dtx & OB_DRAWWIRE) && (base->flag & BASE_SELECTED) && !(dflag & (DRAW_PICKING | DRAW_CONSTCOLOR))) { + draw_object_selected_outline(scene, sl, v3d, ar, base, ob_wire_col); } } } + /* TODO Viewport: draw only for selection */ + if ((dflag & DRAW_PICKING) == 0) { + if ((dt == OB_BOUNDBOX) || ELEM(ob->type, OB_EMPTY, OB_LAMP, OB_CAMERA, OB_SPEAKER)) { + goto afterdraw; + } + } + switch (ob->type) { case OB_MESH: - empty_object = draw_mesh_object(scene, ar, v3d, rv3d, base, dt, ob_wire_col, dflag); + empty_object = draw_mesh_object(scene, sl, ar, v3d, rv3d, base, dt, ob_wire_col, dflag); if ((dflag & DRAW_CONSTCOLOR) == 0) { /* mesh draws wire itself */ dtx &= ~OB_DRAWWIRE; @@ -7654,18 +8753,18 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short case OB_FONT: cu = ob->data; if (cu->editfont) { - draw_editfont(scene, v3d, rv3d, base, dt, dflag, ob_wire_col); + draw_editfont(scene, sl, v3d, rv3d, base, dt, dflag, ob_wire_col); } else if (dt == OB_BOUNDBOX) { if ((render_override && v3d->drawtype >= OB_WIRE) == 0) { #ifdef SEQUENCER_DAG_WORKAROUND ensure_curve_cache(scene, base->object); #endif - draw_bounding_volume(ob, ob->boundtype); + draw_bounding_volume(ob, ob->boundtype, ob_wire_col); } } else if (ED_view3d_boundbox_clip(rv3d, ob->bb)) { - empty_object = drawDispList(scene, v3d, rv3d, base, dt, dflag, ob_wire_col); + empty_object = drawDispList(scene, sl, v3d, rv3d, base, dt, dflag, ob_wire_col); } break; @@ -7675,18 +8774,18 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short if (cu->editnurb) { ListBase *nurbs = BKE_curve_editNurbs_get(cu); - draw_editnurb(scene, v3d, rv3d, base, nurbs->first, dt, dflag, ob_wire_col); + draw_editnurb(scene, sl, v3d, rv3d, base, nurbs->first, dt, dflag, ob_wire_col); } else if (dt == OB_BOUNDBOX) { if ((render_override && (v3d->drawtype >= OB_WIRE)) == 0) { #ifdef SEQUENCER_DAG_WORKAROUND ensure_curve_cache(scene, base->object); #endif - draw_bounding_volume(ob, ob->boundtype); + draw_bounding_volume(ob, ob->boundtype, ob_wire_col); } } else if (ED_view3d_boundbox_clip(rv3d, ob->bb)) { - empty_object = drawDispList(scene, v3d, rv3d, base, dt, dflag, ob_wire_col); + empty_object = drawDispList(scene, sl, v3d, rv3d, base, dt, dflag, ob_wire_col); } break; case OB_MBALL: @@ -7694,17 +8793,17 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short MetaBall *mb = ob->data; if (mb->editelems) - drawmball(scene, v3d, rv3d, base, dt, dflag, ob_wire_col); + drawmball(scene, sl, v3d, rv3d, base, dt, dflag, ob_wire_col); else if (dt == OB_BOUNDBOX) { if ((render_override && (v3d->drawtype >= OB_WIRE)) == 0) { #ifdef SEQUENCER_DAG_WORKAROUND ensure_curve_cache(scene, base->object); #endif - draw_bounding_volume(ob, ob->boundtype); + draw_bounding_volume(ob, ob->boundtype, ob_wire_col); } } else - empty_object = drawmball(scene, v3d, rv3d, base, dt, dflag, ob_wire_col); + empty_object = drawmball(scene, sl, v3d, rv3d, base, dt, dflag, ob_wire_col); break; } case OB_EMPTY: @@ -7713,7 +8812,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short draw_empty_image(ob, dflag, ob_wire_col, v3d->multiview_eye); } else { - drawaxes(rv3d->viewmatob, ob->empty_drawsize, ob->empty_drawtype); + drawaxes(rv3d->viewmatob, ob->empty_drawsize, ob->empty_drawtype, ob_wire_col); } } break; @@ -7731,7 +8830,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short break; case OB_SPEAKER: if (!render_override) - drawspeaker(scene, v3d, rv3d, ob, dflag); + drawspeaker(ob_wire_col); break; case OB_LATTICE: if (!render_override) { @@ -7739,13 +8838,13 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short if ((dt == OB_BOUNDBOX) && (ob->mode & OB_MODE_EDIT)) dt = OB_WIRE; if (dt == OB_BOUNDBOX) { - draw_bounding_volume(ob, ob->boundtype); + draw_bounding_volume(ob, ob->boundtype, ob_wire_col); } else { #ifdef SEQUENCER_DAG_WORKAROUND ensure_curve_cache(scene, ob); #endif - drawlattice(v3d, ob); + drawlattice(v3d, ob, dflag, ob_wire_col); } } break; @@ -7755,21 +8854,33 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short if ((dt == OB_BOUNDBOX) && (ob->mode & (OB_MODE_EDIT | OB_MODE_POSE))) dt = OB_WIRE; if (dt == OB_BOUNDBOX) { - draw_bounding_volume(ob, ob->boundtype); + draw_bounding_volume(ob, ob->boundtype, ob_wire_col); } else { + unsigned char arm_col[4]; glLineWidth(1.0f); - empty_object = draw_armature(scene, v3d, ar, base, dt, dflag, ob_wire_col, false); + + if (ob_wire_col == NULL) { + float fcol[4] = {0.0f, 0.0f, 0.0f, 1.0f}; + rgba_float_to_uchar(arm_col, fcol); + } + else + copy_v4_v4_uchar(arm_col, ob_wire_col); + + empty_object = draw_armature(scene, sl, v3d, ar, base, dt, dflag, arm_col, false); } } break; default: if (!render_override) { - drawaxes(rv3d->viewmatob, 1.0, OB_ARROWS); + drawaxes(rv3d->viewmatob, 1.0, OB_ARROWS, ob_wire_col); } break; } + /* TODO Viewport: some elements are being drawn for object selection only */ +afterdraw: + if (!render_override) { if (ob->soft /*&& dflag & OB_SBMOTION*/) { float mrt[3][3], msc[3][3], mtr[3][3]; @@ -7778,12 +8889,12 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short if ((sb = ob->soft)) { if (sb->solverflags & SBSO_ESTIMATEIPO) { - glLoadMatrixf(rv3d->viewmat); + gpuLoadMatrix(rv3d->viewmat); copy_m3_m3(msc, sb->lscale); copy_m3_m3(mrt, sb->lrot); mul_m3_m3m3(mtr, mrt, msc); ob_draw_RE_motion(sb->lcom, mtr, tipw, tiph, drawsize); - glMultMatrixf(ob->obmat); + gpuMultMatrix(ob->obmat); } } } @@ -7800,15 +8911,9 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short { ParticleSystem *psys; - if ((dflag & DRAW_CONSTCOLOR) == 0) { - /* for visibility, also while wpaint */ - if (col || (ob->flag & SELECT)) { - cpack(0xFFFFFF); - } - } //glDepthMask(GL_FALSE); - glLoadMatrixf(rv3d->viewmat); + gpuLoadMatrix(rv3d->viewmat); view3d_cached_text_draw_begin(); @@ -7817,7 +8922,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short if (ob->mode & OB_MODE_PARTICLE_EDIT && is_obact) { PTCacheEdit *edit = PE_create_current(scene, ob); if (edit && edit->psys == psys) - draw_update_ptcache_edit(scene, ob, edit); + draw_update_ptcache_edit(scene, sl, ob, edit); } draw_new_particle_system(scene, v3d, rv3d, base, psys, dt, dflag); @@ -7825,10 +8930,9 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short invert_m4_m4(ob->imat, ob->obmat); view3d_cached_text_draw_end(v3d, ar, 0); - glMultMatrixf(ob->obmat); + gpuMultMatrix(ob->obmat); //glDepthMask(GL_TRUE); - if (col) cpack(col); } /* draw edit particles last so that they can draw over child particles */ @@ -7839,10 +8943,10 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short if (ob->mode & OB_MODE_PARTICLE_EDIT && is_obact) { PTCacheEdit *edit = PE_create_current(scene, ob); if (edit) { - glLoadMatrixf(rv3d->viewmat); - draw_update_ptcache_edit(scene, ob, edit); + gpuLoadMatrix(rv3d->viewmat); + draw_update_ptcache_edit(scene, sl, ob, edit); draw_ptcache_edit(scene, v3d, edit); - glMultMatrixf(ob->obmat); + gpuMultMatrix(ob->obmat); } } } @@ -7850,21 +8954,25 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short /* draw code for smoke, only draw domains */ if (smd && smd->domain) { SmokeDomainSettings *sds = smd->domain; + const bool show_smoke = (CFRA >= sds->point_cache[0]->startframe); float viewnormal[3]; - glLoadMatrixf(rv3d->viewmat); - glMultMatrixf(ob->obmat); + gpuLoadMatrix(rv3d->viewmat); + gpuMultMatrix(ob->obmat); if (!render_override) { BoundBox bb; float p0[3], p1[3]; + unsigned int pos = VertexFormat_add_attrib(immVertexFormat(), "pos", COMP_F32, 3, KEEP_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + if (ob_wire_col) immUniformColor3ubv(ob_wire_col); /* draw max domain bounds */ if ((sds->flags & MOD_SMOKE_ADAPTIVE_DOMAIN)) { VECSUBFAC(p0, sds->p0, sds->cell_size, sds->adapt_res); VECADDFAC(p1, sds->p1, sds->cell_size, sds->adapt_res); BKE_boundbox_init_from_minmax(&bb, p0, p1); - draw_box(bb.vec, false); + imm_draw_box(bb.vec, false, pos); } /* draw a single voxel to hint the user about the resolution of the fluid */ @@ -7878,11 +8986,13 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short } BKE_boundbox_init_from_minmax(&bb, p0, p1); - draw_box(bb.vec, false); + imm_draw_box(bb.vec, false, pos); + + immUnbindProgram(); } /* don't show smoke before simulation starts, this could be made an option in the future */ - if (sds->fluid && CFRA >= sds->point_cache[0]->startframe) { + if (sds->fluid && show_smoke) { float p0[3], p1[3]; /* get view vector */ @@ -7934,29 +9044,37 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short if ((ob->gameflag & OB_BOUNDS) && (ob->mode == OB_MODE_OBJECT)) { if (ob->boundtype != ob->collision_boundtype || (dtx & OB_DRAWBOUNDOX) == 0) { setlinestyle(2); - draw_bounding_volume(ob, ob->collision_boundtype); + draw_bounding_volume(ob, ob->collision_boundtype, ob_wire_col); setlinestyle(0); } } if (ob->rigidbody_object) { - draw_rigidbody_shape(ob); + draw_rigidbody_shape(ob, ob_wire_col); } /* draw extra: after normal draw because of makeDispList */ if (dtx && (G.f & G_RENDER_OGL) == 0) { if (dtx & OB_AXIS) { - drawaxes(rv3d->viewmatob, 1.0f, OB_ARROWS); + if ((dflag & DRAW_CONSTCOLOR) == 0) { + /* prevent random colors being used */ + drawaxes(rv3d->viewmatob, 1.0f, OB_ARROWS, ob_wire_col); + } + else { + drawaxes(rv3d->viewmatob, 1.0f, OB_ARROWS, NULL); + } } if (dtx & OB_DRAWBOUNDOX) { - draw_bounding_volume(ob, ob->boundtype); + draw_bounding_volume(ob, ob->boundtype, ob_wire_col); } if (dtx & OB_TEXSPACE) { if ((dflag & DRAW_CONSTCOLOR) == 0) { /* prevent random colors being used */ - glColor3ubv(ob_wire_col); + drawtexspace(ob, ob_wire_col); + } + else { + drawtexspace(ob, NULL); } - drawtexspace(ob); } if (dtx & OB_DRAWNAME) { /* patch for several 3d cards (IBM mostly) that crash on GL_SELECT with text drawing */ @@ -7983,16 +9101,21 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short { float imat[4][4], vec[3] = {0.0f, 0.0f, 0.0f}; + unsigned int pos = VertexFormat_add_attrib(immVertexFormat(), "pos", COMP_F32, 3, KEEP_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + invert_m4_m4(imat, rv3d->viewmatob); if ((dflag & DRAW_CONSTCOLOR) == 0) { /* prevent random colors being used */ - glColor3ubv(ob_wire_col); + immUniformColor3ubv(ob_wire_col); } setlinestyle(2); - drawcircball(GL_LINE_LOOP, vec, ob->inertia, imat); + imm_drawcircball(vec, ob->inertia, imat, pos); setlinestyle(0); + + immUnbindProgram(); } } @@ -8002,13 +9125,13 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short /* return warning, clear temp flag */ v3d->flag2 &= ~V3D_SHOW_SOLID_MATCAP; - glLoadMatrixf(rv3d->viewmat); + gpuLoadMatrix(rv3d->viewmat); if (zbufoff) { glDisable(GL_DEPTH_TEST); } - if ((base->flag & OB_FROMDUPLI) || render_override) { + if ((base->flag_legacy & OB_FROMDUPLI) || render_override) { ED_view3d_clear_mats_rv3d(rv3d); return; } @@ -8022,7 +9145,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short } else if (is_obact) do_draw_center = ACTIVE; - else if (base->flag & SELECT) + else if (base->flag & BASE_SELECTED) do_draw_center = SELECT; else if (empty_object || (v3d->flag & V3D_DRAW_CENTERS)) do_draw_center = DESELECT; @@ -8033,10 +9156,15 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short if ((base->sx != IS_CLIPPED) && (U.obcenter_dia != 0.0)) { + unsigned int pos = VertexFormat_add_attrib(immVertexFormat(), "pos", COMP_F32, 3, KEEP_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_POINT_FIXED_SIZE_UNIFORM_COLOR); + /* TODO: short term, use DEPTH_ONLY shader or set appropriate color */ + /* TODO: long term, solve picking & selection problem better */ glPointSize(U.obcenter_dia); - glBegin(GL_POINTS); - glVertex3fv(ob->obmat[3]); - glEnd(); + immBegin(PRIM_POINTS, 1); + immVertex3fv(pos, ob->obmat[3]); + immEnd(); + immUnbindProgram(); } } else if ((dflag & DRAW_CONSTCOLOR) == 0) { @@ -8057,18 +9185,25 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short ListBase *list; RigidBodyCon *rbc = ob->rigidbody_constraint; + unsigned int pos = VertexFormat_add_attrib(immVertexFormat(), "pos", COMP_F32, 3, KEEP_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immUniformColor3ubv(ob_wire_col); + /* draw hook center and offset line */ if (ob != scene->obedit) - draw_hooks(ob); + draw_hooks(ob, pos); /* help lines and so */ - if (ob != scene->obedit && ob->parent && (ob->parent->lay & v3d->lay)) { - setlinestyle(3); - glBegin(GL_LINES); - glVertex3fv(ob->obmat[3]); - glVertex3fv(ob->orig); - glEnd(); - setlinestyle(0); + if (ob != scene->obedit && ob->parent) { + Base *base_parent = BKE_scene_layer_base_find(sl, ob->parent); + if ((base_parent->flag & BASE_VISIBLED) != 0) { + setlinestyle(3); + immBegin(PRIM_LINES, 2); + immVertex3fv(pos, ob->obmat[3]); + immVertex3fv(pos, ob->orig); + immEnd(); + setlinestyle(0); + } } /* Drawing the constraint lines */ @@ -8081,7 +9216,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short UI_GetThemeColor3ubv(TH_GRID, col1); UI_make_axis_color(col1, col2, 'Z'); - glColor3ubv(col2); + immUniformColor3ubv(col2); cob = BKE_constraints_make_evalob(scene, ob, NULL, CONSTRAINT_OBTYPE_OBJECT); @@ -8106,10 +9241,10 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short if (camob) { setlinestyle(3); - glBegin(GL_LINES); - glVertex3fv(camob->obmat[3]); - glVertex3fv(ob->obmat[3]); - glEnd(); + immBegin(PRIM_LINES, 2); + immVertex3fv(pos, camob->obmat[3]); + immVertex3fv(pos, ob->obmat[3]); + immEnd(); setlinestyle(0); } } @@ -8130,10 +9265,10 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short unit_m4(ct->matrix); setlinestyle(3); - glBegin(GL_LINES); - glVertex3fv(ct->matrix[3]); - glVertex3fv(ob->obmat[3]); - glEnd(); + immBegin(PRIM_LINES, 2); + immVertex3fv(pos, ct->matrix[3]); + immVertex3fv(pos, ob->obmat[3]); + immEnd(); setlinestyle(0); } @@ -8146,21 +9281,24 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short BKE_constraints_clear_evalob(cob); } /* draw rigid body constraint lines */ - if (rbc) { - UI_ThemeColor(TH_WIRE); + if (rbc && (rbc->ob1 || rbc->ob2)) { + immUniformThemeColor(TH_WIRE); + setlinestyle(3); - glBegin(GL_LINES); + immBegin(PRIM_LINES, ((int)((bool)rbc->ob1) + (int)((bool)rbc->ob2)) * 2); if (rbc->ob1) { - glVertex3fv(ob->obmat[3]); - glVertex3fv(rbc->ob1->obmat[3]); + immVertex3fv(pos, ob->obmat[3]); + immVertex3fv(pos, rbc->ob1->obmat[3]); } if (rbc->ob2) { - glVertex3fv(ob->obmat[3]); - glVertex3fv(rbc->ob2->obmat[3]); + immVertex3fv(pos, ob->obmat[3]); + immVertex3fv(pos, rbc->ob2->obmat[3]); } - glEnd(); + immEnd(); setlinestyle(0); } + + immUnbindProgram(); } ED_view3d_clear_mats_rv3d(rv3d); @@ -8171,10 +9309,10 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short * Drawing for selection picking, * caller must have called 'GPU_select_load_id(base->selcode)' first. */ -void draw_object_select(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short dflag) +void draw_object_select(Scene *scene, SceneLayer *sl, ARegion *ar, View3D *v3d, Base *base, const short dflag) { BLI_assert(dflag & DRAW_PICKING && dflag & DRAW_CONSTCOLOR); - draw_object(scene, ar, v3d, base, dflag); + draw_object(scene, sl, ar, v3d, base, dflag); /* we draw duplicators for selection too */ if ((base->object->transflag & OB_DUPLI)) { @@ -8182,13 +9320,11 @@ void draw_object_select(Scene *scene, ARegion *ar, View3D *v3d, Base *base, cons DupliObject *dob; Base tbase; - tbase.flag = OB_FROMDUPLI; + tbase.flag_legacy = OB_FROMDUPLI; lb = object_duplilist(G.main->eval_ctx, scene, base->object); for (dob = lb->first; dob; dob = dob->next) { float omat[4][4]; - char dt; - short dtx; tbase.object = dob->ob; copy_m4_m4(omat, dob->ob->obmat); @@ -8196,10 +9332,10 @@ void draw_object_select(Scene *scene, ARegion *ar, View3D *v3d, Base *base, cons /* extra service: draw the duplicator in drawtype of parent */ /* MIN2 for the drawtype to allow bounding box objects in groups for lods */ - dt = tbase.object->dt; tbase.object->dt = MIN2(tbase.object->dt, base->object->dt); - dtx = tbase.object->dtx; tbase.object->dtx = base->object->dtx; + char dt = tbase.object->dt; tbase.object->dt = MIN2(tbase.object->dt, base->object->dt); + short dtx = tbase.object->dtx; tbase.object->dtx = base->object->dtx; - draw_object(scene, ar, v3d, &tbase, dflag); + draw_object(scene, sl, ar, v3d, &tbase, dflag); tbase.object->dt = dt; tbase.object->dtx = dtx; @@ -8219,8 +9355,10 @@ static void bbs_obmode_mesh_verts__mapFunc(void *userData, int index, const floa MVert *mv = &data->mvert[index]; if (!(mv->flag & ME_HIDE)) { - GPU_select_index_set(data->offset + index); - glVertex3fv(co); + int selcol; + GPU_select_index_get(data->offset + index, &selcol); + immAttrib1u(data->col, selcol); + immVertex3fv(data->pos, co); } } @@ -8231,10 +9369,24 @@ static void bbs_obmode_mesh_verts(Object *ob, DerivedMesh *dm, int offset) MVert *mvert = me->mvert; data.mvert = mvert; data.offset = offset; + + const int imm_len = dm->getNumVerts(dm); + + if (imm_len == 0) return; + + VertexFormat *format = immVertexFormat(); + data.pos = VertexFormat_add_attrib(format, "pos", COMP_F32, 3, KEEP_FLOAT); + data.col = VertexFormat_add_attrib(format, "color", COMP_U32, 1, KEEP_INT); + + immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR_U32); + glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE)); - glBegin(GL_POINTS); + + immBeginAtMost(PRIM_POINTS, imm_len); dm->foreachMappedVert(dm, bbs_obmode_mesh_verts__mapFunc, &data, DM_FOREACH_NOP); - glEnd(); + immEnd(); + + immUnbindProgram(); } static void bbs_mesh_verts__mapFunc(void *userData, int index, const float co[3], @@ -8244,97 +9396,170 @@ static void bbs_mesh_verts__mapFunc(void *userData, int index, const float co[3] BMVert *eve = BM_vert_at_index(data->bm, index); if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) { - GPU_select_index_set(data->offset + index); - glVertex3fv(co); + int selcol; + GPU_select_index_get(data->offset + index, &selcol); + immAttrib1u(data->col, selcol); + immVertex3fv(data->pos, co); } } static void bbs_mesh_verts(BMEditMesh *em, DerivedMesh *dm, int offset) { - drawBMOffset_userData data = {em->bm, offset}; + drawBMOffset_userData data; + data.bm = em->bm; + data.offset = offset; + VertexFormat *format = immVertexFormat(); + data.pos = VertexFormat_add_attrib(format, "pos", COMP_F32, 3, KEEP_FLOAT); + data.col = VertexFormat_add_attrib(format, "color", COMP_U32, 1, KEEP_INT); + + immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR_U32); + glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE)); - glBegin(GL_POINTS); + + immBeginAtMost(PRIM_POINTS, em->bm->totvert); dm->foreachMappedVert(dm, bbs_mesh_verts__mapFunc, &data, DM_FOREACH_NOP); - glEnd(); + immEnd(); + + immUnbindProgram(); } -static DMDrawOption bbs_mesh_wire__setDrawOptions(void *userData, int index) +static void bbs_mesh_wire__mapFunc(void *userData, int index, const float v0co[3], const float v1co[3]) { drawBMOffset_userData *data = userData; BMEdge *eed = BM_edge_at_index(data->bm, index); if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) { - GPU_select_index_set(data->offset + index); - return DM_DRAW_OPTION_NORMAL; - } - else { - return DM_DRAW_OPTION_SKIP; + int selcol; + GPU_select_index_get(data->offset + index, &selcol); + immAttrib1u(data->col, selcol); + immVertex3fv(data->pos, v0co); + immVertex3fv(data->pos, v1co); } } + static void bbs_mesh_wire(BMEditMesh *em, DerivedMesh *dm, int offset) { - drawBMOffset_userData data = {em->bm, offset}; - dm->drawMappedEdges(dm, bbs_mesh_wire__setDrawOptions, &data); + drawBMOffset_userData data; + data.bm = em->bm; + data.offset = offset; + + VertexFormat *format = immVertexFormat(); + + const int imm_len = dm->getNumEdges(dm) * 2; + + if (imm_len == 0) return; + + data.pos = VertexFormat_add_attrib(format, "pos", COMP_F32, 3, KEEP_FLOAT); + data.col = VertexFormat_add_attrib(format, "color", COMP_U32, 1, KEEP_INT); + + immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR_U32); + + glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE)); + + immBeginAtMost(PRIM_LINES, imm_len); + dm->foreachMappedEdge(dm, bbs_mesh_wire__mapFunc, &data); + immEnd(); + + immUnbindProgram(); } -/** - * dont set #GPU_framebuffer_index_set. just use to mask other - */ -static DMDrawOption bbs_mesh_mask__setSolidDrawOptions(void *userData, int index) +static void bbs_mesh_face(BMEditMesh *em, DerivedMesh *dm, const bool use_select) { - BMFace *efa = BM_face_at_index(userData, index); - - if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) { - return DM_DRAW_OPTION_NORMAL; + UNUSED_VARS(dm); + + drawBMOffset_userData data; + data.bm = em->bm; + + const int tri_len = em->tottri; + const int imm_len = tri_len * 3; + const char hflag_skip = use_select ? BM_ELEM_HIDDEN : (BM_ELEM_HIDDEN | BM_ELEM_SELECT); + + if (imm_len == 0) return; + + VertexFormat *format = immVertexFormat(); + data.pos = VertexFormat_add_attrib(format, "pos", COMP_F32, 3, KEEP_FLOAT); + data.col = VertexFormat_add_attrib(format, "color", COMP_U32, 1, KEEP_INT); + + immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR_U32); + + immBeginAtMost(PRIM_TRIANGLES, imm_len); + + if (use_select == false) { + int selcol; + GPU_select_index_get(0, &selcol); + immAttrib1u(data.col, selcol); } - else { - return DM_DRAW_OPTION_SKIP; + + int index = 0; + while (index < tri_len) { + const BMFace *f = em->looptris[index][0]->f; + const int ntris = f->len - 2; + if (!BM_elem_flag_test(f, hflag_skip)) { + if (use_select) { + int selcol; + GPU_select_index_get(BM_elem_index_get(f) + 1, &selcol); + immAttrib1u(data.col, selcol); + } + for (int t = 0; t < ntris; t++) { + immVertex3fv(data.pos, em->looptris[index][0]->v->co); + immVertex3fv(data.pos, em->looptris[index][1]->v->co); + immVertex3fv(data.pos, em->looptris[index][2]->v->co); + index++; + } + } + else { + index += ntris; + } } + immEnd(); + + immUnbindProgram(); } -static DMDrawOption bbs_mesh_solid__setSolidDrawOptions(void *userData, int index) +static void bbs_mesh_solid__drawCenter(void *userData, int index, const float cent[3], const float UNUSED(no[3])) { + drawBMOffset_userData *data = (drawBMOffset_userData *)userData; BMFace *efa = BM_face_at_index(userData, index); if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) { - GPU_select_index_set(index + 1); - return DM_DRAW_OPTION_NORMAL; - } - else { - return DM_DRAW_OPTION_SKIP; + int selcol; + GPU_select_index_get(index + 1, &selcol); + immAttrib1u(data->col, selcol); + immVertex3fv(data->pos, cent); } } -static void bbs_mesh_solid__drawCenter(void *userData, int index, const float cent[3], const float UNUSED(no[3])) +static void bbs_mesh_face_dot(BMEditMesh *em, DerivedMesh *dm) { - BMFace *efa = BM_face_at_index(userData, index); + drawBMOffset_userData data; /* don't use offset */ + data.bm = em->bm; + VertexFormat *format = immVertexFormat(); + data.pos = VertexFormat_add_attrib(format, "pos", COMP_F32, 3, KEEP_FLOAT); + data.col = VertexFormat_add_attrib(format, "color", COMP_U32, 1, KEEP_INT); - if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) { - GPU_select_index_set(index + 1); + immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR_U32); - glVertex3fv(cent); - } + glPointSize(UI_GetThemeValuef(TH_FACEDOT_SIZE)); + + immBeginAtMost(PRIM_POINTS, em->bm->totface); + dm->foreachMappedFaceCenter(dm, bbs_mesh_solid__drawCenter, &data, DM_FOREACH_NOP); + immEnd(); + + immUnbindProgram(); } /* two options, facecolors or black */ static void bbs_mesh_solid_EM(BMEditMesh *em, Scene *scene, View3D *v3d, Object *ob, DerivedMesh *dm, bool use_faceselect) { - cpack(0); - if (use_faceselect) { - dm->drawMappedFaces(dm, bbs_mesh_solid__setSolidDrawOptions, NULL, NULL, em->bm, DM_DRAW_SKIP_HIDDEN | DM_DRAW_SELECT_USE_EDITMODE); + bbs_mesh_face(em, dm, true); if (check_ob_drawface_dot(scene, v3d, ob->dt)) { - glPointSize(UI_GetThemeValuef(TH_FACEDOT_SIZE)); - - glBegin(GL_POINTS); - dm->foreachMappedFaceCenter(dm, bbs_mesh_solid__drawCenter, em->bm, DM_FOREACH_NOP); - glEnd(); + bbs_mesh_face_dot(em, dm); } - } else { - dm->drawMappedFaces(dm, bbs_mesh_mask__setSolidDrawOptions, NULL, NULL, em->bm, DM_DRAW_SKIP_SELECT | DM_DRAW_SKIP_HIDDEN | DM_DRAW_SELECT_USE_EDITMODE); + bbs_mesh_face(em, dm, false); } } @@ -8349,7 +9574,6 @@ static DMDrawOption bbs_mesh_solid_hide__setDrawOpts(void *userData, int index) Mesh *me = userData; if (!(me->mpoly[index].flag & ME_HIDE)) { - GPU_select_index_set(index + 1); return DM_DRAW_OPTION_NORMAL; } else { @@ -8374,7 +9598,6 @@ static void bbs_mesh_solid_verts(Scene *scene, Object *ob) { Mesh *me = ob->data; DerivedMesh *dm = mesh_get_derived_final(scene, ob, scene->customdata_mask); - glColor3ub(0, 0, 0); DM_update_materials(dm, ob); @@ -8389,26 +9612,24 @@ static void bbs_mesh_solid_verts(Scene *scene, Object *ob) static void bbs_mesh_solid_faces(Scene *scene, Object *ob) { - DerivedMesh *dm = mesh_get_derived_final(scene, ob, scene->customdata_mask); Mesh *me = ob->data; - - glColor3ub(0, 0, 0); - - DM_update_materials(dm, ob); - - if ((me->editflag & ME_EDIT_PAINT_FACE_SEL)) - dm->drawMappedFaces(dm, bbs_mesh_solid_hide__setDrawOpts, NULL, NULL, me, DM_DRAW_SKIP_HIDDEN); - else - dm->drawMappedFaces(dm, bbs_mesh_solid__setDrawOpts, NULL, NULL, me, 0); - - dm->release(dm); + UNUSED_VARS(scene, bbs_mesh_solid_hide__setDrawOpts, bbs_mesh_solid__setDrawOpts); + Batch *batch; + if ((me->editflag & ME_EDIT_PAINT_FACE_SEL)) { + batch = DRW_mesh_batch_cache_get_triangles_with_select_id(me, true); + } + else { + batch = DRW_mesh_batch_cache_get_triangles_with_select_id(me, false); + } + Batch_set_builtin_program(batch, GPU_SHADER_3D_FLAT_COLOR_U32); + Batch_draw(batch); } void draw_object_backbufsel(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob) { ToolSettings *ts = scene->toolsettings; - glMultMatrixf(ob->obmat); + gpuMultMatrix(ob->obmat); glClearDepth(1.0); glClear(GL_DEPTH_BUFFER_BIT); glEnable(GL_DEPTH_TEST); @@ -8468,7 +9689,7 @@ void draw_object_backbufsel(Scene *scene, View3D *v3d, RegionView3D *rv3d, Objec break; } - glLoadMatrixf(rv3d->viewmat); + gpuLoadMatrix(rv3d->viewmat); } @@ -8476,8 +9697,8 @@ void draw_object_backbufsel(Scene *scene, View3D *v3d, RegionView3D *rv3d, Objec /* assumes all matrices/etc set OK */ /* helper function for drawing object instances - meshes */ -static void draw_object_mesh_instance(Scene *scene, View3D *v3d, RegionView3D *rv3d, - Object *ob, const short dt, int outline) +static void draw_object_mesh_instance(Scene *scene, SceneLayer *sl, View3D *v3d, RegionView3D *rv3d, + Object *ob, const short dt, int outline, const unsigned char ob_wire_col[4]) { Mesh *me = ob->data; DerivedMesh *dm = NULL, *edm = NULL; @@ -8492,6 +9713,7 @@ static void draw_object_mesh_instance(Scene *scene, View3D *v3d, RegionView3D *r } if (dt <= OB_WIRE) { + glColor4ubv(ob_wire_col); if (dm) dm->drawEdges(dm, 1, 0); else if (edm) @@ -8499,11 +9721,11 @@ static void draw_object_mesh_instance(Scene *scene, View3D *v3d, RegionView3D *r } else { if (outline) - draw_mesh_object_outline(v3d, ob, dm ? dm : edm); + draw_mesh_object_outline(v3d, ob, dm ? dm : edm, ob_wire_col); if (dm) { - bool glsl = draw_glsl_material(scene, ob, v3d, dt); - GPU_begin_object_materials(v3d, rv3d, scene, ob, glsl, NULL); + bool glsl = draw_glsl_material(scene, sl, ob, v3d, dt); + GPU_begin_object_materials(v3d, rv3d, scene, sl, ob, glsl, NULL); } glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW); @@ -8522,23 +9744,147 @@ static void draw_object_mesh_instance(Scene *scene, View3D *v3d, RegionView3D *r if (dm) dm->release(dm); } -void draw_object_instance(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, const char dt, int outline) +void draw_object_instance(Scene *scene, SceneLayer *sl, View3D *v3d, RegionView3D *rv3d, Object *ob, const char dt, int outline, const float wire_col[4]) { if (ob == NULL) return; + unsigned char bcol[4]; + rgba_float_to_uchar(bcol, wire_col); + switch (ob->type) { case OB_MESH: - draw_object_mesh_instance(scene, v3d, rv3d, ob, dt, outline); + draw_object_mesh_instance(scene, sl, v3d, rv3d, ob, dt, outline, bcol); break; case OB_EMPTY: if (ob->empty_drawtype == OB_EMPTY_IMAGE) { - /* CONSTCOLOR == no wire outline */ - draw_empty_image(ob, DRAW_CONSTCOLOR, NULL, v3d->multiview_eye); + draw_empty_image(ob, 0, bcol, v3d->multiview_eye); } else { - drawaxes(rv3d->viewmatob, ob->empty_drawsize, ob->empty_drawtype); + drawaxes(rv3d->viewmatob, ob->empty_drawsize, ob->empty_drawtype, bcol); } break; } } + +void ED_draw_object_facemap(Scene *scene, Object *ob, const float col[4], const int facemap) +{ + DerivedMesh *dm = NULL; + + /* happens on undo */ + if (ob->type != OB_MESH || !ob->data) + return; + + dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH); + if (!dm || !CustomData_has_layer(&dm->polyData, CD_FACEMAP)) + return; + + + glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW); + +#if 0 + DM_update_materials(dm, ob); + + /* add polygon offset so we draw above the original surface */ + glPolygonOffset(1.0, 1.0); + + GPU_facemap_setup(dm); + + glColor4fv(col); + + gpuPushAttrib(GL_ENABLE_BIT); + glEnable(GL_BLEND); + glDisable(GL_LIGHTING); + + /* always draw using backface culling */ + glEnable(GL_CULL_FACE); + glCullFace(GL_BACK); + + if (dm->drawObject->facemapindices) { + glDrawElements(GL_TRIANGLES, dm->drawObject->facemap_count[facemap] * 3, GL_UNSIGNED_INT, + (int *)NULL + dm->drawObject->facemap_start[facemap] * 3); + } + gpuPopAttrib(); + + GPU_buffers_unbind(); + + glPolygonOffset(0.0, 0.0); + +#else + + /* Just to create the data to pass to immediate mode, grr! */ + Mesh *me = ob->data; + const int *facemap_data = CustomData_get_layer(&me->pdata, CD_FACEMAP); + if (facemap_data) { + VertexFormat *format = immVertexFormat(); + unsigned int pos = VertexFormat_add_attrib(format, "pos", COMP_F32, 3, KEEP_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immUniformColor4fv(col); + + /* XXX, alpha isn't working yet, not sure why. */ + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_BLEND); + + MVert *mvert; + + MPoly *mpoly; + int mpoly_len; + + MLoop *mloop; + int mloop_len; + + if (dm && CustomData_has_layer(&dm->polyData, CD_FACEMAP)) { + mvert = dm->getVertArray(dm); + mpoly = dm->getPolyArray(dm); + mloop = dm->getLoopArray(dm); + + mpoly_len = dm->getNumPolys(dm); + mloop_len = dm->getNumLoops(dm); + + facemap_data = CustomData_get_layer(&dm->polyData, CD_FACEMAP); + } + else { + mvert = me->mvert; + mpoly = me->mpoly; + mloop = me->mloop; + + mpoly_len = me->totpoly; + mloop_len = me->totloop; + + facemap_data = CustomData_get_layer(&me->pdata, CD_FACEMAP); + } + + /* use gawain immediate mode fore now */ + const int looptris_len = poly_to_tri_count(mpoly_len, mloop_len); + immBeginAtMost(PRIM_TRIANGLES, looptris_len * 3); + + MPoly *mp; + int i; + for (mp = mpoly, i = 0; i < mpoly_len; i++, mp++) { + if (facemap_data[i] == facemap) { + /* Weak, fan-fill, use until we have derived-mesh replaced. */ + const MLoop *ml_start = &mloop[mp->loopstart]; + const MLoop *ml_a = ml_start + 1; + const MLoop *ml_b = ml_start + 2; + for (int j = 2; j < mp->totloop; j++) { + immVertex3fv(pos, mvert[ml_start->v].co); + immVertex3fv(pos, mvert[ml_a->v].co); + immVertex3fv(pos, mvert[ml_b->v].co); + + ml_a++; + ml_b++; + } + } + } + immEnd(); + + immUnbindProgram(); + + glDisable(GL_BLEND); + } +#endif + + dm->release(dm); +} + |