Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'intern/cycles')
-rw-r--r--intern/cycles/CMakeLists.txt3
-rw-r--r--intern/cycles/SConscript5
-rw-r--r--intern/cycles/blender/addon/ui.py1
-rw-r--r--intern/cycles/blender/blender_mesh.cpp110
-rw-r--r--intern/cycles/blender/blender_session.cpp21
-rw-r--r--intern/cycles/blender/blender_session.h5
-rw-r--r--intern/cycles/blender/blender_shader.cpp12
-rw-r--r--intern/cycles/kernel/kernel_textures.h5
-rw-r--r--intern/cycles/kernel/kernel_types.h1
-rw-r--r--intern/cycles/kernel/osl/osl_services.cpp8
-rw-r--r--intern/cycles/kernel/svm/svm_image.h51
-rw-r--r--intern/cycles/render/attribute.cpp7
-rw-r--r--intern/cycles/render/image.cpp150
-rw-r--r--intern/cycles/render/image.h9
-rw-r--r--intern/cycles/render/nodes.cpp233
-rw-r--r--intern/cycles/render/nodes.h26
-rw-r--r--intern/cycles/render/scene.h3
-rw-r--r--intern/cycles/util/util_types.h2
18 files changed, 609 insertions, 43 deletions
diff --git a/intern/cycles/CMakeLists.txt b/intern/cycles/CMakeLists.txt
index 2ba6af48d0d..a893b9dd12d 100644
--- a/intern/cycles/CMakeLists.txt
+++ b/intern/cycles/CMakeLists.txt
@@ -129,8 +129,9 @@ if(WITH_CYCLES_STANDALONE_GUI)
add_definitions(-DWITH_CYCLES_STANDALONE_GUI)
endif()
-if(WITH_CYCLES_PTEX)
+if(WITH_PTEX)
add_definitions(-DWITH_PTEX)
+ include_directories("../../extern/ptex")
endif()
if(WITH_CYCLES_OPENSUBDIV)
diff --git a/intern/cycles/SConscript b/intern/cycles/SConscript
index 9cbdb93ce85..33f1ac87ef9 100644
--- a/intern/cycles/SConscript
+++ b/intern/cycles/SConscript
@@ -81,8 +81,13 @@ incs.append(env['BF_GLEW_INC'])
incs.append('#/intern/glew-mx')
incs.append('#/intern/atomic')
incs.append('#intern/mikktspace')
+if env['WITH_BF_PTEX']:
+ incs.append('#/extern/ptex')
incs.extend('#extern/glew/include #extern/clew/include #extern/cuew/include #intern/mikktspace'.split())
+if env['WITH_BF_PTEX']:
+ defs.append('WITH_PTEX')
+
incs.append(cycles['BF_OIIO_INC'])
incs.append(cycles['BF_BOOST_INC'])
incs.append(cycles['BF_OPENEXR_INC'].split())
diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py
index 651114a12dc..cd8b3c6677a 100644
--- a/intern/cycles/blender/addon/ui.py
+++ b/intern/cycles/blender/addon/ui.py
@@ -1409,6 +1409,7 @@ def get_panels():
"DATA_PT_context_speaker",
"DATA_PT_normals",
"DATA_PT_texture_space",
+ "DATA_PT_ptex",
"DATA_PT_curve_texture_space",
"DATA_PT_mball_texture_space",
"DATA_PT_vertex_groups",
diff --git a/intern/cycles/blender/blender_mesh.cpp b/intern/cycles/blender/blender_mesh.cpp
index a5664fa2800..613d17120dd 100644
--- a/intern/cycles/blender/blender_mesh.cpp
+++ b/intern/cycles/blender/blender_mesh.cpp
@@ -260,6 +260,83 @@ static void create_mesh_volume_attributes(Scene *scene, BL::Object b_ob, Mesh *m
/* Create Mesh */
+static const int quad_split_pattern[2][2][3] = {
+ /* Note that first pattern is the one used for triangle inputs */
+ {{0, 1, 2}, {0, 2, 3}},
+ {{0, 1, 3}, {2, 3, 1}}
+};
+
+static int quad_split_pattern_index(const float3 &a,
+ const float3 &b,
+ const float3 &c,
+ const float3 &d)
+{
+ if (is_zero(cross(b - a, c - a)) || is_zero(cross(c - a, d - a))) {
+ return 1;
+ }
+ else {
+ return 0;
+ }
+}
+
+static void mesh_add_ptex_face_attributes(Mesh *mesh, BL::Mesh b_mesh,
+ const vector<int> &nverts,
+ const vector<int> &face_split_pattern)
+{
+ BL::Mesh::tessfaces_iterator f;
+ Attribute *face_id_attr = mesh->attributes.add(ATTR_STD_PTEX_UV);
+ mesh->attributes.reserve();
+
+ float3 (*dst)[3] = (float3(*)[3])face_id_attr->data_float3();
+ size_t cur_tri = 0;
+ size_t cur_tessface = 0;
+
+ for (b_mesh.tessfaces.begin(f); f != b_mesh.tessfaces.end(); ++f) {
+ BL::PtexTessFace ptex = f->ptex_tess_face();
+ if (!ptex) break;
+ const int num_triangles = (nverts[cur_tessface] == 4) ? 2 : 1;
+ const int spi = face_split_pattern[cur_tessface];
+
+ for (int i = 0; i < num_triangles; i++) {
+ for (int j = 0; j < 3; j++) {
+ const int ci = quad_split_pattern[spi][i][j];
+
+ dst[cur_tri][j] = make_float3(ptex.uv()[ci * 2 + 0],
+ ptex.uv()[ci * 2 + 1],
+ ptex.id());
+ }
+ cur_tri++;
+ }
+
+ cur_tessface++;
+ }
+}
+
+static void mesh_add_ptex_layer_data(Scene *scene, Mesh *mesh, BL::Mesh b_mesh)
+{
+ BL::Mesh::loop_ptex_iterator l;
+ for (b_mesh.loop_ptex.begin(l); l != b_mesh.loop_ptex.end(); ++l) {
+ const ustring layer_name = ustring(l->name());
+ if (mesh->need_attribute(scene, layer_name)) {
+ Attribute *attr = mesh->attributes.add(layer_name,
+ TypeDesc::TypeFloat,
+ ATTR_ELEMENT_MESH);
+ //mesh->attributes.reserve();
+ float *slot = attr->data_float();
+ bool is_float;
+ bool is_linear;
+ // TODO
+
+ BL::Image image = l->image();
+
+ // Other alternative is: get data, pack new image here
+ (*slot) = scene->image_manager->add_image
+ ("TODO", image.ptr.data, false, 1,
+ is_float, is_linear, INTERPOLATION_LINEAR, true);
+ }
+ }
+}
+
static void create_mesh(Scene *scene, Mesh *mesh, BL::Mesh b_mesh, const vector<uint>& used_shaders)
{
/* count vertices and faces */
@@ -307,6 +384,7 @@ static void create_mesh(Scene *scene, Mesh *mesh, BL::Mesh b_mesh, const vector<
/* create faces */
vector<int> nverts(numfaces);
+ vector<int> face_split_pattern(numfaces);
int fi = 0, ti = 0;
for(b_mesh.tessfaces.begin(f); f != b_mesh.tessfaces.end(); ++f, ++fi) {
@@ -338,24 +416,32 @@ static void create_mesh(Scene *scene, Mesh *mesh, BL::Mesh b_mesh, const vector<
}
/* create triangles */
+ int spi;
if(n == 4) {
- if(is_zero(cross(mesh->verts[vi[1]] - mesh->verts[vi[0]], mesh->verts[vi[2]] - mesh->verts[vi[0]])) ||
- is_zero(cross(mesh->verts[vi[2]] - mesh->verts[vi[0]], mesh->verts[vi[3]] - mesh->verts[vi[0]])))
- {
- mesh->set_triangle(ti++, vi[0], vi[1], vi[3], shader, smooth);
- mesh->set_triangle(ti++, vi[2], vi[3], vi[1], shader, smooth);
- }
- else {
- mesh->set_triangle(ti++, vi[0], vi[1], vi[2], shader, smooth);
- mesh->set_triangle(ti++, vi[0], vi[2], vi[3], shader, smooth);
- }
+ spi = quad_split_pattern_index(mesh->verts[vi[0]],
+ mesh->verts[vi[1]],
+ mesh->verts[vi[2]],
+ mesh->verts[vi[3]]);
+
+ }
+ else {
+ spi = 0;
+ }
+ face_split_pattern[fi] = spi;
+
+ for (int i = 0; i < (n == 4 ? 2 : 1); i++) {
+ const int *c = quad_split_pattern[spi][i];
+ mesh->set_triangle(ti++, vi[c[0]], vi[c[1]], vi[c[2]],
+ shader, smooth);
}
- else
- mesh->set_triangle(ti++, vi[0], vi[1], vi[2], shader, smooth);
nverts[fi] = n;
}
+ /* Add Ptex data if needed */
+ mesh_add_ptex_face_attributes(mesh, b_mesh, nverts, face_split_pattern);
+ mesh_add_ptex_layer_data(scene, mesh, b_mesh);
+
/* create vertex color attributes */
{
BL::Mesh::tessface_vertex_colors_iterator l;
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..29cbee7731e 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)
@@ -172,9 +175,9 @@ KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_094)
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_095)
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_096)
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_097)
-KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_098)
/* Kepler and above */
+KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_098)
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_099)
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_100)
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_101)
diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h
index 680094dcd0e..54aa2f478b9 100644
--- a/intern/cycles/kernel/kernel_types.h
+++ b/intern/cycles/kernel/kernel_types.h
@@ -535,6 +535,7 @@ typedef enum AttributeStandard {
ATTR_STD_VOLUME_HEAT,
ATTR_STD_VOLUME_VELOCITY,
ATTR_STD_POINTINESS,
+ ATTR_STD_PTEX_LAYER,
ATTR_STD_NUM,
ATTR_STD_NOT_FOUND = ~0
diff --git a/intern/cycles/kernel/osl/osl_services.cpp b/intern/cycles/kernel/osl/osl_services.cpp
index 1f6015d0d6b..eddf86ca5c5 100644
--- a/intern/cycles/kernel/osl/osl_services.cpp
+++ b/intern/cycles/kernel/osl/osl_services.cpp
@@ -50,7 +50,7 @@
#include "kernel_accumulate.h"
#include "kernel_shader.h"
-#ifdef WITH_PTEX
+#ifdef WITH_PTEX_OSL
#include <Ptexture.h>
#endif
@@ -115,7 +115,7 @@ OSLRenderServices::OSLRenderServices()
kernel_globals = NULL;
osl_ts = NULL;
-#ifdef WITH_PTEX
+#ifdef WITH_PTEX_OSL
size_t maxmem = 16384 * 1024;
ptex_cache = PtexCache::create(0, maxmem);
#endif
@@ -123,7 +123,7 @@ OSLRenderServices::OSLRenderServices()
OSLRenderServices::~OSLRenderServices()
{
-#ifdef WITH_PTEX
+#ifdef WITH_PTEX_OSL
ptex_cache->release();
#endif
}
@@ -848,7 +848,7 @@ bool OSLRenderServices::texture(ustring filename, TextureOpt &options,
ShaderData *sd = (ShaderData *)(sg->renderstate);
KernelGlobals *kg = sd->osl_globals;
-#ifdef WITH_PTEX
+#ifdef WITH_PTEX_OSL
/* todo: this is just a quick hack, only works with particular files and options */
if(string_endswith(filename.string(), ".ptx")) {
float2 uv;
diff --git a/intern/cycles/kernel/svm/svm_image.h b/intern/cycles/kernel/svm/svm_image.h
index e667fc2033d..f168f69306e 100644
--- a/intern/cycles/kernel/svm/svm_image.h
+++ b/intern/cycles/kernel/svm/svm_image.h
@@ -251,9 +251,9 @@ ccl_device float4 svm_image_texture(KernelGlobals *kg, int id, float x, float y,
case 95: r = kernel_tex_image_interp(__tex_image_095, x, y); break;
case 96: r = kernel_tex_image_interp(__tex_image_096, x, y); break;
case 97: r = kernel_tex_image_interp(__tex_image_097, x, y); break;
- case 98: r = kernel_tex_image_interp(__tex_image_098, x, y); break;
#if defined(__CUDA_ARCH__) && (__CUDA_ARCH__ >= 300)
+ case 98: r = kernel_tex_image_interp(__tex_image_098, x, y); break;
case 99: r = kernel_tex_image_interp(__tex_image_099, x, y); break;
case 100: r = kernel_tex_image_interp(__tex_image_100, x, y); break;
case 101: r = kernel_tex_image_interp(__tex_image_101, x, y); break;
@@ -377,7 +377,54 @@ 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) {
+ // TODO: test hacks for Ptex
+ uint face_id = (uint)(co.z + 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 656420f5dbc..22fe2075148 100644
--- a/intern/cycles/render/attribute.cpp
+++ b/intern/cycles/render/attribute.cpp
@@ -232,6 +232,8 @@ const char *Attribute::standard_name(AttributeStandard std)
return "velocity";
case ATTR_STD_POINTINESS:
return "pointiness";
+ case ATTR_STD_PTEX_LAYER:
+ return "ptex_layer";
case ATTR_STD_NOT_FOUND:
case ATTR_STD_NONE:
case ATTR_STD_NUM:
@@ -361,7 +363,7 @@ Attribute *AttributeSet::add(AttributeStandard std, ustring name)
attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_FACE);
break;
case ATTR_STD_PTEX_UV:
- attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_VERTEX);
+ attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CORNER);
break;
case ATTR_STD_GENERATED_TRANSFORM:
attr = add(name, TypeDesc::TypeMatrix, ATTR_ELEMENT_MESH);
@@ -380,6 +382,9 @@ Attribute *AttributeSet::add(AttributeStandard std, ustring name)
case ATTR_STD_POINTINESS:
attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_VERTEX);
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..144a83714f3 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_ptex.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,88 @@ void ImageManager::tag_reload_image(const string& filename, void *builtin_data,
}
}
-bool ImageManager::file_load_image(Image *img, device_vector<uchar4>& tex_img)
+#ifdef WITH_PTEX
+// 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 BPXPackedLayout *layout,
+ void *c)
+{
+ PtexPackUcharContext &context = *static_cast<PtexPackUcharContext*>(c);
+ const int width = BPX_packed_layout_width(layout);
+ const int height = BPX_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 (BPX_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);
+}
+#else
+static PtexRegions ptex_table_reserve(DeviceScene *dscene,
+ const int texture_slot,
+ const int texture_width,
+ const int texture_height,
+ const int num_ptex_regions)
+{
+ return NULL;
+}
+#endif
+
+bool ImageManager::file_load_image(Image *img, device_vector<uchar4>& tex_img,
+ DeviceScene *dscene, int slot)
{
if(img->filename == "")
return false;
@@ -356,6 +442,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 +462,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 +479,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 +493,33 @@ 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) {
+#ifdef WITH_PTEX
+ 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
+ delete in;
+ in = NULL;
+#endif
+ } else {
+ pixels = (uchar*)tex_img.resize(width, height, depth);
+ }
+
if(in) {
if(depth <= 1) {
int scanlinesize = width*components*sizeof(uchar);
@@ -421,8 +539,16 @@ 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 +635,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 +802,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 +915,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 +992,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..44628621191 100644
--- a/intern/cycles/render/image.h
+++ b/intern/cycles/render/image.h
@@ -29,7 +29,7 @@
CCL_NAMESPACE_BEGIN
/* generic */
-#define TEX_NUM_IMAGES 94
+#define TEX_NUM_IMAGES 93
#define TEX_IMAGE_BYTE_START TEX_NUM_FLOAT_IMAGES
/* extended gpu */
@@ -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 46c962b16c3..aaf8d1d09d3 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,13 @@ 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);
+ }
+
image_manager = compiler.image_manager;
if(is_float == -1) {
bool is_float_bool;
@@ -261,6 +273,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 +292,7 @@ void ImageTextureNode::compile(SVMCompiler& compiler)
vector_offset,
color_out->stack_offset,
alpha_out->stack_offset,
- srgb),
+ flags),
projection_enum[projection]);
}
else {
@@ -285,7 +302,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 +381,218 @@ 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);
+}
+
+static NodeType node_attr_from_bump(const ShaderBump bump)
+{
+ if(bump == SHADER_BUMP_DX) {
+ return NODE_ATTR_BUMP_DX;
+ }
+ else if(bump == SHADER_BUMP_DY) {
+ return NODE_ATTR_BUMP_DY;
+ }
+ else {
+ return NODE_ATTR;
+ }
+}
+
+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");
+
+ const int layer_attr_id = compiler.attribute(ptex_layer);
+
+ {
+ int attr = compiler.attribute(ATTR_STD_PTEX_UV);
+ compiler.stack_assign(vector_in);
+
+ compiler.add_node(node_attr_from_bump(bump), attr,
+ vector_in->stack_offset, NODE_ATTR_FLOAT3);
+ }
+
+ image_manager = compiler.image_manager;
+
+ if(!color_out->links.empty())
+ compiler.stack_assign(color_out);
+ if(!alpha_out->links.empty())
+ compiler.stack_assign(alpha_out);
+
+ // TODO
+ 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..3ec8fd269a1 100644
--- a/intern/cycles/util/util_types.h
+++ b/intern/cycles/util/util_types.h
@@ -460,6 +460,8 @@ ccl_device_inline int4 make_int4(const float3& f)
#endif
+typedef uint (*PtexRegions)[4];
+
/* Interpolation types for textures
* cuda also use texture space to store other objects */
enum InterpolationType {