From 0ce3a755f83b047f49f78da1729a73b56b9c9d55 Mon Sep 17 00:00:00 2001 From: Thomas Dinges Date: Fri, 13 Jun 2014 23:40:39 +0200 Subject: Cycles: Add support for uchar4 attributes. * Added support for uchar4 attributes to Cycles' attribute system. * This is used for Vertex Colors now, which saves some memory (4 unsigned characters, instead of 4 floats). * GPU Texture Limit on sm_20 and sm_21 decreased from 95 to 94, because we need a new texture for the uchar4 attributes. This is no problem for sm_30 or newer. Part of my GSoC 2014. --- intern/cycles/blender/blender_curves.cpp | 25 ++++++++++++------------- intern/cycles/blender/blender_mesh.cpp | 20 ++++++++++---------- intern/cycles/kernel/geom/geom_triangle.h | 17 +++++++++++++---- intern/cycles/kernel/kernel_textures.h | 1 + intern/cycles/kernel/kernel_types.h | 1 + intern/cycles/kernel/svm/svm_image.h | 2 +- intern/cycles/render/attribute.cpp | 10 ++++++++++ intern/cycles/render/attribute.h | 2 ++ intern/cycles/render/image.h | 2 +- intern/cycles/render/mesh.cpp | 22 ++++++++++++++++++---- intern/cycles/render/scene.h | 1 + intern/cycles/util/util_color.h | 21 +++++++++++++++++++++ 12 files changed, 91 insertions(+), 33 deletions(-) (limited to 'intern') diff --git a/intern/cycles/blender/blender_curves.cpp b/intern/cycles/blender/blender_curves.cpp index 22de7b64273..7b1a8ec0b15 100644 --- a/intern/cycles/blender/blender_curves.cpp +++ b/intern/cycles/blender/blender_curves.cpp @@ -42,7 +42,7 @@ void ExportCurveSegments(Scene *scene, Mesh *mesh, ParticleCurveData *CData); void ExportCurveTrianglePlanes(Mesh *mesh, ParticleCurveData *CData, float3 RotCam); void ExportCurveTriangleGeometry(Mesh *mesh, ParticleCurveData *CData, int resolution); void ExportCurveTriangleUV(Mesh *mesh, ParticleCurveData *CData, int vert_offset, int resol, float3 *uvdata); -void ExportCurveTriangleVcol(Mesh *mesh, ParticleCurveData *CData, int vert_offset, int resol, float3 *fdata); +void ExportCurveTriangleVcol(Mesh *mesh, ParticleCurveData *CData, int vert_offset, int resol, uchar4 *cdata); ParticleCurveData::ParticleCurveData() { @@ -726,9 +726,9 @@ void ExportCurveTriangleUV(Mesh *mesh, ParticleCurveData *CData, int vert_offset } } -void ExportCurveTriangleVcol(Mesh *mesh, ParticleCurveData *CData, int vert_offset, int resol, float3 *fdata) +void ExportCurveTriangleVcol(Mesh *mesh, ParticleCurveData *CData, int vert_offset, int resol, uchar4 *cdata) { - if(fdata == NULL) + if(cdata == NULL) return; int vertexindex = vert_offset; @@ -740,17 +740,17 @@ void ExportCurveTriangleVcol(Mesh *mesh, ParticleCurveData *CData, int vert_offs for(int curvekey = CData->curve_firstkey[curve]; curvekey < CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1; curvekey++) { for(int section = 0; section < resol; section++) { - fdata[vertexindex] = color_srgb_to_scene_linear(CData->curve_vcol[curve]); + cdata[vertexindex] = color_float_to_byte(color_srgb_to_scene_linear(CData->curve_vcol[curve])); vertexindex++; - fdata[vertexindex] = color_srgb_to_scene_linear(CData->curve_vcol[curve]); + cdata[vertexindex] = color_float_to_byte(color_srgb_to_scene_linear(CData->curve_vcol[curve])); vertexindex++; - fdata[vertexindex] = color_srgb_to_scene_linear(CData->curve_vcol[curve]); + cdata[vertexindex] = color_float_to_byte(color_srgb_to_scene_linear(CData->curve_vcol[curve])); vertexindex++; - fdata[vertexindex] = color_srgb_to_scene_linear(CData->curve_vcol[curve]); + cdata[vertexindex] = color_float_to_byte(color_srgb_to_scene_linear(CData->curve_vcol[curve])); vertexindex++; - fdata[vertexindex] = color_srgb_to_scene_linear(CData->curve_vcol[curve]); + cdata[vertexindex] = color_float_to_byte(color_srgb_to_scene_linear(CData->curve_vcol[curve])); vertexindex++; - fdata[vertexindex] = color_srgb_to_scene_linear(CData->curve_vcol[curve]); + cdata[vertexindex] = color_float_to_byte(color_srgb_to_scene_linear(CData->curve_vcol[curve])); vertexindex++; } } @@ -923,13 +923,12 @@ void BlenderSync::sync_curves(Mesh *mesh, BL::Mesh b_mesh, BL::Object b_ob, bool ObtainCacheParticleVcol(mesh, &b_mesh, &b_ob, &CData, !preview, vcol_num); if(primitive == CURVE_TRIANGLES) { - Attribute *attr_vcol = mesh->attributes.add( - ustring(l->name().c_str()), TypeDesc::TypeColor, ATTR_ELEMENT_CORNER); + ustring(l->name().c_str()), TypeDesc::TypeColor, ATTR_ELEMENT_CORNER_BYTE); - float3 *fdata = attr_vcol->data_float3(); + uchar4 *cdata = attr_vcol->data_uchar4(); - ExportCurveTriangleVcol(mesh, &CData, tri_num * 3, used_res, fdata); + ExportCurveTriangleVcol(mesh, &CData, tri_num * 3, used_res, cdata); } else { Attribute *attr_vcol = mesh->curve_attributes.add( diff --git a/intern/cycles/blender/blender_mesh.cpp b/intern/cycles/blender/blender_mesh.cpp index 27ea552c6a7..07375484a73 100644 --- a/intern/cycles/blender/blender_mesh.cpp +++ b/intern/cycles/blender/blender_mesh.cpp @@ -347,25 +347,25 @@ static void create_mesh(Scene *scene, Mesh *mesh, BL::Mesh b_mesh, const vector< continue; Attribute *attr = mesh->attributes.add( - ustring(l->name().c_str()), TypeDesc::TypeColor, ATTR_ELEMENT_CORNER); + ustring(l->name().c_str()), TypeDesc::TypeColor, ATTR_ELEMENT_CORNER_BYTE); BL::MeshColorLayer::data_iterator c; - float3 *fdata = attr->data_float3(); + uchar4 *cdata = attr->data_uchar4(); size_t i = 0; for(l->data.begin(c); c != l->data.end(); ++c, ++i) { - fdata[0] = color_srgb_to_scene_linear(get_float3(c->color1())); - fdata[1] = color_srgb_to_scene_linear(get_float3(c->color2())); - fdata[2] = color_srgb_to_scene_linear(get_float3(c->color3())); + cdata[0] = color_float_to_byte(color_srgb_to_scene_linear(get_float3(c->color1()))); + cdata[1] = color_float_to_byte(color_srgb_to_scene_linear(get_float3(c->color2()))); + cdata[2] = color_float_to_byte(color_srgb_to_scene_linear(get_float3(c->color3()))); if(nverts[i] == 4) { - fdata[3] = fdata[0]; - fdata[4] = fdata[2]; - fdata[5] = color_srgb_to_scene_linear(get_float3(c->color4())); - fdata += 6; + cdata[3] = cdata[0]; + cdata[4] = cdata[2]; + cdata[5] = color_float_to_byte(color_srgb_to_scene_linear(get_float3(c->color4()))); + cdata += 6; } else - fdata += 3; + cdata += 3; } } } diff --git a/intern/cycles/kernel/geom/geom_triangle.h b/intern/cycles/kernel/geom/geom_triangle.h index 4ee5d5aa6d5..f2f35c2efd0 100644 --- a/intern/cycles/kernel/geom/geom_triangle.h +++ b/intern/cycles/kernel/geom/geom_triangle.h @@ -259,11 +259,20 @@ ccl_device float3 triangle_attribute_float3(KernelGlobals *kg, const ShaderData return sd->u*f0 + sd->v*f1 + (1.0f - sd->u - sd->v)*f2; } - else if(elem == ATTR_ELEMENT_CORNER) { + else if(elem == ATTR_ELEMENT_CORNER || elem == ATTR_ELEMENT_CORNER_BYTE) { int tri = offset + sd->prim*3; - float3 f0 = float4_to_float3(kernel_tex_fetch(__attributes_float3, tri + 0)); - float3 f1 = float4_to_float3(kernel_tex_fetch(__attributes_float3, tri + 1)); - float3 f2 = float4_to_float3(kernel_tex_fetch(__attributes_float3, tri + 2)); + float3 f0, f1, f2; + + if(elem == ATTR_ELEMENT_CORNER) { + f0 = float4_to_float3(kernel_tex_fetch(__attributes_float3, tri + 0)); + f1 = float4_to_float3(kernel_tex_fetch(__attributes_float3, tri + 1)); + f2 = float4_to_float3(kernel_tex_fetch(__attributes_float3, tri + 2)); + } + else { + f0 = color_byte_to_float(kernel_tex_fetch(__attributes_uchar4, tri + 0)); + f1 = color_byte_to_float(kernel_tex_fetch(__attributes_uchar4, tri + 1)); + f2 = color_byte_to_float(kernel_tex_fetch(__attributes_uchar4, tri + 2)); + } #ifdef __RAY_DIFFERENTIALS__ if(dx) *dx = sd->du.dx*f0 + sd->dv.dx*f1 - (sd->du.dx + sd->dv.dx)*f2; diff --git a/intern/cycles/kernel/kernel_textures.h b/intern/cycles/kernel/kernel_textures.h index dfef8ed9c66..55960701318 100644 --- a/intern/cycles/kernel/kernel_textures.h +++ b/intern/cycles/kernel/kernel_textures.h @@ -49,6 +49,7 @@ KERNEL_TEX(float4, texture_float4, __curve_keys) KERNEL_TEX(uint4, texture_uint4, __attributes_map) KERNEL_TEX(float, texture_float, __attributes_float) KERNEL_TEX(float4, texture_float4, __attributes_float3) +KERNEL_TEX(uchar4, texture_uchar4, __attributes_uchar4) /* lights */ KERNEL_TEX(float4, texture_float4, __light_distribution) diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h index 7edbf5ab172..f5c73b72c49 100644 --- a/intern/cycles/kernel/kernel_types.h +++ b/intern/cycles/kernel/kernel_types.h @@ -478,6 +478,7 @@ typedef enum AttributeElement { ATTR_ELEMENT_VERTEX, ATTR_ELEMENT_VERTEX_MOTION, ATTR_ELEMENT_CORNER, + ATTR_ELEMENT_CORNER_BYTE, ATTR_ELEMENT_CURVE, ATTR_ELEMENT_CURVE_KEY, ATTR_ELEMENT_CURVE_KEY_MOTION, diff --git a/intern/cycles/kernel/svm/svm_image.h b/intern/cycles/kernel/svm/svm_image.h index b34c101f5e7..a7abeda18e5 100644 --- a/intern/cycles/kernel/svm/svm_image.h +++ b/intern/cycles/kernel/svm/svm_image.h @@ -252,9 +252,9 @@ ccl_device float4 svm_image_texture(KernelGlobals *kg, int id, float x, float y, 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; - case 99: r = kernel_tex_image_interp(__tex_image_099, x, y); break; #if defined(__CUDA_ARCH__) && (__CUDA_ARCH__ >= 300) + 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; case 102: r = kernel_tex_image_interp(__tex_image_102, x, y); break; diff --git a/intern/cycles/render/attribute.cpp b/intern/cycles/render/attribute.cpp index 72781bb0f9b..8abf869a775 100644 --- a/intern/cycles/render/attribute.cpp +++ b/intern/cycles/render/attribute.cpp @@ -69,6 +69,15 @@ void Attribute::add(const float& f) buffer.push_back(data[i]); } +void Attribute::add(const uchar4& f) +{ + char *data = (char*)&f; + size_t size = sizeof(f); + + for(size_t i = 0; i < size; i++) + buffer.push_back(data[i]); +} + void Attribute::add(const float3& f) { char *data = (char*)&f; @@ -136,6 +145,7 @@ size_t Attribute::element_size(int numverts, int numtris, int numsteps, int numc size = numtris; break; case ATTR_ELEMENT_CORNER: + case ATTR_ELEMENT_CORNER_BYTE: size = numtris*3; break; case ATTR_ELEMENT_CURVE: diff --git a/intern/cycles/render/attribute.h b/intern/cycles/render/attribute.h index 9fc32db8444..f5227ebde52 100644 --- a/intern/cycles/render/attribute.h +++ b/intern/cycles/render/attribute.h @@ -68,6 +68,7 @@ public: float3 *data_float3() { return (float3*)data(); } float4 *data_float4() { return (float4*)data(); } float *data_float() { return (float*)data(); } + uchar4 *data_uchar4() { return (uchar4*)data(); } Transform *data_transform() { return (Transform*)data(); } VoxelAttribute *data_voxel() { return ( VoxelAttribute*)data(); } @@ -80,6 +81,7 @@ public: void add(const float& f); void add(const float3& f); + void add(const uchar4& f); void add(const Transform& f); void add(const VoxelAttribute& f); void add(const char *data); diff --git a/intern/cycles/render/image.h b/intern/cycles/render/image.h index 8abf2a33d74..3eacfa7beed 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 95 +#define TEX_NUM_IMAGES 94 #define TEX_IMAGE_BYTE_START TEX_NUM_FLOAT_IMAGES /* extended gpu */ diff --git a/intern/cycles/render/mesh.cpp b/intern/cycles/render/mesh.cpp index b6826f0066b..808db4fe5b2 100644 --- a/intern/cycles/render/mesh.cpp +++ b/intern/cycles/render/mesh.cpp @@ -745,7 +745,7 @@ void MeshManager::update_svm_attributes(Device *device, DeviceScene *dscene, Sce device->tex_alloc("__attributes_map", dscene->attributes_map); } -static void update_attribute_element_offset(Mesh *mesh, vector& attr_float, vector& attr_float3, +static void update_attribute_element_offset(Mesh *mesh, vector& attr_float, vector& attr_float3, vector& attr_uchar4, Attribute *mattr, TypeDesc& type, int& offset, AttributeElement& element) { if(mattr) { @@ -766,6 +766,15 @@ static void update_attribute_element_offset(Mesh *mesh, vector& attr_floa VoxelAttribute *voxel_data = mattr->data_voxel(); offset = voxel_data->slot; } + if(mattr->element == ATTR_ELEMENT_CORNER_BYTE) { + uchar4 *data = mattr->data_uchar4(); + offset = attr_uchar4.size(); + + attr_uchar4.resize(attr_uchar4.size() + size); + + for(size_t k = 0; k < size; k++) + attr_uchar4[offset+k] = data[k]; + } else if(mattr->type == TypeDesc::TypeFloat) { float *data = mattr->data_float(); offset = attr_float.size(); @@ -802,7 +811,7 @@ static void update_attribute_element_offset(Mesh *mesh, vector& attr_floa offset -= mesh->vert_offset; else if(element == ATTR_ELEMENT_FACE) offset -= mesh->tri_offset; - else if(element == ATTR_ELEMENT_CORNER) + else if(element == ATTR_ELEMENT_CORNER || element == ATTR_ELEMENT_CORNER_BYTE) offset -= 3*mesh->tri_offset; else if(element == ATTR_ELEMENT_CURVE) offset -= mesh->curve_offset; @@ -843,6 +852,7 @@ void MeshManager::device_update_attributes(Device *device, DeviceScene *dscene, * maps next */ vector attr_float; vector attr_float3; + vector attr_uchar4; for(size_t i = 0; i < scene->meshes.size(); i++) { Mesh *mesh = scene->meshes[i]; @@ -863,10 +873,10 @@ void MeshManager::device_update_attributes(Device *device, DeviceScene *dscene, memcpy(triangle_mattr->data_float3(), &mesh->verts[0], sizeof(float3)*mesh->verts.size()); } - update_attribute_element_offset(mesh, attr_float, attr_float3, triangle_mattr, + update_attribute_element_offset(mesh, attr_float, attr_float3, attr_uchar4, triangle_mattr, req.triangle_type, req.triangle_offset, req.triangle_element); - update_attribute_element_offset(mesh, attr_float, attr_float3, curve_mattr, + update_attribute_element_offset(mesh, attr_float, attr_float3, attr_uchar4, curve_mattr, req.curve_type, req.curve_offset, req.curve_element); if(progress.get_cancel()) return; @@ -892,6 +902,10 @@ void MeshManager::device_update_attributes(Device *device, DeviceScene *dscene, dscene->attributes_float3.copy(&attr_float3[0], attr_float3.size()); device->tex_alloc("__attributes_float3", dscene->attributes_float3); } + if(attr_uchar4.size()) { + dscene->attributes_uchar4.copy(&attr_uchar4[0], attr_uchar4.size()); + device->tex_alloc("__attributes_uchar4", dscene->attributes_uchar4); + } } void MeshManager::device_update_mesh(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress) diff --git a/intern/cycles/render/scene.h b/intern/cycles/render/scene.h index 777d26ac79e..e5c7444c92d 100644 --- a/intern/cycles/render/scene.h +++ b/intern/cycles/render/scene.h @@ -85,6 +85,7 @@ public: device_vector attributes_map; device_vector attributes_float; device_vector attributes_float3; + device_vector attributes_uchar4; /* lights */ device_vector light_distribution; diff --git a/intern/cycles/util/util_color.h b/intern/cycles/util/util_color.h index d566e1bf359..d362c8abe25 100644 --- a/intern/cycles/util/util_color.h +++ b/intern/cycles/util/util_color.h @@ -26,6 +26,27 @@ CCL_NAMESPACE_BEGIN +ccl_device uchar float_to_byte(float val) +{ + return ((val <= 0.0f) ? 0 : (((val) > (1.0f - 0.5f / 255.0f)) ? 255 : ((255.0f * (val)) + 0.5f))); +} + +ccl_device uchar4 color_float_to_byte(float3 c) +{ + uchar r, g, b; + + r = float_to_byte(c.x); + g = float_to_byte(c.y); + b = float_to_byte(c.z); + + return make_uchar4(r, g, b, 0); +} + +ccl_device_inline float3 color_byte_to_float(uchar4 c) +{ + return make_float3(c.x*(1.0f/255.0f), c.y*(1.0f/255.0f), c.z*(1.0f/255.0f)); +} + ccl_device float color_srgb_to_scene_linear(float c) { if(c < 0.04045f) -- cgit v1.2.3