Cycles: color space control for image/environment texture nodes. Ideally would
be automated but need to think about how to do this, not so simply in a node system. But guideline for now is, for color textures set to sRGB, for things like bump or roughness map, set to Linear.
This commit is contained in:
@@ -282,15 +282,17 @@ static ShaderNode *add_node(BL::BlendData b_data, ShaderGraph *graph, BL::Node *
|
|||||||
/* todo: handle generated/builtin images */
|
/* todo: handle generated/builtin images */
|
||||||
if(b_image)
|
if(b_image)
|
||||||
image->filename = blender_absolute_path(b_data, b_image, b_image.filepath());
|
image->filename = blender_absolute_path(b_data, b_image, b_image.filepath());
|
||||||
|
image->color_space = ImageTextureNode::color_space_enum[(int)b_image_node.color_space()];
|
||||||
node = image;
|
node = image;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case BL::ShaderNode::type_TEX_ENVIRONMENT: {
|
case BL::ShaderNode::type_TEX_ENVIRONMENT: {
|
||||||
BL::ShaderNodeTexEnvironment b_environment_node(b_node);
|
BL::ShaderNodeTexEnvironment b_env_node(b_node);
|
||||||
BL::Image b_image(b_environment_node.image());
|
BL::Image b_image(b_env_node.image());
|
||||||
EnvironmentTextureNode *env = new EnvironmentTextureNode();
|
EnvironmentTextureNode *env = new EnvironmentTextureNode();
|
||||||
if(b_image)
|
if(b_image)
|
||||||
env->filename = blender_absolute_path(b_data, b_image, b_image.filepath());
|
env->filename = blender_absolute_path(b_data, b_image, b_image.filepath());
|
||||||
|
env->color_space = EnvironmentTextureNode::color_space_enum[(int)b_env_node.color_space()];
|
||||||
node = env;
|
node = env;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@@ -21,8 +21,12 @@
|
|||||||
shader node_environment_texture(
|
shader node_environment_texture(
|
||||||
vector Vector = P,
|
vector Vector = P,
|
||||||
string filename = "",
|
string filename = "",
|
||||||
|
string color_space = "sRGB",
|
||||||
output color Color = color(0.0, 0.0, 0.0))
|
output color Color = color(0.0, 0.0, 0.0))
|
||||||
{
|
{
|
||||||
Color = (color)environment(filename, Vector);
|
Color = (color)environment(filename, Vector);
|
||||||
|
|
||||||
|
if(color_space == "sRGB")
|
||||||
|
Color = color_srgb_to_scene_linear(Color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -21,8 +21,12 @@
|
|||||||
shader node_image_texture(
|
shader node_image_texture(
|
||||||
point Vector = P,
|
point Vector = P,
|
||||||
string filename = "",
|
string filename = "",
|
||||||
|
string color_space = "sRGB",
|
||||||
output color Color = color(0.0, 0.0, 0.0))
|
output color Color = color(0.0, 0.0, 0.0))
|
||||||
{
|
{
|
||||||
Color = (color)texture(filename, Vector[0], 1.0-Vector[1], "wrap", "periodic");
|
Color = (color)texture(filename, Vector[0], 1.0-Vector[1], "wrap", "periodic");
|
||||||
|
|
||||||
|
if(color_space == "sRGB")
|
||||||
|
Color = color_srgb_to_scene_linear(Color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -190,9 +190,9 @@ __device void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, ShaderType type,
|
|||||||
else if(node.x == NODE_TEX_NOISE_V)
|
else if(node.x == NODE_TEX_NOISE_V)
|
||||||
svm_node_tex_noise_v(sd, stack, node.y, node.z);
|
svm_node_tex_noise_v(sd, stack, node.y, node.z);
|
||||||
else if(node.x == NODE_TEX_IMAGE)
|
else if(node.x == NODE_TEX_IMAGE)
|
||||||
svm_node_tex_image(kg, sd, stack, node.y, node.z, node.w);
|
svm_node_tex_image(kg, sd, stack, node);
|
||||||
else if(node.x == NODE_TEX_ENVIRONMENT)
|
else if(node.x == NODE_TEX_ENVIRONMENT)
|
||||||
svm_node_tex_environment(kg, sd, stack, node.y, node.z, node.w);
|
svm_node_tex_environment(kg, sd, stack, node);
|
||||||
else if(node.x == NODE_TEX_SKY)
|
else if(node.x == NODE_TEX_SKY)
|
||||||
svm_node_tex_sky(kg, sd, stack, node.y, node.z);
|
svm_node_tex_sky(kg, sd, stack, node.y, node.z);
|
||||||
else if(node.x == NODE_TEX_BLEND)
|
else if(node.x == NODE_TEX_BLEND)
|
||||||
|
@@ -140,22 +140,40 @@ __device float4 svm_image_texture(KernelGlobals *kg, int id, float x, float y)
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
__device void svm_node_tex_image(KernelGlobals *kg, ShaderData *sd, float *stack, uint id, uint co_offset, uint out_offset)
|
__device void svm_node_tex_image(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node)
|
||||||
{
|
{
|
||||||
|
uint id = node.y;
|
||||||
|
uint co_offset, out_offset, srgb;
|
||||||
|
|
||||||
|
decode_node_uchar4(node.z, &co_offset, &out_offset, &srgb, NULL);
|
||||||
|
|
||||||
float3 co = stack_load_float3(stack, co_offset);
|
float3 co = stack_load_float3(stack, co_offset);
|
||||||
float4 f = svm_image_texture(kg, id, co.x, co.y);
|
float4 f = svm_image_texture(kg, id, co.x, co.y);
|
||||||
|
float3 r = make_float3(f.x, f.y, f.z);
|
||||||
|
|
||||||
stack_store_float3(stack, out_offset, make_float3(f.x, f.y, f.z));
|
if(srgb)
|
||||||
|
r = color_srgb_to_scene_linear(r);
|
||||||
|
|
||||||
|
stack_store_float3(stack, out_offset, r);
|
||||||
}
|
}
|
||||||
|
|
||||||
__device void svm_node_tex_environment(KernelGlobals *kg, ShaderData *sd, float *stack, uint id, uint co_offset, uint out_offset)
|
__device void svm_node_tex_environment(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node)
|
||||||
{
|
{
|
||||||
|
uint id = node.y;
|
||||||
|
uint co_offset, out_offset, srgb;
|
||||||
|
|
||||||
|
decode_node_uchar4(node.z, &co_offset, &out_offset, &srgb, NULL);
|
||||||
|
|
||||||
float3 co = stack_load_float3(stack, co_offset);
|
float3 co = stack_load_float3(stack, co_offset);
|
||||||
float u = (atan2f(co.y, co.x) + M_PI_F)/(2*M_PI_F);
|
float u = (atan2f(co.y, co.x) + M_PI_F)/(2*M_PI_F);
|
||||||
float v = atan2f(co.z, hypotf(co.x, co.y))/M_PI_F + 0.5f;
|
float v = atan2f(co.z, hypotf(co.x, co.y))/M_PI_F + 0.5f;
|
||||||
float4 f = svm_image_texture(kg, id, u, v);
|
float4 f = svm_image_texture(kg, id, u, v);
|
||||||
|
float3 r = make_float3(f.x, f.y, f.z);
|
||||||
|
|
||||||
stack_store_float3(stack, out_offset, make_float3(f.x, f.y, f.z));
|
if(srgb)
|
||||||
|
r = color_srgb_to_scene_linear(r);
|
||||||
|
|
||||||
|
stack_store_float3(stack, out_offset, r);
|
||||||
}
|
}
|
||||||
|
|
||||||
CCL_NAMESPACE_END
|
CCL_NAMESPACE_END
|
||||||
|
@@ -27,12 +27,25 @@ CCL_NAMESPACE_BEGIN
|
|||||||
|
|
||||||
/* Image Texture */
|
/* Image Texture */
|
||||||
|
|
||||||
|
static ShaderEnum color_space_init()
|
||||||
|
{
|
||||||
|
ShaderEnum enm;
|
||||||
|
|
||||||
|
enm.insert("Linear", 0);
|
||||||
|
enm.insert("sRGB", 1);
|
||||||
|
|
||||||
|
return enm;
|
||||||
|
}
|
||||||
|
|
||||||
|
ShaderEnum ImageTextureNode::color_space_enum = color_space_init();
|
||||||
|
|
||||||
ImageTextureNode::ImageTextureNode()
|
ImageTextureNode::ImageTextureNode()
|
||||||
: ShaderNode("image_texture")
|
: ShaderNode("image_texture")
|
||||||
{
|
{
|
||||||
image_manager = NULL;
|
image_manager = NULL;
|
||||||
slot = -1;
|
slot = -1;
|
||||||
filename = "";
|
filename = "";
|
||||||
|
color_space = ustring("sRGB");
|
||||||
|
|
||||||
add_input("Vector", SHADER_SOCKET_POINT, ShaderInput::TEXTURE_COORDINATE);
|
add_input("Vector", SHADER_SOCKET_POINT, ShaderInput::TEXTURE_COORDINATE);
|
||||||
add_output("Color", SHADER_SOCKET_COLOR);
|
add_output("Color", SHADER_SOCKET_COLOR);
|
||||||
@@ -65,7 +78,12 @@ void ImageTextureNode::compile(SVMCompiler& compiler)
|
|||||||
|
|
||||||
if(slot != -1) {
|
if(slot != -1) {
|
||||||
compiler.stack_assign(vector_in);
|
compiler.stack_assign(vector_in);
|
||||||
compiler.add_node(NODE_TEX_IMAGE, slot, vector_in->stack_offset, color_out->stack_offset);
|
compiler.add_node(NODE_TEX_IMAGE,
|
||||||
|
slot,
|
||||||
|
compiler.encode_uchar4(
|
||||||
|
vector_in->stack_offset,
|
||||||
|
color_out->stack_offset,
|
||||||
|
color_space_enum[color_space]));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* image not found */
|
/* image not found */
|
||||||
@@ -77,17 +95,21 @@ void ImageTextureNode::compile(SVMCompiler& compiler)
|
|||||||
void ImageTextureNode::compile(OSLCompiler& compiler)
|
void ImageTextureNode::compile(OSLCompiler& compiler)
|
||||||
{
|
{
|
||||||
compiler.parameter("filename", filename.c_str());
|
compiler.parameter("filename", filename.c_str());
|
||||||
|
compiler.parameter("color_space", color_space.c_str());
|
||||||
compiler.add(this, "node_image_texture");
|
compiler.add(this, "node_image_texture");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Environment Texture */
|
/* Environment Texture */
|
||||||
|
|
||||||
|
ShaderEnum EnvironmentTextureNode::color_space_enum = color_space_init();
|
||||||
|
|
||||||
EnvironmentTextureNode::EnvironmentTextureNode()
|
EnvironmentTextureNode::EnvironmentTextureNode()
|
||||||
: ShaderNode("environment_texture")
|
: ShaderNode("environment_texture")
|
||||||
{
|
{
|
||||||
image_manager = NULL;
|
image_manager = NULL;
|
||||||
slot = -1;
|
slot = -1;
|
||||||
filename = "";
|
filename = "";
|
||||||
|
color_space = ustring("sRGB");
|
||||||
|
|
||||||
add_input("Vector", SHADER_SOCKET_VECTOR, ShaderInput::POSITION);
|
add_input("Vector", SHADER_SOCKET_VECTOR, ShaderInput::POSITION);
|
||||||
add_output("Color", SHADER_SOCKET_COLOR);
|
add_output("Color", SHADER_SOCKET_COLOR);
|
||||||
@@ -120,7 +142,12 @@ void EnvironmentTextureNode::compile(SVMCompiler& compiler)
|
|||||||
|
|
||||||
if(slot != -1) {
|
if(slot != -1) {
|
||||||
compiler.stack_assign(vector_in);
|
compiler.stack_assign(vector_in);
|
||||||
compiler.add_node(NODE_TEX_ENVIRONMENT, slot, vector_in->stack_offset, color_out->stack_offset);
|
compiler.add_node(NODE_TEX_ENVIRONMENT,
|
||||||
|
slot,
|
||||||
|
compiler.encode_uchar4(
|
||||||
|
vector_in->stack_offset,
|
||||||
|
color_out->stack_offset,
|
||||||
|
color_space_enum[color_space]));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* image not found */
|
/* image not found */
|
||||||
@@ -132,6 +159,7 @@ void EnvironmentTextureNode::compile(SVMCompiler& compiler)
|
|||||||
void EnvironmentTextureNode::compile(OSLCompiler& compiler)
|
void EnvironmentTextureNode::compile(OSLCompiler& compiler)
|
||||||
{
|
{
|
||||||
compiler.parameter("filename", filename.c_str());
|
compiler.parameter("filename", filename.c_str());
|
||||||
|
compiler.parameter("color_space", color_space.c_str());
|
||||||
compiler.add(this, "node_environment_texture");
|
compiler.add(this, "node_environment_texture");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -39,6 +39,9 @@ public:
|
|||||||
ImageManager *image_manager;
|
ImageManager *image_manager;
|
||||||
int slot;
|
int slot;
|
||||||
string filename;
|
string filename;
|
||||||
|
ustring color_space;
|
||||||
|
|
||||||
|
static ShaderEnum color_space_enum;
|
||||||
};
|
};
|
||||||
|
|
||||||
class EnvironmentTextureNode : public ShaderNode {
|
class EnvironmentTextureNode : public ShaderNode {
|
||||||
@@ -50,6 +53,9 @@ public:
|
|||||||
ImageManager *image_manager;
|
ImageManager *image_manager;
|
||||||
int slot;
|
int slot;
|
||||||
string filename;
|
string filename;
|
||||||
|
ustring color_space;
|
||||||
|
|
||||||
|
static ShaderEnum color_space_enum;
|
||||||
};
|
};
|
||||||
|
|
||||||
class SkyTextureNode : public ShaderNode {
|
class SkyTextureNode : public ShaderNode {
|
||||||
|
@@ -400,6 +400,7 @@ static void node_shader_buts_tex_image(uiLayout *layout, bContext *C, PointerRNA
|
|||||||
{
|
{
|
||||||
//uiItemR(layout, ptr, "image", 0, "", ICON_NONE);
|
//uiItemR(layout, ptr, "image", 0, "", ICON_NONE);
|
||||||
uiTemplateID(layout, C, ptr, "image", NULL, "IMAGE_OT_open", NULL);
|
uiTemplateID(layout, C, ptr, "image", NULL, "IMAGE_OT_open", NULL);
|
||||||
|
uiItemR(layout, ptr, "color_space", 0, "", ICON_NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void node_shader_buts_tex_sky(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
|
static void node_shader_buts_tex_sky(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
|
||||||
|
@@ -355,11 +355,11 @@ typedef struct NodeTexSky {
|
|||||||
} NodeTexSky;
|
} NodeTexSky;
|
||||||
|
|
||||||
typedef struct NodeTexImage {
|
typedef struct NodeTexImage {
|
||||||
int pad;
|
int color_space;
|
||||||
} NodeTexImage;
|
} NodeTexImage;
|
||||||
|
|
||||||
typedef struct NodeTexEnvironment {
|
typedef struct NodeTexEnvironment {
|
||||||
int pad;
|
int color_space;
|
||||||
} NodeTexEnvironment;
|
} NodeTexEnvironment;
|
||||||
|
|
||||||
typedef struct NodeTexBlend {
|
typedef struct NodeTexBlend {
|
||||||
@@ -499,6 +499,10 @@ typedef struct TexNodeOutput {
|
|||||||
#define SHD_WOOD_BAND_NOISE 2
|
#define SHD_WOOD_BAND_NOISE 2
|
||||||
#define SHD_WOOD_RING_NOISE 3
|
#define SHD_WOOD_RING_NOISE 3
|
||||||
|
|
||||||
|
/* image/environment texture */
|
||||||
|
#define SHD_COLORSPACE_LINEAR 0
|
||||||
|
#define SHD_COLORSPACE_SRGB 1
|
||||||
|
|
||||||
/* blur node */
|
/* blur node */
|
||||||
#define CMP_NODE_BLUR_ASPECT_NONE 0
|
#define CMP_NODE_BLUR_ASPECT_NONE 0
|
||||||
#define CMP_NODE_BLUR_ASPECT_Y 1
|
#define CMP_NODE_BLUR_ASPECT_Y 1
|
||||||
|
@@ -1044,20 +1044,11 @@ static void def_sh_tex_sky(StructRNA *srna)
|
|||||||
|
|
||||||
static void def_sh_tex_environment(StructRNA *srna)
|
static void def_sh_tex_environment(StructRNA *srna)
|
||||||
{
|
{
|
||||||
PropertyRNA *prop;
|
static const EnumPropertyItem prop_color_space_items[]= {
|
||||||
|
{SHD_COLORSPACE_SRGB, "SRGB", 0, "sRGB", "Image is in sRGB color space"},
|
||||||
|
{SHD_COLORSPACE_LINEAR, "LINEAR", 0, "Linear", "Image is in scene linear color space"},
|
||||||
|
{0, NULL, 0, NULL, NULL}};
|
||||||
|
|
||||||
prop = RNA_def_property(srna, "image", PROP_POINTER, PROP_NONE);
|
|
||||||
RNA_def_property_pointer_sdna(prop, NULL, "id");
|
|
||||||
RNA_def_property_struct_type(prop, "Image");
|
|
||||||
RNA_def_property_flag(prop, PROP_EDITABLE);
|
|
||||||
RNA_def_property_ui_text(prop, "Image", "");
|
|
||||||
RNA_def_property_update(prop, NC_NODE|NA_EDITED, "rna_Node_update");
|
|
||||||
|
|
||||||
RNA_def_struct_sdna_from(srna, "NodeTexEnvironment", "storage");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void def_sh_tex_image(StructRNA *srna)
|
|
||||||
{
|
|
||||||
PropertyRNA *prop;
|
PropertyRNA *prop;
|
||||||
|
|
||||||
prop = RNA_def_property(srna, "image", PROP_POINTER, PROP_NONE);
|
prop = RNA_def_property(srna, "image", PROP_POINTER, PROP_NONE);
|
||||||
@@ -1068,6 +1059,35 @@ static void def_sh_tex_image(StructRNA *srna)
|
|||||||
RNA_def_property_update(prop, NC_NODE|NA_EDITED, "rna_Node_update");
|
RNA_def_property_update(prop, NC_NODE|NA_EDITED, "rna_Node_update");
|
||||||
|
|
||||||
RNA_def_struct_sdna_from(srna, "NodeTexImage", "storage");
|
RNA_def_struct_sdna_from(srna, "NodeTexImage", "storage");
|
||||||
|
|
||||||
|
prop= RNA_def_property(srna, "color_space", PROP_ENUM, PROP_NONE);
|
||||||
|
RNA_def_property_enum_items(prop, prop_color_space_items);
|
||||||
|
RNA_def_property_ui_text(prop, "Color Space", "Image file color space");
|
||||||
|
RNA_def_property_update(prop, 0, "rna_Node_update");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void def_sh_tex_image(StructRNA *srna)
|
||||||
|
{
|
||||||
|
static const EnumPropertyItem prop_color_space_items[]= {
|
||||||
|
{SHD_COLORSPACE_LINEAR, "LINEAR", 0, "Linear", "Image is in scene linear color space"},
|
||||||
|
{SHD_COLORSPACE_SRGB, "SRGB", 0, "sRGB", "Image is in sRGB color space"},
|
||||||
|
{0, NULL, 0, NULL, NULL}};
|
||||||
|
|
||||||
|
PropertyRNA *prop;
|
||||||
|
|
||||||
|
prop = RNA_def_property(srna, "image", PROP_POINTER, PROP_NONE);
|
||||||
|
RNA_def_property_pointer_sdna(prop, NULL, "id");
|
||||||
|
RNA_def_property_struct_type(prop, "Image");
|
||||||
|
RNA_def_property_flag(prop, PROP_EDITABLE);
|
||||||
|
RNA_def_property_ui_text(prop, "Image", "");
|
||||||
|
RNA_def_property_update(prop, NC_NODE|NA_EDITED, "rna_Node_update");
|
||||||
|
|
||||||
|
RNA_def_struct_sdna_from(srna, "NodeTexImage", "storage");
|
||||||
|
|
||||||
|
prop= RNA_def_property(srna, "color_space", PROP_ENUM, PROP_NONE);
|
||||||
|
RNA_def_property_enum_items(prop, prop_color_space_items);
|
||||||
|
RNA_def_property_ui_text(prop, "Color Space", "Image file color space");
|
||||||
|
RNA_def_property_update(prop, 0, "rna_Node_update");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void def_sh_tex_blend(StructRNA *srna)
|
static void def_sh_tex_blend(StructRNA *srna)
|
||||||
|
@@ -44,6 +44,7 @@ static bNodeSocketType sh_node_tex_environment_out[]= {
|
|||||||
static void node_shader_init_tex_environment(bNode *node)
|
static void node_shader_init_tex_environment(bNode *node)
|
||||||
{
|
{
|
||||||
NodeTexEnvironment *tex = MEM_callocN(sizeof(NodeTexEnvironment), "NodeTexEnvironment");
|
NodeTexEnvironment *tex = MEM_callocN(sizeof(NodeTexEnvironment), "NodeTexEnvironment");
|
||||||
|
tex->color_space = SHD_COLORSPACE_SRGB;
|
||||||
|
|
||||||
node->storage = tex;
|
node->storage = tex;
|
||||||
}
|
}
|
||||||
|
@@ -44,6 +44,7 @@ static bNodeSocketType sh_node_tex_image_out[]= {
|
|||||||
static void node_shader_init_tex_image(bNode *node)
|
static void node_shader_init_tex_image(bNode *node)
|
||||||
{
|
{
|
||||||
NodeTexImage *tex = MEM_callocN(sizeof(NodeTexImage), "NodeTexImage");
|
NodeTexImage *tex = MEM_callocN(sizeof(NodeTexImage), "NodeTexImage");
|
||||||
|
tex->color_space = SHD_COLORSPACE_SRGB;
|
||||||
|
|
||||||
node->storage = tex;
|
node->storage = tex;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user