diff --git a/intern/cycles/CMakeLists.txt b/intern/cycles/CMakeLists.txt index 9b84f882046..44b0ba808cf 100644 --- a/intern/cycles/CMakeLists.txt +++ b/intern/cycles/CMakeLists.txt @@ -62,6 +62,10 @@ if(WITH_CYCLES_NETWORK) add_definitions(-DWITH_NETWORK) endif() +if(WITH_CYCLES_PTEX) + add_definitions(-DWITH_PTEX) +endif() + if(WITH_CYCLES_OSL) add_definitions(-DWITH_OSL) add_definitions(-DOSL_STATIC_LIBRARY) diff --git a/intern/cycles/kernel/osl/osl_services.cpp b/intern/cycles/kernel/osl/osl_services.cpp index 309f5ded96d..d7d3301c0b0 100644 --- a/intern/cycles/kernel/osl/osl_services.cpp +++ b/intern/cycles/kernel/osl/osl_services.cpp @@ -44,6 +44,10 @@ #include "kernel_camera.h" #include "kernel_shader.h" +#ifdef WITH_PTEX +#include +#endif + CCL_NAMESPACE_BEGIN /* RenderServices implementation */ @@ -98,10 +102,18 @@ OSLRenderServices::OSLRenderServices() { kernel_globals = NULL; osl_ts = NULL; + +#ifdef WITH_PTEX + size_t maxmem = 16384 * 1024; + ptex_cache = PtexCache::create(0, maxmem); +#endif } OSLRenderServices::~OSLRenderServices() { +#ifdef WITH_PTEX + ptex_cache->release(); +#endif } void OSLRenderServices::thread_init(KernelGlobals *kernel_globals_, OSL::TextureSystem *osl_ts_) @@ -776,6 +788,45 @@ bool OSLRenderServices::texture(ustring filename, TextureOpt &options, OSL::TextureSystem *ts = osl_ts; ShaderData *sd = (ShaderData *)(sg->renderstate); KernelGlobals *kg = sd->osl_globals; + +#ifdef WITH_PTEX + /* todo: this is just a quick hack, only works with particular files and options */ + if(string_endswith(filename.string(), ".ptx")) { + float2 uv; + int faceid; + + if(!primitive_ptex(kg, sd, &uv, &faceid)) + return false; + + float u = uv.x; + float v = uv.y; + float dudx = 0.0f; + float dvdx = 0.0f; + float dudy = 0.0f; + float dvdy = 0.0f; + + Ptex::String error; + PtexPtr r(ptex_cache->get(filename.c_str(), error)); + + if(!r) { + //std::cerr << error.c_str() << std::endl; + return false; + } + + bool mipmaplerp = false; + float sharpness = 1.0f; + PtexFilter::Options opts(PtexFilter::f_bicubic, mipmaplerp, sharpness); + PtexPtr f(PtexFilter::getFilter(r, opts)); + + f->eval(result, options.firstchannel, options.nchannels, faceid, u, v, dudx, dvdx, dudy, dvdy); + + for(int c = r->numChannels(); c < options.nchannels; c++) + result[c] = result[0]; + + return true; + } +#endif + OSLThreadData *tdata = kg->osl_tdata; OIIO::TextureSystem::Perthread *thread_info = tdata->oiio_thread_info; diff --git a/intern/cycles/kernel/osl/osl_services.h b/intern/cycles/kernel/osl/osl_services.h index f62895047b3..21609621b1d 100644 --- a/intern/cycles/kernel/osl/osl_services.h +++ b/intern/cycles/kernel/osl/osl_services.h @@ -28,6 +28,10 @@ #include #include +#ifdef WITH_PTEX +class PtexCache; +#endif + CCL_NAMESPACE_BEGIN class Object; @@ -148,6 +152,9 @@ public: private: KernelGlobals *kernel_globals; OSL::TextureSystem *osl_ts; +#ifdef WITH_PTEX + PtexCache *ptex_cache; +#endif }; CCL_NAMESPACE_END diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp index daf75c81396..fcc92b641fd 100644 --- a/intern/cycles/render/nodes.cpp +++ b/intern/cycles/render/nodes.cpp @@ -217,6 +217,21 @@ ShaderNode *ImageTextureNode::clone() const return node; } +void ImageTextureNode::attributes(AttributeRequestSet *attributes) +{ +#ifdef WITH_PTEX + /* todo: avoid loading other texture coordinates when using ptex, + * and hide texture coordinate socket in the UI */ + if (string_endswith(filename, ".ptx")) { + /* ptex */ + attributes->add(ATTR_STD_PTEX_FACE_ID); + attributes->add(ATTR_STD_PTEX_UV); + } +#endif + + ShaderNode::attributes(attributes); +} + void ImageTextureNode::compile(SVMCompiler& compiler) { ShaderInput *vector_in = input("Vector"); @@ -352,6 +367,19 @@ ShaderNode *EnvironmentTextureNode::clone() const return node; } +void EnvironmentTextureNode::attributes(AttributeRequestSet *attributes) +{ +#ifdef WITH_PTEX + if (string_endswith(filename, ".ptx")) { + /* ptex */ + attributes->add(ATTR_STD_PTEX_FACE_ID); + attributes->add(ATTR_STD_PTEX_UV); + } +#endif + + ShaderNode::attributes(attributes); +} + void EnvironmentTextureNode::compile(SVMCompiler& compiler) { ShaderInput *vector_in = input("Vector"); diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h index 430c37158f4..d7a110af83b 100644 --- a/intern/cycles/render/nodes.h +++ b/intern/cycles/render/nodes.h @@ -66,6 +66,7 @@ public: SHADER_NODE_NO_CLONE_CLASS(ImageTextureNode) ~ImageTextureNode(); ShaderNode *clone() const; + void attributes(AttributeRequestSet *attributes); ImageManager *image_manager; int slot; @@ -87,6 +88,7 @@ public: SHADER_NODE_NO_CLONE_CLASS(EnvironmentTextureNode) ~EnvironmentTextureNode(); ShaderNode *clone() const; + void attributes(AttributeRequestSet *attributes); ImageManager *image_manager; int slot; diff --git a/intern/cycles/util/util_string.cpp b/intern/cycles/util/util_string.cpp index 53603c54da0..c4a81fc7190 100644 --- a/intern/cycles/util/util_string.cpp +++ b/intern/cycles/util/util_string.cpp @@ -86,5 +86,15 @@ void string_split(vector& tokens, const string& str, const string& separ tokens.push_back(token); } +bool string_endswith(const string& s, const char *end) +{ + size_t len = strlen(end); + + if(len > s.size()) + return 0; + else + return strncmp(s.c_str() + s.size() - len, end, len) == 0; +} + CCL_NAMESPACE_END diff --git a/intern/cycles/util/util_string.h b/intern/cycles/util/util_string.h index ee924340716..2d63a075e71 100644 --- a/intern/cycles/util/util_string.h +++ b/intern/cycles/util/util_string.h @@ -40,6 +40,7 @@ string string_printf(const char *format, ...) PRINTF_ATTRIBUTE; bool string_iequals(const string& a, const string& b); void string_split(vector& tokens, const string& str, const string& separators = "\t "); +bool string_endswith(const string& s, const char *end); CCL_NAMESPACE_END