diff options
author | Nicholas Bishop <nicholasbishop@gmail.com> | 2015-01-19 22:04:27 +0300 |
---|---|---|
committer | Nicholas Bishop <nicholasbishop@gmail.com> | 2015-02-06 19:19:49 +0300 |
commit | 964285c25e299589b013893be0cf9b7fe36606db (patch) | |
tree | 4b4fd52e593580fb1122b7b54d2dc1b4c96b96f0 /intern/cycles | |
parent | c50694060db83a1a77685dbe2cb01350a7bed98d (diff) |
Add Ptex support to Cycles image node, also add Ptex node
Diffstat (limited to 'intern/cycles')
-rw-r--r-- | intern/cycles/CMakeLists.txt | 5 | ||||
-rw-r--r-- | intern/cycles/blender/blender_session.cpp | 21 | ||||
-rw-r--r-- | intern/cycles/blender/blender_session.h | 5 | ||||
-rw-r--r-- | intern/cycles/blender/blender_shader.cpp | 12 | ||||
-rw-r--r-- | intern/cycles/kernel/kernel_textures.h | 3 | ||||
-rw-r--r-- | intern/cycles/kernel/kernel_types.h | 1 | ||||
-rw-r--r-- | intern/cycles/kernel/svm/svm_image.h | 52 | ||||
-rw-r--r-- | intern/cycles/render/attribute.cpp | 5 | ||||
-rw-r--r-- | intern/cycles/render/image.cpp | 133 | ||||
-rw-r--r-- | intern/cycles/render/image.h | 7 | ||||
-rw-r--r-- | intern/cycles/render/nodes.cpp | 244 | ||||
-rw-r--r-- | intern/cycles/render/nodes.h | 26 | ||||
-rw-r--r-- | intern/cycles/render/scene.h | 3 | ||||
-rw-r--r-- | intern/cycles/util/util_types.h | 6 |
14 files changed, 499 insertions, 24 deletions
diff --git a/intern/cycles/CMakeLists.txt b/intern/cycles/CMakeLists.txt index 2ba6af48d0d..34a51957bdf 100644 --- a/intern/cycles/CMakeLists.txt +++ b/intern/cycles/CMakeLists.txt @@ -129,9 +129,10 @@ if(WITH_CYCLES_STANDALONE_GUI) add_definitions(-DWITH_CYCLES_STANDALONE_GUI) endif() -if(WITH_CYCLES_PTEX) +#if(WITH_CYCLES_PTEX) add_definitions(-DWITH_PTEX) -endif() + include_directories("../../extern/ptex") +#endif() if(WITH_CYCLES_OPENSUBDIV) add_definitions(-DWITH_OPENSUBDIV) diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp index eb3f54ae90c..db70bad4e1f 100644 --- a/intern/cycles/blender/blender_session.cpp +++ b/intern/cycles/blender/blender_session.cpp @@ -101,8 +101,8 @@ void BlenderSession::create_session() scene = new Scene(scene_params, session_params.device); /* setup callbacks for builtin image support */ - scene->image_manager->builtin_image_info_cb = function_bind(&BlenderSession::builtin_image_info, this, _1, _2, _3, _4, _5, _6, _7); - scene->image_manager->builtin_image_pixels_cb = function_bind(&BlenderSession::builtin_image_pixels, this, _1, _2, _3); + scene->image_manager->builtin_image_info_cb = function_bind(&BlenderSession::builtin_image_info, this, _1, _2, _3, _4, _5, _6, _7, _8); + scene->image_manager->builtin_image_pixels_cb = function_bind(&BlenderSession::builtin_image_pixels, this, _1, _2, _3, _4, _5); scene->image_manager->builtin_image_float_pixels_cb = function_bind(&BlenderSession::builtin_image_float_pixels, this, _1, _2, _3); /* create session */ @@ -927,7 +927,7 @@ int BlenderSession::builtin_image_frame(const string &builtin_name) return atoi(builtin_name.substr(last + 1, builtin_name.size() - last - 1).c_str()); } -void BlenderSession::builtin_image_info(const string &builtin_name, void *builtin_data, bool &is_float, int &width, int &height, int &depth, int &channels) +void BlenderSession::builtin_image_info(const string &builtin_name, void *builtin_data, bool &is_float, int &width, int &height, int &depth, int &channels, int &num_ptex_regions) { /* empty image */ is_float = false; @@ -953,6 +953,10 @@ void BlenderSession::builtin_image_info(const string &builtin_name, void *builti height = b_image.size()[1]; depth = 1; channels = b_image.channels(); + + // TODO: ptex + is_float = false; + num_ptex_regions = b_image.ptex_regions().length; } else if(b_id.is_a(&RNA_Object)) { /* smoke volume data */ @@ -981,7 +985,8 @@ void BlenderSession::builtin_image_info(const string &builtin_name, void *builti } } -bool BlenderSession::builtin_image_pixels(const string &builtin_name, void *builtin_data, unsigned char *pixels) +bool BlenderSession::builtin_image_pixels(const string &builtin_name, void *builtin_data, unsigned char *pixels, + PtexRegions ptex_regions, const int num_ptex_regions) { if(!builtin_data) return false; @@ -1019,6 +1024,14 @@ bool BlenderSession::builtin_image_pixels(const string &builtin_name, void *buil } } + { + // TODO + BL::DynamicArray<int> regions = b_image.ptex_regions(); + assert(num_ptex_regions == regions.length); + memcpy(ptex_regions, regions.data, + sizeof(**ptex_regions) * num_ptex_regions); + } + /* premultiply, byte images are always straight for blender */ unsigned char *cp = pixels; for(int i = 0; i < width * height; i++, cp += channels) { diff --git a/intern/cycles/blender/blender_session.h b/intern/cycles/blender/blender_session.h index 33da3076b55..0eeabdaade8 100644 --- a/intern/cycles/blender/blender_session.h +++ b/intern/cycles/blender/blender_session.h @@ -104,8 +104,9 @@ protected: void do_write_update_render_tile(RenderTile& rtile, bool do_update_only); int builtin_image_frame(const string &builtin_name); - void builtin_image_info(const string &builtin_name, void *builtin_data, bool &is_float, int &width, int &height, int &depth, int &channels); - bool builtin_image_pixels(const string &builtin_name, void *builtin_data, unsigned char *pixels); + void builtin_image_info(const string &builtin_name, void *builtin_data, bool &is_float, int &width, int &height, int &depth, int &channels, int &num_ptex_regions); + bool builtin_image_pixels(const string &builtin_name, void *builtin_data, unsigned char *pixels, + PtexRegions ptex_regions, int num_ptex_regions); bool builtin_image_float_pixels(const string &builtin_name, void *builtin_data, float *pixels); }; diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp index baf79a78987..c141b9eeabd 100644 --- a/intern/cycles/blender/blender_shader.cpp +++ b/intern/cycles/blender/blender_shader.cpp @@ -577,6 +577,9 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen image->animated = b_image_node.image_user().use_auto_refresh(); image->use_alpha = b_image.use_alpha(); + // TODO(nicholasbishop) + image->ptex = string_endswith(image->filename, ".ptx"); + /* TODO(sergey): Does not work properly when we change builtin type. */ if (b_image.is_updated()) { scene->image_manager->tag_reload_image(image->filename, @@ -591,6 +594,15 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen get_tex_mapping(&image->tex_mapping, b_image_node.texture_mapping()); node = image; } + else if (b_node.is_a(&RNA_ShaderNodeTexPtex)) { + // TODO + BL::ShaderNodeTexPtex b_image_node(b_node); + PtexTextureNode *image = new PtexTextureNode(); + + image->ptex = true; + image->ptex_layer = b_image_node.layer_name(); + node = image; + } else if (b_node.is_a(&RNA_ShaderNodeTexEnvironment)) { BL::ShaderNodeTexEnvironment b_env_node(b_node); BL::Image b_image(b_env_node.image()); diff --git a/intern/cycles/kernel/kernel_textures.h b/intern/cycles/kernel/kernel_textures.h index 374dc6d1dd9..ca2da1fca06 100644 --- a/intern/cycles/kernel/kernel_textures.h +++ b/intern/cycles/kernel/kernel_textures.h @@ -71,6 +71,9 @@ KERNEL_TEX(float, texture_float, __lookup_table) /* sobol */ KERNEL_TEX(uint, texture_uint, __sobol_directions) +/* ptex */ +KERNEL_TEX(uint, texture_uint, __ptex_table) + /* full-float image */ KERNEL_IMAGE_TEX(float4, texture_image_float4, __tex_image_float_000) KERNEL_IMAGE_TEX(float4, texture_image_float4, __tex_image_float_001) diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h index 77d3ea874d0..19452b97c30 100644 --- a/intern/cycles/kernel/kernel_types.h +++ b/intern/cycles/kernel/kernel_types.h @@ -534,6 +534,7 @@ typedef enum AttributeStandard { ATTR_STD_VOLUME_FLAME, ATTR_STD_VOLUME_HEAT, ATTR_STD_VOLUME_VELOCITY, + ATTR_STD_PTEX_LAYER, ATTR_STD_NUM, ATTR_STD_NOT_FOUND = ~0 diff --git a/intern/cycles/kernel/svm/svm_image.h b/intern/cycles/kernel/svm/svm_image.h index e667fc2033d..139c637bb19 100644 --- a/intern/cycles/kernel/svm/svm_image.h +++ b/intern/cycles/kernel/svm/svm_image.h @@ -377,7 +377,57 @@ ccl_device void svm_node_tex_image(KernelGlobals *kg, ShaderData *sd, float *sta co = texco_remap_square(co); map_to_tube(&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; + + // TODO + bool err = false; + if (srgb & 4) { + AttributeElement ae; + int image_attr_offset = find_attribute(kg, sd, id, &ae); + if(image_attr_offset == ATTR_STD_NOT_FOUND) { + /* Error */ + err = true; + } + else { + float fid = kernel_tex_fetch(__attributes_float, + image_attr_offset); + id = (int)(fid + 0.5f); + } + } + + if (err) { + f = make_float4(1.0f, 0.0f, 1.0f, 1.0f); + } + else if (srgb & 2) { + assert(co.x >= 0 && co.x <= 1); + assert(co.y >= 0 && co.y <= 1); + + // TODO: test hacks for Ptex + uint face_id = (uint)(co[2] + 0.5f); + uint offset = kernel_tex_fetch(__ptex_table, id - /* TODO */ 1024); + float2 tex_size = + make_float2((float)kernel_tex_fetch(__ptex_table, offset + 0), + (float)kernel_tex_fetch(__ptex_table, offset + 1)); + offset += 2; + offset += 4 * face_id; + + float2 ptex_origin = + make_float2((float)kernel_tex_fetch(__ptex_table, offset + 0), + (float)kernel_tex_fetch(__ptex_table, offset + 1)); + float2 ptex_res = + make_float2((float)kernel_tex_fetch(__ptex_table, offset + 2), + (float)kernel_tex_fetch(__ptex_table, offset + 3)); + + float2 ptex_uv = ptex_origin + make_float2(co.x, co.y) * ptex_res; + ptex_uv /= tex_size; + + f = svm_image_texture(kg, id, ptex_uv.x, ptex_uv.y, srgb, + use_alpha); + } + else { + f = svm_image_texture(kg, id, co.x, co.y, srgb, use_alpha); + } if(stack_valid(out_offset)) stack_store_float3(stack, out_offset, make_float3(f.x, f.y, f.z)); diff --git a/intern/cycles/render/attribute.cpp b/intern/cycles/render/attribute.cpp index 15d7134cc55..fbd751fd778 100644 --- a/intern/cycles/render/attribute.cpp +++ b/intern/cycles/render/attribute.cpp @@ -230,6 +230,8 @@ const char *Attribute::standard_name(AttributeStandard std) return "heat"; case ATTR_STD_VOLUME_VELOCITY: return "velocity"; + case ATTR_STD_PTEX_LAYER: + return "ptex_layer"; case ATTR_STD_NOT_FOUND: case ATTR_STD_NONE: case ATTR_STD_NUM: @@ -375,6 +377,9 @@ Attribute *AttributeSet::add(AttributeStandard std, ustring name) case ATTR_STD_VOLUME_VELOCITY: attr = add(name, TypeDesc::TypeVector, ATTR_ELEMENT_VOXEL); break; + case ATTR_STD_PTEX_LAYER: + attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_MESH); + break; default: assert(0); break; diff --git a/intern/cycles/render/image.cpp b/intern/cycles/render/image.cpp index 61a0a81d51d..3eb6bd53a19 100644 --- a/intern/cycles/render/image.cpp +++ b/intern/cycles/render/image.cpp @@ -27,6 +27,10 @@ #include <OSL/oslexec.h> #endif +#ifdef WITH_PTEX +#include "BPX_pack.h" +#endif + CCL_NAMESPACE_BEGIN ImageManager::ImageManager() @@ -96,7 +100,8 @@ bool ImageManager::is_float_image(const string& filename, void *builtin_data, bo if(builtin_data) { if(builtin_image_info_cb) { int width, height, depth, channels; - builtin_image_info_cb(filename, builtin_data, is_float, width, height, depth, channels); + int num_ptex_regions; + builtin_image_info_cb(filename, builtin_data, is_float, width, height, depth, channels, num_ptex_regions); } if(is_float) @@ -348,7 +353,77 @@ void ImageManager::tag_reload_image(const string& filename, void *builtin_data, } } -bool ImageManager::file_load_image(Image *img, device_vector<uchar4>& tex_img) +// TODO +static PtexRegions ptex_table_reserve(DeviceScene *dscene, + const int texture_slot, + const int texture_width, + const int texture_height, + const int num_ptex_regions) +{ + // Simple encoding (not necessarily a good one): + // + // Two-step lookup: index is image slot, value there is an another + // index into same array. At that index, two ints store + // width/height of the whole texture. Then come 4-tuples of Ptex + // regions (x, y, w, h ints). + if (dscene->ptex_table.size() == 0) { + dscene->ptex_table.resize(TEX_EXTENDED_NUM_IMAGES_CPU); + } + + uint offset = dscene->ptex_table.size(); + uint *table_data = dscene->ptex_table.resize(offset + + 2 + + num_ptex_regions); + table_data[texture_slot] = offset; + table_data[offset] = texture_width; + offset++; + table_data[offset] = texture_height; + offset++; + + return (PtexRegions)(&table_data[offset]); +} + +struct PtexPackUcharContext { + uchar **pixels; + device_vector<uchar4> &tex_img; + DeviceScene *dscene; + int slot; +}; + +static BPXImageBuf *ptex_pack_uchar_cb(const struct PtexPackedLayout *layout, + void *c) +{ + PtexPackUcharContext &context = *static_cast<PtexPackUcharContext*>(c); + const int width = ptex_packed_layout_width(layout); + const int height = ptex_packed_layout_height(layout); + const int depth = 1; + (*context.pixels) = (uchar*)context.tex_img.resize(width, height, depth); + + const int num_regions = BPX_packed_layout_num_regions(layout); + PtexRegions regions = ptex_table_reserve(context.dscene, context.slot, + // TODO: 4 + width, height, num_regions*4); + + for (int i = 0; i < num_regions; i++) { + int x, y, w, h; + if (ptex_packed_layout_item(layout, i, &x, &y, &w, &h)) { + regions[i][0] = x; + regions[i][1] = y; + regions[i][2] = w; + regions[i][3] = h; + } + else { + // TODO + assert(!"TODO"); + } + } + + return BPX_image_buf_wrap(width, height, 4, BPX_TYPE_DESC_UINT8, + *context.pixels); +} + +bool ImageManager::file_load_image(Image *img, device_vector<uchar4>& tex_img, + DeviceScene *dscene, int slot) { if(img->filename == "") return false; @@ -356,6 +431,8 @@ bool ImageManager::file_load_image(Image *img, device_vector<uchar4>& tex_img) ImageInput *in = NULL; int width, height, depth, components; + bool use_ptex_file = false; + int num_ptex_regions = 0; if(!img->builtin_data) { /* load image from file through OIIO */ in = ImageInput::create(img->filename); @@ -374,8 +451,14 @@ bool ImageManager::file_load_image(Image *img, device_vector<uchar4>& tex_img) return false; } - width = spec.width; - height = spec.height; + if (in->format_name() == std::string("ptex")) { + use_ptex_file = true; + } + else { + width = spec.width; + height = spec.height; + } + depth = spec.depth; components = spec.nchannels; } @@ -385,7 +468,7 @@ bool ImageManager::file_load_image(Image *img, device_vector<uchar4>& tex_img) return false; bool is_float; - builtin_image_info_cb(img->filename, img->builtin_data, is_float, width, height, depth, components); + builtin_image_info_cb(img->filename, img->builtin_data, is_float, width, height, depth, components, num_ptex_regions); } /* we only handle certain number of components */ @@ -399,9 +482,28 @@ bool ImageManager::file_load_image(Image *img, device_vector<uchar4>& tex_img) } /* read RGBA pixels */ - uchar *pixels = (uchar*)tex_img.resize(width, height, depth); + uchar *pixels = NULL; bool cmyk = false; + if (use_ptex_file) { + BPXImageBuf *packed_buf; + BPXImageInput *bpx_in = reinterpret_cast<BPXImageInput*>(in); + // TODO, subtraction + PtexPackUcharContext context = {&pixels, tex_img, dscene, slot - 1024}; + packed_buf = BPX_image_buf_ptex_pack(bpx_in, ptex_pack_uchar_cb, + &context); + delete in; + + if (!packed_buf) { + return false; + } + + BPX_image_buf_free(packed_buf); + in = NULL; + } else { + pixels = (uchar*)tex_img.resize(width, height, depth); + } + if(in) { if(depth <= 1) { int scanlinesize = width*components*sizeof(uchar); @@ -421,8 +523,15 @@ bool ImageManager::file_load_image(Image *img, device_vector<uchar4>& tex_img) in->close(); delete in; } - else { - builtin_image_pixels_cb(img->filename, img->builtin_data, pixels); + else if (!use_ptex_file) { + PtexRegions ptex_regions; + thread_scoped_lock device_lock(device_mutex); + ptex_regions = ptex_table_reserve(dscene, slot - 1024, width, + height, num_ptex_regions); + + + builtin_image_pixels_cb(img->filename, img->builtin_data, pixels, + ptex_regions, num_ptex_regions); } if(cmyk) { @@ -509,7 +618,8 @@ bool ImageManager::file_load_float_image(Image *img, device_vector<float4>& tex_ return false; bool is_float; - builtin_image_info_cb(img->filename, img->builtin_data, is_float, width, height, depth, components); + int num_ptex_regions; + builtin_image_info_cb(img->filename, img->builtin_data, is_float, width, height, depth, components, num_ptex_regions); } if(components < 1 || width == 0 || height == 0) { @@ -675,7 +785,7 @@ void ImageManager::device_load_image(Device *device, DeviceScene *dscene, int sl device->tex_free(tex_img); } - if(!file_load_image(img, tex_img)) { + if(!file_load_image(img, tex_img, dscene, slot)) { /* on failure to load, we set a 1x1 pixels pink image */ uchar *pixels = (uchar*)tex_img.resize(1, 1); @@ -788,6 +898,7 @@ void ImageManager::device_update(Device *device, DeviceScene *dscene, Progress& if(pack_images) device_pack_images(device, dscene, progress); + device->tex_alloc("__ptex_table", dscene->ptex_table); need_update = false; } @@ -864,9 +975,11 @@ void ImageManager::device_free(Device *device, DeviceScene *dscene) device->tex_free(dscene->tex_image_packed); device->tex_free(dscene->tex_image_packed_info); + device->tex_free(dscene->ptex_table); dscene->tex_image_packed.clear(); dscene->tex_image_packed_info.clear(); + dscene->ptex_table.clear(); images.clear(); float_images.clear(); diff --git a/intern/cycles/render/image.h b/intern/cycles/render/image.h index 2f5dcb6efd5..2abfd3995bf 100644 --- a/intern/cycles/render/image.h +++ b/intern/cycles/render/image.h @@ -73,8 +73,8 @@ public: bool need_update; - boost::function<void(const string &filename, void *data, bool &is_float, int &width, int &height, int &depth, int &channels)> builtin_image_info_cb; - boost::function<bool(const string &filename, void *data, unsigned char *pixels)> builtin_image_pixels_cb; + boost::function<void(const string &filename, void *data, bool &is_float, int &width, int &height, int &depth, int &channels, int &num_ptex_regions)> builtin_image_info_cb; + boost::function<bool(const string &filename, void *data, unsigned char *pixels, PtexRegions ptex_regions, int num_ptex_regions)> builtin_image_pixels_cb; boost::function<bool(const string &filename, void *data, float *pixels)> builtin_image_float_pixels_cb; struct Image { @@ -102,7 +102,8 @@ private: void *osl_texture_system; bool pack_images; - bool file_load_image(Image *img, device_vector<uchar4>& tex_img); + bool file_load_image(Image *img, device_vector<uchar4>& tex_img, + DeviceScene *dscene, int slot); bool file_load_float_image(Image *img, device_vector<float4>& tex_img); void device_load_image(Device *device, DeviceScene *dscene, int slot, Progress *progess); diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp index 3448209f101..4e9678e20ae 100644 --- a/intern/cycles/render/nodes.cpp +++ b/intern/cycles/render/nodes.cpp @@ -200,6 +200,7 @@ ImageTextureNode::ImageTextureNode() interpolation = INTERPOLATION_LINEAR; projection_blend = 0.0f; animated = false; + ptex = false; add_input("Vector", SHADER_SOCKET_POINT, ShaderInput::TEXTURE_UV); add_output("Color", SHADER_SOCKET_COLOR); @@ -234,6 +235,10 @@ void ImageTextureNode::attributes(Shader *shader, AttributeRequestSet *attribute } #endif + if (ptex) { + attributes->add(ATTR_STD_PTEX_UV); + } + ShaderNode::attributes(shader, attributes); } @@ -243,6 +248,21 @@ void ImageTextureNode::compile(SVMCompiler& compiler) ShaderOutput *color_out = output("Color"); ShaderOutput *alpha_out = output("Alpha"); + if (ptex) { + int attr = compiler.attribute(ATTR_STD_PTEX_UV); + compiler.stack_assign(vector_in); + compiler.add_node(NODE_ATTR, attr, vector_in->stack_offset, + NODE_ATTR_FLOAT3); + } + + if (ptex) { + // TODO + // int attr = compiler.attribute(ATTR_STD_PTEX_LAYER); + // compiler.stack_assign(out); + // compiler.add_node(attr_node, attr, out->stack_offset, NODE_ATTR_FLOAT3); + // slot = + } + image_manager = compiler.image_manager; if(is_float == -1) { bool is_float_bool; @@ -261,6 +281,11 @@ void ImageTextureNode::compile(SVMCompiler& compiler) compiler.stack_assign(vector_in); int srgb = (is_linear || color_space != "Color")? 0: 1; + // TODO(nicholasbishop): clean this up of course + int flags = srgb; + if (ptex || string_endswith(filename, ".ptx")) { + flags |= 2; + } int vector_offset = vector_in->stack_offset; if(!tex_mapping.skip()) { @@ -275,7 +300,7 @@ void ImageTextureNode::compile(SVMCompiler& compiler) vector_offset, color_out->stack_offset, alpha_out->stack_offset, - srgb), + flags), projection_enum[projection]); } else { @@ -285,7 +310,7 @@ void ImageTextureNode::compile(SVMCompiler& compiler) vector_offset, color_out->stack_offset, alpha_out->stack_offset, - srgb), + flags & 1), __float_as_int(projection_blend)); } @@ -364,6 +389,221 @@ void ImageTextureNode::compile(OSLCompiler& compiler) compiler.add(this, "node_image_texture"); } +PtexTextureNode::PtexTextureNode() +: ShaderNode("ptex_texture") +{ + image_manager = NULL; + slot = -1; + is_float = -1; + is_linear = false; + use_alpha = true; + filename = ""; + builtin_data = NULL; + color_space = ustring("Color"); + projection = ustring("Flat"); + interpolation = INTERPOLATION_LINEAR; + projection_blend = 0.0f; + animated = false; + + add_input("Layer", SHADER_SOCKET_FLOAT); + add_input("Vector", SHADER_SOCKET_POINT); + add_output("Color", SHADER_SOCKET_COLOR); + add_output("Alpha", SHADER_SOCKET_FLOAT); +} + +PtexTextureNode::~PtexTextureNode() +{ + // if(image_manager) + // image_manager->remove_image(filename, builtin_data, interpolation); +} + +ShaderNode *PtexTextureNode::clone() const +{ + PtexTextureNode *node = new PtexTextureNode(*this); + node->image_manager = NULL; + node->slot = -1; + node->is_float = -1; + node->is_linear = false; + return node; +} + +void PtexTextureNode::attributes(Shader *shader, AttributeRequestSet *attributes) +{ +#ifdef WITH_PTEX + /* todo: avoid loading other texture coordinates when using ptex, + * and hide texture coordinate socket in the UI */ + if (shader->has_surface && string_endswith(filename, ".ptx")) { + /* ptex */ + attributes->add(ATTR_STD_PTEX_FACE_ID); + attributes->add(ATTR_STD_PTEX_UV); + } +#endif + + attributes->add(ptex_layer); + attributes->add(ATTR_STD_PTEX_UV); + + ShaderNode::attributes(shader, attributes); +} + +void PtexTextureNode::compile(SVMCompiler& compiler) +{ + ShaderInput *layer_in = input("Layer"); + ShaderInput *vector_in = input("Vector"); + ShaderOutput *color_out = output("Color"); + ShaderOutput *alpha_out = output("Alpha"); + int layer_attr_id = -1; + + + { + // TODO + layer_attr_id = compiler.attribute(ptex_layer); + //compiler.stack_assign(layer_in); + // compiler.add_node(NODE_ATTR, attr, layer_in->stack_offset, + // NODE_ATTR_FLOAT); + } + + { + int attr = compiler.attribute(ATTR_STD_PTEX_UV); + compiler.stack_assign(vector_in); + compiler.add_node(NODE_ATTR, attr, vector_in->stack_offset, + NODE_ATTR_FLOAT3); + } + + image_manager = compiler.image_manager; + + + + // if(slot != -1 && is_float == -1) { + // bool is_float_bool; + // slot = image_manager->add_image(filename, builtin_data, + // animated, 0, is_float_bool, is_linear, + // interpolation, use_alpha); + // is_float = (int)is_float_bool; + // } + + if(!color_out->links.empty()) + compiler.stack_assign(color_out); + if(!alpha_out->links.empty()) + compiler.stack_assign(alpha_out); + + if (true) + { + //if(slot != -1) { + compiler.stack_assign(layer_in); + compiler.stack_assign(vector_in); + + int srgb = (is_linear || color_space != "Color")? 0: 1; + // TODO(nicholasbishop): clean this up of course + int flags = srgb; + if (ptex || string_endswith(filename, ".ptx")) { + flags |= 2; + } + flags |= 4; + int vector_offset = vector_in->stack_offset; + + // if(!tex_mapping.skip()) { + // vector_offset = compiler.stack_find_offset(SHADER_SOCKET_VECTOR); + // tex_mapping.compile(compiler, vector_in->stack_offset, vector_offset); + // } + + if(projection != "Box") { + compiler.add_node(NODE_TEX_IMAGE, + layer_attr_id, + compiler.encode_uchar4( + vector_offset, + color_out->stack_offset, + alpha_out->stack_offset, + flags), + ImageTextureNode::projection_enum[projection]); + } + else { + compiler.add_node(NODE_TEX_IMAGE_BOX, + slot, + compiler.encode_uchar4( + vector_offset, + color_out->stack_offset, + alpha_out->stack_offset, + flags & 1), + __float_as_int(projection_blend)); + } + + if(vector_offset != vector_in->stack_offset) + compiler.stack_clear_offset(vector_in->type, vector_offset); + } + else { + /* image not found */ + if(!color_out->links.empty()) { + compiler.add_node(NODE_VALUE_V, color_out->stack_offset); + compiler.add_node(NODE_VALUE_V, make_float3(TEX_IMAGE_MISSING_R, + TEX_IMAGE_MISSING_G, + TEX_IMAGE_MISSING_B)); + } + if(!alpha_out->links.empty()) + compiler.add_node(NODE_VALUE_F, __float_as_int(TEX_IMAGE_MISSING_A), alpha_out->stack_offset); + } +} + +void PtexTextureNode::compile(OSLCompiler& compiler) +{ + #if 0 + ShaderOutput *alpha_out = output("Alpha"); + + tex_mapping.compile(compiler); + + image_manager = compiler.image_manager; + if(is_float == -1) { + if(builtin_data == NULL) { + is_float = (int)image_manager->is_float_image(filename, NULL, is_linear); + } + else { + bool is_float_bool; + slot = image_manager->add_image(filename, builtin_data, + animated, 0, is_float_bool, is_linear, + interpolation, use_alpha); + is_float = (int)is_float_bool; + } + } + + if(slot == -1) { + compiler.parameter("filename", filename.c_str()); + } + else { + /* TODO(sergey): It's not so simple to pass custom attribute + * to the texture() function in order to make builtin images + * support more clear. So we use special file name which is + * "@<slot_number>" and check whether file name matches this + * mask in the OSLRenderServices::texture(). + */ + compiler.parameter("filename", string_printf("@%d", slot).c_str()); + } + if(is_linear || color_space != "Color") + compiler.parameter("color_space", "Linear"); + else + compiler.parameter("color_space", "sRGB"); + compiler.parameter("projection", projection); + compiler.parameter("projection_blend", projection_blend); + compiler.parameter("is_float", is_float); + compiler.parameter("use_alpha", !alpha_out->links.empty()); + + switch (interpolation) { + case INTERPOLATION_CLOSEST: + compiler.parameter("interpolation", "closest"); + break; + case INTERPOLATION_CUBIC: + compiler.parameter("interpolation", "cubic"); + break; + case INTERPOLATION_SMART: + compiler.parameter("interpolation", "smart"); + break; + case INTERPOLATION_LINEAR: + default: + compiler.parameter("interpolation", "linear"); + break; + } + compiler.add(this, "node_image_texture"); +#endif +} + /* Environment Texture */ static ShaderEnum env_projection_init() diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h index 0ec0fce512f..513fb334ff7 100644 --- a/intern/cycles/render/nodes.h +++ b/intern/cycles/render/nodes.h @@ -80,11 +80,37 @@ public: InterpolationType interpolation; float projection_blend; bool animated; + bool ptex; + ustring ptex_layer; static ShaderEnum color_space_enum; static ShaderEnum projection_enum; }; +// TODO +class PtexTextureNode : public ShaderNode { +public: + SHADER_NODE_NO_CLONE_CLASS(PtexTextureNode) + ~PtexTextureNode(); + ShaderNode *clone() const; + void attributes(Shader *shader, AttributeRequestSet *attributes); + + ImageManager *image_manager; + int slot; + int is_float; + bool is_linear; + bool use_alpha; + string filename; + void *builtin_data; + ustring color_space; + ustring projection; + InterpolationType interpolation; + float projection_blend; + bool animated; + bool ptex; + ustring ptex_layer; +}; + class EnvironmentTextureNode : public TextureNode { public: SHADER_NODE_NO_CLONE_CLASS(EnvironmentTextureNode) diff --git a/intern/cycles/render/scene.h b/intern/cycles/render/scene.h index 53c3a95903c..781d0b4cb7c 100644 --- a/intern/cycles/render/scene.h +++ b/intern/cycles/render/scene.h @@ -108,6 +108,9 @@ public: /* integrator */ device_vector<uint> sobol_directions; + /* ptex */ + device_vector<uint> ptex_table; + /* cpu images */ device_vector<uchar4> tex_image[TEX_EXTENDED_NUM_IMAGES_CPU]; device_vector<float4> tex_float_image[TEX_EXTENDED_NUM_FLOAT_IMAGES]; diff --git a/intern/cycles/util/util_types.h b/intern/cycles/util/util_types.h index df61b6ead21..0951684ab85 100644 --- a/intern/cycles/util/util_types.h +++ b/intern/cycles/util/util_types.h @@ -460,6 +460,12 @@ ccl_device_inline int4 make_int4(const float3& f) #endif +// TODO +typedef uint (*PtexRegions)[4]; +struct PtexRegion { + int x, y, width, height; +}; + /* Interpolation types for textures * cuda also use texture space to store other objects */ enum InterpolationType { |