Cycles: Support sphere mapping for the image texture

This commit is contained in:
Sergey Sharybin 2015-01-21 22:44:30 +05:00
parent cd72396797
commit 12ccac657f
6 changed files with 49 additions and 11 deletions

@ -17,6 +17,25 @@
#include "stdosl.h" #include "stdosl.h"
#include "node_color.h" #include "node_color.h"
point map_to_sphere(vector dir)
{
float len = length(dir);
float v, u;
if(len > 0.0) {
if(dir[0] == 0.0 && dir[1] == 0.0) {
u = 0.0; /* othwise domain error */
}
else {
u = (1.0 - atan2(dir[0], dir[1]) / M_PI) / 2.0;
}
v = 1.0 - acos(dir[2] / len) / M_PI;
}
else {
v = u = 0.0; /* to avoid un-initialized variables */
}
return point(u, v, 0.0);
}
color image_texture_lookup(string filename, string color_space, float u, float v, output float Alpha, int use_alpha, int is_float, string interpolation) color image_texture_lookup(string filename, string color_space, float u, float v, output float Alpha, int use_alpha, int is_float, string interpolation)
{ {
color rgb = (color)texture(filename, u, 1.0 - v, "wrap", "periodic", "interp", interpolation, "alpha", Alpha); color rgb = (color)texture(filename, u, 1.0 - v, "wrap", "periodic", "interp", interpolation, "alpha", Alpha);
@ -136,5 +155,10 @@ shader node_image_texture(
Alpha += weight[2] * tmp_alpha; Alpha += weight[2] * tmp_alpha;
} }
} }
else if (projection == "Sphere") {
point projected = map_to_sphere((p - vector(0.5, 0.5, 0.5)) * 2.0);
Color = image_texture_lookup(filename, color_space,
projected[0], projected[1],
Alpha, use_alpha, is_float, interpolation);
}
} }

@ -363,6 +363,10 @@ ccl_device void svm_node_tex_image(KernelGlobals *kg, ShaderData *sd, float *sta
float3 co = stack_load_float3(stack, co_offset); float3 co = stack_load_float3(stack, co_offset);
uint use_alpha = stack_valid(alpha_offset); uint use_alpha = stack_valid(alpha_offset);
if(node.w == NODE_IMAGE_PROJ_SPHERE) {
co = (co - make_float3(0.5f, 0.5f, 0.5f)) * 2.0f;
map_to_sphere(&co.x, &co.y, co.x, co.y, co.z);
}
float4 f = svm_image_texture(kg, id, co.x, co.y, srgb, use_alpha); float4 f = svm_image_texture(kg, id, co.x, co.y, srgb, use_alpha);
if(stack_valid(out_offset)) if(stack_valid(out_offset))
@ -463,7 +467,6 @@ ccl_device void svm_node_tex_image_box(KernelGlobals *kg, ShaderData *sd, float
stack_store_float(stack, alpha_offset, f.w); stack_store_float(stack, alpha_offset, f.w);
} }
ccl_device void svm_node_tex_environment(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node) ccl_device void svm_node_tex_environment(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node)
{ {
uint id = node.y; uint id = node.y;

@ -334,6 +334,12 @@ typedef enum NodeNormalMapSpace {
NODE_NORMAL_MAP_BLENDER_WORLD, NODE_NORMAL_MAP_BLENDER_WORLD,
} NodeNormalMapSpace; } NodeNormalMapSpace;
typedef enum NodeImageProjection {
NODE_IMAGE_PROJ_FLAT = 0,
NODE_IMAGE_PROJ_BOX = 1,
NODE_IMAGE_PROJ_SPHERE = 2,
} NodeImageProjection;
typedef enum ShaderType { typedef enum ShaderType {
SHADER_TYPE_SURFACE, SHADER_TYPE_SURFACE,
SHADER_TYPE_VOLUME, SHADER_TYPE_VOLUME,

@ -174,8 +174,9 @@ static ShaderEnum image_projection_init()
{ {
ShaderEnum enm; ShaderEnum enm;
enm.insert("Flat", 0); enm.insert("Flat", NODE_IMAGE_PROJ_FLAT);
enm.insert("Box", 1); enm.insert("Box", NODE_IMAGE_PROJ_BOX);
enm.insert("Sphere", NODE_IMAGE_PROJ_SPHERE);
return enm; return enm;
} }
@ -266,14 +267,15 @@ void ImageTextureNode::compile(SVMCompiler& compiler)
tex_mapping.compile(compiler, vector_in->stack_offset, vector_offset); tex_mapping.compile(compiler, vector_in->stack_offset, vector_offset);
} }
if(projection == "Flat") { if(projection != "Box") {
compiler.add_node(NODE_TEX_IMAGE, compiler.add_node(NODE_TEX_IMAGE,
slot, slot,
compiler.encode_uchar4( compiler.encode_uchar4(
vector_offset, vector_offset,
color_out->stack_offset, color_out->stack_offset,
alpha_out->stack_offset, alpha_out->stack_offset,
srgb)); srgb),
projection_enum[projection]);
} }
else { else {
compiler.add_node(NODE_TEX_IMAGE_BOX, compiler.add_node(NODE_TEX_IMAGE_BOX,
@ -285,7 +287,7 @@ void ImageTextureNode::compile(SVMCompiler& compiler)
srgb), srgb),
__float_as_int(projection_blend)); __float_as_int(projection_blend));
} }
if(vector_offset != vector_in->stack_offset) if(vector_offset != vector_in->stack_offset)
compiler.stack_clear_offset(vector_in->type, vector_offset); compiler.stack_clear_offset(vector_in->type, vector_offset);
} }

@ -962,6 +962,7 @@ typedef struct NodeSunBeams {
/* image texture */ /* image texture */
#define SHD_PROJ_FLAT 0 #define SHD_PROJ_FLAT 0
#define SHD_PROJ_BOX 1 #define SHD_PROJ_BOX 1
#define SHD_PROJ_SPHERE 2
/* image texture interpolation */ /* image texture interpolation */
#define SHD_INTERP_LINEAR 0 #define SHD_INTERP_LINEAR 0

@ -3431,10 +3431,12 @@ static void def_sh_tex_image(StructRNA *srna)
}; };
static const EnumPropertyItem prop_projection_items[] = { static const EnumPropertyItem prop_projection_items[] = {
{SHD_PROJ_FLAT, "FLAT", 0, "Flat", {SHD_PROJ_FLAT, "FLAT", 0, "Flat",
"Image is projected flat using the X and Y coordinates of the texture vector"}, "Image is projected flat using the X and Y coordinates of the texture vector"},
{SHD_PROJ_BOX, "BOX", 0, "Box", {SHD_PROJ_BOX, "BOX", 0, "Box",
"Image is projected using different components for each side of the object space bounding box"}, "Image is projected using different components for each side of the object space bounding box"},
{SHD_PROJ_SPHERE, "SPHERE", 0, "Sphere",
"Image is projected spherically using the Z axis as central"},
{0, NULL, 0, NULL, NULL} {0, NULL, 0, NULL, NULL}
}; };