diff options
author | Ralf Hölzemer <r.hoelzemer@googlemail.com> | 2016-05-30 11:23:43 +0300 |
---|---|---|
committer | Sergey Sharybin <sergey.vfx@gmail.com> | 2016-05-30 11:29:46 +0300 |
commit | 4aaf7b0c7a65473b4d1356fb36ba24eb2df4be49 (patch) | |
tree | d14cc57024ddd21c4d5a17e85eac7c3d6b73402c /source/blender/gpu/shaders | |
parent | 0f86a545e7bcee0e52e7dd6dc28bba40308598b1 (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
Diffstat (limited to 'source/blender/gpu/shaders')
-rw-r--r-- | source/blender/gpu/shaders/gpu_shader_material.glsl | 112 |
1 files changed, 112 insertions, 0 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); |