diff options
Diffstat (limited to 'source')
21 files changed, 619 insertions, 141 deletions
diff --git a/source/blender/blenkernel/BKE_image.h b/source/blender/blenkernel/BKE_image.h index 1d4a405a89c..aec5b0afa45 100644 --- a/source/blender/blenkernel/BKE_image.h +++ b/source/blender/blenkernel/BKE_image.h @@ -259,6 +259,9 @@ bool BKE_image_scale(struct Image *image, int width, int height); /* check if texture has alpha (depth=32) */ bool BKE_image_has_alpha(struct Image *image); +/* check if texture has gpu texture code */ +bool BKE_image_has_bindcode(struct Image *ima); + void BKE_image_get_size(struct Image *image, struct ImageUser *iuser, int *width, int *height); void BKE_image_get_size_fl(struct Image *image, struct ImageUser *iuser, float size[2]); void BKE_image_get_aspect(struct Image *image, float *aspx, float *aspy); diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index 7c40674dd6c..d48b455ae81 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -657,6 +657,18 @@ bool BKE_image_scale(Image *image, int width, int height) return (ibuf != NULL); } +bool BKE_image_has_bindcode(Image *ima) +{ + bool has_bindcode = false; + for (int i = 0; i < TEXTARGET_COUNT; i++) { + if (ima->bindcode[i]) { + has_bindcode = true; + break; + } + } + return has_bindcode; +} + static void image_init_color_management(Image *ima) { ImBuf *ibuf; diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 8899af1d755..b8470b16e14 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -1565,8 +1565,9 @@ void blo_make_image_pointer_map(FileData *fd, Main *oldmain) for (; ima; ima = ima->id.next) { if (ima->cache) oldnewmap_insert(fd->imamap, ima->cache, ima->cache, 0); - if (ima->gputexture) - oldnewmap_insert(fd->imamap, ima->gputexture, ima->gputexture, 0); + for (a = 0; a < TEXTARGET_COUNT; a++) + if (ima->gputexture[a]) + oldnewmap_insert(fd->imamap, ima->gputexture[a], ima->gputexture[a], 0); if (ima->rr) oldnewmap_insert(fd->imamap, ima->rr, ima->rr, 0); for (a=0; a < IMA_MAX_RENDER_SLOT; a++) @@ -1602,15 +1603,18 @@ void blo_end_image_pointer_map(FileData *fd, Main *oldmain) for (; ima; ima = ima->id.next) { ima->cache = newimaadr(fd, ima->cache); if (ima->cache == NULL) { - ima->bindcode = 0; ima->tpageflag &= ~IMA_GLBIND_IS_DATA; - ima->gputexture = NULL; + for (i = 0; i < TEXTARGET_COUNT; i++) { + ima->bindcode[i] = 0; + ima->gputexture[i] = NULL; + } ima->rr = NULL; } for (i = 0; i < IMA_MAX_RENDER_SLOT; i++) ima->renders[i] = newimaadr(fd, ima->renders[i]); - ima->gputexture = newimaadr(fd, ima->gputexture); + for (i = 0; i < TEXTARGET_COUNT; i++) + ima->gputexture[i] = newimaadr(fd, ima->gputexture[i]); ima->rr = newimaadr(fd, ima->rr); } for (; sce; sce = sce->id.next) { @@ -3644,9 +3648,11 @@ static void direct_link_image(FileData *fd, Image *ima) /* if not restored, we keep the binded opengl index */ if (!ima->cache) { - ima->bindcode = 0; ima->tpageflag &= ~IMA_GLBIND_IS_DATA; - ima->gputexture = NULL; + for (int i = 0; i < TEXTARGET_COUNT; i++) { + ima->bindcode[i] = 0; + ima->gputexture[i] = NULL; + } ima->rr = NULL; } diff --git a/source/blender/editors/space_view3d/drawmesh.c b/source/blender/editors/space_view3d/drawmesh.c index 8deabfb31ab..11ba6fb709b 100644 --- a/source/blender/editors/space_view3d/drawmesh.c +++ b/source/blender/editors/space_view3d/drawmesh.c @@ -318,7 +318,7 @@ static bool set_draw_settings_cached(int clearcache, MTexPoly *texface, Material if (textured) { if (texpaint) { c_badtex = false; - if (GPU_verify_image(ima, NULL, 0, 1, 0, false)) { + if (GPU_verify_image(ima, NULL, GL_TEXTURE_2D, 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); @@ -337,7 +337,7 @@ static bool set_draw_settings_cached(int clearcache, MTexPoly *texface, Material 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); + glBindTexture(GL_TEXTURE_2D, ima->bindcode[TEXTARGET_TEXTURE_2D]); glActiveTexture(GL_TEXTURE0); } else { @@ -465,7 +465,7 @@ static void draw_textured_begin(Scene *scene, View3D *v3d, RegionView3D *rv3d, O /* load the stencil texture here */ if (Gtexdraw.stencil != NULL) { glActiveTexture(GL_TEXTURE2); - if (GPU_verify_image(Gtexdraw.stencil, NULL, false, false, false, false)) { + if (GPU_verify_image(Gtexdraw.stencil, NULL, GL_TEXTURE_2D, 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); @@ -1046,7 +1046,7 @@ static void tex_mat_set_texture_cb(void *userData, int mat_nr, void *attribs) 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, 0, 0, mipmap, false) : 0; + int bindcode = (ima) ? GPU_verify_image(ima, iuser, GL_TEXTURE_2D, 0, 0, mipmap, false) : 0; if (bindcode) { NodeTexBase *texbase = node->storage; @@ -1055,7 +1055,7 @@ static void tex_mat_set_texture_cb(void *userData, int mat_nr, void *attribs) GPU_object_material_unbind(); /* bind texture */ - glBindTexture(GL_TEXTURE_2D, ima->bindcode); + glBindTexture(GL_TEXTURE_2D, ima->bindcode[TEXTARGET_TEXTURE_2D]); glMatrixMode(GL_TEXTURE); glLoadMatrixf(texbase->tex_mapping.mat); diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index c37d90b1878..adffcb63293 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -99,6 +99,7 @@ #include "GPU_framebuffer.h" #include "GPU_material.h" #include "GPU_compositing.h" +#include "GPU_extensions.h" #include "view3d_intern.h" /* own include */ @@ -2971,8 +2972,7 @@ void ED_view3d_draw_offscreen_init(Scene *scene, View3D *v3d) static void view3d_main_region_clear(Scene *scene, View3D *v3d, ARegion *ar) { if (scene->world && (v3d->flag3 & V3D_SHOW_WORLD)) { - bool glsl = BKE_scene_use_new_shading_nodes(scene) && scene->world->nodetree && scene->world->use_nodes; - + bool glsl = GPU_glsl_support(); if (glsl) { RegionView3D *rv3d = ar->regiondata; GPUMaterial *gpumat = GPU_material_world(scene, scene->world); diff --git a/source/blender/gpu/GPU_draw.h b/source/blender/gpu/GPU_draw.h index afb1cbcf71d..75d6362f13e 100644 --- a/source/blender/gpu/GPU_draw.h +++ b/source/blender/gpu/GPU_draw.h @@ -132,13 +132,13 @@ void GPU_set_gpu_mipmapping(int gpu_mipmap); void GPU_paint_update_image(struct Image *ima, struct ImageUser *iuser, int x, int y, int w, int h); void GPU_update_images_framechange(void); int GPU_update_image_time(struct Image *ima, double time); -int GPU_verify_image(struct Image *ima, struct ImageUser *iuser, int tftile, bool compare, bool mipmap, bool is_data); -void GPU_create_gl_tex( - unsigned int *bind, unsigned int *rect, float *frect, int rectw, int recth, - bool mipmap, bool use_hight_bit_depth, struct Image *ima); +int GPU_verify_image(struct Image *ima, + struct ImageUser *iuser, int textarget, int tftile, bool compare, bool mipmap, bool is_data); +void GPU_create_gl_tex(unsigned int *bind, unsigned int *rect, float *frect, int rectw, int recth, + int textarget, bool mipmap, bool use_hight_bit_depth, struct Image *ima); void GPU_create_gl_tex_compressed( - unsigned int *bind, unsigned int *pix, int x, int y, int mipmap, - struct Image *ima, struct ImBuf *ibuf); + unsigned int *bind, unsigned int *pix, int x, int y, int mipmap, + int textarget, struct Image *ima, struct ImBuf *ibuf); bool GPU_upload_dxt_texture(struct ImBuf *ibuf); void GPU_free_image(struct Image *ima); void GPU_free_images(void); diff --git a/source/blender/gpu/GPU_extensions.h b/source/blender/gpu/GPU_extensions.h index 64167e94933..4a728c881b6 100644 --- a/source/blender/gpu/GPU_extensions.h +++ b/source/blender/gpu/GPU_extensions.h @@ -53,6 +53,7 @@ int GPU_max_texture_size(void); int GPU_max_textures(void); float GPU_max_texture_anisotropy(void); int GPU_max_color_texture_samples(void); +int GPU_max_cube_map_size(void); int GPU_color_depth(void); void GPU_get_dfdy_factors(float fac[2]); diff --git a/source/blender/gpu/GPU_material.h b/source/blender/gpu/GPU_material.h index 65cdf834533..3bcc7e23f06 100644 --- a/source/blender/gpu/GPU_material.h +++ b/source/blender/gpu/GPU_material.h @@ -78,6 +78,7 @@ typedef enum GPUType { GPU_TEX2D = 1002, GPU_SHADOW2D = 1003, + GPU_TEXCUBE = 1004, GPU_ATTRIB = 3001 } GPUType; @@ -179,6 +180,7 @@ typedef enum GPUDynamicType { GPU_DYNAMIC_HORIZON_COLOR = 1 | GPU_DYNAMIC_GROUP_WORLD, GPU_DYNAMIC_AMBIENT_COLOR = 2 | GPU_DYNAMIC_GROUP_WORLD, + GPU_DYNAMIC_ZENITH_COLOR = 3 | GPU_DYNAMIC_GROUP_WORLD, GPU_DYNAMIC_MAT_DIFFRGB = 1 | GPU_DYNAMIC_GROUP_MAT, GPU_DYNAMIC_MAT_REF = 2 | GPU_DYNAMIC_GROUP_MAT, @@ -194,6 +196,7 @@ GPUNodeLink *GPU_attribute(CustomDataType type, const char *name); GPUNodeLink *GPU_uniform(float *num); GPUNodeLink *GPU_dynamic_uniform(float *num, GPUDynamicType dynamictype, void *data); GPUNodeLink *GPU_image(struct Image *ima, struct ImageUser *iuser, bool is_data); +GPUNodeLink *GPU_cube_map(struct Image *ima, struct ImageUser *iuser, bool is_data); GPUNodeLink *GPU_image_preview(struct PreviewImage *prv); GPUNodeLink *GPU_texture(int size, float *pixels); GPUNodeLink *GPU_dynamic_texture(struct GPUTexture *tex, GPUDynamicType dynamictype, void *data); diff --git a/source/blender/gpu/GPU_texture.h b/source/blender/gpu/GPU_texture.h index 4166aaf293d..efa98f7ca2a 100644 --- a/source/blender/gpu/GPU_texture.h +++ b/source/blender/gpu/GPU_texture.h @@ -72,7 +72,7 @@ GPUTexture *GPU_texture_create_2D_multisample( int w, int h, const float *pixels, GPUHDRType hdr, int samples, char err_out[256]); GPUTexture *GPU_texture_create_depth_multisample(int w, int h, int samples, char err_out[256]); GPUTexture *GPU_texture_from_blender( - struct Image *ima, struct ImageUser *iuser, bool is_data, double time, int mipmap); + struct Image *ima, struct ImageUser *iuser, int textarget, bool is_data, double time, int mipmap); GPUTexture *GPU_texture_from_preview(struct PreviewImage *prv, int mipmap); void GPU_invalid_tex_init(void); void GPU_invalid_tex_bind(int mode); diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c index fb46b167f0f..c3f79bc9492 100644 --- a/source/blender/gpu/intern/gpu_codegen.c +++ b/source/blender/gpu/intern/gpu_codegen.c @@ -177,6 +177,9 @@ static void gpu_parse_functions_string(GHash *hash, char *code) } } + if (!type && gpu_str_prefix(code, "samplerCube")) { + type = GPU_TEXCUBE; + } if (!type && gpu_str_prefix(code, "sampler2DShadow")) { type = GPU_SHADOW2D; } @@ -505,8 +508,9 @@ static int codegen_print_uniforms_functions(DynStr *ds, ListBase *nodes) /* create exactly one sampler for each texture */ if (codegen_input_has_texture(input) && input->bindtex) { BLI_dynstr_appendf(ds, "uniform %s samp%d;\n", - (input->textype == GPU_TEX2D) ? "sampler2D" : "sampler2DShadow", - input->texid); + (input->textype == GPU_TEX2D) ? "sampler2D" : + (input->textype == GPU_TEXCUBE) ? "samplerCube" : "sampler2DShadow", + input->texid); } } else if (input->source == GPU_SOURCE_BUILTIN) { @@ -1015,7 +1019,7 @@ void GPU_pass_bind(GPUPass *pass, double time, int mipmap) /* create the textures */ 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); + input->tex = GPU_texture_from_blender(input->ima, input->iuser, input->textarget, input->image_isdata, time, mipmap); else if (input->prv) input->tex = GPU_texture_from_preview(input->prv, mipmap); } @@ -1192,15 +1196,25 @@ static void gpu_node_input_link(GPUNode *node, GPUNodeLink *link, const GPUType input->type = GPU_VEC4; input->source = GPU_SOURCE_TEX; - if (link->image == GPU_NODE_LINK_IMAGE_PREVIEW) + if (link->image == GPU_NODE_LINK_IMAGE_PREVIEW) { input->prv = link->ptr1; - else { + input->textarget = GL_TEXTURE_2D; + input->textype = GPU_TEX2D; + } + else if (link->image == GPU_NODE_LINK_IMAGE_BLENDER) { input->ima = link->ptr1; input->iuser = link->ptr2; input->image_isdata = link->image_isdata; + input->textarget = GL_TEXTURE_2D; + input->textype = GPU_TEX2D; + } + else if (link->image == GPU_NODE_LINK_IMAGE_CUBE_MAP) { + input->ima = link->ptr1; + input->iuser = link->ptr2; + input->image_isdata = link->image_isdata; + input->textarget = GL_TEXTURE_CUBE_MAP; + input->textype = GPU_TEXCUBE; } - input->textarget = GL_TEXTURE_2D; - input->textype = GPU_TEX2D; MEM_freeN(link); } else if (link->attribtype) { @@ -1405,6 +1419,18 @@ GPUNodeLink *GPU_image(Image *ima, ImageUser *iuser, bool is_data) return link; } +GPUNodeLink *GPU_cube_map(Image *ima, ImageUser *iuser, bool is_data) +{ + GPUNodeLink *link = GPU_node_link_create(); + + link->image = GPU_NODE_LINK_IMAGE_CUBE_MAP; + link->ptr1 = ima; + link->ptr2 = iuser; + link->image_isdata = is_data; + + return link; +} + GPUNodeLink *GPU_image_preview(PreviewImage *prv) { GPUNodeLink *link = GPU_node_link_create(); diff --git a/source/blender/gpu/intern/gpu_codegen.h b/source/blender/gpu/intern/gpu_codegen.h index 5aa187014ba..75102658c88 100644 --- a/source/blender/gpu/intern/gpu_codegen.h +++ b/source/blender/gpu/intern/gpu_codegen.h @@ -63,7 +63,8 @@ typedef enum GPUDataSource { typedef enum { GPU_NODE_LINK_IMAGE_NONE = 0, GPU_NODE_LINK_IMAGE_BLENDER = 1, - GPU_NODE_LINK_IMAGE_PREVIEW = 2 + GPU_NODE_LINK_IMAGE_PREVIEW = 2, + GPU_NODE_LINK_IMAGE_CUBE_MAP = 3 } GPUNodeLinkImage; struct GPUNode { diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c index a7f802a4502..be5235b77bb 100644 --- a/source/blender/gpu/intern/gpu_draw.c +++ b/source/blender/gpu/intern/gpu_draw.c @@ -224,11 +224,12 @@ static bool is_power_of_2_resolution(int w, int h) return is_power_of_2_i(w) && is_power_of_2_i(h); } -static bool is_over_resolution_limit(int w, int h) +static bool is_over_resolution_limit(GLenum textarget, int w, int h) { + int size = (textarget == GL_TEXTURE_2D)? + GPU_max_texture_size() : GPU_max_cube_map_size(); int reslimit = (U.glreslimit != 0) ? - min_ii(U.glreslimit, GPU_max_texture_size()) : - GPU_max_texture_size(); + min_ii(U.glreslimit, size) : size; return (w > reslimit || h > reslimit); } @@ -398,6 +399,18 @@ static void gpu_make_repbind(Image *ima) BKE_image_release_ibuf(ima, ibuf, NULL); } +static unsigned int *gpu_get_image_bindcode(Image *ima, GLenum textarget) +{ + unsigned int *bind = 0; + + if (textarget == GL_TEXTURE_2D) + bind = &ima->bindcode[TEXTARGET_TEXTURE_2D]; + else if (textarget == GL_TEXTURE_CUBE_MAP) + bind = &ima->bindcode[TEXTARGET_TEXTURE_CUBE_MAP]; + + return bind; +} + void GPU_clear_tpage(bool force) { if (GTS.lasttface == NULL && !force) @@ -496,7 +509,7 @@ static void gpu_verify_reflection(Image *ima) } } -int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, bool compare, bool mipmap, bool is_data) +int GPU_verify_image(Image *ima, ImageUser *iuser, int textarget, int tftile, bool compare, bool mipmap, bool is_data) { unsigned int *bind = NULL; int tpx = 0, tpy = 0; @@ -587,8 +600,8 @@ int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, bool compare, boo if (GTS.tile >= ima->totbind) GTS.tile = 0; /* this happens when you change repeat buttons */ - if (ima->repbind) bind = &ima->repbind[GTS.tile]; - else bind = &ima->bindcode; + if (ima->repbind && textarget == GL_TEXTURE_2D) bind = &ima->repbind[GTS.tile]; + else bind = gpu_get_image_bindcode(ima, textarget); if (*bind == 0) { short texwindx = ibuf->x / ima->xrep; @@ -628,7 +641,7 @@ int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, bool compare, boo } else { /* regular image mode */ - bind = &ima->bindcode; + bind = gpu_get_image_bindcode(ima, textarget); if (*bind == 0) { tpx = ibuf->x; @@ -653,7 +666,7 @@ int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, bool compare, boo if (*bind != 0) { /* enable opengl drawing with textures */ - glBindTexture(GL_TEXTURE_2D, *bind); + glBindTexture(textarget, *bind); BKE_image_release_ibuf(ima, ibuf, NULL); return *bind; } @@ -694,10 +707,10 @@ int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, bool compare, boo #ifdef WITH_DDS if (ibuf->ftype == IMB_FTYPE_DDS) - GPU_create_gl_tex_compressed(bind, rect, rectw, recth, mipmap, ima, ibuf); + GPU_create_gl_tex_compressed(bind, rect, rectw, recth, textarget, mipmap, ima, ibuf); else #endif - GPU_create_gl_tex(bind, rect, frect, rectw, recth, mipmap, use_high_bit_depth, ima); + GPU_create_gl_tex(bind, rect, frect, rectw, recth, textarget, mipmap, use_high_bit_depth, ima); /* mark as non-color data texture */ if (*bind) { @@ -720,9 +733,76 @@ int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, bool compare, boo return *bind; } +static void **gpu_gen_cube_map(unsigned int *rect, float *frect, int rectw, int recth, bool use_high_bit_depth) +{ + size_t block_size = use_high_bit_depth ? sizeof(float) * 4 : sizeof(unsigned char) * 4; + void **sides = NULL; + int h = recth / 2; + int w = rectw / 3; + + if ((use_high_bit_depth && frect == NULL) || (!use_high_bit_depth && rect == NULL) || w != h) + return sides; + + /* PosX, NegX, PosY, NegY, PosZ, NegZ */ + sides = MEM_mallocN(sizeof(void*) * 6, ""); + for (int i = 0; i < 6; i++) + sides[i] = MEM_mallocN(block_size * w * h, ""); + + /* divide image into six parts */ + /* ______________________ + * | | | | + * | NegX | NegY | PosX | + * |______|______|______| + * | | | | + * | NegZ | PosZ | PosY | + * |______|______|______| + */ + if (use_high_bit_depth) { + float (*frectb)[4] = (float(*)[4])frect; + float (**fsides)[4] = (float(**)[4])sides; + + for (int y = 0; y < h; y++) { + for (int x = 0; x < w; x++) { + memcpy(&fsides[0][x * h + y], &frectb[(recth - y - 1) * rectw + 2 * w + x], block_size); + memcpy(&fsides[1][x * h + y], &frectb[(y + h) * rectw + w - 1 - x], block_size); + memcpy(&fsides[3][y * w + x], &frectb[(recth - y - 1) * rectw + 2 * w - 1 - x], block_size); + memcpy(&fsides[5][y * w + x], &frectb[(h - y - 1) * rectw + w - 1 - x], block_size); + } + memcpy(&fsides[2][y * w], frectb[y * rectw + 2 * w], block_size * w); + memcpy(&fsides[4][y * w], frectb[y * rectw + w], block_size * w); + } + } + else { + unsigned int **isides = (unsigned int **)sides; + + for (int y = 0; y < h; y++) { + for (int x = 0; x < w; x++) { + isides[0][x * h + y] = rect[(recth - y - 1) * rectw + 2 * w + x]; + isides[1][x * h + y] = rect[(y + h) * rectw + w - 1 - x]; + isides[3][y * w + x] = rect[(recth - y - 1) * rectw + 2 * w - 1 - x]; + isides[5][y * w + x] = rect[(h - y - 1) * rectw + w - 1 - x]; + } + memcpy(&isides[2][y * w], &rect[y * rectw + 2 * w], block_size * w); + memcpy(&isides[4][y * w], &rect[y * rectw + w], block_size * w); + } + } + + return sides; +} + +static void gpu_del_cube_map(void **cube_map) +{ + int i; + if (cube_map == NULL) + return; + for (i = 0; i < 6; i++) + MEM_freeN(cube_map[i]); + MEM_freeN(cube_map); +} + /* Image *ima can be NULL */ void GPU_create_gl_tex(unsigned int *bind, unsigned int *rect, float *frect, int rectw, int recth, - bool mipmap, bool use_high_bit_depth, Image *ima) + int textarget, bool mipmap, bool use_high_bit_depth, Image *ima) { ImBuf *ibuf = NULL; @@ -732,12 +812,13 @@ void GPU_create_gl_tex(unsigned int *bind, unsigned int *rect, float *frect, int /* scale if not a power of two. this is not strictly necessary for newer * GPUs (OpenGL version >= 2.0) since they support non-power-of-two-textures * Then don't bother scaling for hardware that supports NPOT textures! */ - if ((!GPU_full_non_power_of_two_support() && !is_power_of_2_resolution(rectw, recth)) || - is_over_resolution_limit(rectw, recth)) + if (textarget == GL_TEXTURE_2D && + (!GPU_full_non_power_of_two_support() && !is_power_of_2_resolution(rectw, recth) || + is_over_resolution_limit(textarget, rectw, recth))) { rectw = smaller_power_of_2_limit(rectw); recth = smaller_power_of_2_limit(recth); - + if (use_high_bit_depth) { ibuf = IMB_allocFromBuffer(NULL, frect, tpx, tpy); IMB_scaleImBuf(ibuf, rectw, recth); @@ -754,62 +835,123 @@ void GPU_create_gl_tex(unsigned int *bind, unsigned int *rect, float *frect, int /* create image */ glGenTextures(1, (GLuint *)bind); - glBindTexture(GL_TEXTURE_2D, *bind); + glBindTexture(textarget, *bind); - if (use_high_bit_depth) { - if (GLEW_ARB_texture_float) - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F_ARB, rectw, recth, 0, GL_RGBA, GL_FLOAT, frect); + if (textarget == GL_TEXTURE_2D) { + if (use_high_bit_depth) { + if (GLEW_ARB_texture_float) + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F_ARB, rectw, recth, 0, GL_RGBA, GL_FLOAT, frect); + else + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16, rectw, recth, 0, GL_RGBA, GL_FLOAT, frect); + } else - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16, rectw, recth, 0, GL_RGBA, GL_FLOAT, frect); - } - else - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, rectw, recth, 0, GL_RGBA, GL_UNSIGNED_BYTE, rect); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, rectw, recth, 0, GL_RGBA, GL_UNSIGNED_BYTE, rect); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1)); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1)); - if (GPU_get_mipmap() && mipmap) { - if (GTS.gpu_mipmap) { - gpu_generate_mipmap(GL_TEXTURE_2D); - } - else { - if (!ibuf) { - if (use_high_bit_depth) { - ibuf = IMB_allocFromBuffer(NULL, frect, tpx, tpy); + if (GPU_get_mipmap() && mipmap) { + if (GTS.gpu_mipmap) { + gpu_generate_mipmap(GL_TEXTURE_2D); + } + else { + int i; + if (!ibuf) { + if (use_high_bit_depth) { + ibuf = IMB_allocFromBuffer(NULL, frect, tpx, tpy); + } + else { + ibuf = IMB_allocFromBuffer(rect, NULL, tpx, tpy); + } } - else { - ibuf = IMB_allocFromBuffer(rect, NULL, tpx, tpy); + IMB_makemipmap(ibuf, true); + + for (i = 1; i < ibuf->miptot; i++) { + ImBuf *mip = ibuf->mipmap[i - 1]; + if (use_high_bit_depth) { + if (GLEW_ARB_texture_float) + glTexImage2D(GL_TEXTURE_2D, i, GL_RGBA16F_ARB, mip->x, mip->y, 0, GL_RGBA, GL_FLOAT, mip->rect_float); + else + glTexImage2D(GL_TEXTURE_2D, i, GL_RGBA16, mip->x, mip->y, 0, GL_RGBA, GL_FLOAT, mip->rect_float); + } + else { + glTexImage2D(GL_TEXTURE_2D, i, GL_RGBA8, mip->x, mip->y, 0, GL_RGBA, GL_UNSIGNED_BYTE, mip->rect); + } } } + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gpu_get_mipmap_filter(0)); + if (ima) + ima->tpageflag |= IMA_MIPMAP_COMPLETE; + } + else { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + } + } + else if (textarget == GL_TEXTURE_CUBE_MAP) { + int w = rectw / 3, h = recth / 2; + + if (h == w && is_power_of_2_i(h) && !is_over_resolution_limit(textarget, h, w)) { + void **cube_map = gpu_gen_cube_map(rect, frect, rectw, recth, use_high_bit_depth); + GLenum informat = use_high_bit_depth ? (GLEW_ARB_texture_float ? GL_RGBA16F_ARB : GL_RGBA16) : GL_RGBA8; + GLenum type = use_high_bit_depth ? GL_FLOAT : GL_UNSIGNED_BYTE; - IMB_makemipmap(ibuf, true); - - for (int i = 1; i < ibuf->miptot; i++) { - ImBuf *mip = ibuf->mipmap[i - 1]; - if (use_high_bit_depth) { - if (GLEW_ARB_texture_float) - glTexImage2D(GL_TEXTURE_2D, i, GL_RGBA16F_ARB, mip->x, mip->y, - 0, GL_RGBA, GL_FLOAT, mip->rect_float); - else - glTexImage2D(GL_TEXTURE_2D, i, GL_RGBA16, mip->x, mip->y, - 0, GL_RGBA, GL_FLOAT, mip->rect_float); + if (cube_map) + for (int i = 0; i < 6; i++) + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, informat, w, h, 0, GL_RGBA, type, cube_map[i]); + + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1)); + + if (GPU_get_mipmap() && mipmap) { + if (GTS.gpu_mipmap) { + gpu_generate_mipmap(GL_TEXTURE_CUBE_MAP); } else { - glTexImage2D(GL_TEXTURE_2D, i, GL_RGBA8, mip->x, mip->y, - 0, GL_RGBA, GL_UNSIGNED_BYTE, mip->rect); + if (!ibuf) { + if (use_high_bit_depth) { + ibuf = IMB_allocFromBuffer(NULL, frect, tpx, tpy); + } + else { + ibuf = IMB_allocFromBuffer(rect, NULL, tpx, tpy); + } + } + + IMB_makemipmap(ibuf, true); + + for (int i = 1; i < ibuf->miptot; i++) { + ImBuf *mip = ibuf->mipmap[i - 1]; + void **mip_cube_map = gpu_gen_cube_map(mip->rect, mip->rect_float, + mip->x, mip->y, use_high_bit_depth); + int mipw = mip->x / 3, miph = mip->y / 2; + + if (mip_cube_map) { + for (int j = 0; j < 6; j++) { + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + j, i, + informat, mipw, miph, 0, GL_RGBA, type, mip_cube_map[j]); + } + } + gpu_del_cube_map(mip_cube_map); + } } + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, gpu_get_mipmap_filter(0)); + + if (ima) + ima->tpageflag |= IMA_MIPMAP_COMPLETE; } - } - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gpu_get_mipmap_filter(0)); + else { + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + } + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); - if (ima) - ima->tpageflag |= IMA_MIPMAP_COMPLETE; - } - else { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + gpu_del_cube_map(cube_map); + } + else { + printf("Incorrect envmap size\n"); + } } if (GLEW_EXT_texture_filter_anisotropic) - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, GPU_get_anisotropic()); + glTexParameterf(textarget, GL_TEXTURE_MAX_ANISOTROPY_EXT, GPU_get_anisotropic()); if (ibuf) IMB_freeImBuf(ibuf); @@ -882,20 +1024,20 @@ bool GPU_upload_dxt_texture(ImBuf *ibuf) } void GPU_create_gl_tex_compressed( - unsigned int *bind, unsigned int *pix, int x, int y, int mipmap, - Image *ima, ImBuf *ibuf) + unsigned int *bind, unsigned int *pix, int x, int y, + int textarget, int mipmap, Image *ima, ImBuf *ibuf) { #ifndef WITH_DDS (void)ibuf; /* Fall back to uncompressed if DDS isn't enabled */ - GPU_create_gl_tex(bind, pix, NULL, x, y, mipmap, 0, ima); + GPU_create_gl_tex(bind, pix, NULL, x, y, textarget, mipmap, 0, ima); #else glGenTextures(1, (GLuint *)bind); - glBindTexture(GL_TEXTURE_2D, *bind); + glBindTexture(textarget, *bind); - if (GPU_upload_dxt_texture(ibuf) == 0) { + if (textarget == GL_TEXTURE_2D && GPU_upload_dxt_texture(ibuf) == 0) { glDeleteTextures(1, (GLuint *)bind); - GPU_create_gl_tex(bind, pix, NULL, x, y, mipmap, 0, ima); + GPU_create_gl_tex(bind, pix, NULL, x, y, textarget, mipmap, 0, ima); } #endif } @@ -927,7 +1069,7 @@ int GPU_set_tpage(MTexPoly *mtexpoly, int mipmap, int alphablend) gpu_verify_alpha_blend(alphablend); gpu_verify_reflection(ima); - if (GPU_verify_image(ima, NULL, mtexpoly->tile, 1, mipmap, false)) { + if (GPU_verify_image(ima, NULL, GL_TEXTURE_2D, mtexpoly->tile, 1, mipmap, false)) { GTS.curtile = GTS.tile; GTS.curima = GTS.ima; GTS.curtilemode = GTS.tilemode; @@ -969,11 +1111,18 @@ void GPU_paint_set_mipmap(bool mipmap) if (mipmap) { for (Image *ima = G.main->image.first; ima; ima = ima->id.next) { - if (ima->bindcode) { + if (BKE_image_has_bindcode(ima)) { if (ima->tpageflag & IMA_MIPMAP_COMPLETE) { - glBindTexture(GL_TEXTURE_2D, ima->bindcode); - 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)); + if (ima->bindcode[TEXTARGET_TEXTURE_2D]) { + glBindTexture(GL_TEXTURE_2D, ima->bindcode[TEXTARGET_TEXTURE_2D]); + 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)); + } + if (ima->bindcode[TEXTARGET_TEXTURE_CUBE_MAP]) { + glBindTexture(GL_TEXTURE_CUBE_MAP, ima->bindcode[TEXTARGET_TEXTURE_CUBE_MAP]); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, gpu_get_mipmap_filter(0)); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1)); + } } else GPU_free_image(ima); @@ -985,10 +1134,17 @@ void GPU_paint_set_mipmap(bool mipmap) } else { for (Image *ima = G.main->image.first; ima; ima = ima->id.next) { - if (ima->bindcode) { - glBindTexture(GL_TEXTURE_2D, ima->bindcode); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1)); + if (BKE_image_has_bindcode(ima)) { + if (ima->bindcode[TEXTARGET_TEXTURE_2D]) { + glBindTexture(GL_TEXTURE_2D, ima->bindcode[TEXTARGET_TEXTURE_2D]); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1)); + } + if (ima->bindcode[TEXTARGET_TEXTURE_CUBE_MAP]) { + glBindTexture(GL_TEXTURE_CUBE_MAP, ima->bindcode[TEXTARGET_TEXTURE_CUBE_MAP]); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1)); + } } else ima->tpageflag &= ~IMA_MIPMAP_COMPLETE; @@ -1001,7 +1157,7 @@ void GPU_paint_set_mipmap(bool mipmap) static bool GPU_check_scaled_image(ImBuf *ibuf, Image *ima, float *frect, int x, int y, int w, int h) { if ((!GPU_full_non_power_of_two_support() && !is_power_of_2_resolution(ibuf->x, ibuf->y)) || - is_over_resolution_limit(ibuf->x, ibuf->y)) + is_over_resolution_limit(GL_TEXTURE_2D, ibuf->x, ibuf->y)) { int x_limit = smaller_power_of_2_limit(ibuf->x); int y_limit = smaller_power_of_2_limit(ibuf->y); @@ -1027,7 +1183,7 @@ static bool GPU_check_scaled_image(ImBuf *ibuf, Image *ima, float *frect, int x, ImBuf *ibuf_scale = IMB_allocFromBuffer(NULL, frect, w, h); IMB_scaleImBuf(ibuf_scale, rectw, recth); - glBindTexture(GL_TEXTURE_2D, ima->bindcode); + glBindTexture(GL_TEXTURE_2D, ima->bindcode[TEXTARGET_TEXTURE_2D]); glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, rectw, recth, GL_RGBA, GL_FLOAT, ibuf_scale->rect_float); @@ -1047,7 +1203,7 @@ static bool GPU_check_scaled_image(ImBuf *ibuf, Image *ima, float *frect, int x, bilinear_interpolation_color_wrap(ibuf, (unsigned char *)(p + i + j * (rectw)), NULL, u, v); } } - glBindTexture(GL_TEXTURE_2D, ima->bindcode); + glBindTexture(GL_TEXTURE_2D, ima->bindcode[TEXTARGET_TEXTURE_2D]); glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, rectw, recth, GL_RGBA, GL_UNSIGNED_BYTE, scalerect); @@ -1071,7 +1227,7 @@ void GPU_paint_update_image(Image *ima, ImageUser *iuser, int x, int y, int w, i { ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL); - if (ima->repbind || (GPU_get_mipmap() && !GTS.gpu_mipmap) || !ima->bindcode || !ibuf || + if (ima->repbind || (GPU_get_mipmap() && !GTS.gpu_mipmap) || BKE_image_has_bindcode(ima) || !ibuf || (w == 0) || (h == 0)) { /* these cases require full reload still */ @@ -1094,7 +1250,7 @@ void GPU_paint_update_image(Image *ima, ImageUser *iuser, int x, int y, int w, i return; } - glBindTexture(GL_TEXTURE_2D, ima->bindcode); + glBindTexture(GL_TEXTURE_2D, ima->bindcode[TEXTARGET_TEXTURE_2D]); glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, GL_RGBA, GL_FLOAT, buffer); MEM_freeN(buffer); @@ -1117,7 +1273,7 @@ void GPU_paint_update_image(Image *ima, ImageUser *iuser, int x, int y, int w, i return; } - glBindTexture(GL_TEXTURE_2D, ima->bindcode); + glBindTexture(GL_TEXTURE_2D, ima->bindcode[TEXTARGET_TEXTURE_2D]); glGetIntegerv(GL_UNPACK_ROW_LENGTH, &row_length); glGetIntegerv(GL_UNPACK_SKIP_PIXELS, &skip_pixels); @@ -1303,16 +1459,17 @@ void GPU_free_image(Image *ima) return; } - /* free regular image binding */ - if (ima->bindcode) { - glDeleteTextures(1, (GLuint *)&ima->bindcode); - ima->bindcode = 0; - } - - /* free glsl image binding */ - if (ima->gputexture) { - GPU_texture_free(ima->gputexture); - ima->gputexture = NULL; + for (int i = 0; i < TEXTARGET_COUNT; i++) { + /* free regular image binding */ + if (ima->bindcode[i]) { + glDeleteTextures(1, (GLuint *)&ima->bindcode[i]); + ima->bindcode[i] = 0; + } + /* free glsl image binding */ + if (ima->gputexture[i]) { + GPU_texture_free(ima->gputexture[i]); + ima->gputexture[i] = NULL; + } } /* free repeated image binding */ @@ -1366,7 +1523,7 @@ void GPU_free_images_old(void) if ((ima->flag & IMA_NOCOLLECT) == 0 && ctime - ima->lastused > U.textimeout) { /* If it's in GL memory, deallocate and set time tag to current time * This gives textures a "second chance" to be used before dying. */ - if (ima->bindcode || ima->repbind) { + if (BKE_image_has_bindcode(ima) || ima->repbind) { GPU_free_image(ima); ima->lastused = ctime; } diff --git a/source/blender/gpu/intern/gpu_extensions.c b/source/blender/gpu/intern/gpu_extensions.c index a53c55b6016..fd660d2e97c 100644 --- a/source/blender/gpu/intern/gpu_extensions.c +++ b/source/blender/gpu/intern/gpu_extensions.c @@ -73,6 +73,7 @@ static struct GPUGlobal { GLint maxtexsize; + GLint maxcubemapsize; GLint maxtextures; bool extdisabled; int colordepth; @@ -120,6 +121,11 @@ int GPU_max_color_texture_samples(void) return GG.samples_color_texture_max; } +int GPU_max_cube_map_size(void) +{ + return GG.maxcubemapsize; +} + void GPU_get_dfdy_factors(float fac[2]) { copy_v2_v2(fac, GG.dfdyfactors); @@ -133,6 +139,7 @@ void gpu_extensions_init(void) glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &GG.maxtextures); glGetIntegerv(GL_MAX_TEXTURE_SIZE, &GG.maxtexsize); + glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, &GG.maxcubemapsize); if (GLEW_EXT_texture_filter_anisotropic) glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &GG.max_anisotropy); diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c index 81f04f0ef22..09d326e2ee8 100644 --- a/source/blender/gpu/intern/gpu_material.c +++ b/source/blender/gpu/intern/gpu_material.c @@ -1814,6 +1814,198 @@ GPUMaterial *GPU_material_matcap(Scene *scene, Material *ma, bool use_opensubdiv return mat; } +static void do_world_tex(GPUShadeInput *shi, struct World *wo, GPUNodeLink **hor, GPUNodeLink **zen, GPUNodeLink **blend) +{ + GPUMaterial *mat = shi->gpumat; + GPUNodeLink *texco, *tin, *trgb, *stencil, *tcol, *zenfac; + MTex *mtex; + Tex *tex; + float ofs[3], zero = 0.0f; + int tex_nr, rgbnor; + + GPU_link(mat, "set_value_one", &stencil); + /* go over texture slots */ + for (tex_nr = 0; tex_nr < MAX_MTEX; tex_nr++) { + if (wo->mtex[tex_nr]) { + mtex = wo->mtex[tex_nr]; + tex = mtex->tex; + if (tex == NULL || !tex->ima || (tex->type != TEX_IMAGE && tex->type != TEX_ENVMAP)) + continue; + /* which coords */ + if (mtex->texco == TEXCO_VIEW || mtex->texco == TEXCO_GLOB) { + if (tex->type == TEX_IMAGE) + texco = GPU_builtin(GPU_VIEW_POSITION); + else if (tex->type == TEX_ENVMAP) + GPU_link(mat, "background_transform_to_world", GPU_builtin(GPU_VIEW_POSITION), &texco); + } + else if (mtex->texco == TEXCO_EQUIRECTMAP || mtex->texco == TEXCO_ANGMAP) { + if ((tex->type == TEX_IMAGE && wo->skytype & WO_SKYREAL) || tex->type == TEX_ENVMAP) + GPU_link(mat, "background_transform_to_world", GPU_builtin(GPU_VIEW_POSITION), &texco); + else + texco = GPU_builtin(GPU_VIEW_POSITION); + } + else + continue; + GPU_link(mat, "texco_norm", texco, &texco); + if (tex->type == TEX_IMAGE && !(wo->skytype & WO_SKYREAL)) { + GPU_link(mat, "mtex_2d_mapping", texco, &texco); + } + if (mtex->size[0] != 1.0f || mtex->size[1] != 1.0f || mtex->size[2] != 1.0f) { + float size[3] = { mtex->size[0], mtex->size[1], mtex->size[2] }; + if (tex->type == TEX_ENVMAP) { + size[1] = mtex->size[2]; + size[2] = mtex->size[1]; + } + GPU_link(mat, "mtex_mapping_size", texco, GPU_uniform(size), &texco); + } + ofs[0] = mtex->ofs[0] + 0.5f - 0.5f * mtex->size[0]; + if (tex->type == TEX_ENVMAP) { + ofs[1] = -mtex->ofs[2] + 0.5f - 0.5f * mtex->size[2]; + ofs[2] = mtex->ofs[1] + 0.5f - 0.5f * mtex->size[1]; + } + else { + ofs[1] = mtex->ofs[1] + 0.5f - 0.5f * mtex->size[1]; + ofs[2] = 0.0; + } + if (ofs[0] != 0.0f || ofs[1] != 0.0f || ofs[2] != 0.0f) + GPU_link(mat, "mtex_mapping_ofs", texco, GPU_uniform(ofs), &texco); + if (mtex->texco == TEXCO_EQUIRECTMAP) { + GPU_link(mat, "node_tex_environment_equirectangular", texco, GPU_image(tex->ima, &tex->iuser, false), &trgb); + } + else if (mtex->texco == TEXCO_ANGMAP) { + GPU_link(mat, "node_tex_environment_mirror_ball", texco, GPU_image(tex->ima, &tex->iuser, false), &trgb); + } + else { + if (tex->type == TEX_ENVMAP) + GPU_link(mat, "mtex_cube_map", texco, GPU_cube_map(tex->ima, &tex->iuser, false), &tin, &trgb); + else if (tex->type == TEX_IMAGE) + GPU_link(mat, "mtex_image", texco, GPU_image(tex->ima, &tex->iuser, false), &tin, &trgb); + } + rgbnor = TEX_RGB; + if (tex->type == TEX_IMAGE || tex->type == TEX_ENVMAP) + if (GPU_material_do_color_management(mat)) + GPU_link(mat, "srgb_to_linearrgb", trgb, &trgb); + /* texture output */ + if ((rgbnor & TEX_RGB) && (mtex->texflag & MTEX_RGBTOINT)) { + GPU_link(mat, "mtex_rgbtoint", trgb, &tin); + rgbnor -= TEX_RGB; + } + if (mtex->texflag & MTEX_NEGATIVE) { + if (rgbnor & TEX_RGB) + GPU_link(mat, "mtex_rgb_invert", trgb, &trgb); + else + GPU_link(mat, "mtex_value_invert", tin, &tin); + } + if (mtex->texflag & MTEX_STENCIL) { + if (rgbnor & TEX_RGB) + GPU_link(mat, "mtex_rgb_stencil", stencil, trgb, &stencil, &trgb); + else + GPU_link(mat, "mtex_value_stencil", stencil, tin, &stencil, &tin); + } + else { + if (rgbnor & TEX_RGB) + GPU_link(mat, "mtex_alpha_multiply_value", trgb, stencil, &trgb); + else + GPU_link(mat, "math_multiply", stencil, tin, &tin); + } + /* color mapping */ + if (mtex->mapto & (WOMAP_HORIZ + WOMAP_ZENUP + WOMAP_ZENDOWN)) { + if ((rgbnor & TEX_RGB) == 0) + GPU_link(mat, "set_rgb", GPU_uniform(&mtex->r), &trgb); + else + GPU_link(mat, "mtex_alpha_from_col", trgb, &tin); + GPU_link(mat, "set_rgb", trgb, &tcol); + if (mtex->mapto & WOMAP_HORIZ) { + texture_rgb_blend(mat, tcol, *hor, tin, GPU_uniform(&mtex->colfac), mtex->blendtype, hor); + } + if (mtex->mapto & (WOMAP_ZENUP + WOMAP_ZENDOWN)) { + GPU_link(mat, "set_value_zero", &zenfac); + if (wo->skytype & WO_SKYREAL) { + if (mtex->mapto & WOMAP_ZENUP) { + if (mtex->mapto & WOMAP_ZENDOWN) { + GPU_link(mat, "world_zen_mapping", shi->view, GPU_uniform(&mtex->zenupfac), + GPU_uniform(&mtex->zendownfac), &zenfac); + } + else { + GPU_link(mat, "world_zen_mapping", shi->view, GPU_uniform(&mtex->zenupfac), + GPU_uniform(&zero), &zenfac); + } + } + else if (mtex->mapto & WOMAP_ZENDOWN) + GPU_link(mat, "world_zen_mapping", shi->view, GPU_uniform(&zero), + GPU_uniform(&mtex->zendownfac), &zenfac); + } + else { + if (mtex->mapto & WOMAP_ZENUP) + GPU_link(mat, "set_value", GPU_uniform(&mtex->zenupfac), &zenfac); + else if (mtex->mapto & WOMAP_ZENDOWN) + GPU_link(mat, "set_value", GPU_uniform(&mtex->zendownfac), &zenfac); + } + texture_rgb_blend(mat, tcol, *zen, tin, zenfac, mtex->blendtype, zen); + } + } + if (mtex->mapto & WOMAP_BLEND && wo->skytype & WO_SKYBLEND) { + if (rgbnor & TEX_RGB) + GPU_link(mat, "mtex_rgbtoint", trgb, &tin); + texture_value_blend(mat, GPU_uniform(&mtex->def_var), *blend, tin, GPU_uniform(&mtex->blendfac), mtex->blendtype, blend); + } + } + } +} + +static void GPU_material_old_world(struct GPUMaterial *mat, struct World *wo) +{ + GPUShadeInput shi; + GPUShadeResult shr; + GPUNodeLink *hor, *zen, *ray, *blend; + + shi.gpumat = mat; + + for (int i = 0; i < MAX_MTEX; i++) { + if (wo->mtex[i] && wo->mtex[i]->tex) { + wo->skytype |= WO_SKYTEX; + break; + } + } + if ((wo->skytype & (WO_SKYBLEND + WO_SKYTEX)) == 0) { + GPU_link(mat, "set_rgb", GPU_dynamic_uniform(&wo->horr, GPU_DYNAMIC_HORIZON_COLOR, NULL), &shr.combined); + } + else { + GPU_link(mat, "set_rgb_zero", &shi.rgb); + GPU_link(mat, "background_transform_to_world", GPU_builtin(GPU_VIEW_POSITION), &ray); + if (wo->skytype & WO_SKYPAPER) + GPU_link(mat, "world_paper_view", GPU_builtin(GPU_VIEW_POSITION), &shi.view); + else + GPU_link(mat, "shade_view", ray, &shi.view); + if (wo->skytype & WO_SKYBLEND) { + if (wo->skytype & WO_SKYPAPER) { + if (wo->skytype & WO_SKYREAL) + GPU_link(mat, "world_blend_paper_real", GPU_builtin(GPU_VIEW_POSITION), &blend); + else + GPU_link(mat, "world_blend_paper", GPU_builtin(GPU_VIEW_POSITION), &blend); + } + else { + if (wo->skytype & WO_SKYREAL) + GPU_link(mat, "world_blend_real", ray, &blend); + else + GPU_link(mat, "world_blend", ray, &blend); + } + } + else { + GPU_link(mat, "set_value_zero", &blend); + } + GPU_link(mat, "set_rgb", GPU_dynamic_uniform(&wo->horr, GPU_DYNAMIC_HORIZON_COLOR, NULL), &hor); + GPU_link(mat, "set_rgb", GPU_dynamic_uniform(&wo->zenr, GPU_DYNAMIC_ZENITH_COLOR, NULL), &zen); + do_world_tex(&shi, wo, &hor, &zen, &blend); + if (wo->skytype & WO_SKYBLEND) + GPU_link(mat, "node_mix_shader", blend, hor, zen, &shi.rgb); + else + GPU_link(mat, "set_rgb", hor, &shi.rgb); + GPU_link(mat, "set_rgb", shi.rgb, &shr.combined); + } + GPU_material_output_link(mat, shr.combined); +} + GPUMaterial *GPU_material_world(struct Scene *scene, struct World *wo) { LinkData *link; @@ -1832,7 +2024,7 @@ GPUMaterial *GPU_material_world(struct Scene *scene, struct World *wo) if (BKE_scene_use_new_shading_nodes(scene) && wo->nodetree && wo->use_nodes) ntreeGPUMaterialNodes(wo->nodetree, mat, NODE_NEW_SHADING); else { - /* old fixed function world */ + GPU_material_old_world(mat, wo); } if (GPU_material_do_color_management(mat)) @@ -2424,6 +2616,7 @@ GPUShaderExport *GPU_shader_export(struct Scene *scene, struct Material *ma) break; case GPU_NONE: + case GPU_TEXCUBE: case GPU_FLOAT: case GPU_VEC2: case GPU_VEC3: @@ -2459,6 +2652,7 @@ GPUShaderExport *GPU_shader_export(struct Scene *scene, struct Material *ma) case GPU_NONE: case GPU_TEX2D: + case GPU_TEXCUBE: case GPU_SHADOW2D: case GPU_ATTRIB: break; diff --git a/source/blender/gpu/intern/gpu_texture.c b/source/blender/gpu/intern/gpu_texture.c index f410edb60b0..294b08f155a 100644 --- a/source/blender/gpu/intern/gpu_texture.c +++ b/source/blender/gpu/intern/gpu_texture.c @@ -368,27 +368,33 @@ GPUTexture *GPU_texture_create_3D(int w, int h, int depth, int channels, const f return tex; } -GPUTexture *GPU_texture_from_blender(Image *ima, ImageUser *iuser, bool is_data, double time, int mipmap) +GPUTexture *GPU_texture_from_blender(Image *ima, ImageUser *iuser, int textarget, bool is_data, double time, int mipmap) { - GPU_update_image_time(ima, time); + int gputt; /* this binds a texture, so that's why to restore it to 0 */ - GLint bindcode = GPU_verify_image(ima, iuser, 0, 0, mipmap, is_data); + GLint bindcode = GPU_verify_image(ima, iuser, textarget, 0, 0, mipmap, is_data); + GPU_update_image_time(ima, time); - if (ima->gputexture) { - ima->gputexture->bindcode = bindcode; - glBindTexture(GL_TEXTURE_2D, 0); - return ima->gputexture; + 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 = GL_TEXTURE_2D; + tex->target = textarget; tex->target_base = GL_TEXTURE_2D; tex->fromblender = 1; - ima->gputexture = tex; + ima->gputexture[gputt] = tex; if (!glIsTexture(tex->bindcode)) { GPU_ASSERT_NO_GL_ERRORS("Blender Texture Not Loaded"); @@ -396,16 +402,23 @@ GPUTexture *GPU_texture_from_blender(Image *ima, ImageUser *iuser, bool is_data, else { GLint w, h, border; - 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); + 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(GL_TEXTURE_2D, 0); + glBindTexture(textarget, 0); return tex; } @@ -420,7 +433,7 @@ GPUTexture *GPU_texture_from_preview(PreviewImage *prv, int mipmap) /* this binds a texture, so that's why we restore it to 0 */ if (bindcode == 0) { - GPU_create_gl_tex(&bindcode, prv->rect[0], NULL, prv->w[0], prv->h[0], mipmap, 0, NULL); + GPU_create_gl_tex(&bindcode, prv->rect[0], NULL, prv->w[0], prv->h[0], GL_TEXTURE_2D, mipmap, 0, NULL); } if (tex) { tex->bindcode = bindcode; @@ -641,6 +654,8 @@ void GPU_texture_unbind(GPUTexture *tex) GLenum arbnumber = (GLenum)((GLuint)GL_TEXTURE0 + tex->number); if (tex->number != 0) glActiveTexture(arbnumber); glBindTexture(tex->target, 0); + glDisable(tex->target); + glBindTexture(tex->target_base, 0); glDisable(tex->target_base); if (tex->number != 0) glActiveTexture(GL_TEXTURE0); diff --git a/source/blender/gpu/shaders/gpu_shader_material.glsl b/source/blender/gpu/shaders/gpu_shader_material.glsl index e7072016cc0..c8ce9f7a229 100644 --- a/source/blender/gpu/shaders/gpu_shader_material.glsl +++ b/source/blender/gpu/shaders/gpu_shader_material.glsl @@ -1204,6 +1204,11 @@ void mtex_alpha_to_col(vec4 col, float alpha, out vec4 outcol) outcol = vec4(col.rgb, alpha); } +void mtex_alpha_multiply_value(vec4 col, float value, out vec4 outcol) +{ + outcol = vec4(col.rgb, col.a * value); +} + void mtex_rgbtoint(vec4 rgb, out float intensity) { intensity = dot(vec3(0.35, 0.45, 0.2), rgb.rgb); @@ -1253,6 +1258,12 @@ vec3 mtex_2d_mapping(vec3 vec) return vec3(vec.xy*0.5 + vec2(0.5), vec.z); } +void mtex_cube_map(vec3 co, samplerCube ima, out float value, out vec4 color) +{ + color = textureCube(ima, co); + value = 1.0; +} + void mtex_image(vec3 texco, sampler2D ima, out float value, out vec4 color) { color = texture2D(ima, texco.xy); @@ -1653,6 +1664,40 @@ void lamp_visibility_clamp(float visifac, out float outvisifac) outvisifac = (visifac < 0.001)? 0.0: visifac; } +void world_paper_view(vec3 vec, out vec3 outvec) +{ + vec3 nvec = normalize(vec); + outvec = (gl_ProjectionMatrix[3][3] == 0.0) ? vec3(nvec.x, 0.0, nvec.y) : vec3(0.0, 0.0, -1.0); +} + +void world_zen_mapping(vec3 view, float zenup, float zendown, out float zenfac) +{ + if (view.z >= 0.0) + zenfac = zenup; + else + zenfac = zendown; +} + +void world_blend_paper_real(vec3 vec, out float blend) +{ + blend = abs(vec.y); +} + +void world_blend_paper(vec3 vec, out float blend) +{ + blend = (vec.y + 1.0) * 0.5; +} + +void world_blend_real(vec3 vec, out float blend) +{ + blend = abs(normalize(vec).z); +} + +void world_blend(vec3 vec, out float blend) +{ + blend = (normalize(vec).z + 1) * 0.5; +} + void shade_view(vec3 co, out vec3 view) { /* handle perspective/orthographic */ diff --git a/source/blender/makesdna/DNA_image_types.h b/source/blender/makesdna/DNA_image_types.h index d48ce863338..b4bc26f45cd 100644 --- a/source/blender/makesdna/DNA_image_types.h +++ b/source/blender/makesdna/DNA_image_types.h @@ -90,13 +90,19 @@ typedef struct RenderSlot { #define IMA_NEED_FRAME_RECALC 8 #define IMA_SHOW_STEREO 16 +enum { + TEXTARGET_TEXTURE_2D = 0, + TEXTARGET_TEXTURE_CUBE_MAP = 1, + TEXTARGET_COUNT = 2 +}; + typedef struct Image { ID id; char name[1024]; /* file path, 1024 = FILE_MAX */ struct MovieCache *cache; /* not written in file */ - struct GPUTexture *gputexture; /* not written in file */ + struct GPUTexture *gputexture[2]; /* not written in file 2 = TEXTARGET_COUNT */ /* sources from: */ ListBase anims; @@ -113,7 +119,8 @@ typedef struct Image { short tpageflag, totbind; short xrep, yrep; short twsta, twend; - unsigned int bindcode; /* only for current image... */ + unsigned int bindcode[2]; /* only for current image... 2 = TEXTARGET_COUNT */ + char pad1[4]; unsigned int *repbind; /* for repeat of parts of images */ struct PackedFile *packedfile DNA_DEPRECATED; /* deprecated */ diff --git a/source/blender/makesrna/intern/rna_image_api.c b/source/blender/makesrna/intern/rna_image_api.c index 23643f722d6..eb8dd5a63d4 100644 --- a/source/blender/makesrna/intern/rna_image_api.c +++ b/source/blender/makesrna/intern/rna_image_api.c @@ -224,7 +224,7 @@ static void rna_Image_scale(Image *image, ReportList *reports, int width, int he static int rna_Image_gl_load(Image *image, ReportList *reports, int frame, int filter, int mag) { ImBuf *ibuf; - unsigned int *bind = &image->bindcode; + unsigned int *bind = &image->bindcode[TEXTARGET_TEXTURE_2D]; int error = GL_NO_ERROR; ImageUser iuser = {NULL}; void *lock; @@ -245,7 +245,7 @@ static int rna_Image_gl_load(Image *image, ReportList *reports, int frame, int f return (int)GL_INVALID_OPERATION; } - GPU_create_gl_tex(bind, ibuf->rect, ibuf->rect_float, ibuf->x, ibuf->y, + GPU_create_gl_tex(bind, ibuf->rect, ibuf->rect_float, GL_TEXTURE_2D, ibuf->x, ibuf->y, (filter != GL_NEAREST && filter != GL_LINEAR), false, image); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (GLint)filter); @@ -255,7 +255,7 @@ static int rna_Image_gl_load(Image *image, ReportList *reports, int frame, int f if (error) { glDeleteTextures(1, (GLuint *)bind); - image->bindcode = 0; + image->bindcode[TEXTARGET_TEXTURE_2D] = 0; } BKE_image_release_ibuf(image, ibuf, NULL); @@ -265,7 +265,7 @@ static int rna_Image_gl_load(Image *image, ReportList *reports, int frame, int f static int rna_Image_gl_touch(Image *image, ReportList *reports, int frame, int filter, int mag) { - unsigned int *bind = &image->bindcode; + unsigned int *bind = &image->bindcode[TEXTARGET_TEXTURE_2D]; int error = GL_NO_ERROR; BKE_image_tag_time(image); diff --git a/source/blender/python/intern/gpu.c b/source/blender/python/intern/gpu.c index c6e47de8c90..66c1ddcc352 100644 --- a/source/blender/python/intern/gpu.c +++ b/source/blender/python/intern/gpu.c @@ -128,6 +128,7 @@ static PyObject *PyInit_gpu(void) /* GPU_DYNAMIC_GROUP_WORLD */ PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_HORIZON_COLOR); PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_AMBIENT_COLOR); + PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_ZENITH_COLOR); /* GPU_DYNAMIC_GROUP_MAT */ PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_MAT_DIFFRGB); PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_MAT_REF); diff --git a/source/gameengine/Ketsji/BL_Texture.cpp b/source/gameengine/Ketsji/BL_Texture.cpp index 0b0a0f5d403..730e49c4918 100644 --- a/source/gameengine/Ketsji/BL_Texture.cpp +++ b/source/gameengine/Ketsji/BL_Texture.cpp @@ -138,7 +138,7 @@ bool BL_Texture::InitFromImage(int unit, Image *img, bool mipmap) mipmap = mipmap && GPU_get_mipmap(); - mTexture = img->bindcode; + mTexture = img->bindcode[TEXTARGET_TEXTURE_2D]; mType = GL_TEXTURE_2D; mUnit = unit; diff --git a/source/gameengine/VideoTexture/Texture.cpp b/source/gameengine/VideoTexture/Texture.cpp index cc010f08b17..f1c7bc303ee 100644 --- a/source/gameengine/VideoTexture/Texture.cpp +++ b/source/gameengine/VideoTexture/Texture.cpp @@ -299,7 +299,7 @@ PyObject *Texture_close(Texture * self) self->m_matTexture->swapTexture(self->m_orgTex); else { - self->m_imgTexture->bindcode = self->m_orgTex; + self->m_imgTexture->bindcode[TEXTARGET_TEXTURE_2D] = self->m_orgTex; BKE_image_release_ibuf(self->m_imgTexture, self->m_imgBuf, NULL); self->m_imgBuf = NULL; } @@ -357,8 +357,8 @@ static PyObject *Texture_refresh(Texture *self, PyObject *args) // WARNING: GPU has a ImageUser to pass, we don't. Using NULL // works on image file, not necessarily on other type of image. self->m_imgBuf = BKE_image_acquire_ibuf(self->m_imgTexture, NULL, NULL); - self->m_orgTex = self->m_imgTexture->bindcode; - self->m_imgTexture->bindcode = self->m_actTex; + self->m_orgTex = self->m_imgTexture->bindcode[TEXTARGET_TEXTURE_2D]; + self->m_imgTexture->bindcode[TEXTARGET_TEXTURE_2D] = self->m_actTex; } } |