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:
authorRalf Hölzemer <r.hoelzemer@googlemail.com>2016-05-30 11:23:43 +0300
committerSergey Sharybin <sergey.vfx@gmail.com>2016-05-30 11:29:46 +0300
commit4aaf7b0c7a65473b4d1356fb36ba24eb2df4be49 (patch)
treed14cc57024ddd21c4d5a17e85eac7c3d6b73402c
parent0f86a545e7bcee0e52e7dd6dc28bba40308598b1 (diff)
Support all Cycles image texture projections in the GLSL viewport
This patch enables Tube, Sphere and Box projections in GLSL for the image texture node. Reviewers: sergey Projects: #nodes, #opengl_gfx Differential Revision: https://developer.blender.org/D2036
-rw-r--r--source/blender/gpu/shaders/gpu_shader_material.glsl112
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_image.c36
2 files changed, 146 insertions, 2 deletions
diff --git a/source/blender/gpu/shaders/gpu_shader_material.glsl b/source/blender/gpu/shaders/gpu_shader_material.glsl
index 84806e9f096..a3b05803063 100644
--- a/source/blender/gpu/shaders/gpu_shader_material.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_material.glsl
@@ -218,6 +218,42 @@ void point_transform_m4v3(vec3 vin, mat4 mat, out vec3 vout)
vout = (mat * vec4(vin, 1.0)).xyz;
}
+void point_texco_remap_square(vec3 vin, out vec3 vout)
+{
+ vout = vec3(vin - vec3(0.5, 0.5, 0.5)) * 2.0;
+}
+
+void point_map_to_sphere(vec3 vin, out vec3 vout)
+{
+ float len = length(vin);
+ float v, u;
+ if (len > 0.0) {
+ if (vin.x == 0.0 && vin.y == 0.0)
+ u = 0.0;
+ else
+ u = (1.0 - atan(vin.x, vin.y) / M_PI) / 2.0;
+
+ v = 1.0 - acos(vin.z / len) / M_PI;
+ }
+ else
+ v = u = 0.0;
+
+ vout = vec3(u, v, 0.0);
+}
+
+void point_map_to_tube(vec3 vin, out vec3 vout)
+{
+ float u, v;
+ v = (vin.z + 1.0) * 0.5;
+ float len = sqrt(vin.x * vin.x + vin.y * vin[1]);
+ if (len > 0.0)
+ u = (1.0 - (atan(vin.x / len, vin.y / len) / M_PI)) * 0.5;
+ else
+ v = u = 0.0;
+
+ vout = vec3(u, v, 0.0);
+}
+
void mapping(vec3 vec, mat4 mat, vec3 minvec, vec3 maxvec, float domin, float domax, out vec3 outvec)
{
outvec = (mat * vec4(vec, 1.0)).xyz;
@@ -2872,6 +2908,82 @@ void node_tex_image(vec3 co, sampler2D ima, out vec4 color, out float alpha)
alpha = color.a;
}
+void node_tex_image_box(vec3 texco,
+ vec3 nob,
+ sampler2D ima,
+ float blend,
+ out vec4 color,
+ out float alpha)
+{
+ /* project from direction vector to barycentric coordinates in triangles */
+ nob = vec3(abs(nob.x), abs(nob.y), abs(nob.z));
+ nob /= (nob.x + nob.y + nob.z);
+
+ /* 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,
+ * in between we blend between two textures, and in the middle we a blend
+ * between three textures.
+ *
+ * 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 */
+
+ vec3 weight = vec3(0.0, 0.0, 0.0);
+ float limit = 0.5 * (1.0 + blend);
+
+ /* first test for corners with single texture */
+ if (nob.x > limit * (nob.x + nob.y) && nob.x > limit * (nob.x + nob.z)) {
+ weight.x = 1.0;
+ }
+ else if (nob.y > limit * (nob.x + nob.y) && nob.y > limit * (nob.y + nob.z)) {
+ weight.y = 1.0;
+ }
+ else if (nob.z > limit * (nob.x + nob.z) && nob.z > limit * (nob.y + nob.z)) {
+ weight.z = 1.0;
+ }
+ else if (blend > 0.0) {
+ /* in case of blending, test for mixes between two textures */
+ if (nob.z < (1.0 - limit) * (nob.y + nob.x)) {
+ weight.x = nob.x / (nob.x + nob.y);
+ weight.x = clamp((weight.x - 0.5 * (1.0 - blend)) / blend, 0.0, 1.0);
+ weight.y = 1.0 - weight.x;
+ }
+ else if (nob.x < (1.0 - limit) * (nob.y + nob.z)) {
+ weight.y = nob.y / (nob.y + nob.z);
+ weight.y = clamp((weight.y - 0.5 * (1.0 - blend)) / blend, 0.0, 1.0);
+ weight.z = 1.0 - weight.y;
+ }
+ else if (nob.y < (1.0 - limit) * (nob.x + nob.z)) {
+ weight.x = nob.x / (nob.x + nob.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) * nob.x + (limit - 1.0)) / (2.0 * limit - 1.0);
+ weight.y = ((2.0 - limit) * nob.y + (limit - 1.0)) / (2.0 * limit - 1.0);
+ weight.z = ((2.0 - limit) * nob.z + (limit - 1.0)) / (2.0 * limit - 1.0);
+ }
+ }
+ else {
+ /* Desperate mode, no valid choice anyway, fallback to one side.*/
+ weight.x = 1.0;
+ }
+
+ if (weight.x > 0.0) {
+ color += weight.x * texture2D(ima, texco.yz);
+ }
+ if (weight.y > 0.0) {
+ color += weight.y * texture2D(ima, texco.xz);
+ }
+ if (weight.z > 0.0) {
+ color += weight.z * texture2D(ima, texco.yx);
+ }
+
+ alpha = color.a;
+}
+
void node_tex_image_empty(vec3 co, out vec4 color, out float alpha)
{
color = vec4(0.0);
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 f0a8cda045e..71200dfe9d3 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_image.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_image.c
@@ -59,17 +59,49 @@ static int node_shader_gpu_tex_image(GPUMaterial *mat, bNode *node, bNodeExecDat
Image *ima = (Image *)node->id;
ImageUser *iuser = NULL;
NodeTexImage *tex = node->storage;
+
+ GPUNodeLink *norm;
+
int isdata = tex->color_space == SHD_COLORSPACE_NONE;
+ float blend = tex->projection_blend;
if (!ima)
return GPU_stack_link(mat, "node_tex_image_empty", in, out);
-
+
if (!in[0].link)
in[0].link = GPU_attribute(CD_MTFACE, "");
node_shader_gpu_tex_mapping(mat, node, in, out);
- GPU_stack_link(mat, "node_tex_image", in, out, GPU_image(ima, iuser, isdata));
+ switch (tex->projection) {
+ case SHD_PROJ_FLAT:
+ GPU_stack_link(mat, "node_tex_image", in, out, GPU_image(ima, iuser, isdata));
+ break;
+ case SHD_PROJ_BOX:
+ GPU_link(mat, "direction_transform_m4v3", GPU_builtin(GPU_VIEW_NORMAL),
+ GPU_builtin(GPU_INVERSE_VIEW_MATRIX),
+ &norm);
+ GPU_link(mat, "direction_transform_m4v3", norm,
+ GPU_builtin(GPU_INVERSE_OBJECT_MATRIX),
+ &norm);
+ GPU_link(mat, "node_tex_image_box", in[0].link,
+ norm,
+ GPU_image(ima, iuser, isdata),
+ GPU_uniform(&blend),
+ &out[0].link,
+ &out[1].link);
+ break;
+ case SHD_PROJ_SPHERE:
+ GPU_link(mat, "point_texco_remap_square", in[0].link, &in[0].link);
+ GPU_link(mat, "point_map_to_sphere", in[0].link, &in[0].link);
+ GPU_stack_link(mat, "node_tex_image", in, out, GPU_image(ima, iuser, isdata));
+ break;
+ case SHD_PROJ_TUBE:
+ GPU_link(mat, "point_texco_remap_square", in[0].link, &in[0].link);
+ GPU_link(mat, "point_map_to_tube", in[0].link, &in[0].link);
+ GPU_stack_link(mat, "node_tex_image", in, out, GPU_image(ima, iuser, isdata));
+ break;
+ }
ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL);
if ((tex->color_space == SHD_COLORSPACE_COLOR) &&