[Bf-blender-cvs] [9e50469] cycles-ptex-06: Checkpoint

Nicholas Bishop noreply at git.blender.org
Thu Jan 15 20:13:19 CET 2015


Commit: 9e5046980fbbf0f9c6884d13f8fa792f27104806
Author: Nicholas Bishop
Date:   Tue Jan 13 10:42:03 2015 +0100
Branches: cycles-ptex-06
https://developer.blender.org/rB9e5046980fbbf0f9c6884d13f8fa792f27104806

Checkpoint

===================================================================

M	intern/cycles/blender/blender_mesh.cpp
M	intern/cycles/kernel/kernel_textures.h
M	intern/cycles/kernel/svm/svm_image.h
M	intern/cycles/render/image.cpp
M	intern/cycles/render/image.h
M	intern/cycles/render/scene.h

===================================================================

diff --git a/intern/cycles/blender/blender_mesh.cpp b/intern/cycles/blender/blender_mesh.cpp
index 561a4d0..60e9fcb 100644
--- a/intern/cycles/blender/blender_mesh.cpp
+++ b/intern/cycles/blender/blender_mesh.cpp
@@ -430,18 +430,29 @@ static void create_mesh(Scene *scene, Mesh *mesh, BL::Mesh b_mesh, const vector<
 				float3 *fdata = attr->data_float3();
 				size_t i = 0;
 
+				b_mesh.tessfaces.begin(f);
 				for(l->data.begin(t); t != l->data.end(); ++t, ++i) {
+					const float ptex_face_id = (float)f->ptex_face_index();
+
 					fdata[0] =  get_float3(t->uv1());
 					fdata[1] =  get_float3(t->uv2());
 					fdata[2] =  get_float3(t->uv3());
+					fdata[0].z = (float)ptex_face_id;
+					fdata[1].z = (float)ptex_face_id;
+					fdata[2].z = (float)ptex_face_id;
 					fdata += 3;
 
 					if(nverts[i] == 4) {
 						fdata[0] =  get_float3(t->uv1());
 						fdata[1] =  get_float3(t->uv3());
 						fdata[2] =  get_float3(t->uv4());
+						fdata[0].z = (float)ptex_face_id;
+						fdata[1].z = (float)ptex_face_id;
+						fdata[2].z = (float)ptex_face_id;
 						fdata += 3;
 					}
+
+					++f;
 				}
 			}
 
diff --git a/intern/cycles/kernel/kernel_textures.h b/intern/cycles/kernel/kernel_textures.h
index 374dc6d..ca2da1f 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/svm/svm_image.h b/intern/cycles/kernel/svm/svm_image.h
index 9948a19..6cafa52 100644
--- a/intern/cycles/kernel/svm/svm_image.h
+++ b/intern/cycles/kernel/svm/svm_image.h
@@ -354,6 +354,37 @@ ccl_device float4 svm_image_texture(KernelGlobals *kg, int id, float x, float y,
 
 #endif
 
+// Adapted from GPU Pro 4 Listing 2.2
+ccl_device float2 ptex_compute_uv(uint face_id,
+								  float2 face_uv,
+								  uint nlog2,
+								  uint tex_width,
+								  uint tex_height,
+								  uint res_offset,
+								  uint row_offset,
+								  uint border_size)
+{
+	float face_width = 1 << nlog2;
+	// TODO
+	float face_height = face_width;
+	float bordered_face_width = face_width + 2 * border_size;
+	float bordered_face_height = bordered_face_width;
+
+	int faces_per_row = (int)tex_width / (int)bordered_face_width;
+	int face_index_in_block = face_id - res_offset;
+
+	float2 face_origin =
+		make_float2((face_index_in_block % faces_per_row) * bordered_face_width,
+					(face_index_in_block / faces_per_row) * bordered_face_height +
+					row_offset);
+
+	float2 uv = make_float2(face_width, face_height) * face_uv;
+	uv += make_float2(border_size, border_size);
+	uv += face_origin;
+
+	return uv / make_float2(tex_width, tex_height);
+}
+
 ccl_device void svm_node_tex_image(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node)
 {
 	uint id = node.y;
@@ -363,7 +394,35 @@ ccl_device void svm_node_tex_image(KernelGlobals *kg, ShaderData *sd, float *sta
 
 	float3 co = stack_load_float3(stack, co_offset);
 	uint use_alpha = stack_valid(alpha_offset);
-	float4 f = svm_image_texture(kg, id, co.x, co.y, srgb, use_alpha);
+
+	// TODO: test hacks for Ptex
+	uint face_id = (uint)co[2];
+	uint offset = kernel_tex_fetch(__ptex_table, id);
+	float tex_width = (float)kernel_tex_fetch(__ptex_table, offset);
+	offset++;
+	float tex_height = (float)kernel_tex_fetch(__ptex_table, offset);
+	offset++;
+	offset += 3 * face_id;
+	uint origin_x = kernel_tex_fetch(__ptex_table, offset);
+	offset++;
+	uint origin_y = kernel_tex_fetch(__ptex_table, offset);
+	offset++;
+	uint ures = kernel_tex_fetch(__ptex_table, offset);
+	offset++;
+	uint vres = kernel_tex_fetch(__ptex_table, offset);
+	offset++;
+
+	float xco = (float)origin_x + co.x * ures;
+	float yco = (float)origin_y + co.y * ures;
+
+	float uco = (float)xco / tex_width;
+	float vco = (float)yco / tex_height;
+
+	float4 f = svm_image_texture(kg, id, uco, vco, srgb, use_alpha);
+	f.x = co[0];
+	f.y = co[1];
+	f.z = 0;
+	//float4 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/image.cpp b/intern/cycles/render/image.cpp
index 61a0a81..ef69ba0 100644
--- a/intern/cycles/render/image.cpp
+++ b/intern/cycles/render/image.cpp
@@ -27,8 +27,182 @@
 #include <OSL/oslexec.h>
 #endif
 
+#ifdef WITH_PTEX
+#include <Ptexture.h>
+#endif
+
 CCL_NAMESPACE_BEGIN
 
+struct PtexXY {
+	uint x, y;
+	uint ures, vres;
+};
+
+typedef std::map<int, PtexXY> PtexCoordMap;
+
+struct PtexPackedTexture {
+	PtexPackedTexture() : width(0), height(0) {}
+
+	vector<uint8_t> texels;
+
+	PtexCoordMap face_coord_map;
+
+	int width;
+	int height;
+
+	int num_channels;
+
+	void test_write() {
+		// Quick test to visually examine the packed output
+		const char *filename = "/tmp/packed.png";
+		ImageOutput *out = ImageOutput::create(filename);
+		if (out) {
+			ImageSpec spec(width, height, num_channels, TypeDesc::UINT8);
+			out->open(filename, spec);
+			out->write_image(TypeDesc::UINT8, texels.data());
+			std::cout << "ptex test written: " << filename << std::endl;
+			out->close();
+		}
+	}
+};
+
+struct OrdVal {
+	vector<int> face_ids;
+	int elem_width;
+	int elem_per_row;
+	int num_rows;
+	int ures, vres;
+};
+
+static int ptex_data_type_size_in_bytes(const Ptex::DataType dt)
+{
+	switch (dt) {
+		case Ptex::dt_uint8:
+			return 1;
+		case Ptex::dt_uint16:
+			return 2;
+		case Ptex::dt_half:
+			return 2;
+		case Ptex::dt_float:
+			return 4;
+	}
+
+	// Error
+	return 0;
+}
+
+// TODO
+static bool ptex_pack(PtexPackedTexture *output, const char *path,
+					  const int width, PtexCache *ptex_cache) {
+	Ptex::String error;
+	PtexPtr<PtexTexture> r(ptex_cache->get(path, error));
+
+	if(!r) {
+		std::cerr << error.c_str() << std::endl;
+		return false;
+	}
+
+	// TODO: for now packing all faces as squares
+
+	// Sorted, res -> face_id array. int8_t matches Ptex api
+	
+	typedef std::map<int, OrdVal> Ord;
+	Ord ord;
+
+	const uint border = 1;
+
+	const int num_faces = r->numFaces();
+	for (int face_index = 0; face_index < num_faces; face_index++) {
+		const Ptex::FaceInfo &face_info = r->getFaceInfo(face_index);
+		const Ptex::Res &res = face_info.res;
+		const int larger = std::max(res.u(), res.v());
+		if (ord.find(larger) == ord.end()) {
+			ord[larger] = OrdVal();
+		}
+
+		ord[larger].face_ids.push_back(face_index);
+
+		ord[larger].ures = res.u() + 2 * border;
+		ord[larger].vres = res.v() + 2 * border;
+	}
+
+	// TODO: for now only packing mipmap level zero
+
+	// Calc size
+	output->width = width;
+	output->height = 0;
+	for (Ord::iterator iter = ord.begin(); iter != ord.end(); ++iter) {
+		OrdVal &val = iter->second;
+		const int res = iter->first;
+
+		val.elem_width = border + res + border;
+		val.elem_per_row = output->width / val.elem_width;
+		const int num_elem = val.face_ids.size();
+
+		val.num_rows = num_elem / val.elem_per_row;
+		if ((num_elem % val.elem_per_row) != 0) {
+			val.num_rows += 1;
+		}
+
+		output->height += val.elem_width * val.num_rows;
+	}
+
+	
+	const int type_size_in_bytes = ptex_data_type_size_in_bytes(r->dataType());
+	const int texel_size_in_bytes = r->numChannels() * type_size_in_bytes;
+
+	output->num_channels = r->numChannels();
+	
+	output->texels.resize(output->width * output->height *
+						  texel_size_in_bytes);
+
+	// Copy face textures
+	uint dst_y = 0;
+	bool yinc = false;
+
+	const int dst_stride = output->width * texel_size_in_bytes;
+	for (Ord::const_iterator iter = ord.begin(); iter != ord.end(); ++iter) {
+		const OrdVal &val = iter->second;
+		const int num_elem = val.face_ids.size();
+		int column = 0;
+		uint dst_x = 0;
+
+		for (int i = 0; i < num_elem; i++) {
+			const int face_id = val.face_ids[i];
+
+			PtexXY coord = {dst_x + border, dst_y + border, (uint)val.ures, (uint)val.vres};
+			output->face_coord_map[face_id] = coord;
+
+			const int dst_offset = ((coord.y * output->width + coord.x) *
+									texel_size_in_bytes);
+
+			r->getData(face_id,
+					   output->texels.data() + dst_offset,
+					   dst_stride);
+
+			// TODO: have to fill in borders too...
+
+			dst_x += val.elem_width;
+			yinc = true;
+
+			column += 1;
+			if (column == val.elem_per_row) {
+				column = 0;
+				dst_x = 0;
+				dst_y += val.elem_width;
+				yinc = false;
+			}
+		}
+
+		if (yinc) {
+			dst_y += val.elem_width;
+			yinc = false;
+		}
+	}
+
+	return true;
+}
+
 ImageManager::ImageManager()
 {
 	need_update = true;
@@ -39,6 +213,11 @@ ImageManager::ImageManager()
 	tex_num_images = TEX_NUM_IMAGES;
 	tex_num_float_images = TEX_NUM_FLOAT_IMAGES;
 	tex_image_byte_start = TEX_IMAGE_BYTE_START;
+
+#ifdef WITH_PTEX
+	size_t maxmem = 16384 * 1024;
+	ptex_cache = PtexCache::create(0, maxmem);
+#endif
 }
 
 ImageManager::~ImageManager()
@@ -348,7 +527,8 @@ void ImageManager::tag_reload_image(const string& filename, void *builtin_data,
 	}
 }
 
-bool ImageManager::file_load_image(Image *img, device_vector<uchar4>& tex_img)
+bool ImageManager::file_load_image(Image *img, device_vector<uchar4>& tex_img,
+								   DeviceScene *dscene, int slot)
 {
 	if(img->filename == "")
 		return false;
@@ -356,7 +536,24 @@ bool ImageManager::file_load_image(Image *img, device_vector<uchar4>& tex_img)
 	ImageInput *in = NULL;
 	int width, height, depth, components;
 
-	if(!img->builtin_data) {
+	PtexPackedTexture ptex_packed_texture;
+	bool use_ptex = false;
+	if(string_endswith(img->filename, ".ptx")) {
+		// Arbitrary choice for now...
+		width = 1 << 10;
+
+		ptex_pack(&ptex_packed_texture, img->filename.c_str(),
+				  width, ptex_cache);
+
+		ptex_packed_texture.test_write();
+
+		height = ptex_packed_texture.height;
+		depth = 1;
+		components = ptex_packed_texture.num_channels;
+
+		use_ptex = true;
+	}
+	else if(!img->builtin_data) {
 		/* load image from file through OIIO */
 		in = ImageInput::create(img->filename);
 
@@ -421,6 +618,42 @@ bool ImageManager::file_load_image(

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list