From 49df707496e505c8a8b21c1ea36b479e950cc66c Mon Sep 17 00:00:00 2001 From: Thomas Dinges Date: Fri, 13 Jun 2014 21:27:21 +0200 Subject: Cycles: Calculate face normal on the fly. Instead of pre-calculation and storage, we now calculate the face normal during render. This gives a small slowdown (~1%) but decreases memory usage, which is especially important for GPUs, where you have limited VRAM. Part of my GSoC 2014. --- intern/cycles/kernel/geom/geom_bvh_shadow.h | 3 +-- intern/cycles/kernel/geom/geom_motion_triangle.h | 3 +-- intern/cycles/kernel/geom/geom_triangle.h | 22 ++++++++++++++++--- intern/cycles/kernel/kernel_shader.h | 13 +++++------- intern/cycles/kernel/kernel_textures.h | 2 +- intern/cycles/render/mesh.cpp | 27 +++++++----------------- intern/cycles/render/mesh.h | 2 +- intern/cycles/render/scene.h | 2 +- 8 files changed, 37 insertions(+), 37 deletions(-) (limited to 'intern/cycles') diff --git a/intern/cycles/kernel/geom/geom_bvh_shadow.h b/intern/cycles/kernel/geom/geom_bvh_shadow.h index 48876da049e..1f6e4942fab 100644 --- a/intern/cycles/kernel/geom/geom_bvh_shadow.h +++ b/intern/cycles/kernel/geom/geom_bvh_shadow.h @@ -252,8 +252,7 @@ ccl_device bool BVH_FUNCTION_NAME if(kernel_tex_fetch(__prim_type, isect_array->prim) & PRIMITIVE_ALL_TRIANGLE) #endif { - float4 Ns = kernel_tex_fetch(__tri_normal, prim); - shader = __float_as_int(Ns.w); + shader = __float_as_int(kernel_tex_fetch(__tri_shader, prim)); } #ifdef __HAIR__ else { diff --git a/intern/cycles/kernel/geom/geom_motion_triangle.h b/intern/cycles/kernel/geom/geom_motion_triangle.h index 73fcf1adda6..5ab0b731bdd 100644 --- a/intern/cycles/kernel/geom/geom_motion_triangle.h +++ b/intern/cycles/kernel/geom/geom_motion_triangle.h @@ -233,8 +233,7 @@ ccl_device_inline float3 motion_triangle_refine_subsurface(KernelGlobals *kg, Sh ccl_device_noinline void motion_triangle_shader_setup(KernelGlobals *kg, ShaderData *sd, const Intersection *isect, const Ray *ray, bool subsurface) { /* get shader */ - float4 Ns = kernel_tex_fetch(__tri_normal, sd->prim); - sd->shader = __float_as_int(Ns.w); + sd->shader = __float_as_int(kernel_tex_fetch(__tri_shader, sd->prim)); /* get motion info */ int numsteps, numverts; diff --git a/intern/cycles/kernel/geom/geom_triangle.h b/intern/cycles/kernel/geom/geom_triangle.h index 355e36fef0c..4ee5d5aa6d5 100644 --- a/intern/cycles/kernel/geom/geom_triangle.h +++ b/intern/cycles/kernel/geom/geom_triangle.h @@ -116,6 +116,20 @@ ccl_device_inline float3 triangle_refine_subsurface(KernelGlobals *kg, ShaderDat #endif } +/* normal on triangle */ +ccl_device_inline float3 triangle_normal(KernelGlobals *kg, int prim) +{ + /* load triangle vertices */ + float3 tri_vindex = float4_to_float3(kernel_tex_fetch(__tri_vindex, prim)); + + float3 v0 = float4_to_float3(kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.x))); + float3 v1 = float4_to_float3(kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.y))); + float3 v2 = float4_to_float3(kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.z))); + + /* return normal */ + return normalize(cross(v1 - v0, v2 - v0)); +} + /* point and normal on triangle */ ccl_device_inline void triangle_point_normal(KernelGlobals *kg, int prim, float u, float v, float3 *P, float3 *Ng, int *shader) { @@ -130,9 +144,11 @@ ccl_device_inline void triangle_point_normal(KernelGlobals *kg, int prim, float float t = 1.0f - u - v; *P = (u*v0 + v*v1 + t*v2); - float4 Nm = kernel_tex_fetch(__tri_normal, prim); - *Ng = make_float3(Nm.x, Nm.y, Nm.z); - *shader = __float_as_int(Nm.w); + /* compute normal */ + *Ng = normalize(cross(v1 - v0, v2 - v0)); + + /* shader`*/ + *shader = __float_as_int(kernel_tex_fetch(__tri_shader, prim)); } /* Triangle vertex locations */ diff --git a/intern/cycles/kernel/kernel_shader.h b/intern/cycles/kernel/kernel_shader.h index c6a7f9f1570..0ea21a85fcb 100644 --- a/intern/cycles/kernel/kernel_shader.h +++ b/intern/cycles/kernel/kernel_shader.h @@ -86,9 +86,8 @@ ccl_device void shader_setup_from_ray(KernelGlobals *kg, ShaderData *sd, #endif if(sd->type & PRIMITIVE_TRIANGLE) { /* static triangle */ - float4 Ns = kernel_tex_fetch(__tri_normal, sd->prim); - float3 Ng = make_float3(Ns.x, Ns.y, Ns.z); - sd->shader = __float_as_int(Ns.w); + float3 Ng = triangle_normal(kg, sd->prim); + sd->shader = __float_as_int(kernel_tex_fetch(__tri_shader, sd->prim)); /* vectors */ sd->P = triangle_refine(kg, sd, isect, ray); @@ -166,9 +165,8 @@ ccl_device_inline void shader_setup_from_subsurface(KernelGlobals *kg, ShaderDat /* fetch triangle data */ if(sd->type == PRIMITIVE_TRIANGLE) { - float4 Ns = kernel_tex_fetch(__tri_normal, sd->prim); - float3 Ng = make_float3(Ns.x, Ns.y, Ns.z); - sd->shader = __float_as_int(Ns.w); + float3 Ng = triangle_normal(kg, sd->prim); + sd->shader = __float_as_int(kernel_tex_fetch(__tri_shader, sd->prim)); /* static triangle */ sd->P = triangle_refine_subsurface(kg, sd, isect, ray); @@ -1028,8 +1026,7 @@ ccl_device bool shader_transparent_shadow(KernelGlobals *kg, Intersection *isect #ifdef __HAIR__ if(kernel_tex_fetch(__prim_type, isect->prim) & PRIMITIVE_ALL_TRIANGLE) { #endif - float4 Ns = kernel_tex_fetch(__tri_normal, prim); - shader = __float_as_int(Ns.w); + shader = __float_as_int(kernel_tex_fetch(__tri_shader, prim)); #ifdef __HAIR__ } else { diff --git a/intern/cycles/kernel/kernel_textures.h b/intern/cycles/kernel/kernel_textures.h index b07075c6c95..dfef8ed9c66 100644 --- a/intern/cycles/kernel/kernel_textures.h +++ b/intern/cycles/kernel/kernel_textures.h @@ -36,7 +36,7 @@ KERNEL_TEX(float4, texture_float4, __objects) KERNEL_TEX(float4, texture_float4, __objects_vector) /* triangles */ -KERNEL_TEX(float4, texture_float4, __tri_normal) +KERNEL_TEX(float, texture_float, __tri_shader) KERNEL_TEX(float4, texture_float4, __tri_vnormal) KERNEL_TEX(float4, texture_float4, __tri_vindex) KERNEL_TEX(float4, texture_float4, __tri_verts) diff --git a/intern/cycles/render/mesh.cpp b/intern/cycles/render/mesh.cpp index 9c5ddd55010..b6826f0066b 100644 --- a/intern/cycles/render/mesh.cpp +++ b/intern/cycles/render/mesh.cpp @@ -377,12 +377,10 @@ void Mesh::add_vertex_normals() } } -void Mesh::pack_normals(Scene *scene, float4 *normal, float4 *vnormal) +void Mesh::pack_normals(Scene *scene, float *tri_shader, float4 *vnormal) { - Attribute *attr_fN = attributes.find(ATTR_STD_FACE_NORMAL); Attribute *attr_vN = attributes.find(ATTR_STD_VERTEX_NORMAL); - float3 *fN = attr_fN->data_float3(); float3 *vN = attr_vN->data_float3(); int shader_id = 0; uint last_shader = -1; @@ -394,24 +392,15 @@ void Mesh::pack_normals(Scene *scene, float4 *normal, float4 *vnormal) bool do_transform = transform_applied; Transform ntfm = transform_normal; + /* save shader */ for(size_t i = 0; i < triangles_size; i++) { - float3 fNi = fN[i]; - - if(do_transform) - fNi = normalize(transform_direction(&ntfm, fNi)); - - normal[i].x = fNi.x; - normal[i].y = fNi.y; - normal[i].z = fNi.z; - - /* stuff shader id in here too */ if(shader_ptr[i] != last_shader || last_smooth != smooth[i]) { last_shader = shader_ptr[i]; last_smooth = smooth[i]; shader_id = scene->shader_manager->get_shader_id(last_shader, this, last_smooth); } - normal[i].w = __int_as_float(shader_id); + tri_shader[i] = __int_as_float(shader_id); } size_t verts_size = verts.size(); @@ -932,13 +921,13 @@ void MeshManager::device_update_mesh(Device *device, DeviceScene *dscene, Scene /* normals */ progress.set_status("Updating Mesh", "Computing normals"); - float4 *normal = dscene->tri_normal.resize(tri_size); + float *tri_shader = dscene->tri_shader.resize(tri_size); float4 *vnormal = dscene->tri_vnormal.resize(vert_size); float4 *tri_verts = dscene->tri_verts.resize(vert_size); float4 *tri_vindex = dscene->tri_vindex.resize(tri_size); foreach(Mesh *mesh, scene->meshes) { - mesh->pack_normals(scene, &normal[mesh->tri_offset], &vnormal[mesh->vert_offset]); + mesh->pack_normals(scene, &tri_shader[mesh->tri_offset], &vnormal[mesh->vert_offset]); mesh->pack_verts(&tri_verts[mesh->vert_offset], &tri_vindex[mesh->tri_offset], mesh->vert_offset); if(progress.get_cancel()) return; @@ -947,7 +936,7 @@ void MeshManager::device_update_mesh(Device *device, DeviceScene *dscene, Scene /* vertex coordinates */ progress.set_status("Updating Mesh", "Copying Mesh to device"); - device->tex_alloc("__tri_normal", dscene->tri_normal); + device->tex_alloc("__tri_shader", dscene->tri_shader); device->tex_alloc("__tri_vnormal", dscene->tri_vnormal); device->tex_alloc("__tri_verts", dscene->tri_verts); device->tex_alloc("__tri_vindex", dscene->tri_vindex); @@ -1119,7 +1108,7 @@ void MeshManager::device_free(Device *device, DeviceScene *dscene) device->tex_free(dscene->prim_visibility); device->tex_free(dscene->prim_index); device->tex_free(dscene->prim_object); - device->tex_free(dscene->tri_normal); + device->tex_free(dscene->tri_shader); device->tex_free(dscene->tri_vnormal); device->tex_free(dscene->tri_vindex); device->tex_free(dscene->tri_verts); @@ -1136,7 +1125,7 @@ void MeshManager::device_free(Device *device, DeviceScene *dscene) dscene->prim_visibility.clear(); dscene->prim_index.clear(); dscene->prim_object.clear(); - dscene->tri_normal.clear(); + dscene->tri_shader.clear(); dscene->tri_vnormal.clear(); dscene->tri_vindex.clear(); dscene->tri_verts.clear(); diff --git a/intern/cycles/render/mesh.h b/intern/cycles/render/mesh.h index 247e3dd555e..5ee774bacc1 100644 --- a/intern/cycles/render/mesh.h +++ b/intern/cycles/render/mesh.h @@ -120,7 +120,7 @@ public: void add_face_normals(); void add_vertex_normals(); - void pack_normals(Scene *scene, float4 *normal, float4 *vnormal); + void pack_normals(Scene *scene, float *shader, float4 *vnormal); void pack_verts(float4 *tri_verts, float4 *tri_vindex, size_t vert_offset); void pack_curves(Scene *scene, float4 *curve_key_co, float4 *curve_data, size_t curvekey_offset); void compute_bvh(SceneParams *params, Progress *progress, int n, int total); diff --git a/intern/cycles/render/scene.h b/intern/cycles/render/scene.h index d657e48e478..777d26ac79e 100644 --- a/intern/cycles/render/scene.h +++ b/intern/cycles/render/scene.h @@ -69,7 +69,7 @@ public: device_vector prim_object; /* mesh */ - device_vector tri_normal; + device_vector tri_shader; device_vector tri_vnormal; device_vector tri_vindex; device_vector tri_verts; -- cgit v1.2.3