diff options
Diffstat (limited to 'source/blender')
-rw-r--r-- | source/blender/gpu/shaders/gpu_shader_material.glsl | 116 | ||||
-rw-r--r-- | source/blender/nodes/shader/nodes/node_shader_tex_image.c | 31 |
2 files changed, 78 insertions, 69 deletions
diff --git a/source/blender/gpu/shaders/gpu_shader_material.glsl b/source/blender/gpu/shaders/gpu_shader_material.glsl index d1183c792f5..4b376160105 100644 --- a/source/blender/gpu/shaders/gpu_shader_material.glsl +++ b/source/blender/gpu/shaders/gpu_shader_material.glsl @@ -1804,18 +1804,46 @@ void node_tex_image(vec3 co, sampler2D ima, out vec4 color, out float alpha) alpha = color.a; } +void tex_box_sample(vec3 texco, + vec3 N, + sampler2D ima, + out vec4 color1, + out vec4 color2, + out vec4 color3) +{ + /* X projection */ + vec2 uv = texco.yz; + if (N.x < 0.0) { + uv.x = 1.0 - uv.x; + } + color1 = texture(ima, uv); + /* Y projection */ + uv = texco.xz; + if (N.y > 0.0) { + uv.x = 1.0 - uv.x; + } + color2 = texture(ima, uv); + /* Z projection */ + uv = texco.yx; + if (N.z > 0.0) { + uv.x = 1.0 - uv.x; + } + color3 = texture(ima, uv); +} + void node_tex_image_box(vec3 texco, vec3 N, + vec4 color1, + vec4 color2, + vec4 color3, sampler2D ima, float blend, out vec4 color, out float alpha) { - vec3 signed_N = N; - /* project from direction vector to barycentric coordinates in triangles */ - N = vec3(abs(N.x), abs(N.y), abs(N.z)); - N /= (N.x + N.y + N.z); + N = abs(N); + N /= dot(N, vec3(1.0)); /* basic idea is to think of this as a triangle, each corner representing * one of the 3 faces of the cube. in the corners we have single textures, @@ -1825,72 +1853,36 @@ void node_tex_image_box(vec3 texco, * the Nxyz values are the barycentric coordinates in an equilateral * triangle, which in case of blending, in the middle has a smaller * equilateral triangle where 3 textures blend. this divides things into - * 7 zones, with an if () test for each zone */ + * 7 zones, with an if () test for each zone + * EDIT: Now there is only 4 if's. */ - vec3 weight = vec3(0.0, 0.0, 0.0); - float limit = 0.5 * (1.0 + blend); + float limit = 0.5 + 0.5 * blend; - /* first test for corners with single texture */ - if (N.x > limit * (N.x + N.y) && N.x > limit * (N.x + N.z)) { - weight.x = 1.0; - } - else if (N.y > limit * (N.x + N.y) && N.y > limit * (N.y + N.z)) { - weight.y = 1.0; + vec3 weight; + weight.x = N.x / (N.x + N.y); + weight.y = N.y / (N.y + N.z); + weight.z = N.z / (N.x + N.z); + weight = clamp((weight - 0.5 * (1.0 - blend)) / max(1e-8, blend), 0.0, 1.0); + + /* test for mixes between two textures */ + if (N.z < (1.0 - limit) * (N.y + N.x)) { + weight.z = 0.0; + weight.y = 1.0 - weight.x; } - else if (N.z > limit * (N.x + N.z) && N.z > limit * (N.y + N.z)) { - weight.z = 1.0; + else if (N.x < (1.0 - limit) * (N.y + N.z)) { + weight.x = 0.0; + weight.z = 1.0 - weight.y; } - else if (blend > 0.0) { - /* in case of blending, test for mixes between two textures */ - if (N.z < (1.0 - limit) * (N.y + N.x)) { - weight.x = N.x / (N.x + N.y); - weight.x = clamp((weight.x - 0.5 * (1.0 - blend)) / blend, 0.0, 1.0); - weight.y = 1.0 - weight.x; - } - else if (N.x < (1.0 - limit) * (N.y + N.z)) { - weight.y = N.y / (N.y + N.z); - weight.y = clamp((weight.y - 0.5 * (1.0 - blend)) / blend, 0.0, 1.0); - weight.z = 1.0 - weight.y; - } - else if (N.y < (1.0 - limit) * (N.x + N.z)) { - weight.x = N.x / (N.x + N.z); - weight.x = clamp((weight.x - 0.5 * (1.0 - blend)) / blend, 0.0, 1.0); - weight.z = 1.0 - weight.x; - } - else { - /* last case, we have a mix between three */ - weight.x = ((2.0 - limit) * N.x + (limit - 1.0)) / (2.0 * limit - 1.0); - weight.y = ((2.0 - limit) * N.y + (limit - 1.0)) / (2.0 * limit - 1.0); - weight.z = ((2.0 - limit) * N.z + (limit - 1.0)) / (2.0 * limit - 1.0); - } + else if (N.y < (1.0 - limit) * (N.x + N.z)) { + weight.y = 0.0; + weight.x = 1.0 - weight.z; } else { - /* Desperate mode, no valid choice anyway, fallback to one side.*/ - weight.x = 1.0; - } - color = vec4(0); - if (weight.x > 0.0) { - vec2 uv = texco.yz; - if(signed_N.x < 0.0) { - uv.x = 1.0 - uv.x; - } - color += weight.x * texture(ima, uv); - } - if (weight.y > 0.0) { - vec2 uv = texco.xz; - if(signed_N.y > 0.0) { - uv.x = 1.0 - uv.x; - } - color += weight.y * texture(ima, uv); - } - if (weight.z > 0.0) { - vec2 uv = texco.yx; - if(signed_N.z > 0.0) { - uv.x = 1.0 - uv.x; - } - color += weight.z * texture(ima, uv); + /* last case, we have a mix between three */ + weight = ((2.0 - limit) * N + (limit - 1.0)) / max(1e-8, 2.0 * limit - 1.0); } + color = weight.x * color1 + weight.y * color2 + weight.z * color3; alpha = color.a; } diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_image.c b/source/blender/nodes/shader/nodes/node_shader_tex_image.c index 2bbe3617bee..20753445aa6 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_image.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_image.c @@ -58,8 +58,9 @@ static int node_shader_gpu_tex_image(GPUMaterial *mat, bNode *node, bNodeExecDat Image *ima = (Image *)node->id; ImageUser *iuser = NULL; NodeTexImage *tex = node->storage; + bool do_color_correction = false; - GPUNodeLink *norm; + GPUNodeLink *norm, *col1, *col2, *col3; int isdata = tex->color_space == SHD_COLORSPACE_NONE; float blend = tex->projection_blend; @@ -67,6 +68,15 @@ static int node_shader_gpu_tex_image(GPUMaterial *mat, bNode *node, bNodeExecDat if (!ima) return GPU_stack_link(mat, node, "node_tex_image_empty", in, out); + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL); + if ((tex->color_space == SHD_COLORSPACE_COLOR) && + ibuf && (ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA) == 0 && + GPU_material_do_color_management(mat)) + { + do_color_correction = true; + } + BKE_image_release_ibuf(ima, ibuf, NULL); + if (!in[0].link) in[0].link = GPU_attribute(CD_MTFACE, ""); @@ -83,8 +93,20 @@ static int node_shader_gpu_tex_image(GPUMaterial *mat, bNode *node, bNodeExecDat GPU_link(mat, "direction_transform_m4v3", norm, GPU_builtin(GPU_INVERSE_OBJECT_MATRIX), &norm); + GPU_link(mat, "tex_box_sample", in[0].link, + norm, + GPU_image(ima, iuser, isdata), + &col1, + &col2, + &col3); + if (do_color_correction) { + GPU_link(mat, "srgb_to_linearrgb", col1, &col1); + GPU_link(mat, "srgb_to_linearrgb", col2, &col2); + GPU_link(mat, "srgb_to_linearrgb", col3, &col3); + } GPU_link(mat, "node_tex_image_box", in[0].link, norm, + col1, col2, col3, GPU_image(ima, iuser, isdata), GPU_uniform(&blend), &out[0].link, @@ -102,14 +124,9 @@ static int node_shader_gpu_tex_image(GPUMaterial *mat, bNode *node, bNodeExecDat break; } - ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL); - if ((tex->color_space == SHD_COLORSPACE_COLOR) && - ibuf && (ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA) == 0 && - GPU_material_do_color_management(mat)) - { + if (do_color_correction && (tex->projection != SHD_PROJ_BOX)) { GPU_link(mat, "srgb_to_linearrgb", out[0].link, &out[0].link); } - BKE_image_release_ibuf(ima, ibuf, NULL); return true; } |