diff options
author | Ton Roosendaal <ton@blender.org> | 2013-01-22 15:18:41 +0400 |
---|---|---|
committer | Ton Roosendaal <ton@blender.org> | 2013-01-22 15:18:41 +0400 |
commit | e11d22a6b751c750c40226cb027e7805adb7d4e4 (patch) | |
tree | c7a7afd211db440cbcbd154f76379e7685cb03fe /source/blender | |
parent | 1e3a2931ac0cfc9af790717bf19577e22ebda4f5 (diff) |
Matcap support in 3D Viewport.
Full log is here:
http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.66/Usability#Matcap_in_3D_viewport
Implementation notes:
- Matcaps are an extension of Solid draw mode, and don't show in other drawmodes.
(It's mostly intended to aid modeling/sculpt)
- By design, Matcaps are a UI feature, and only stored locally for the UI itself, and
won't affect rendering or materials.
- Currently a set of 16 (GPL licensed) Matcaps have been compiled into Blender.
It doesn't take memory or cpu time, until you use it.
- Brush Icons and Matcaps use same code now, and only get generated/allocated on
actually using it (instead of on startup).
- The current set might get new or different images still, based on user feedback.
- Matcap images are 512x512 pixels, so each image takes 1 Mb memory. Unused matcaps get
freed immediately. The Matcap icon previews (128x128 pixels) stay in memory.
- Loading own matcap image files will be added later. That needs design and code work
to get it stable and memory-friendly.
- The GLSL code uses the ID PreviewImage for matcaps. I tested it using the existing
Material previews, which has its limits... especially for textured previews the
normal-mapped matcap won't look good.
Diffstat (limited to 'source/blender')
24 files changed, 675 insertions, 99 deletions
diff --git a/source/blender/blenkernel/intern/icons.c b/source/blender/blenkernel/intern/icons.c index d8c3e260399..9c265814b8f 100644 --- a/source/blender/blenkernel/intern/icons.c +++ b/source/blender/blenkernel/intern/icons.c @@ -51,6 +51,8 @@ #include "BLO_sys_types.h" // for intptr_t support +#include "GPU_extensions.h" + /* GLOBALS */ static GHash *gIcons = NULL; @@ -138,7 +140,10 @@ void BKE_previewimg_freefunc(void *link) MEM_freeN(prv->rect[i]); prv->rect[i] = NULL; } + if (prv->gputexture[i]) + GPU_texture_free(prv->gputexture[i]); } + MEM_freeN(prv); } } @@ -165,6 +170,7 @@ PreviewImage *BKE_previewimg_copy(PreviewImage *prv) else { prv_img->rect[i] = NULL; } + prv_img->gputexture[i] = NULL; } } return prv_img; diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index f4672fe2b5e..d042e43f9ca 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -1850,8 +1850,8 @@ static PreviewImage *direct_link_preview_image(FileData *fd, PreviewImage *old_p if (prv->rect[i]) { prv->rect[i] = newdataadr(fd, prv->rect[i]); } + prv->gputexture[i] = NULL; } -// prv->gputexture[0] = prv->gputexture[1] = NULL; } return prv; @@ -5998,6 +5998,7 @@ static void direct_link_screen(FileData *fd, bScreen *sc) v3d->afterdraw_xray.first = v3d->afterdraw_xray.last = NULL; v3d->afterdraw_xraytransp.first = v3d->afterdraw_xraytransp.last = NULL; v3d->properties_storage = NULL; + v3d->defmaterial = NULL; /* render can be quite heavy, set to wire on load */ if (v3d->drawtype == OB_RENDER) diff --git a/source/blender/editors/datafiles/CMakeLists.txt b/source/blender/editors/datafiles/CMakeLists.txt index 6d6b7ecdd82..e9b33a6c2a6 100644 --- a/source/blender/editors/datafiles/CMakeLists.txt +++ b/source/blender/editors/datafiles/CMakeLists.txt @@ -81,6 +81,25 @@ if(WITH_BLENDER) data_to_c_simple(../../../../release/datafiles/brushicons/thumb.png SRC) data_to_c_simple(../../../../release/datafiles/brushicons/twist.png SRC) data_to_c_simple(../../../../release/datafiles/brushicons/vertexdraw.png SRC) + + # matcap + data_to_c_simple(../../../../release/datafiles/matcaps/mc01.jpg SRC) + data_to_c_simple(../../../../release/datafiles/matcaps/mc02.jpg SRC) + data_to_c_simple(../../../../release/datafiles/matcaps/mc03.jpg SRC) + data_to_c_simple(../../../../release/datafiles/matcaps/mc04.jpg SRC) + data_to_c_simple(../../../../release/datafiles/matcaps/mc05.jpg SRC) + data_to_c_simple(../../../../release/datafiles/matcaps/mc06.jpg SRC) + data_to_c_simple(../../../../release/datafiles/matcaps/mc07.jpg SRC) + data_to_c_simple(../../../../release/datafiles/matcaps/mc08.jpg SRC) + data_to_c_simple(../../../../release/datafiles/matcaps/mc09.jpg SRC) + data_to_c_simple(../../../../release/datafiles/matcaps/mc10.jpg SRC) + data_to_c_simple(../../../../release/datafiles/matcaps/mc11.jpg SRC) + data_to_c_simple(../../../../release/datafiles/matcaps/mc12.jpg SRC) + data_to_c_simple(../../../../release/datafiles/matcaps/mc13.jpg SRC) + data_to_c_simple(../../../../release/datafiles/matcaps/mc14.jpg SRC) + data_to_c_simple(../../../../release/datafiles/matcaps/mc15.jpg SRC) + data_to_c_simple(../../../../release/datafiles/matcaps/mc16.jpg SRC) + endif() data_to_c_simple(../../../../release/datafiles/startup.blend SRC) diff --git a/source/blender/editors/datafiles/SConscript b/source/blender/editors/datafiles/SConscript index cb6fe11dbb2..49888d573a0 100644 --- a/source/blender/editors/datafiles/SConscript +++ b/source/blender/editors/datafiles/SConscript @@ -77,6 +77,24 @@ sources.extend(( os.path.join(env['DATA_SOURCES'], "thumb.png.c"), os.path.join(env['DATA_SOURCES'], "twist.png.c"), os.path.join(env['DATA_SOURCES'], "vertexdraw.png.c"), + + os.path.join(env['DATA_SOURCES'], "mc01.jpg.c"), + os.path.join(env['DATA_SOURCES'], "mc02.jpg.c"), + os.path.join(env['DATA_SOURCES'], "mc03.jpg.c"), + os.path.join(env['DATA_SOURCES'], "mc04.jpg.c"), + os.path.join(env['DATA_SOURCES'], "mc05.jpg.c"), + os.path.join(env['DATA_SOURCES'], "mc06.jpg.c"), + os.path.join(env['DATA_SOURCES'], "mc07.jpg.c"), + os.path.join(env['DATA_SOURCES'], "mc08.jpg.c"), + os.path.join(env['DATA_SOURCES'], "mc09.jpg.c"), + os.path.join(env['DATA_SOURCES'], "mc10.jpg.c"), + os.path.join(env['DATA_SOURCES'], "mc11.jpg.c"), + os.path.join(env['DATA_SOURCES'], "mc12.jpg.c"), + os.path.join(env['DATA_SOURCES'], "mc13.jpg.c"), + os.path.join(env['DATA_SOURCES'], "mc14.jpg.c"), + os.path.join(env['DATA_SOURCES'], "mc15.jpg.c"), + os.path.join(env['DATA_SOURCES'], "mc16.jpg.c"), + )) env.BlenderLib ( 'bf_editor_datafiles', sources, Split(incs), [], libtype=['core', 'player'], priority=[235, 30] ) diff --git a/source/blender/editors/include/ED_datafiles.h b/source/blender/editors/include/ED_datafiles.h index 6d7bcecc630..afe23090ae3 100644 --- a/source/blender/editors/include/ED_datafiles.h +++ b/source/blender/editors/include/ED_datafiles.h @@ -150,6 +150,57 @@ extern char datatoc_twist_png[]; extern int datatoc_vertexdraw_png_size; extern char datatoc_vertexdraw_png[]; +/* Matcap files */ + +extern int datatoc_mc01_jpg_size; +extern char datatoc_mc01_jpg[]; + +extern int datatoc_mc02_jpg_size; +extern char datatoc_mc02_jpg[]; + +extern int datatoc_mc03_jpg_size; +extern char datatoc_mc03_jpg[]; + +extern int datatoc_mc04_jpg_size; +extern char datatoc_mc04_jpg[]; + +extern int datatoc_mc05_jpg_size; +extern char datatoc_mc05_jpg[]; + +extern int datatoc_mc06_jpg_size; +extern char datatoc_mc06_jpg[]; + +extern int datatoc_mc07_jpg_size; +extern char datatoc_mc07_jpg[]; + +extern int datatoc_mc08_jpg_size; +extern char datatoc_mc08_jpg[]; + +extern int datatoc_mc09_jpg_size; +extern char datatoc_mc09_jpg[]; + +extern int datatoc_mc10_jpg_size; +extern char datatoc_mc10_jpg[]; + +extern int datatoc_mc11_jpg_size; +extern char datatoc_mc11_jpg[]; + +extern int datatoc_mc12_jpg_size; +extern char datatoc_mc12_jpg[]; + +extern int datatoc_mc13_jpg_size; +extern char datatoc_mc13_jpg[]; + +extern int datatoc_mc14_jpg_size; +extern char datatoc_mc14_jpg[]; + +extern int datatoc_mc15_jpg_size; +extern char datatoc_mc15_jpg[]; + +extern int datatoc_mc16_jpg_size; +extern char datatoc_mc16_jpg[]; + + #endif /* __ED_DATAFILES_H__ */ diff --git a/source/blender/editors/include/UI_icons.h b/source/blender/editors/include/UI_icons.h index fa04048ec91..f5ac3f19b5b 100644 --- a/source/blender/editors/include/UI_icons.h +++ b/source/blender/editors/include/UI_icons.h @@ -990,6 +990,24 @@ DEF_ICON(BRUSH_THUMB) DEF_ICON(BRUSH_ROTATE) DEF_ICON(BRUSH_VERTEXDRAW) + /* Matcaps */ +DEF_ICON(MATCAP_01) +DEF_ICON(MATCAP_02) +DEF_ICON(MATCAP_03) +DEF_ICON(MATCAP_04) +DEF_ICON(MATCAP_05) +DEF_ICON(MATCAP_06) +DEF_ICON(MATCAP_07) +DEF_ICON(MATCAP_08) +DEF_ICON(MATCAP_09) +DEF_ICON(MATCAP_10) +DEF_ICON(MATCAP_11) +DEF_ICON(MATCAP_12) +DEF_ICON(MATCAP_13) +DEF_ICON(MATCAP_14) +DEF_ICON(MATCAP_15) +DEF_ICON(MATCAP_16) + /* vector icons, VICO_ prefix added */ DEF_VICO(VIEW3D_VEC) DEF_VICO(EDIT_VEC) diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index 292cc4cdca0..e9cb2eff7e3 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -807,6 +807,7 @@ uiLayout *uiTemplateModifier(uiLayout *layout, struct bContext *C, struct Pointe uiLayout *uiTemplateConstraint(uiLayout *layout, struct PointerRNA *ptr); void uiTemplatePreview(uiLayout *layout, struct ID *id, int show_buttons, struct ID *parent, struct MTex *slot); void uiTemplateColorRamp(uiLayout *layout, struct PointerRNA *ptr, const char *propname, int expand); +void uiTemplateIconView(uiLayout *layout, struct PointerRNA *ptr, const char *propname); void uiTemplateHistogram(uiLayout *layout, struct PointerRNA *ptr, const char *propname); void uiTemplateWaveform(uiLayout *layout, struct PointerRNA *ptr, const char *propname); void uiTemplateVectorscope(uiLayout *layout, struct PointerRNA *ptr, const char *propname); diff --git a/source/blender/editors/include/UI_interface_icons.h b/source/blender/editors/include/UI_interface_icons.h index f578d68b852..10026bbd50f 100644 --- a/source/blender/editors/include/UI_interface_icons.h +++ b/source/blender/editors/include/UI_interface_icons.h @@ -39,6 +39,7 @@ struct World; struct Tex; struct Lamp; struct Material; +struct PreviewImage; struct PointerRNA; typedef struct IconFile { @@ -76,6 +77,8 @@ void UI_icons_free_drawinfo(void *drawinfo); struct ListBase *UI_iconfile_list(void); int UI_iconfile_get_index(const char *filename); +struct PreviewImage *UI_icon_to_preview(int icon_id); + int UI_rnaptr_icon_get(struct bContext *C, struct PointerRNA *ptr, int rnaicon, int big); #endif /* __UI_INTERFACE_ICONS_H__ */ diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c index f002bcbe3b3..4f62a6d90ae 100644 --- a/source/blender/editors/interface/interface_icons.c +++ b/source/blender/editors/interface/interface_icons.c @@ -75,10 +75,6 @@ #include "interface_intern.h" - -// #define ICON_IMAGE_W 600 -// #define ICON_IMAGE_H 640 - #define ICON_GRID_COLS 26 #define ICON_GRID_ROWS 30 @@ -89,7 +85,9 @@ typedef struct IconImage { int w; int h; - unsigned int *rect; + unsigned int *rect; + unsigned char *datatoc_rect; + int datatoc_size; } IconImage; typedef void (*VectorDrawFunc)(int x, int y, int w, int h, float alpha); @@ -132,13 +130,12 @@ static IconTexture icongltex = {0, 0, 0, 0.0f, 0.0f}; /* **************************************************** */ -static void def_internal_icon(ImBuf *bbuf, int icon_id, int xofs, int yofs, int size, int type) + +static DrawInfo *def_internal_icon(ImBuf *bbuf, int icon_id, int xofs, int yofs, int size, int type) { Icon *new_icon = NULL; IconImage *iimg = NULL; DrawInfo *di; - int y = 0; - int imgsize = 0; new_icon = MEM_callocN(sizeof(Icon), "texicon"); @@ -155,17 +152,27 @@ static void def_internal_icon(ImBuf *bbuf, int icon_id, int xofs, int yofs, int di->data.texture.h = size; } else if (type == ICON_TYPE_BUFFER) { - iimg = MEM_mallocN(sizeof(IconImage), "icon_img"); - iimg->rect = MEM_mallocN(size * size * sizeof(unsigned int), "icon_rect"); + iimg = MEM_callocN(sizeof(IconImage), "icon_img"); iimg->w = size; iimg->h = size; - /* Here we store the rect in the icon - same as before */ - imgsize = bbuf->x; - for (y = 0; y < size; y++) { - memcpy(&iimg->rect[y * size], &bbuf->rect[(y + yofs) * imgsize + xofs], size * sizeof(int)); + /* icon buffers can get initialized runtime now, via datatoc */ + if (bbuf) { + int y, imgsize; + + iimg->rect = MEM_mallocN(size * size * sizeof(unsigned int), "icon_rect"); + + /* Here we store the rect in the icon - same as before */ + if (size == bbuf->x && size == bbuf->y && xofs == 0 && yofs == 0) + memcpy(iimg->rect, bbuf->rect, size * size * sizeof(int)); + else { + /* this code assumes square images */ + imgsize = bbuf->x; + for (y = 0; y < size; y++) { + memcpy(&iimg->rect[y * size], &bbuf->rect[(y + yofs) * imgsize + xofs], imgsize * sizeof(int)); + } + } } - di->data.buffer.image = iimg; } @@ -173,6 +180,8 @@ static void def_internal_icon(ImBuf *bbuf, int icon_id, int xofs, int yofs, int new_icon->drawinfo = di; BKE_icon_set(icon_id, new_icon); + + return di; } static void def_internal_vicon(int icon_id, VectorDrawFunc drawFunc) @@ -463,21 +472,19 @@ static void vicon_move_down_draw(int x, int y, int w, int h, float UNUSED(alpha) static void init_brush_icons(void) { -#define INIT_BRUSH_ICON(icon_id, name) \ - { \ - bbuf = IMB_ibImageFromMemory((unsigned char *)datatoc_ ##name## _png, \ - datatoc_ ##name## _png_size, \ - IB_rect, NULL, "<brush icon>"); \ - if (bbuf) { \ - IMB_premultiply_alpha(bbuf); \ - def_internal_icon(bbuf, icon_id, 0, 0, w, ICON_TYPE_BUFFER); \ - } \ - IMB_freeImBuf(bbuf); \ - } (void)0 +#define INIT_BRUSH_ICON(icon_id, name) \ + { \ + unsigned char *rect = (unsigned char *)datatoc_ ##name## _png; \ + int size = datatoc_ ##name## _png_size; \ + DrawInfo *di; \ + \ + di = def_internal_icon(NULL, icon_id, 0, 0, w, ICON_TYPE_BUFFER); \ + di->data.buffer.image->datatoc_rect = rect; \ + di->data.buffer.image->datatoc_size = size; \ + } /* end INIT_BRUSH_ICON */ - ImBuf *bbuf; - const int w = 96; + const int w = 96; /* warning, brush size hardcoded in C, but it gets scaled */ INIT_BRUSH_ICON(ICON_BRUSH_ADD, add); INIT_BRUSH_ICON(ICON_BRUSH_BLOB, blob); @@ -513,6 +520,60 @@ static void init_brush_icons(void) #undef INIT_BRUSH_ICON } +static void icon_verify_datatoc(IconImage *iimg) +{ + /* if it has own rect, things are all OK */ + if (iimg->rect) + return; + + if (iimg->datatoc_rect) { + ImBuf *bbuf = IMB_ibImageFromMemory(iimg->datatoc_rect, + iimg->datatoc_size, IB_rect, NULL, "<matcap icon>"); + /* w and h were set on initialize */ + if (bbuf->x != iimg->h && bbuf->y != iimg->w) + IMB_scalefastImBuf(bbuf, iimg->w, iimg->h); + + iimg->rect = bbuf->rect; + bbuf->rect = NULL; + IMB_freeImBuf(bbuf); + } +} + +static void init_matcap_icons(void) +{ + /* dynamic allocation now, tucking datatoc pointers in DrawInfo */ +#define INIT_MATCAP_ICON(icon_id, name) \ + { \ + unsigned char *rect = (unsigned char *)datatoc_ ##name## _jpg; \ + int size = datatoc_ ##name## _jpg_size; \ + DrawInfo *di; \ + \ + di = def_internal_icon(NULL, icon_id, 0, 0, 128, ICON_TYPE_BUFFER); \ + di->data.buffer.image->datatoc_rect = rect; \ + di->data.buffer.image->datatoc_size = size; \ + } + + INIT_MATCAP_ICON(ICON_MATCAP_01, mc01); + INIT_MATCAP_ICON(ICON_MATCAP_02, mc02); + INIT_MATCAP_ICON(ICON_MATCAP_03, mc03); + INIT_MATCAP_ICON(ICON_MATCAP_04, mc04); + INIT_MATCAP_ICON(ICON_MATCAP_05, mc05); + INIT_MATCAP_ICON(ICON_MATCAP_06, mc06); + INIT_MATCAP_ICON(ICON_MATCAP_07, mc07); + INIT_MATCAP_ICON(ICON_MATCAP_08, mc08); + INIT_MATCAP_ICON(ICON_MATCAP_09, mc09); + INIT_MATCAP_ICON(ICON_MATCAP_10, mc10); + INIT_MATCAP_ICON(ICON_MATCAP_11, mc11); + INIT_MATCAP_ICON(ICON_MATCAP_12, mc12); + INIT_MATCAP_ICON(ICON_MATCAP_13, mc13); + INIT_MATCAP_ICON(ICON_MATCAP_14, mc14); + INIT_MATCAP_ICON(ICON_MATCAP_15, mc15); + INIT_MATCAP_ICON(ICON_MATCAP_16, mc16); + +#undef INIT_MATCAP_ICON + +} + static void init_internal_icons(void) { // bTheme *btheme = UI_GetTheme(); @@ -762,7 +823,8 @@ void UI_icons_free_drawinfo(void *drawinfo) if (di) { if (di->type == ICON_TYPE_BUFFER) { if (di->data.buffer.image) { - MEM_freeN(di->data.buffer.image->rect); + if (di->data.buffer.image->rect) + MEM_freeN(di->data.buffer.image->rect); MEM_freeN(di->data.buffer.image); } } @@ -842,6 +904,7 @@ void UI_icons_init(int first_dyn_id) BKE_icons_init(first_dyn_id); init_internal_icons(); init_brush_icons(); + init_matcap_icons(); #endif } @@ -891,6 +954,34 @@ static void icon_set_image(bContext *C, ID *id, PreviewImage *prv_img, enum eIco prv_img->w[size], prv_img->h[size]); } +PreviewImage *UI_icon_to_preview(int icon_id) +{ + Icon *icon = BKE_icon_get(icon_id); + + if (icon) { + DrawInfo *di = (DrawInfo *)icon->drawinfo; + if (di && di->data.buffer.image) { + ImBuf *bbuf; + + bbuf = IMB_ibImageFromMemory(di->data.buffer.image->datatoc_rect, di->data.buffer.image->datatoc_size, IB_rect, NULL, "<matcap buffer>"); + if (bbuf) { + PreviewImage *prv = BKE_previewimg_create(); + + prv->rect[0] = bbuf->rect; + + prv->w[0] = bbuf->x; + prv->h[0] = bbuf->y; + + bbuf->rect = NULL; + IMB_freeImBuf(bbuf); + + return prv; + } + } + } + return NULL; +} + static void icon_draw_rect(float x, float y, int w, int h, float UNUSED(aspect), int rw, int rh, unsigned int *rect, float alpha, const float rgb[3], short is_preview) { @@ -994,6 +1085,8 @@ static int get_draw_size(enum eIconSizes size) return 0; } + + static void icon_draw_size(float x, float y, int icon_id, float aspect, float alpha, const float rgb[3], enum eIconSizes size, int draw_size, int UNUSED(nocreate), short is_preview) { @@ -1042,6 +1135,8 @@ static void icon_draw_size(float x, float y, int icon_id, float aspect, float al /* it is a builtin icon */ iimg = di->data.buffer.image; + icon_verify_datatoc(iimg); + if (!iimg->rect) return; /* something has gone wrong! */ glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index ec212bb18ff..70a367256ed 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -1554,6 +1554,88 @@ void uiTemplateColorRamp(uiLayout *layout, PointerRNA *ptr, const char *propname MEM_freeN(cb); } + +/********************* Icon viewer Template ************************/ + +/* ID Search browse menu, open */ +static uiBlock *icon_view_menu(bContext *C, ARegion *ar, void *arg_litem) +{ + static RNAUpdateCb cb; + uiBlock *block; + uiBut *but; + int icon; + EnumPropertyItem *item; + int a, free; + + /* arg_litem is malloced, can be freed by parent button */ + cb = *((RNAUpdateCb *)arg_litem); + + icon = RNA_property_enum_get(&cb.ptr, cb.prop); + + block = uiBeginBlock(C, ar, "_popup", UI_EMBOSS); + uiBlockSetFlag(block, UI_BLOCK_LOOP | UI_BLOCK_REDRAW); + + + RNA_property_enum_items(C, &cb.ptr, cb.prop, &item, NULL, &free); + + for (a = 0; item[a].identifier; a++) { + int x, y; + + x = (a % 8) * UI_UNIT_X * 6; + y = (a / 8) * UI_UNIT_X * 6; + + icon = item[a].icon; + but = uiDefIconButR_prop(block, ROW, 0, icon, x, y, UI_UNIT_X * 6, UI_UNIT_Y * 6, &cb.ptr, cb.prop, -1, 0, icon, -1, -1, NULL); + uiButSetFlag(but, UI_HAS_ICON | UI_ICON_PREVIEW); + } + + uiBoundsBlock(block, 0.3f * U.widget_unit); + uiBlockSetDirection(block, UI_TOP); + uiEndBlock(C, block); + + if (free) { + MEM_freeN(item); + } + + return block; +} + +void uiTemplateIconView(uiLayout *layout, PointerRNA *ptr, const char *propname) +{ + PropertyRNA *prop = RNA_struct_find_property(ptr, propname); + RNAUpdateCb *cb; + uiBlock *block; + uiBut *but; + rctf rect; + int icon; + + if (!prop || RNA_property_type(prop) != PROP_ENUM) + return; + + icon = RNA_property_enum_get(ptr, prop); + + cb = MEM_callocN(sizeof(RNAUpdateCb), "RNAUpdateCb"); + cb->ptr = *ptr; + cb->prop = prop; + + rect.xmin = 0; rect.xmax = 10.0f * UI_UNIT_X; + rect.ymin = 0; rect.ymax = 10.0f * UI_UNIT_X; + + block = uiLayoutAbsoluteBlock(layout); + + but = uiDefBlockButN(block, icon_view_menu, MEM_dupallocN(cb), "", 0, 0, UI_UNIT_X * 6, UI_UNIT_Y * 6, ""); + + +// but = uiDefIconButR_prop(block, ROW, 0, icon, 0, 0, BLI_rctf_size_x(&rect), BLI_rctf_size_y(&rect), ptr, prop, -1, 0, icon, -1, -1, NULL); + + but->icon = icon; + uiButSetFlag(but, UI_HAS_ICON | UI_ICON_PREVIEW); + + uiButSetNFunc(but, rna_update_cb, MEM_dupallocN(cb), NULL); + + MEM_freeN(cb); +} + /********************* Histogram Template ************************/ void uiTemplateHistogram(uiLayout *layout, PointerRNA *ptr, const char *propname) diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index bf9cd4f6334..63ffe54aeed 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -88,6 +88,7 @@ #include "ED_types.h" #include "UI_resources.h" +#include "UI_interface_icons.h" #include "WM_api.h" #include "BLF_api.h" @@ -175,8 +176,9 @@ static int check_object_draw_texture(Scene *scene, View3D *v3d, int drawtype) return TRUE; /* textured solid */ - if (v3d->drawtype == OB_SOLID && (v3d->flag2 & V3D_SOLID_TEX) && !BKE_scene_use_new_shading_nodes(scene)) - return TRUE; + if (v3d->drawtype == OB_SOLID && (v3d->flag2 & (V3D_SOLID_TEX | V3D_SHOW_SOLID_MATCAP)) + && !BKE_scene_use_new_shading_nodes(scene)) + return TRUE; return FALSE; } @@ -219,6 +221,9 @@ int draw_glsl_material(Scene *scene, Object *ob, View3D *v3d, const char dt) if (BKE_scene_use_new_shading_nodes(scene)) return 0; + if (v3d->flag2 & V3D_SHOW_SOLID_MATCAP) + return 1; + return (scene->gm.matmode == GAME_MAT_GLSL) && (dt > OB_SOLID); } @@ -6224,6 +6229,34 @@ static void draw_object_wire_color(Scene *scene, Base *base, unsigned char r_ob_ r_ob_wire_col[3] = 255; } +static void draw_object_matcap_check(Scene *scene, View3D *v3d, Object *ob) +{ + /* fixed rule, active object draws as matcap */ + if (ob == OBACT) { + if (ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT)) + return; + + if (v3d->defmaterial == NULL) { + extern Material defmaterial; + + v3d->defmaterial = MEM_mallocN(sizeof(Material), "matcap material"); + *(v3d->defmaterial) = defmaterial; + v3d->defmaterial->gpumaterial.first = v3d->defmaterial->gpumaterial.last = NULL; + v3d->defmaterial->preview = NULL; + } + /* first time users */ + if (v3d->matcap_icon == 0) + v3d->matcap_icon = ICON_MATCAP_01; + + if (v3d->defmaterial->preview == NULL) + v3d->defmaterial->preview = UI_icon_to_preview(v3d->matcap_icon); + + /* signal to all material checks, gets cleared below */ + v3d->flag2 |= V3D_SHOW_SOLID_MATCAP; + } + +} + /** * main object drawing function, draws in selection * \param dflag (draw flag) can be DRAW_PICKING and/or DRAW_CONSTCOLOR, DRAW_SCENESET @@ -6313,6 +6346,10 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short dt = MIN2(dt, ob->dt); if (v3d->zbuf == 0 && dt > OB_WIRE) dt = OB_WIRE; dtx = 0; + + /* matcap check */ + if (dt == OB_SOLID && (v3d->flag2 & V3D_SOLID_MATCAP)) + draw_object_matcap_check(scene, v3d, ob); /* faceselect exception: also draw solid when (dt == wire), except in editmode */ if (is_obact && (ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT))) { @@ -6813,7 +6850,9 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short /* return warning, this is cached text draw */ invert_m4_m4(ob->imat, ob->obmat); view3d_cached_text_draw_end(v3d, ar, 1, NULL); - + /* return warning, clear temp flag */ + v3d->flag2 &= ~V3D_SHOW_SOLID_MATCAP; + glLoadMatrixf(rv3d->viewmat); if (zbufoff) { diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c index 09bf029154c..b2d58cf41de 100644 --- a/source/blender/editors/space_view3d/space_view3d.c +++ b/source/blender/editors/space_view3d/space_view3d.c @@ -32,6 +32,7 @@ #include <string.h> #include <stdio.h> +#include "DNA_material_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" @@ -42,16 +43,18 @@ #include "BLI_rand.h" #include "BLI_utildefines.h" -#include "BKE_object.h" #include "BKE_context.h" +#include "BKE_icons.h" +#include "BKE_object.h" #include "BKE_screen.h" #include "ED_space_api.h" #include "ED_screen.h" #include "ED_object.h" -#include "BIF_gl.h" +#include "GPU_material.h" +#include "BIF_gl.h" #include "WM_api.h" #include "WM_types.h" @@ -335,6 +338,14 @@ static void view3d_free(SpaceLink *sl) if (vd->localvd) MEM_freeN(vd->localvd); if (vd->properties_storage) MEM_freeN(vd->properties_storage); + + /* matcap material, its preview rect gets freed via icons */ + if (vd->defmaterial) { + if (vd->defmaterial->gpumaterial.first) + GPU_material_free(vd->defmaterial); + BKE_previewimg_free(&vd->defmaterial->preview); + MEM_freeN(vd->defmaterial); + } } @@ -365,6 +376,8 @@ static SpaceLink *view3d_duplicate(SpaceLink *sl) /* copy or clear inside new stuff */ + v3dn->defmaterial = NULL; + BLI_duplicatelist(&v3dn->bgpicbase, &v3do->bgpicbase); v3dn->properties_storage = NULL; diff --git a/source/blender/gpu/GPU_extensions.h b/source/blender/gpu/GPU_extensions.h index 7eaa4084e61..66a7c917a55 100644 --- a/source/blender/gpu/GPU_extensions.h +++ b/source/blender/gpu/GPU_extensions.h @@ -38,7 +38,8 @@ extern "C" { struct Image; struct ImageUser; - +struct PreviewImage; + struct GPUTexture; typedef struct GPUTexture GPUTexture; @@ -112,6 +113,8 @@ GPUTexture *GPU_texture_create_depth(int w, int h, char err_out[256]); GPUTexture *GPU_texture_create_vsm_shadow_map(int size, char err_out[256]); GPUTexture *GPU_texture_from_blender(struct Image *ima, struct ImageUser *iuser, int isdata, double time, int mipmap); +GPUTexture *GPU_texture_from_preview(struct PreviewImage *prv, int mipmap); + void GPU_texture_free(GPUTexture *tex); void GPU_texture_ref(GPUTexture *tex); diff --git a/source/blender/gpu/GPU_material.h b/source/blender/gpu/GPU_material.h index 22cfdab6043..17d3ce3cd73 100644 --- a/source/blender/gpu/GPU_material.h +++ b/source/blender/gpu/GPU_material.h @@ -54,6 +54,7 @@ struct GPUNodeStack; struct GPUMaterial; struct GPUTexture; struct GPULamp; +struct PreviewImage; typedef struct GPUNode GPUNode; typedef struct GPUNodeLink GPUNodeLink; @@ -108,6 +109,7 @@ GPUNodeLink *GPU_attribute(int type, const char *name); GPUNodeLink *GPU_uniform(float *num); GPUNodeLink *GPU_dynamic_uniform(float *num, int dynamictype, void *data); GPUNodeLink *GPU_image(struct Image *ima, struct ImageUser *iuser, int isdata); +GPUNodeLink *GPU_image_preview(struct PreviewImage *prv); GPUNodeLink *GPU_texture(int size, float *pixels); GPUNodeLink *GPU_dynamic_texture(struct GPUTexture *tex, int dynamictype, void *data); GPUNodeLink *GPU_builtin(GPUBuiltin builtin); @@ -122,6 +124,7 @@ GPUBlendMode GPU_material_alpha_blend(GPUMaterial *material, float obcol[4]); /* High level functions to create and use GPU materials */ GPUMaterial *GPU_material_from_blender(struct Scene *scene, struct Material *ma); +GPUMaterial *GPU_material_matcap(struct Scene *scene, struct Material *ma); void GPU_material_free(struct Material *ma); void GPU_materials_free(void); diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c index 4432627ee7e..b27a4be9f21 100644 --- a/source/blender/gpu/intern/gpu_codegen.c +++ b/source/blender/gpu/intern/gpu_codegen.c @@ -68,6 +68,9 @@ static char *glsl_material_library = NULL; static const char* GPU_DATATYPE_STR[17] = {"", "float", "vec2", "vec3", "vec4", NULL, NULL, NULL, NULL, "mat3", NULL, NULL, NULL, NULL, NULL, NULL, "mat4"}; +#define LINK_IMAGE_BLENDER 1 +#define LINK_IMAGE_PREVIEW 2 + /* GLSL code parsing for finding function definitions. * These are stored in a hash for lookup when creating a material. */ @@ -339,7 +342,7 @@ static int codegen_input_has_texture(GPUInput *input) { if (input->link) return 0; - else if (input->ima) + else if (input->ima || input->prv) return 1; else return input->tex != NULL; @@ -411,6 +414,17 @@ static void codegen_set_unique_ids(ListBase *nodes) else input->texid = GET_INT_FROM_POINTER(BLI_ghash_lookup(bindhash, input->ima)); } + else if (input->prv) { + /* input is texture from preview render, assign only one texid per + * buffer to avoid sampling the same texture twice */ + if (!BLI_ghash_haskey(bindhash, input->prv)) { + input->texid = texid++; + input->bindtex = 1; + BLI_ghash_insert(bindhash, input->prv, SET_INT_IN_POINTER(input->texid)); + } + else + input->texid = GET_INT_FROM_POINTER(BLI_ghash_lookup(bindhash, input->prv)); + } else { if (!BLI_ghash_haskey(bindhash, input->tex)) { /* input is user created texture, check tex pointer */ @@ -718,7 +732,7 @@ static void GPU_nodes_extract_dynamic_inputs(GPUPass *pass, ListBase *nodes) continue; } - if (input->ima || input->tex) + if (input->ima || input->tex || input->prv) BLI_snprintf(input->shadername, sizeof(input->shadername), "samp%d", input->texid); else BLI_snprintf(input->shadername, sizeof(input->shadername), "unf%d", input->id); @@ -726,7 +740,7 @@ static void GPU_nodes_extract_dynamic_inputs(GPUPass *pass, ListBase *nodes) /* pass non-dynamic uniforms to opengl */ extract = 0; - if (input->ima || input->tex) { + if (input->ima || input->tex || input->prv) { if (input->bindtex) extract = 1; } @@ -762,11 +776,14 @@ void GPU_pass_bind(GPUPass *pass, double time, int mipmap) for (input=inputs->first; input; input=input->next) { if (input->ima) input->tex = GPU_texture_from_blender(input->ima, input->iuser, input->image_isdata, time, mipmap); + else if (input->prv) + input->tex = GPU_texture_from_preview(input->prv, mipmap); if (input->tex && input->bindtex) { GPU_texture_bind(input->tex, input->texid); GPU_shader_uniform_texture(shader, input->shaderloc, input->tex); } + } } @@ -781,7 +798,7 @@ void GPU_pass_update_uniforms(GPUPass *pass) /* pass dynamic inputs to opengl, others were removed */ for (input=inputs->first; input; input=input->next) - if (!(input->ima || input->tex)) + if (!(input->ima || input->tex || input->prv)) GPU_shader_uniform_vector(shader, input->shaderloc, input->type, 1, input->dynamicvec); } @@ -799,7 +816,7 @@ void GPU_pass_unbind(GPUPass *pass) if (input->tex && input->bindtex) GPU_texture_unbind(input->tex); - if (input->ima) + if (input->ima || input->prv) input->tex = NULL; } @@ -915,9 +932,13 @@ static void gpu_node_input_link(GPUNode *node, GPUNodeLink *link, int type) input->type = GPU_VEC4; input->source = GPU_SOURCE_TEX; - input->ima = link->ptr1; - input->iuser = link->ptr2; - input->image_isdata = link->image_isdata; + if (link->image == LINK_IMAGE_PREVIEW) + input->prv = link->ptr1; + else { + input->ima = link->ptr1; + input->iuser = link->ptr2; + input->image_isdata = link->image_isdata; + } input->textarget = GL_TEXTURE_2D; input->textype = GPU_TEX2D; MEM_freeN(link); @@ -1117,7 +1138,7 @@ GPUNodeLink *GPU_image(Image *ima, ImageUser *iuser, int isdata) { GPUNodeLink *link = GPU_node_link_create(0); - link->image= 1; + link->image= LINK_IMAGE_BLENDER; link->ptr1= ima; link->ptr2= iuser; link->image_isdata= isdata; @@ -1125,6 +1146,17 @@ GPUNodeLink *GPU_image(Image *ima, ImageUser *iuser, int isdata) return link; } +GPUNodeLink *GPU_image_preview(PreviewImage *prv) +{ + GPUNodeLink *link = GPU_node_link_create(0); + + link->image= LINK_IMAGE_PREVIEW; + link->ptr1= prv; + + return link; +} + + GPUNodeLink *GPU_texture(int size, float *pixels) { GPUNodeLink *link = GPU_node_link_create(0); diff --git a/source/blender/gpu/intern/gpu_codegen.h b/source/blender/gpu/intern/gpu_codegen.h index f61f34908c5..2e4cfe2e37c 100644 --- a/source/blender/gpu/intern/gpu_codegen.h +++ b/source/blender/gpu/intern/gpu_codegen.h @@ -43,6 +43,7 @@ struct GPUOutput; struct GPUNode; struct GPUVertexAttribs; struct GPUFrameBuffer; +struct PreviewImage; #define MAX_FUNCTION_NAME 64 #define MAX_PARAMETER 32 @@ -138,6 +139,7 @@ typedef struct GPUInput { struct Image *ima; /* image */ struct ImageUser *iuser;/* image user */ + struct PreviewImage *prv; /* preview images & icons */ int image_isdata; /* image does not contain color data */ float *dynamicvec; /* vector data in case it is dynamic */ int dynamictype; /* origin of the dynamic uniform (GPUDynamicType) */ diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c index 254899e6e07..90a92dbcddc 100644 --- a/source/blender/gpu/intern/gpu_draw.c +++ b/source/blender/gpu/intern/gpu_draw.c @@ -664,6 +664,7 @@ int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, int compare, int return *bind; } +/* Image *ima can be NULL */ void GPU_create_gl_tex(unsigned int *bind, unsigned int *pix, float * frect, int rectw, int recth, int mipmap, int use_high_bit_depth, Image *ima) { unsigned int *scalerect = NULL; @@ -723,7 +724,8 @@ void GPU_create_gl_tex(unsigned int *bind, unsigned int *pix, float * frect, int glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gpu_get_mipmap_filter(0)); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1)); - ima->tpageflag |= IMA_MIPMAP_COMPLETE; + if (ima) + ima->tpageflag |= IMA_MIPMAP_COMPLETE; } if (GLEW_EXT_texture_filter_anisotropic) @@ -1283,10 +1285,9 @@ void GPU_begin_object_materials(View3D *v3d, RegionView3D *rv3d, Scene *scene, O GPUMaterial *gpumat; GPUBlendMode alphablend; int a; - int gamma = BKE_scene_check_color_management_enabled(scene); - int new_shading_nodes = BKE_scene_use_new_shading_nodes(scene); + int use_matcap = (v3d->flag2 & V3D_SHOW_SOLID_MATCAP); /* assumes v3d->defmaterial->preview is set */ /* initialize state */ memset(&GMS, 0, sizeof(GMS)); @@ -1298,7 +1299,7 @@ void GPU_begin_object_materials(View3D *v3d, RegionView3D *rv3d, Scene *scene, O GMS.gob = ob; GMS.gscene = scene; - GMS.totmat= ob->totcol+1; /* materials start from 1, default material is 0 */ + GMS.totmat= use_matcap? 1 : ob->totcol+1; /* materials start from 1, default material is 0 */ GMS.glay= (v3d->localvd)? v3d->localvd->lay: v3d->lay; /* keep lamps visible in local view */ GMS.gviewmat= rv3d->viewmat; GMS.gviewinv= rv3d->viewinv; @@ -1324,59 +1325,72 @@ void GPU_begin_object_materials(View3D *v3d, RegionView3D *rv3d, Scene *scene, O GMS.alphablend= GMS.alphablend_fixed; } - /* no materials assigned? */ - if (ob->totcol==0) { - gpu_material_to_fixed(&GMS.matbuf[0], &defmaterial, 0, ob, new_shading_nodes); - + /* viewport material, setup in space_view3d, defaults to matcap using ma->preview now */ + if (use_matcap) { + GMS.gmatbuf[0] = v3d->defmaterial; + GPU_material_matcap(scene, v3d->defmaterial); + /* do material 1 too, for displists! */ memcpy(&GMS.matbuf[1], &GMS.matbuf[0], sizeof(GPUMaterialFixed)); - - if (glsl) { - GMS.gmatbuf[0]= &defmaterial; - GPU_material_from_blender(GMS.gscene, &defmaterial); - } - + GMS.alphablend[0]= GPU_BLEND_SOLID; } + else { - /* setup materials */ - for (a=1; a<=ob->totcol; a++) { - /* find a suitable material */ - ma= give_current_material(ob, a); - if (!glsl && !new_shading_nodes) ma= gpu_active_node_material(ma); - if (ma==NULL) ma= &defmaterial; - - /* create glsl material if requested */ - gpumat = (glsl)? GPU_material_from_blender(GMS.gscene, ma): NULL; - - if (gpumat) { - /* do glsl only if creating it succeed, else fallback */ - GMS.gmatbuf[a]= ma; - alphablend = GPU_material_alpha_blend(gpumat, ob->col); - } - else { - /* fixed function opengl materials */ - gpu_material_to_fixed(&GMS.matbuf[a], ma, gamma, ob, new_shading_nodes); + /* no materials assigned? */ + if (ob->totcol==0) { + gpu_material_to_fixed(&GMS.matbuf[0], &defmaterial, 0, ob, new_shading_nodes); + + /* do material 1 too, for displists! */ + memcpy(&GMS.matbuf[1], &GMS.matbuf[0], sizeof(GPUMaterialFixed)); - if (GMS.use_alpha_pass) { - GMS.matbuf[a].diff[3]= ma->alpha; - alphablend = (ma->alpha == 1.0f)? GPU_BLEND_SOLID: GPU_BLEND_ALPHA; + if (glsl) { + GMS.gmatbuf[0]= &defmaterial; + GPU_material_from_blender(GMS.gscene, &defmaterial); + } + + GMS.alphablend[0]= GPU_BLEND_SOLID; + } + + /* setup materials */ + for (a=1; a<=ob->totcol; a++) { + /* find a suitable material */ + ma= give_current_material(ob, a); + if (!glsl && !new_shading_nodes) ma= gpu_active_node_material(ma); + if (ma==NULL) ma= &defmaterial; + + /* create glsl material if requested */ + gpumat = (glsl)? GPU_material_from_blender(GMS.gscene, ma): NULL; + + if (gpumat) { + /* do glsl only if creating it succeed, else fallback */ + GMS.gmatbuf[a]= ma; + alphablend = GPU_material_alpha_blend(gpumat, ob->col); } else { - GMS.matbuf[a].diff[3]= 1.0f; - alphablend = GPU_BLEND_SOLID; + /* fixed function opengl materials */ + gpu_material_to_fixed(&GMS.matbuf[a], ma, gamma, ob, new_shading_nodes); + + if (GMS.use_alpha_pass) { + GMS.matbuf[a].diff[3]= ma->alpha; + alphablend = (ma->alpha == 1.0f)? GPU_BLEND_SOLID: GPU_BLEND_ALPHA; + } + else { + GMS.matbuf[a].diff[3]= 1.0f; + alphablend = GPU_BLEND_SOLID; + } } - } - /* setting 'do_alpha_after = TRUE' indicates this object needs to be - * drawn in a second alpha pass for improved blending */ - if (do_alpha_after && !GMS.is_alpha_pass) - if (ELEM3(alphablend, GPU_BLEND_ALPHA, GPU_BLEND_ADD, GPU_BLEND_ALPHA_SORT)) - *do_alpha_after = TRUE; + /* setting 'do_alpha_after = TRUE' indicates this object needs to be + * drawn in a second alpha pass for improved blending */ + if (do_alpha_after && !GMS.is_alpha_pass) + if (ELEM3(alphablend, GPU_BLEND_ALPHA, GPU_BLEND_ADD, GPU_BLEND_ALPHA_SORT)) + *do_alpha_after = TRUE; - GMS.alphablend[a]= alphablend; + GMS.alphablend[a]= alphablend; + } } - + /* let's start with a clean state */ GPU_disable_material(); } diff --git a/source/blender/gpu/intern/gpu_extensions.c b/source/blender/gpu/intern/gpu_extensions.c index bc859d0ec07..0ef60aaf978 100644 --- a/source/blender/gpu/intern/gpu_extensions.c +++ b/source/blender/gpu/intern/gpu_extensions.c @@ -539,6 +539,7 @@ GPUTexture *GPU_texture_from_blender(Image *ima, ImageUser *iuser, int isdata, d glGetIntegerv(GL_TEXTURE_BINDING_2D, &lastbindcode); GPU_update_image_time(ima, time); + /* this binds a texture, so that's why to restore it with lastbindcode */ bindcode = GPU_verify_image(ima, iuser, 0, 0, mipmap, isdata); if (ima->gputexture) { @@ -579,6 +580,59 @@ GPUTexture *GPU_texture_from_blender(Image *ima, ImageUser *iuser, int isdata, d return tex; } +GPUTexture *GPU_texture_from_preview(PreviewImage *prv, int mipmap) +{ + GPUTexture *tex = prv->gputexture[0]; + GLint w, h, lastbindcode; + GLuint bindcode = 0; + + glGetIntegerv(GL_TEXTURE_BINDING_2D, &lastbindcode); + + if (tex) + bindcode = tex->bindcode; + + /* this binds a texture, so that's why to restore it */ + if (bindcode == 0) { + GPU_create_gl_tex(&bindcode, prv->rect[0], NULL, prv->w[0], prv->h[0], mipmap, 0, NULL); + } + if (tex) { + tex->bindcode = bindcode; + glBindTexture(GL_TEXTURE_2D, lastbindcode); + return tex; + } + + /* error binding anything */ + if (!bindcode) { + glBindTexture(GL_TEXTURE_2D, lastbindcode); + return NULL; + } + + tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture"); + tex->bindcode = bindcode; + tex->number = -1; + tex->refcount = 1; + tex->target = GL_TEXTURE_2D; + + prv->gputexture[0]= tex; + + if (!glIsTexture(tex->bindcode)) { + GPU_print_error("Blender Texture"); + } + else { + glBindTexture(GL_TEXTURE_2D, tex->bindcode); + glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &w); + glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &h); + + tex->w = w; + tex->h = h; + } + + glBindTexture(GL_TEXTURE_2D, lastbindcode); + + return tex; + +} + GPUTexture *GPU_texture_create_1D(int w, float *fpixels, char err_out[256]) { GPUTexture *tex = GPU_texture_create_nD(w, 1, 1, fpixels, 0, err_out); diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c index f6403e9359d..9731d7a6b3a 100644 --- a/source/blender/gpu/intern/gpu_material.c +++ b/source/blender/gpu/intern/gpu_material.c @@ -1506,6 +1506,52 @@ static GPUNodeLink *gpu_material_diffuse_bsdf(GPUMaterial *mat, Material *ma) return outlink; } +static GPUNodeLink *gpu_material_preview_matcap(GPUMaterial *mat, Material *ma) +{ + GPUNodeLink *outlink; + + GPU_link(mat, "material_preview_matcap", GPU_uniform(&ma->r), GPU_image_preview(ma->preview), GPU_builtin(GPU_VIEW_NORMAL), &outlink); + + return outlink; +} + +/* new solid draw mode with glsl matcaps */ +GPUMaterial *GPU_material_matcap(Scene *scene, Material *ma) +{ + GPUMaterial *mat; + GPUNodeLink *outlink; + LinkData *link; + + for (link=ma->gpumaterial.first; link; link=link->next) + if (((GPUMaterial*)link->data)->scene == scene) + return link->data; + + /* allocate material */ + mat = GPU_material_construct_begin(ma); + mat->scene = scene; + + if (ma->preview && ma->preview->rect[0]) { + outlink = gpu_material_preview_matcap(mat, ma); + } + else { + outlink = gpu_material_diffuse_bsdf(mat, ma); + } + + GPU_material_output_link(mat, outlink); + + GPU_material_construct_end(mat); + + /* note that even if building the shader fails in some way, we still keep + * it to avoid trying to compile again and again, and simple do not use + * the actual shader on drawing */ + + link = MEM_callocN(sizeof(LinkData), "GPUMaterialLink"); + link->data = mat; + BLI_addtail(&ma->gpumaterial, link); + + return mat; +} + GPUMaterial *GPU_material_from_blender(Scene *scene, Material *ma) { GPUMaterial *mat; diff --git a/source/blender/gpu/shaders/gpu_shader_material.glsl b/source/blender/gpu/shaders/gpu_shader_material.glsl index e89be91c89a..45e7831d20d 100644 --- a/source/blender/gpu/shaders/gpu_shader_material.glsl +++ b/source/blender/gpu/shaders/gpu_shader_material.glsl @@ -2256,3 +2256,18 @@ void node_output_material(vec4 surface, vec4 volume, float displacement, out vec result = surface; } +/* ********************** matcap style render ******************** */ + +void material_preview_matcap(vec4 color, sampler2D ima, vec3 N, out vec4 result) +{ + vec2 tex; + + if (N.z < 0.0) { + N.z = 0.0; + N = normalize(N); + } + + tex.x = 0.5 + 0.49 * N.x; + tex.y = 0.5 + 0.49 * N.y; + result = texture2D(ima, tex); +} diff --git a/source/blender/makesdna/DNA_ID.h b/source/blender/makesdna/DNA_ID.h index cf3f6176ba7..91e98181ab9 100644 --- a/source/blender/makesdna/DNA_ID.h +++ b/source/blender/makesdna/DNA_ID.h @@ -43,7 +43,8 @@ struct Library; struct FileData; struct ID; struct PackedFile; - +struct GPUTexture; + typedef struct IDPropertyData { void *pointer; ListBase group; @@ -154,6 +155,7 @@ typedef struct PreviewImage { short changed[2]; short changed_timestamp[2]; unsigned int *rect[2]; + struct GPUTexture *gputexture[2]; } PreviewImage; /** diff --git a/source/blender/makesdna/DNA_view3d_types.h b/source/blender/makesdna/DNA_view3d_types.h index dbe54a4fcdf..d9d6db5ff91 100644 --- a/source/blender/makesdna/DNA_view3d_types.h +++ b/source/blender/makesdna/DNA_view3d_types.h @@ -46,6 +46,7 @@ struct RenderEngine; struct bGPdata; struct SmoothView3DStore; struct wmTimer; +struct Material; /* This is needed to not let VC choke on near and far... old * proprietary MS extensions... */ @@ -160,8 +161,8 @@ typedef struct View3D { float bundle_size; /* size of bundles in reconstructed data */ short bundle_drawtype; /* display style for bundle */ - - char pad[6]; + short pad; + int matcap_icon; /* icon id */ unsigned int lay_used; /* used while drawing */ @@ -209,11 +210,11 @@ typedef struct View3D { /* drawflags, denoting state */ short zbuf, transp, xray; - char pad3[2]; - void *properties_storage; /* Nkey panel stores stuff here (runtime only!) */ - + void *properties_storage; /* Nkey panel stores stuff here (runtime only!) */ + struct Material *defmaterial; /* used by matcap now */ + /* XXX deprecated? */ struct bGPdata *gpd DNA_DEPRECATED; /* Grease-Pencil Data (annotation layers) */ @@ -264,12 +265,14 @@ typedef struct View3D { #define V3D_SOLID_TEX 8 #define V3D_SHOW_GPENCIL 16 #define V3D_LOCK_CAMERA 32 -#define V3D_RENDER_SHADOW 64 /* This is a runtime only flag that's used to tell draw_mesh_object() that we're doing a shadow pass instead of a regular draw */ -#define V3D_SHOW_RECONSTRUCTION 128 +#define V3D_RENDER_SHADOW 64 /* This is a runtime only flag that's used to tell draw_mesh_object() that we're doing a shadow pass instead of a regular draw */ +#define V3D_SHOW_RECONSTRUCTION 128 #define V3D_SHOW_CAMERAPATH 256 #define V3D_SHOW_BUNDLENAME 512 #define V3D_BACKFACE_CULLING 1024 -#define V3D_RENDER_BORDER 2048 +#define V3D_RENDER_BORDER 2048 +#define V3D_SOLID_MATCAP 4096 /* user flag */ +#define V3D_SHOW_SOLID_MATCAP 8192 /* runtime flag */ /* View3D->around */ #define V3D_CENTER 0 diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index 926b141ef24..dad5a6dc3a4 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -41,6 +41,7 @@ #include "DNA_action_types.h" #include "DNA_key_types.h" +#include "DNA_material_types.h" #include "DNA_node_types.h" #include "DNA_object_types.h" #include "DNA_space_types.h" @@ -376,6 +377,24 @@ static void rna_SpaceView3D_viewport_shade_update(Main *UNUSED(bmain), Scene *UN } } +static void rna_SpaceView3D_matcap_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) +{ + View3D *v3d = (View3D *)(ptr->data); + + if (v3d->defmaterial) { + Material *ma = v3d->defmaterial; + + if (ma->preview) + BKE_previewimg_free(&ma->preview); + + if (ma->gpumaterial.first) + GPU_material_free(ma); + + WM_main_add_notifier(NC_MATERIAL | ND_SHADING_DRAW, ma); + } +} + + static void rna_SpaceView3D_pivot_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr) { if (U.uiflag & USER_LOCKAROUND) { @@ -1463,6 +1482,7 @@ static void rna_def_backgroundImages(BlenderRNA *brna, PropertyRNA *cprop) RNA_def_function_ui_description(func, "Remove all background images"); } + static void rna_def_space_view3d(BlenderRNA *brna) { StructRNA *srna; @@ -1499,6 +1519,27 @@ static void rna_def_space_view3d(BlenderRNA *brna) {0, NULL, 0, NULL, NULL} }; + static EnumPropertyItem view3d_matcap_items[] = { + {ICON_MATCAP_01, "01", ICON_MATCAP_01, "", ""}, + {ICON_MATCAP_02, "02", ICON_MATCAP_02, "", ""}, + {ICON_MATCAP_03, "03", ICON_MATCAP_03, "", ""}, + {ICON_MATCAP_04, "04", ICON_MATCAP_04, "", ""}, + {ICON_MATCAP_05, "05", ICON_MATCAP_05, "", ""}, + {ICON_MATCAP_06, "06", ICON_MATCAP_06, "", ""}, + {ICON_MATCAP_07, "07", ICON_MATCAP_07, "", ""}, + {ICON_MATCAP_08, "08", ICON_MATCAP_08, "", ""}, + {ICON_MATCAP_09, "09", ICON_MATCAP_09, "", ""}, + {ICON_MATCAP_10, "10", ICON_MATCAP_10, "", ""}, + {ICON_MATCAP_11, "11", ICON_MATCAP_11, "", ""}, + {ICON_MATCAP_12, "12", ICON_MATCAP_12, "", ""}, + {ICON_MATCAP_13, "13", ICON_MATCAP_13, "", ""}, + {ICON_MATCAP_14, "14", ICON_MATCAP_14, "", ""}, + {ICON_MATCAP_15, "15", ICON_MATCAP_15, "", ""}, + {ICON_MATCAP_16, "16", ICON_MATCAP_16, "", ""}, + {0, NULL, 0, NULL, NULL} + }; + + srna = RNA_def_struct(brna, "SpaceView3D", "Space"); RNA_def_struct_sdna(srna, "View3D"); RNA_def_struct_ui_text(srna, "3D View Space", "3D View space data"); @@ -1819,6 +1860,17 @@ static void rna_def_space_view3d(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Show 3D Marker Names", "Show names for reconstructed tracks objects"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); + prop = RNA_def_property(srna, "use_matcap", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag2", V3D_SOLID_MATCAP); + RNA_def_property_ui_text(prop, "Matcap", "Active Objects draw images mapped on normals, enhancing Solid Draw Mode"); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); + + prop = RNA_def_property(srna, "matcap_icon", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "matcap_icon"); + RNA_def_property_enum_items(prop, view3d_matcap_items); + RNA_def_property_ui_text(prop, "Matcap", "Image to use for Material Capture, active objects only"); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_SpaceView3D_matcap_update"); + /* region */ srna = RNA_def_struct(brna, "RegionView3D", NULL); diff --git a/source/blender/makesrna/intern/rna_ui_api.c b/source/blender/makesrna/intern/rna_ui_api.c index 93410383a58..22a9ec72f0f 100644 --- a/source/blender/makesrna/intern/rna_ui_api.c +++ b/source/blender/makesrna/intern/rna_ui_api.c @@ -512,6 +512,10 @@ void RNA_api_ui_layout(StructRNA *srna) api_ui_item_rna_common(func); RNA_def_boolean(func, "expand", 0, "", "Expand button to show more detail"); + func = RNA_def_function(srna, "template_icon_view", "uiTemplateIconView"); + RNA_def_function_ui_description(func, "Enum. Large widget showing Icon previews"); + api_ui_item_rna_common(func); + func = RNA_def_function(srna, "template_histogram", "uiTemplateHistogram"); RNA_def_function_ui_description(func, "Item. A histogramm widget to analyze imaga data"); api_ui_item_rna_common(func); |