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
Notes: blender-bot 2023-02-14 08:09:00 +01:00
Referenced by commit 431a5b623e, Fix T47688: Regression in gl_load
Referenced by issue #47688, glBindTexture is not working in 2.77RC1 as expected
Referenced by issue #47635, Slowdown of texture painting
21 changed files with 624 additions and 146 deletions

View File

@ -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);

View File

@ -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;

View File

@ -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;
}

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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]);

View File

@ -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);

View File

@ -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);

View File

@ -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();

View File

@ -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 {

View File

@ -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);
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);
}
}
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 {
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];
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, GL_LINEAR);
}
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;
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)
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;
}

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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 */

View File

@ -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 */

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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;
}
}