World textures displaying for viewport in BI.

This patch supports "Image or Movie" and "Environment map" types of world texture for the viewport.
It supports:

  - "View", "AngMap" and "Equirectangular" types of mapping.

  - Different types of texture blending (according to BI world render).

  - Same color blending as when it lacked textures (but render via glsl).

{F207734}
{F207735}

Example: {F275180}
Original author: @valentin_b4w

Regards,
Alexander (Blend4Web Team).

Reviewers: sergey, valentin_b4w, brecht, merwin

Reviewed By: merwin

Subscribers: campbellbarton, merwin, blueprintrandom, youle, a.romanov, yurikovelenov, AlexKowel, Evgeny_Rodygin

Projects: #rendering, #opengl_gfx, #bf_blender:_next

Differential Revision: https://developer.blender.org/D1414
This commit is contained in:
Alexander Romanov 2016-01-27 12:06:57 +03:00
parent f6ff8f27e3
commit 771f73b6be
21 changed files with 624 additions and 146 deletions

@ -259,6 +259,9 @@ bool BKE_image_scale(struct Image *image, int width, int height);
/* check if texture has alpha (depth=32) */ /* check if texture has alpha (depth=32) */
bool BKE_image_has_alpha(struct Image *image); 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(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_size_fl(struct Image *image, struct ImageUser *iuser, float size[2]);
void BKE_image_get_aspect(struct Image *image, float *aspx, float *aspy); void BKE_image_get_aspect(struct Image *image, float *aspx, float *aspy);

@ -657,6 +657,18 @@ bool BKE_image_scale(Image *image, int width, int height)
return (ibuf != NULL); 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) static void image_init_color_management(Image *ima)
{ {
ImBuf *ibuf; ImBuf *ibuf;

@ -1565,8 +1565,9 @@ void blo_make_image_pointer_map(FileData *fd, Main *oldmain)
for (; ima; ima = ima->id.next) { for (; ima; ima = ima->id.next) {
if (ima->cache) if (ima->cache)
oldnewmap_insert(fd->imamap, ima->cache, ima->cache, 0); oldnewmap_insert(fd->imamap, ima->cache, ima->cache, 0);
if (ima->gputexture) for (a = 0; a < TEXTARGET_COUNT; a++)
oldnewmap_insert(fd->imamap, ima->gputexture, ima->gputexture, 0); if (ima->gputexture[a])
oldnewmap_insert(fd->imamap, ima->gputexture[a], ima->gputexture[a], 0);
if (ima->rr) if (ima->rr)
oldnewmap_insert(fd->imamap, ima->rr, ima->rr, 0); oldnewmap_insert(fd->imamap, ima->rr, ima->rr, 0);
for (a=0; a < IMA_MAX_RENDER_SLOT; a++) 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) { for (; ima; ima = ima->id.next) {
ima->cache = newimaadr(fd, ima->cache); ima->cache = newimaadr(fd, ima->cache);
if (ima->cache == NULL) { if (ima->cache == NULL) {
ima->bindcode = 0;
ima->tpageflag &= ~IMA_GLBIND_IS_DATA; 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; ima->rr = NULL;
} }
for (i = 0; i < IMA_MAX_RENDER_SLOT; i++) for (i = 0; i < IMA_MAX_RENDER_SLOT; i++)
ima->renders[i] = newimaadr(fd, ima->renders[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); ima->rr = newimaadr(fd, ima->rr);
} }
for (; sce; sce = sce->id.next) { 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 not restored, we keep the binded opengl index */
if (!ima->cache) { if (!ima->cache) {
ima->bindcode = 0;
ima->tpageflag &= ~IMA_GLBIND_IS_DATA; 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; ima->rr = NULL;
} }

@ -318,7 +318,7 @@ static bool set_draw_settings_cached(int clearcache, MTexPoly *texface, Material
if (textured) { if (textured) {
if (texpaint) { if (texpaint) {
c_badtex = false; 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); glEnable(GL_TEXTURE_2D);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE); 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_OPERAND2_RGB, GL_SRC_ALPHA);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_PREVIOUS); 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); glActiveTexture(GL_TEXTURE0);
} }
else { else {
@ -465,7 +465,7 @@ static void draw_textured_begin(Scene *scene, View3D *v3d, RegionView3D *rv3d, O
/* load the stencil texture here */ /* load the stencil texture here */
if (Gtexdraw.stencil != NULL) { if (Gtexdraw.stencil != NULL) {
glActiveTexture(GL_TEXTURE2); 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}; float col[4] = {imapaint->stencil_col[0], imapaint->stencil_col[1], imapaint->stencil_col[2], 1.0f};
glEnable(GL_TEXTURE_2D); glEnable(GL_TEXTURE_2D);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); 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)) { if (ED_object_get_active_image(data->ob, mat_nr, &ima, &iuser, &node, NULL)) {
/* get openl texture */ /* get openl texture */
int mipmap = 1; 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) { if (bindcode) {
NodeTexBase *texbase = node->storage; 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(); GPU_object_material_unbind();
/* bind texture */ /* bind texture */
glBindTexture(GL_TEXTURE_2D, ima->bindcode); glBindTexture(GL_TEXTURE_2D, ima->bindcode[TEXTARGET_TEXTURE_2D]);
glMatrixMode(GL_TEXTURE); glMatrixMode(GL_TEXTURE);
glLoadMatrixf(texbase->tex_mapping.mat); glLoadMatrixf(texbase->tex_mapping.mat);

@ -99,6 +99,7 @@
#include "GPU_framebuffer.h" #include "GPU_framebuffer.h"
#include "GPU_material.h" #include "GPU_material.h"
#include "GPU_compositing.h" #include "GPU_compositing.h"
#include "GPU_extensions.h"
#include "view3d_intern.h" /* own include */ #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) static void view3d_main_region_clear(Scene *scene, View3D *v3d, ARegion *ar)
{ {
if (scene->world && (v3d->flag3 & V3D_SHOW_WORLD)) { 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) { if (glsl) {
RegionView3D *rv3d = ar->regiondata; RegionView3D *rv3d = ar->regiondata;
GPUMaterial *gpumat = GPU_material_world(scene, scene->world); GPUMaterial *gpumat = GPU_material_world(scene, scene->world);

@ -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_paint_update_image(struct Image *ima, struct ImageUser *iuser, int x, int y, int w, int h);
void GPU_update_images_framechange(void); void GPU_update_images_framechange(void);
int GPU_update_image_time(struct Image *ima, double time); 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); int GPU_verify_image(struct Image *ima,
void GPU_create_gl_tex( struct ImageUser *iuser, int textarget, int tftile, bool compare, bool mipmap, bool is_data);
unsigned int *bind, unsigned int *rect, float *frect, int rectw, int recth, 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 textarget, bool mipmap, bool use_hight_bit_depth, struct Image *ima);
void GPU_create_gl_tex_compressed( void GPU_create_gl_tex_compressed(
unsigned int *bind, unsigned int *pix, int x, int y, int mipmap, unsigned int *bind, unsigned int *pix, int x, int y, int mipmap,
struct Image *ima, struct ImBuf *ibuf); int textarget, struct Image *ima, struct ImBuf *ibuf);
bool GPU_upload_dxt_texture(struct ImBuf *ibuf); bool GPU_upload_dxt_texture(struct ImBuf *ibuf);
void GPU_free_image(struct Image *ima); void GPU_free_image(struct Image *ima);
void GPU_free_images(void); void GPU_free_images(void);

@ -53,6 +53,7 @@ int GPU_max_texture_size(void);
int GPU_max_textures(void); int GPU_max_textures(void);
float GPU_max_texture_anisotropy(void); float GPU_max_texture_anisotropy(void);
int GPU_max_color_texture_samples(void); int GPU_max_color_texture_samples(void);
int GPU_max_cube_map_size(void);
int GPU_color_depth(void); int GPU_color_depth(void);
void GPU_get_dfdy_factors(float fac[2]); void GPU_get_dfdy_factors(float fac[2]);

@ -78,6 +78,7 @@ typedef enum GPUType {
GPU_TEX2D = 1002, GPU_TEX2D = 1002,
GPU_SHADOW2D = 1003, GPU_SHADOW2D = 1003,
GPU_TEXCUBE = 1004,
GPU_ATTRIB = 3001 GPU_ATTRIB = 3001
} GPUType; } GPUType;
@ -179,6 +180,7 @@ typedef enum GPUDynamicType {
GPU_DYNAMIC_HORIZON_COLOR = 1 | GPU_DYNAMIC_GROUP_WORLD, GPU_DYNAMIC_HORIZON_COLOR = 1 | GPU_DYNAMIC_GROUP_WORLD,
GPU_DYNAMIC_AMBIENT_COLOR = 2 | 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_DIFFRGB = 1 | GPU_DYNAMIC_GROUP_MAT,
GPU_DYNAMIC_MAT_REF = 2 | 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_uniform(float *num);
GPUNodeLink *GPU_dynamic_uniform(float *num, GPUDynamicType dynamictype, void *data); GPUNodeLink *GPU_dynamic_uniform(float *num, GPUDynamicType dynamictype, void *data);
GPUNodeLink *GPU_image(struct Image *ima, struct ImageUser *iuser, bool is_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_image_preview(struct PreviewImage *prv);
GPUNodeLink *GPU_texture(int size, float *pixels); GPUNodeLink *GPU_texture(int size, float *pixels);
GPUNodeLink *GPU_dynamic_texture(struct GPUTexture *tex, GPUDynamicType dynamictype, void *data); GPUNodeLink *GPU_dynamic_texture(struct GPUTexture *tex, GPUDynamicType dynamictype, void *data);

@ -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]); 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_create_depth_multisample(int w, int h, int samples, char err_out[256]);
GPUTexture *GPU_texture_from_blender( 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); GPUTexture *GPU_texture_from_preview(struct PreviewImage *prv, int mipmap);
void GPU_invalid_tex_init(void); void GPU_invalid_tex_init(void);
void GPU_invalid_tex_bind(int mode); void GPU_invalid_tex_bind(int mode);

@ -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")) { if (!type && gpu_str_prefix(code, "sampler2DShadow")) {
type = GPU_SHADOW2D; type = GPU_SHADOW2D;
} }
@ -505,8 +508,9 @@ static int codegen_print_uniforms_functions(DynStr *ds, ListBase *nodes)
/* create exactly one sampler for each texture */ /* create exactly one sampler for each texture */
if (codegen_input_has_texture(input) && input->bindtex) { if (codegen_input_has_texture(input) && input->bindtex) {
BLI_dynstr_appendf(ds, "uniform %s samp%d;\n", BLI_dynstr_appendf(ds, "uniform %s samp%d;\n",
(input->textype == GPU_TEX2D) ? "sampler2D" : "sampler2DShadow", (input->textype == GPU_TEX2D) ? "sampler2D" :
input->texid); (input->textype == GPU_TEXCUBE) ? "samplerCube" : "sampler2DShadow",
input->texid);
} }
} }
else if (input->source == GPU_SOURCE_BUILTIN) { else if (input->source == GPU_SOURCE_BUILTIN) {
@ -1015,7 +1019,7 @@ void GPU_pass_bind(GPUPass *pass, double time, int mipmap)
/* create the textures */ /* create the textures */
for (input = inputs->first; input; input = input->next) { for (input = inputs->first; input; input = input->next) {
if (input->ima) 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) else if (input->prv)
input->tex = GPU_texture_from_preview(input->prv, mipmap); 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->type = GPU_VEC4;
input->source = GPU_SOURCE_TEX; 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; 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->ima = link->ptr1;
input->iuser = link->ptr2; input->iuser = link->ptr2;
input->image_isdata = link->image_isdata; 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); MEM_freeN(link);
} }
else if (link->attribtype) { else if (link->attribtype) {
@ -1405,6 +1419,18 @@ GPUNodeLink *GPU_image(Image *ima, ImageUser *iuser, bool is_data)
return link; 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 *GPU_image_preview(PreviewImage *prv)
{ {
GPUNodeLink *link = GPU_node_link_create(); GPUNodeLink *link = GPU_node_link_create();

@ -63,7 +63,8 @@ typedef enum GPUDataSource {
typedef enum { typedef enum {
GPU_NODE_LINK_IMAGE_NONE = 0, GPU_NODE_LINK_IMAGE_NONE = 0,
GPU_NODE_LINK_IMAGE_BLENDER = 1, 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; } GPUNodeLinkImage;
struct GPUNode { struct GPUNode {

@ -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); 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) ? int reslimit = (U.glreslimit != 0) ?
min_ii(U.glreslimit, GPU_max_texture_size()) : min_ii(U.glreslimit, size) : size;
GPU_max_texture_size();
return (w > reslimit || h > reslimit); return (w > reslimit || h > reslimit);
} }
@ -398,6 +399,18 @@ static void gpu_make_repbind(Image *ima)
BKE_image_release_ibuf(ima, ibuf, NULL); 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) void GPU_clear_tpage(bool force)
{ {
if (GTS.lasttface == NULL && !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; unsigned int *bind = NULL;
int tpx = 0, tpy = 0; 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; if (GTS.tile >= ima->totbind) GTS.tile = 0;
/* this happens when you change repeat buttons */ /* this happens when you change repeat buttons */
if (ima->repbind) bind = &ima->repbind[GTS.tile]; if (ima->repbind && textarget == GL_TEXTURE_2D) bind = &ima->repbind[GTS.tile];
else bind = &ima->bindcode; else bind = gpu_get_image_bindcode(ima, textarget);
if (*bind == 0) { if (*bind == 0) {
short texwindx = ibuf->x / ima->xrep; short texwindx = ibuf->x / ima->xrep;
@ -628,7 +641,7 @@ int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, bool compare, boo
} }
else { else {
/* regular image mode */ /* regular image mode */
bind = &ima->bindcode; bind = gpu_get_image_bindcode(ima, textarget);
if (*bind == 0) { if (*bind == 0) {
tpx = ibuf->x; tpx = ibuf->x;
@ -653,7 +666,7 @@ int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, bool compare, boo
if (*bind != 0) { if (*bind != 0) {
/* enable opengl drawing with textures */ /* enable opengl drawing with textures */
glBindTexture(GL_TEXTURE_2D, *bind); glBindTexture(textarget, *bind);
BKE_image_release_ibuf(ima, ibuf, NULL); BKE_image_release_ibuf(ima, ibuf, NULL);
return *bind; return *bind;
} }
@ -694,10 +707,10 @@ int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, bool compare, boo
#ifdef WITH_DDS #ifdef WITH_DDS
if (ibuf->ftype == IMB_FTYPE_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 else
#endif #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 */ /* mark as non-color data texture */
if (*bind) { if (*bind) {
@ -720,9 +733,76 @@ int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, bool compare, boo
return *bind; 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 */ /* Image *ima can be NULL */
void GPU_create_gl_tex(unsigned int *bind, unsigned int *rect, float *frect, int rectw, int recth, 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; 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 /* 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 * GPUs (OpenGL version >= 2.0) since they support non-power-of-two-textures
* Then don't bother scaling for hardware that supports NPOT 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)) || if (textarget == GL_TEXTURE_2D &&
is_over_resolution_limit(rectw, recth)) (!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); rectw = smaller_power_of_2_limit(rectw);
recth = smaller_power_of_2_limit(recth); recth = smaller_power_of_2_limit(recth);
if (use_high_bit_depth) { if (use_high_bit_depth) {
ibuf = IMB_allocFromBuffer(NULL, frect, tpx, tpy); ibuf = IMB_allocFromBuffer(NULL, frect, tpx, tpy);
IMB_scaleImBuf(ibuf, rectw, recth); 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 */ /* create image */
glGenTextures(1, (GLuint *)bind); glGenTextures(1, (GLuint *)bind);
glBindTexture(GL_TEXTURE_2D, *bind); glBindTexture(textarget, *bind);
if (use_high_bit_depth) { if (textarget == GL_TEXTURE_2D) {
if (GLEW_ARB_texture_float) if (use_high_bit_depth) {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F_ARB, rectw, recth, 0, GL_RGBA, GL_FLOAT, frect); 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 else
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16, rectw, recth, 0, GL_RGBA, GL_FLOAT, frect); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, rectw, recth, 0, GL_RGBA, GL_UNSIGNED_BYTE, rect);
}
else
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 (GPU_get_mipmap() && mipmap) {
if (GTS.gpu_mipmap) { if (GTS.gpu_mipmap) {
gpu_generate_mipmap(GL_TEXTURE_2D); 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);
}
}
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 { else {
if (!ibuf) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
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];
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 { else if (textarget == GL_TEXTURE_CUBE_MAP) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 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;
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 {
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;
}
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);
gpu_del_cube_map(cube_map);
}
else {
printf("Incorrect envmap size\n");
}
} }
if (GLEW_EXT_texture_filter_anisotropic) 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) if (ibuf)
IMB_freeImBuf(ibuf); IMB_freeImBuf(ibuf);
@ -882,20 +1024,20 @@ bool GPU_upload_dxt_texture(ImBuf *ibuf)
} }
void GPU_create_gl_tex_compressed( void GPU_create_gl_tex_compressed(
unsigned int *bind, unsigned int *pix, int x, int y, int mipmap, unsigned int *bind, unsigned int *pix, int x, int y,
Image *ima, ImBuf *ibuf) int textarget, int mipmap, Image *ima, ImBuf *ibuf)
{ {
#ifndef WITH_DDS #ifndef WITH_DDS
(void)ibuf; (void)ibuf;
/* Fall back to uncompressed if DDS isn't enabled */ /* 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 #else
glGenTextures(1, (GLuint *)bind); 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); 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 #endif
} }
@ -927,7 +1069,7 @@ int GPU_set_tpage(MTexPoly *mtexpoly, int mipmap, int alphablend)
gpu_verify_alpha_blend(alphablend); gpu_verify_alpha_blend(alphablend);
gpu_verify_reflection(ima); 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.curtile = GTS.tile;
GTS.curima = GTS.ima; GTS.curima = GTS.ima;
GTS.curtilemode = GTS.tilemode; GTS.curtilemode = GTS.tilemode;
@ -969,11 +1111,18 @@ void GPU_paint_set_mipmap(bool mipmap)
if (mipmap) { if (mipmap) {
for (Image *ima = G.main->image.first; ima; ima = ima->id.next) { 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) { if (ima->tpageflag & IMA_MIPMAP_COMPLETE) {
glBindTexture(GL_TEXTURE_2D, ima->bindcode); if (ima->bindcode[TEXTARGET_TEXTURE_2D]) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gpu_get_mipmap_filter(0)); glBindTexture(GL_TEXTURE_2D, ima->bindcode[TEXTARGET_TEXTURE_2D]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1)); 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 else
GPU_free_image(ima); GPU_free_image(ima);
@ -985,10 +1134,17 @@ void GPU_paint_set_mipmap(bool mipmap)
} }
else { else {
for (Image *ima = G.main->image.first; ima; ima = ima->id.next) { for (Image *ima = G.main->image.first; ima; ima = ima->id.next) {
if (ima->bindcode) { if (BKE_image_has_bindcode(ima)) {
glBindTexture(GL_TEXTURE_2D, ima->bindcode); if (ima->bindcode[TEXTARGET_TEXTURE_2D]) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glBindTexture(GL_TEXTURE_2D, ima->bindcode[TEXTARGET_TEXTURE_2D]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1)); 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 else
ima->tpageflag &= ~IMA_MIPMAP_COMPLETE; 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) 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)) || 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 x_limit = smaller_power_of_2_limit(ibuf->x);
int y_limit = smaller_power_of_2_limit(ibuf->y); 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); ImBuf *ibuf_scale = IMB_allocFromBuffer(NULL, frect, w, h);
IMB_scaleImBuf(ibuf_scale, rectw, recth); 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, glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, rectw, recth, GL_RGBA,
GL_FLOAT, ibuf_scale->rect_float); 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); 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, glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, rectw, recth, GL_RGBA,
GL_UNSIGNED_BYTE, scalerect); 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); 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)) (w == 0) || (h == 0))
{ {
/* these cases require full reload still */ /* 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; 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); glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, GL_RGBA, GL_FLOAT, buffer);
MEM_freeN(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; 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_ROW_LENGTH, &row_length);
glGetIntegerv(GL_UNPACK_SKIP_PIXELS, &skip_pixels); glGetIntegerv(GL_UNPACK_SKIP_PIXELS, &skip_pixels);
@ -1303,16 +1459,17 @@ void GPU_free_image(Image *ima)
return; return;
} }
/* free regular image binding */ for (int i = 0; i < TEXTARGET_COUNT; i++) {
if (ima->bindcode) { /* free regular image binding */
glDeleteTextures(1, (GLuint *)&ima->bindcode); if (ima->bindcode[i]) {
ima->bindcode = 0; glDeleteTextures(1, (GLuint *)&ima->bindcode[i]);
} ima->bindcode[i] = 0;
}
/* free glsl image binding */ /* free glsl image binding */
if (ima->gputexture) { if (ima->gputexture[i]) {
GPU_texture_free(ima->gputexture); GPU_texture_free(ima->gputexture[i]);
ima->gputexture = NULL; ima->gputexture[i] = NULL;
}
} }
/* free repeated image binding */ /* 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 ((ima->flag & IMA_NOCOLLECT) == 0 && ctime - ima->lastused > U.textimeout) {
/* If it's in GL memory, deallocate and set time tag to current time /* 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. */ * 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); GPU_free_image(ima);
ima->lastused = ctime; ima->lastused = ctime;
} }

@ -73,6 +73,7 @@
static struct GPUGlobal { static struct GPUGlobal {
GLint maxtexsize; GLint maxtexsize;
GLint maxcubemapsize;
GLint maxtextures; GLint maxtextures;
bool extdisabled; bool extdisabled;
int colordepth; int colordepth;
@ -120,6 +121,11 @@ int GPU_max_color_texture_samples(void)
return GG.samples_color_texture_max; return GG.samples_color_texture_max;
} }
int GPU_max_cube_map_size(void)
{
return GG.maxcubemapsize;
}
void GPU_get_dfdy_factors(float fac[2]) void GPU_get_dfdy_factors(float fac[2])
{ {
copy_v2_v2(fac, GG.dfdyfactors); 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_IMAGE_UNITS, &GG.maxtextures);
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &GG.maxtexsize); glGetIntegerv(GL_MAX_TEXTURE_SIZE, &GG.maxtexsize);
glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, &GG.maxcubemapsize);
if (GLEW_EXT_texture_filter_anisotropic) if (GLEW_EXT_texture_filter_anisotropic)
glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &GG.max_anisotropy); glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &GG.max_anisotropy);

@ -1814,6 +1814,198 @@ GPUMaterial *GPU_material_matcap(Scene *scene, Material *ma, bool use_opensubdiv
return mat; 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) GPUMaterial *GPU_material_world(struct Scene *scene, struct World *wo)
{ {
LinkData *link; 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) if (BKE_scene_use_new_shading_nodes(scene) && wo->nodetree && wo->use_nodes)
ntreeGPUMaterialNodes(wo->nodetree, mat, NODE_NEW_SHADING); ntreeGPUMaterialNodes(wo->nodetree, mat, NODE_NEW_SHADING);
else { else {
/* old fixed function world */ GPU_material_old_world(mat, wo);
} }
if (GPU_material_do_color_management(mat)) if (GPU_material_do_color_management(mat))
@ -2424,6 +2616,7 @@ GPUShaderExport *GPU_shader_export(struct Scene *scene, struct Material *ma)
break; break;
case GPU_NONE: case GPU_NONE:
case GPU_TEXCUBE:
case GPU_FLOAT: case GPU_FLOAT:
case GPU_VEC2: case GPU_VEC2:
case GPU_VEC3: case GPU_VEC3:
@ -2459,6 +2652,7 @@ GPUShaderExport *GPU_shader_export(struct Scene *scene, struct Material *ma)
case GPU_NONE: case GPU_NONE:
case GPU_TEX2D: case GPU_TEX2D:
case GPU_TEXCUBE:
case GPU_SHADOW2D: case GPU_SHADOW2D:
case GPU_ATTRIB: case GPU_ATTRIB:
break; break;

@ -368,27 +368,33 @@ GPUTexture *GPU_texture_create_3D(int w, int h, int depth, int channels, const f
return tex; 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 */ /* 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) { if (textarget == GL_TEXTURE_2D)
ima->gputexture->bindcode = bindcode; gputt = TEXTARGET_TEXTURE_2D;
glBindTexture(GL_TEXTURE_2D, 0); else
return ima->gputexture; 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"); GPUTexture *tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture");
tex->bindcode = bindcode; tex->bindcode = bindcode;
tex->number = -1; tex->number = -1;
tex->refcount = 1; tex->refcount = 1;
tex->target = GL_TEXTURE_2D; tex->target = textarget;
tex->target_base = GL_TEXTURE_2D; tex->target_base = GL_TEXTURE_2D;
tex->fromblender = 1; tex->fromblender = 1;
ima->gputexture = tex; ima->gputexture[gputt] = tex;
if (!glIsTexture(tex->bindcode)) { if (!glIsTexture(tex->bindcode)) {
GPU_ASSERT_NO_GL_ERRORS("Blender Texture Not Loaded"); 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 { else {
GLint w, h, border; GLint w, h, border;
glBindTexture(GL_TEXTURE_2D, tex->bindcode); GLenum gettarget;
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &w);
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &h); if (textarget == GL_TEXTURE_2D)
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_BORDER, &border); 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->w = w - border;
tex->h = h - border; tex->h = h - border;
} }
glBindTexture(GL_TEXTURE_2D, 0); glBindTexture(textarget, 0);
return tex; 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 */ /* this binds a texture, so that's why we restore it to 0 */
if (bindcode == 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) { if (tex) {
tex->bindcode = bindcode; tex->bindcode = bindcode;
@ -641,6 +654,8 @@ void GPU_texture_unbind(GPUTexture *tex)
GLenum arbnumber = (GLenum)((GLuint)GL_TEXTURE0 + tex->number); GLenum arbnumber = (GLenum)((GLuint)GL_TEXTURE0 + tex->number);
if (tex->number != 0) glActiveTexture(arbnumber); if (tex->number != 0) glActiveTexture(arbnumber);
glBindTexture(tex->target, 0); glBindTexture(tex->target, 0);
glDisable(tex->target);
glBindTexture(tex->target_base, 0);
glDisable(tex->target_base); glDisable(tex->target_base);
if (tex->number != 0) glActiveTexture(GL_TEXTURE0); if (tex->number != 0) glActiveTexture(GL_TEXTURE0);

@ -1204,6 +1204,11 @@ void mtex_alpha_to_col(vec4 col, float alpha, out vec4 outcol)
outcol = vec4(col.rgb, alpha); 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) void mtex_rgbtoint(vec4 rgb, out float intensity)
{ {
intensity = dot(vec3(0.35, 0.45, 0.2), rgb.rgb); 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); 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) void mtex_image(vec3 texco, sampler2D ima, out float value, out vec4 color)
{ {
color = texture2D(ima, texco.xy); 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; 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) void shade_view(vec3 co, out vec3 view)
{ {
/* handle perspective/orthographic */ /* handle perspective/orthographic */

@ -90,13 +90,19 @@ typedef struct RenderSlot {
#define IMA_NEED_FRAME_RECALC 8 #define IMA_NEED_FRAME_RECALC 8
#define IMA_SHOW_STEREO 16 #define IMA_SHOW_STEREO 16
enum {
TEXTARGET_TEXTURE_2D = 0,
TEXTARGET_TEXTURE_CUBE_MAP = 1,
TEXTARGET_COUNT = 2
};
typedef struct Image { typedef struct Image {
ID id; ID id;
char name[1024]; /* file path, 1024 = FILE_MAX */ char name[1024]; /* file path, 1024 = FILE_MAX */
struct MovieCache *cache; /* not written in file */ 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: */ /* sources from: */
ListBase anims; ListBase anims;
@ -113,7 +119,8 @@ typedef struct Image {
short tpageflag, totbind; short tpageflag, totbind;
short xrep, yrep; short xrep, yrep;
short twsta, twend; 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 */ unsigned int *repbind; /* for repeat of parts of images */
struct PackedFile *packedfile DNA_DEPRECATED; /* deprecated */ struct PackedFile *packedfile DNA_DEPRECATED; /* deprecated */

@ -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) static int rna_Image_gl_load(Image *image, ReportList *reports, int frame, int filter, int mag)
{ {
ImBuf *ibuf; ImBuf *ibuf;
unsigned int *bind = &image->bindcode; unsigned int *bind = &image->bindcode[TEXTARGET_TEXTURE_2D];
int error = GL_NO_ERROR; int error = GL_NO_ERROR;
ImageUser iuser = {NULL}; ImageUser iuser = {NULL};
void *lock; 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; 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); (filter != GL_NEAREST && filter != GL_LINEAR), false, image);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (GLint)filter); 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) { if (error) {
glDeleteTextures(1, (GLuint *)bind); glDeleteTextures(1, (GLuint *)bind);
image->bindcode = 0; image->bindcode[TEXTARGET_TEXTURE_2D] = 0;
} }
BKE_image_release_ibuf(image, ibuf, NULL); 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) 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; int error = GL_NO_ERROR;
BKE_image_tag_time(image); BKE_image_tag_time(image);

@ -128,6 +128,7 @@ static PyObject *PyInit_gpu(void)
/* GPU_DYNAMIC_GROUP_WORLD */ /* GPU_DYNAMIC_GROUP_WORLD */
PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_HORIZON_COLOR); 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_AMBIENT_COLOR);
PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_ZENITH_COLOR);
/* GPU_DYNAMIC_GROUP_MAT */ /* GPU_DYNAMIC_GROUP_MAT */
PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_MAT_DIFFRGB); PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_MAT_DIFFRGB);
PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_MAT_REF); PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_MAT_REF);

@ -138,7 +138,7 @@ bool BL_Texture::InitFromImage(int unit, Image *img, bool mipmap)
mipmap = mipmap && GPU_get_mipmap(); mipmap = mipmap && GPU_get_mipmap();
mTexture = img->bindcode; mTexture = img->bindcode[TEXTARGET_TEXTURE_2D];
mType = GL_TEXTURE_2D; mType = GL_TEXTURE_2D;
mUnit = unit; mUnit = unit;

@ -299,7 +299,7 @@ PyObject *Texture_close(Texture * self)
self->m_matTexture->swapTexture(self->m_orgTex); self->m_matTexture->swapTexture(self->m_orgTex);
else 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); BKE_image_release_ibuf(self->m_imgTexture, self->m_imgBuf, NULL);
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 // WARNING: GPU has a ImageUser to pass, we don't. Using NULL
// works on image file, not necessarily on other type of image. // 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_imgBuf = BKE_image_acquire_ibuf(self->m_imgTexture, NULL, NULL);
self->m_orgTex = self->m_imgTexture->bindcode; self->m_orgTex = self->m_imgTexture->bindcode[TEXTARGET_TEXTURE_2D];
self->m_imgTexture->bindcode = self->m_actTex; self->m_imgTexture->bindcode[TEXTARGET_TEXTURE_2D] = self->m_actTex;
} }
} }