Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/gpu')
-rw-r--r--source/blender/gpu/GPU_material.h2
-rw-r--r--source/blender/gpu/intern/gpu_codegen.c20
-rw-r--r--source/blender/gpu/intern/gpu_codegen.h2
-rw-r--r--source/blender/gpu/intern/gpu_draw.c67
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_tex_image.glsl65
5 files changed, 124 insertions, 32 deletions
diff --git a/source/blender/gpu/GPU_material.h b/source/blender/gpu/GPU_material.h
index 4dc0019978a..a5363c7a42c 100644
--- a/source/blender/gpu/GPU_material.h
+++ b/source/blender/gpu/GPU_material.h
@@ -142,7 +142,7 @@ typedef enum eGPUMaterialStatus {
GPUNodeLink *GPU_attribute(CustomDataType type, const char *name);
GPUNodeLink *GPU_constant(float *num);
GPUNodeLink *GPU_uniform(float *num);
-GPUNodeLink *GPU_image(struct Image *ima, struct ImageUser *iuser);
+GPUNodeLink *GPU_image(struct Image *ima, struct ImageUser *iuser, int tile);
GPUNodeLink *GPU_color_band(GPUMaterial *mat, int size, float *pixels, float *layer);
GPUNodeLink *GPU_builtin(eGPUBuiltin builtin);
diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c
index 410e23c9576..23ea9a62ef8 100644
--- a/source/blender/gpu/intern/gpu_codegen.c
+++ b/source/blender/gpu/intern/gpu_codegen.c
@@ -581,17 +581,19 @@ const char *GPU_builtin_name(eGPUBuiltin builtin)
}
/* assign only one texid per buffer to avoid sampling the same texture twice */
-static void codegen_set_texid(GHash *bindhash, GPUInput *input, int *texid, void *key)
+static void codegen_set_texid(GHash *bindhash, GPUInput *input, int *texid, void *key1, int key2)
{
- if (BLI_ghash_haskey(bindhash, key)) {
+ GHashPair pair = {key1, POINTER_FROM_INT(key2)};
+ if (BLI_ghash_haskey(bindhash, &pair)) {
/* Reuse existing texid */
- input->texid = POINTER_AS_INT(BLI_ghash_lookup(bindhash, key));
+ input->texid = POINTER_AS_INT(BLI_ghash_lookup(bindhash, &pair));
}
else {
/* Allocate new texid */
input->texid = *texid;
(*texid)++;
input->bindtex = true;
+ void *key = BLI_ghashutil_pairalloc(key1, POINTER_FROM_INT(key2));
BLI_ghash_insert(bindhash, key, POINTER_FROM_INT(input->texid));
}
}
@@ -604,7 +606,7 @@ static void codegen_set_unique_ids(ListBase *nodes)
GPUOutput *output;
int id = 1, texid = 0;
- bindhash = BLI_ghash_ptr_new("codegen_set_unique_ids1 gh");
+ bindhash = BLI_ghash_pair_new("codegen_set_unique_ids1 gh");
for (node = nodes->first; node; node = node->next) {
for (input = node->inputs.first; input; input = input->next) {
@@ -616,11 +618,11 @@ static void codegen_set_unique_ids(ListBase *nodes)
input->bindtex = false;
if (input->ima) {
/* input is texture from image */
- codegen_set_texid(bindhash, input, &texid, input->ima);
+ codegen_set_texid(bindhash, input, &texid, input->ima, input->image_tile);
}
else if (input->coba) {
/* input is color band texture, check coba pointer */
- codegen_set_texid(bindhash, input, &texid, input->coba);
+ codegen_set_texid(bindhash, input, &texid, input->coba, 0);
}
else {
/* Either input->ima or input->coba should be non-NULL. */
@@ -635,7 +637,7 @@ static void codegen_set_unique_ids(ListBase *nodes)
}
}
- BLI_ghash_free(bindhash, NULL, NULL);
+ BLI_ghash_free(bindhash, BLI_ghashutil_pairfree, NULL);
}
/**
@@ -1545,6 +1547,7 @@ static void gpu_node_input_link(GPUNode *node, GPUNodeLink *link, const eGPUType
input->source = GPU_SOURCE_TEX;
input->ima = link->ima;
input->iuser = link->iuser;
+ input->image_tile = link->image_tile;
break;
case GPU_NODE_LINK_ATTR:
input->source = GPU_SOURCE_ATTR;
@@ -1789,12 +1792,13 @@ GPUNodeLink *GPU_uniform(float *num)
return link;
}
-GPUNodeLink *GPU_image(Image *ima, ImageUser *iuser)
+GPUNodeLink *GPU_image(Image *ima, ImageUser *iuser, int tile)
{
GPUNodeLink *link = GPU_node_link_create();
link->link_type = GPU_NODE_LINK_IMAGE_BLENDER;
link->ima = ima;
link->iuser = iuser;
+ link->image_tile = tile;
return link;
}
diff --git a/source/blender/gpu/intern/gpu_codegen.h b/source/blender/gpu/intern/gpu_codegen.h
index 4e09f16ebf8..0e6982c603e 100644
--- a/source/blender/gpu/intern/gpu_codegen.h
+++ b/source/blender/gpu/intern/gpu_codegen.h
@@ -99,6 +99,7 @@ struct GPUNodeLink {
struct {
struct Image *ima;
struct ImageUser *iuser;
+ int image_tile;
};
};
};
@@ -138,6 +139,7 @@ typedef struct GPUInput {
struct ImageUser *iuser; /* image user */
bool bindtex; /* input is responsible for binding the texture? */
int texid; /* number for multitexture, starting from zero */
+ int image_tile; /* image tile */
eGPUType textype; /* texture type (2D, 1D Array ...) */
};
/* GPU_SOURCE_ATTR */
diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c
index 7fa2eb6424c..2d70ce009e2 100644
--- a/source/blender/gpu/intern/gpu_draw.c
+++ b/source/blender/gpu/intern/gpu_draw.c
@@ -195,13 +195,13 @@ float GPU_get_anisotropic(void)
/* Set OpenGL state for an MTFace */
-static GPUTexture **gpu_get_image_gputexture(Image *ima, GLenum textarget)
+static GPUTexture **gpu_get_tile_gputexture(ImageTile *tile, GLenum textarget)
{
if (textarget == GL_TEXTURE_2D) {
- return &ima->gputexture[TEXTARGET_TEXTURE_2D];
+ return &tile->gputexture[TEXTARGET_TEXTURE_2D];
}
else if (textarget == GL_TEXTURE_CUBE_MAP) {
- return &ima->gputexture[TEXTARGET_TEXTURE_CUBE_MAP];
+ return &tile->gputexture[TEXTARGET_TEXTURE_CUBE_MAP];
}
return NULL;
@@ -476,8 +476,19 @@ GPUTexture *GPU_texture_from_blender(Image *ima, ImageUser *iuser, int textarget
/* Tag as in active use for garbage collector. */
BKE_image_tag_time(ima);
+ ImageTile *tile = BKE_image_get_tile_from_iuser(ima, iuser);
+
+ if (tile == NULL) {
+ /* TODO(lukas): When a tile gets deleted, the materials using the image
+ * aren't rebuilt and therefore continue to use it.
+ * This workaround isn't ideal, the result should be a pink color
+ * (for a missing tile). With the current behaviour, new tiles also won't
+ * be detected. */
+ tile = BKE_image_get_tile(ima, 0);
+ }
+
/* Test if we already have a texture. */
- GPUTexture **tex = gpu_get_image_gputexture(ima, textarget);
+ GPUTexture **tex = gpu_get_tile_gputexture(tile, textarget);
if (*tex) {
return *tex;
}
@@ -485,7 +496,7 @@ GPUTexture *GPU_texture_from_blender(Image *ima, ImageUser *iuser, int textarget
/* Check if we have a valid image. If not, we return a dummy
* texture with zero bindcode so we don't keep trying. */
uint bindcode = 0;
- if (ima->ok == 0) {
+ if (tile->ok == 0) {
*tex = GPU_texture_from_bindcode(textarget, bindcode);
return *tex;
}
@@ -861,11 +872,14 @@ void GPU_paint_set_mipmap(Main *bmain, bool mipmap)
for (Image *ima = bmain->images.first; ima; ima = ima->id.next) {
if (BKE_image_has_opengl_texture(ima)) {
if (ima->gpuflag & IMA_GPU_MIPMAP_COMPLETE) {
- if (ima->gputexture[TEXTARGET_TEXTURE_2D]) {
- GPU_texture_bind(ima->gputexture[TEXTARGET_TEXTURE_2D], 0);
- 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));
- GPU_texture_unbind(ima->gputexture[TEXTARGET_TEXTURE_2D]);
+ LISTBASE_FOREACH (ImageTile *, tile, &ima->tiles) {
+ GPUTexture *tex = tile->gputexture[TEXTARGET_TEXTURE_2D];
+ if (tex != NULL) {
+ GPU_texture_bind(tex, 0);
+ 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));
+ GPU_texture_unbind(tex);
+ }
}
}
else {
@@ -880,11 +894,14 @@ void GPU_paint_set_mipmap(Main *bmain, bool mipmap)
else {
for (Image *ima = bmain->images.first; ima; ima = ima->id.next) {
if (BKE_image_has_opengl_texture(ima)) {
- if (ima->gputexture[TEXTARGET_TEXTURE_2D]) {
- GPU_texture_bind(ima->gputexture[TEXTARGET_TEXTURE_2D], 0);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1));
- GPU_texture_unbind(ima->gputexture[TEXTARGET_TEXTURE_2D]);
+ LISTBASE_FOREACH (ImageTile *, tile, &ima->tiles) {
+ GPUTexture *tex = tile->gputexture[TEXTARGET_TEXTURE_2D];
+ if (tex != NULL) {
+ GPU_texture_bind(tex, 0);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1));
+ GPU_texture_unbind(tex);
+ }
}
}
else {
@@ -897,14 +914,16 @@ void GPU_paint_set_mipmap(Main *bmain, bool mipmap)
void GPU_paint_update_image(Image *ima, ImageUser *iuser, int x, int y, int w, int h)
{
ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL);
+ ImageTile *tile = BKE_image_get_tile_from_iuser(ima, iuser);
+ GPUTexture *tex = tile->gputexture[TEXTARGET_TEXTURE_2D];
- if ((ima->gputexture[TEXTARGET_TEXTURE_2D] == NULL) || (ibuf == NULL) || (w == 0) || (h == 0)) {
+ if ((tex == NULL) || (ibuf == NULL) || (w == 0) || (h == 0)) {
/* Full reload of texture. */
GPU_free_image(ima);
}
else {
/* Partial update of texture. */
- GPU_texture_bind(ima->gputexture[TEXTARGET_TEXTURE_2D], 0);
+ GPU_texture_bind(tex, 0);
gpu_texture_update_from_ibuf(ima, ibuf, x, y, w, h);
@@ -915,7 +934,7 @@ void GPU_paint_update_image(Image *ima, ImageUser *iuser, int x, int y, int w, i
ima->gpuflag &= ~IMA_GPU_MIPMAP_COMPLETE;
}
- GPU_texture_unbind(ima->gputexture[TEXTARGET_TEXTURE_2D]);
+ GPU_texture_unbind(tex);
}
BKE_image_release_ibuf(ima, ibuf, NULL);
@@ -1323,11 +1342,13 @@ void GPU_free_unused_buffers(Main *bmain)
static void gpu_free_image_immediate(Image *ima)
{
- for (int i = 0; i < TEXTARGET_COUNT; i++) {
- /* free glsl image binding */
- if (ima->gputexture[i]) {
- GPU_texture_free(ima->gputexture[i]);
- ima->gputexture[i] = NULL;
+ LISTBASE_FOREACH (ImageTile *, tile, &ima->tiles) {
+ for (int i = 0; i < TEXTARGET_COUNT; i++) {
+ /* free glsl image binding */
+ if (tile->gputexture[i] != NULL) {
+ GPU_texture_free(tile->gputexture[i]);
+ tile->gputexture[i] = NULL;
+ }
}
}
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_tex_image.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_tex_image.glsl
index bc2bf998145..fadb3b92df4 100644
--- a/source/blender/gpu/shaders/material/gpu_shader_material_tex_image.glsl
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_tex_image.glsl
@@ -353,3 +353,68 @@ void node_tex_image_empty(vec3 co, out vec4 color, out float alpha)
color = vec4(0.0);
alpha = 0.0;
}
+
+void node_tex_tile_map(vec3 co, out vec4 color, out vec3 map)
+{
+ float tx = floor(co.x);
+ float ty = floor(co.y);
+
+ if (tx < 0 || ty < 0 || tx >= 10)
+ map = vec3(0, 0, -1);
+ else
+ map = vec3(co.x - tx, co.y - ty, 1001 + 10 * ty + tx);
+
+ color = vec4(1.0, 0.0, 1.0, 1.0);
+}
+
+void node_tex_tile_linear(
+ vec3 map, float tile_id, sampler2D ima, vec4 in_color, out vec4 color, out float alpha)
+{
+ if (map.z == tile_id) {
+ vec3 co = map.xyy;
+ node_tex_image_linear(co, ima, color, alpha);
+ }
+ else {
+ color = in_color;
+ alpha = color.a;
+ }
+}
+
+void node_tex_tile_nearest(
+ vec3 map, float tile_id, sampler2D ima, vec4 in_color, out vec4 color, out float alpha)
+{
+ if (map.z == tile_id) {
+ vec3 co = map.xyy;
+ node_tex_image_nearest(co, ima, color, alpha);
+ }
+ else {
+ color = in_color;
+ alpha = color.a;
+ }
+}
+
+void node_tex_tile_cubic(
+ vec3 map, float tile_id, sampler2D ima, vec4 in_color, out vec4 color, out float alpha)
+{
+ if (map.z == tile_id) {
+ vec3 co = map.xyy;
+ node_tex_image_cubic(co, ima, color, alpha);
+ }
+ else {
+ color = in_color;
+ alpha = color.a;
+ }
+}
+
+void node_tex_tile_smart(
+ vec3 map, float tile_id, sampler2D ima, vec4 in_color, out vec4 color, out float alpha)
+{
+ if (map.z == tile_id) {
+ vec3 co = map.xyy;
+ node_tex_image_smart(co, ima, color, alpha);
+ }
+ else {
+ color = in_color;
+ alpha = color.a;
+ }
+}