GPUTexture *GPU_texture_from_blender(Image *ima, ImageUser *iuser, int textarget, bool is_data, double time, int mipmap) { int gputt; /* this binds a texture, so that's why to restore it to 0 */ GLint bindcode = GPU_verify_image(ima, iuser, textarget, 0, 0, mipmap, is_data); GPU_update_image_time(ima, time); if (textarget == GL_TEXTURE_2D) gputt = TEXTARGET_TEXTURE_2D; else gputt = TEXTARGET_TEXTURE_CUBE_MAP; if (ima->gputexture[gputt]) { ima->gputexture[gputt]->bindcode = bindcode; glBindTexture(textarget, 0); return ima->gputexture[gputt]; } GPUTexture *tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture"); tex->bindcode = bindcode; tex->number = -1; tex->refcount = 1; tex->target = textarget; tex->target_base = GL_TEXTURE_2D; tex->fromblender = 1; ima->gputexture[gputt] = tex; if (!glIsTexture(tex->bindcode)) { GPU_ASSERT_NO_GL_ERRORS("Blender Texture Not Loaded"); } else { GLint w, h, border; GLenum gettarget; if (textarget == GL_TEXTURE_2D) gettarget = GL_TEXTURE_2D; else gettarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X; glBindTexture(textarget, tex->bindcode); glGetTexLevelParameteriv(gettarget, 0, GL_TEXTURE_WIDTH, &w); glGetTexLevelParameteriv(gettarget, 0, GL_TEXTURE_HEIGHT, &h); glGetTexLevelParameteriv(gettarget, 0, GL_TEXTURE_BORDER, &border); tex->w = w - border; tex->h = h - border; } glBindTexture(textarget, 0); return tex; }
GPUTexture *GPU_texture_from_blender(Image *ima, ImageUser *iuser, int isdata, double time, int mipmap) { GPUTexture *tex; GLint w, h, border, lastbindcode, bindcode; 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) { ima->gputexture->bindcode = bindcode; glBindTexture(GL_TEXTURE_2D, lastbindcode); return ima->gputexture; } 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; tex->fromblender = 1; ima->gputexture= 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); glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_BORDER, &border); tex->w = w - border; tex->h = h - border; } glBindTexture(GL_TEXTURE_2D, lastbindcode); return tex; }
static void tex_mat_set_texture_cb(void *userData, int mat_nr, void *attribs) { /* texture draw mode without GLSL */ TexMatCallback *data = (TexMatCallback *)userData; GPUVertexAttribs *gattribs = attribs; Image *ima; ImageUser *iuser; bNode *node; int texture_set = 0; /* draw image texture if we find one */ if (ED_object_get_active_image(data->ob, mat_nr, &ima, &iuser, &node)) { /* get openl texture */ int mipmap = 1; int bindcode = (ima) ? GPU_verify_image(ima, iuser, 0, 0, mipmap, false) : 0; float zero[4] = {0.0f, 0.0f, 0.0f, 0.0f}; if (bindcode) { NodeTexBase *texbase = node->storage; /* disable existing material */ GPU_disable_material(); glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, zero); glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, zero); glMateriali(GL_FRONT_AND_BACK, GL_SHININESS, 0); /* bind texture */ glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE); glEnable(GL_COLOR_MATERIAL); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, ima->bindcode); glColor3f(1.0f, 1.0f, 1.0f); glMatrixMode(GL_TEXTURE); glLoadMatrixf(texbase->tex_mapping.mat); glMatrixMode(GL_MODELVIEW); /* use active UV texture layer */ memset(gattribs, 0, sizeof(*gattribs)); gattribs->layer[0].type = CD_MTFACE; gattribs->layer[0].name[0] = '\0'; gattribs->layer[0].gltexco = 1; gattribs->totlayer = 1; texture_set = 1; } } if (!texture_set) { glMatrixMode(GL_TEXTURE); glLoadIdentity(); glMatrixMode(GL_MODELVIEW); /* disable texture */ glDisable(GL_TEXTURE_2D); glDisable(GL_COLOR_MATERIAL); /* draw single color */ GPU_enable_material(mat_nr, attribs); } }
static void draw_textured_begin(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob) { unsigned char obcol[4]; bool is_tex, solidtex; Mesh *me = ob->data; ImagePaintSettings *imapaint = &scene->toolsettings->imapaint; /* XXX scene->obedit warning */ /* texture draw is abused for mask selection mode, do this so wire draw * with face selection in weight paint is not lit. */ if ((v3d->drawtype <= OB_WIRE) && (ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT))) { solidtex = false; Gtexdraw.is_lit = 0; } else if (v3d->drawtype == OB_SOLID || ((ob->mode & OB_MODE_EDIT) && v3d->drawtype != OB_TEXTURE) || (BKE_scene_use_new_shading_nodes(scene) && (ob->mode & OB_MODE_TEXTURE_PAINT))) { /* draw with default lights in solid draw mode and edit mode */ solidtex = true; Gtexdraw.is_lit = -1; } else { /* draw with lights in the scene otherwise */ solidtex = false; if (v3d->flag2 & V3D_SHADELESS_TEX) Gtexdraw.is_lit = 0; else Gtexdraw.is_lit = GPU_scene_object_lights(scene, ob, v3d->lay, rv3d->viewmat, !rv3d->is_persp); } rgba_float_to_uchar(obcol, ob->col); if (solidtex || v3d->drawtype == OB_TEXTURE) is_tex = true; else is_tex = false; Gtexdraw.ob = ob; Gtexdraw.stencil = (imapaint->flag & IMAGEPAINT_PROJECT_LAYER_STENCIL) ? imapaint->stencil : NULL; Gtexdraw.is_texpaint = (ob->mode == OB_MODE_TEXTURE_PAINT); Gtexdraw.texpaint_material = (imapaint->mode == IMAGEPAINT_MODE_MATERIAL); Gtexdraw.canvas = (Gtexdraw.texpaint_material) ? NULL : imapaint->canvas; Gtexdraw.is_tex = is_tex; /* naughty multitexturing hacks to quickly support stencil + shading + alpha blending * in new texpaint code. The better solution here would be to support GLSL */ if (Gtexdraw.is_texpaint) { glActiveTexture(GL_TEXTURE1); glEnable(GL_TEXTURE_2D); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE); glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PREVIOUS); glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_PRIMARY_COLOR); glTexEnvi(GL_TEXTURE_ENV, GL_SRC2_RGB, GL_PREVIOUS); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_ALPHA); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE); glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_PREVIOUS); /* load the stencil texture here */ if (Gtexdraw.stencil != NULL) { glActiveTexture(GL_TEXTURE2); if (GPU_verify_image(Gtexdraw.stencil, NULL, false, false, false, false)) { float col[4] = {imapaint->stencil_col[0], imapaint->stencil_col[1], imapaint->stencil_col[2], 1.0f}; glEnable(GL_TEXTURE_2D); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE); glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PREVIOUS); glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_CONSTANT); glTexEnvi(GL_TEXTURE_ENV, GL_SRC2_RGB, GL_TEXTURE); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE); glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_PREVIOUS); glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_ALPHA, GL_TEXTURE); glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, col); if ((imapaint->flag & IMAGEPAINT_PROJECT_LAYER_STENCIL_INV) == 0) { glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_ONE_MINUS_SRC_COLOR); } else { glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_COLOR); } } } glActiveTexture(GL_TEXTURE0); } Gtexdraw.color_profile = BKE_scene_check_color_management_enabled(scene); Gtexdraw.use_game_mat = (RE_engines_find(scene->r.engine)->flag & RE_GAME) != 0; Gtexdraw.use_backface_culling = (v3d->flag2 & V3D_BACKFACE_CULLING) != 0; memcpy(Gtexdraw.obcol, obcol, sizeof(obcol)); set_draw_settings_cached(1, NULL, NULL, Gtexdraw); glShadeModel(GL_SMOOTH); glCullFace(GL_BACK); glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, (me->flag & ME_TWOSIDED) ? GL_TRUE : GL_FALSE); }
static bool set_draw_settings_cached(int clearcache, MTexPoly *texface, Material *ma, struct TextureDrawState gtexdraw) { static Material *c_ma; static int c_textured; static MTexPoly c_texface; static int c_backculled; static bool c_badtex; static int c_lit; static int c_has_texface; int backculled = 1; int alphablend = GPU_BLEND_SOLID; int textured = 0; int lit = 0; int has_texface = texface != NULL; bool need_set_tpage = false; bool texpaint = ((gtexdraw.ob->mode & OB_MODE_TEXTURE_PAINT) != 0); Image *ima = NULL; if (ma != NULL) { if (ma->mode & MA_TRANSP) { alphablend = GPU_BLEND_ALPHA; } } if (clearcache) { c_textured = c_lit = c_backculled = -1; memset(&c_texface, 0, sizeof(c_texface)); c_badtex = false; c_has_texface = -1; c_ma = NULL; } else { textured = gtexdraw.is_tex; } /* convert number of lights into boolean */ if (gtexdraw.is_lit) lit = 1; backculled = gtexdraw.use_backface_culling; if (ma) { if (ma->mode & MA_SHLESS) lit = 0; if (gtexdraw.use_game_mat) { backculled = backculled || (ma->game.flag & GEMAT_BACKCULL); alphablend = ma->game.alpha_blend; } } if (texface && !texpaint) { textured = textured && (texface->tpage); /* no material, render alpha if texture has depth=32 */ if (!ma && BKE_image_has_alpha(texface->tpage)) alphablend = GPU_BLEND_ALPHA; } else if (texpaint) { if (gtexdraw.texpaint_material) ima = ma && ma->texpaintslot ? ma->texpaintslot[ma->paint_active_slot].ima : NULL; else ima = gtexdraw.canvas; } else textured = 0; if (backculled != c_backculled) { if (backculled) glEnable(GL_CULL_FACE); else glDisable(GL_CULL_FACE); c_backculled = backculled; } /* need to re-set tpage if textured flag changed or existsment of texface changed.. */ need_set_tpage = textured != c_textured || has_texface != c_has_texface; /* ..or if settings inside texface were changed (if texface was used) */ need_set_tpage |= (texpaint && c_ma != ma) || (texface && memcmp(&c_texface, texface, sizeof(c_texface))); if (need_set_tpage) { if (textured) { if (texpaint) { c_badtex = false; if (GPU_verify_image(ima, NULL, 0, 1, 0, false)) { glEnable(GL_TEXTURE_2D); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE); glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_TEXTURE); glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_PRIMARY_COLOR); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE); glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_TEXTURE); glActiveTexture(GL_TEXTURE1); glEnable(GL_TEXTURE_2D); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE); glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PREVIOUS); glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_PRIMARY_COLOR); glTexEnvi(GL_TEXTURE_ENV, GL_SRC2_RGB, GL_PREVIOUS); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_ALPHA); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE); glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_PREVIOUS); glBindTexture(GL_TEXTURE_2D, ima->bindcode); glActiveTexture(GL_TEXTURE0); } else { glActiveTexture(GL_TEXTURE1); glDisable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, 0); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glActiveTexture(GL_TEXTURE0); c_badtex = true; GPU_clear_tpage(true); glDisable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, 0); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); } } else { c_badtex = !GPU_set_tpage(texface, !texpaint, alphablend); } } else { GPU_set_tpage(NULL, 0, 0); c_badtex = false; } c_textured = textured; c_has_texface = has_texface; if (texface) memcpy(&c_texface, texface, sizeof(c_texface)); } if (c_badtex) lit = 0; if (lit != c_lit || ma != c_ma) { if (lit) { float spec[4]; if (!ma) ma = give_current_material_or_def(NULL, 0); /* default material */ spec[0] = ma->spec * ma->specr; spec[1] = ma->spec * ma->specg; spec[2] = ma->spec * ma->specb; spec[3] = 1.0; glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, spec); glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE); glMateriali(GL_FRONT_AND_BACK, GL_SHININESS, CLAMPIS(ma->har, 0, 128)); glEnable(GL_LIGHTING); glEnable(GL_COLOR_MATERIAL); } else { glDisable(GL_LIGHTING); glDisable(GL_COLOR_MATERIAL); } c_lit = lit; c_ma = ma; } return c_badtex; }
static void tex_mat_set_texture_cb(void *userData, int mat_nr, void *attribs) { /* texture draw mode without GLSL */ TexMatCallback *data = (TexMatCallback *)userData; GPUVertexAttribs *gattribs = attribs; Image *ima; ImageUser *iuser; bNode *node; /* draw image texture if we find one */ if (ED_object_get_active_image(data->ob, mat_nr, &ima, &iuser, &node, NULL)) { /* get openl texture */ int mipmap = 1; int bindcode = (ima) ? GPU_verify_image(ima, iuser, GL_TEXTURE_2D, 0, 0, mipmap, false) : 0; if (bindcode) { NodeTexBase *texbase = node->storage; /* disable existing material */ GPU_object_material_unbind(); /* bind texture */ glBindTexture(GL_TEXTURE_2D, ima->bindcode[TEXTARGET_TEXTURE_2D]); glMatrixMode(GL_TEXTURE); glLoadMatrixf(texbase->tex_mapping.mat); glMatrixMode(GL_MODELVIEW); /* use active UV texture layer */ memset(gattribs, 0, sizeof(*gattribs)); gattribs->layer[0].type = CD_MTFACE; gattribs->layer[0].name[0] = '\0'; gattribs->layer[0].gltexco = 1; gattribs->totlayer = 1; /* bind material */ float diffuse[3] = {1.0f, 1.0f, 1.0f}; int options = GPU_SHADER_TEXTURE_2D; if (!data->shadeless) options |= GPU_SHADER_LIGHTING; if (data->two_sided_lighting) options |= GPU_SHADER_TWO_SIDED; GPU_basic_shader_colors(diffuse, NULL, 0, 1.0f); GPU_basic_shader_bind(options); return; } } /* disable texture material */ GPU_basic_shader_bind(GPU_SHADER_USE_COLOR); if (data->shadeless) { glColor3f(1.0f, 1.0f, 1.0f); memset(gattribs, 0, sizeof(*gattribs)); } else { glMatrixMode(GL_TEXTURE); glLoadIdentity(); glMatrixMode(GL_MODELVIEW); /* enable solid material */ GPU_object_material_bind(mat_nr, attribs); } }