Cycles code internals: add support for mesh voxel grid attributes.
These are internally stored as a 3D image textures, but accessible like e.g. UV coordinates though the attribute node and getattribute(). This is convenient for rendering e.g. smoke objects where data like density is really a property of the mesh, and it avoids having to specify the smoke object in a texture node, instead the material will work with any smoke domain.
This commit is contained in:
@@ -119,6 +119,7 @@ set(SRC_GEOM_HEADERS
|
|||||||
geom/geom_object.h
|
geom/geom_object.h
|
||||||
geom/geom_primitive.h
|
geom/geom_primitive.h
|
||||||
geom/geom_triangle.h
|
geom/geom_triangle.h
|
||||||
|
geom/geom_volume.h
|
||||||
)
|
)
|
||||||
|
|
||||||
set(SRC_UTIL_HEADERS
|
set(SRC_UTIL_HEADERS
|
||||||
|
@@ -38,6 +38,7 @@
|
|||||||
#include "geom_motion_triangle.h"
|
#include "geom_motion_triangle.h"
|
||||||
#include "geom_motion_curve.h"
|
#include "geom_motion_curve.h"
|
||||||
#include "geom_curve.h"
|
#include "geom_curve.h"
|
||||||
|
#include "geom_volume.h"
|
||||||
#include "geom_primitive.h"
|
#include "geom_primitive.h"
|
||||||
#include "geom_bvh.h"
|
#include "geom_bvh.h"
|
||||||
|
|
||||||
|
@@ -32,13 +32,6 @@ ccl_device_inline int find_attribute(KernelGlobals *kg, const ShaderData *sd, ui
|
|||||||
if(sd->object == PRIM_NONE)
|
if(sd->object == PRIM_NONE)
|
||||||
return (int)ATTR_STD_NOT_FOUND;
|
return (int)ATTR_STD_NOT_FOUND;
|
||||||
|
|
||||||
#ifdef __OSL__
|
|
||||||
if (kg->osl) {
|
|
||||||
return OSLShader::find_attribute(kg, sd, id, elem);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
/* for SVM, find attribute by unique id */
|
/* for SVM, find attribute by unique id */
|
||||||
uint attr_offset = sd->object*kernel_data.bvh.attributes_map_stride;
|
uint attr_offset = sd->object*kernel_data.bvh.attributes_map_stride;
|
||||||
#ifdef __HAIR__
|
#ifdef __HAIR__
|
||||||
@@ -58,9 +51,10 @@ ccl_device_inline int find_attribute(KernelGlobals *kg, const ShaderData *sd, ui
|
|||||||
|
|
||||||
/* return result */
|
/* return result */
|
||||||
return (attr_map.y == ATTR_ELEMENT_NONE) ? (int)ATTR_STD_NOT_FOUND : (int)attr_map.z;
|
return (attr_map.y == ATTR_ELEMENT_NONE) ? (int)ATTR_STD_NOT_FOUND : (int)attr_map.z;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Transform matrix attribute on meshes */
|
||||||
|
|
||||||
ccl_device Transform primitive_attribute_matrix(KernelGlobals *kg, const ShaderData *sd, int offset)
|
ccl_device Transform primitive_attribute_matrix(KernelGlobals *kg, const ShaderData *sd, int offset)
|
||||||
{
|
{
|
||||||
Transform tfm;
|
Transform tfm;
|
||||||
|
@@ -25,26 +25,46 @@ CCL_NAMESPACE_BEGIN
|
|||||||
|
|
||||||
ccl_device float primitive_attribute_float(KernelGlobals *kg, const ShaderData *sd, AttributeElement elem, int offset, float *dx, float *dy)
|
ccl_device float primitive_attribute_float(KernelGlobals *kg, const ShaderData *sd, AttributeElement elem, int offset, float *dx, float *dy)
|
||||||
{
|
{
|
||||||
#ifdef __HAIR__
|
if(sd->type & PRIMITIVE_ALL_TRIANGLE) {
|
||||||
if(sd->type & PRIMITIVE_ALL_TRIANGLE)
|
|
||||||
#endif
|
|
||||||
return triangle_attribute_float(kg, sd, elem, offset, dx, dy);
|
return triangle_attribute_float(kg, sd, elem, offset, dx, dy);
|
||||||
|
}
|
||||||
#ifdef __HAIR__
|
#ifdef __HAIR__
|
||||||
else
|
else if(sd->type & PRIMITIVE_ALL_CURVE) {
|
||||||
return curve_attribute_float(kg, sd, elem, offset, dx, dy);
|
return curve_attribute_float(kg, sd, elem, offset, dx, dy);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef __VOLUME__
|
||||||
|
else if(sd->object != OBJECT_NONE && elem == ATTR_ELEMENT_VOXEL) {
|
||||||
|
return volume_attribute_float(kg, sd, elem, offset, dx, dy);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
else {
|
||||||
|
if(dx) *dx = 0.0f;
|
||||||
|
if(dy) *dy = 0.0f;
|
||||||
|
return 0.0f;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ccl_device float3 primitive_attribute_float3(KernelGlobals *kg, const ShaderData *sd, AttributeElement elem, int offset, float3 *dx, float3 *dy)
|
ccl_device float3 primitive_attribute_float3(KernelGlobals *kg, const ShaderData *sd, AttributeElement elem, int offset, float3 *dx, float3 *dy)
|
||||||
{
|
{
|
||||||
#ifdef __HAIR__
|
if(sd->type & PRIMITIVE_ALL_TRIANGLE) {
|
||||||
if(sd->type & PRIMITIVE_ALL_TRIANGLE)
|
|
||||||
#endif
|
|
||||||
return triangle_attribute_float3(kg, sd, elem, offset, dx, dy);
|
return triangle_attribute_float3(kg, sd, elem, offset, dx, dy);
|
||||||
|
}
|
||||||
#ifdef __HAIR__
|
#ifdef __HAIR__
|
||||||
else
|
else if(sd->type & PRIMITIVE_ALL_CURVE) {
|
||||||
return curve_attribute_float3(kg, sd, elem, offset, dx, dy);
|
return curve_attribute_float3(kg, sd, elem, offset, dx, dy);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef __VOLUME__
|
||||||
|
else if(sd->object != OBJECT_NONE && elem == ATTR_ELEMENT_VOXEL) {
|
||||||
|
return volume_attribute_float3(kg, sd, elem, offset, dx, dy);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
else {
|
||||||
|
if(dx) *dx = make_float3(0.0f, 0.0f, 0.0f);
|
||||||
|
if(dy) *dy = make_float3(0.0f, 0.0f, 0.0f);
|
||||||
|
return make_float3(0.0f, 0.0f, 0.0f);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Default UV coordinate */
|
/* Default UV coordinate */
|
||||||
|
75
intern/cycles/kernel/geom/geom_volume.h
Normal file
75
intern/cycles/kernel/geom/geom_volume.h
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2011-2013 Blender Foundation
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Volume Primitive
|
||||||
|
*
|
||||||
|
* Volumes are just regions inside meshes with the mesh surface as boundaries.
|
||||||
|
* There isn't as much data to access as for surfaces, there is only a position
|
||||||
|
* to do lookups in 3D voxel or procedural textures.
|
||||||
|
*
|
||||||
|
* 3D voxel textures can be assigned as attributes per mesh, which means the
|
||||||
|
* same shader can be used for volume objects with different densities, etc. */
|
||||||
|
|
||||||
|
CCL_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
#ifdef __VOLUME__
|
||||||
|
|
||||||
|
/* Return position normalized to 0..1 in mesh bounds */
|
||||||
|
|
||||||
|
ccl_device float3 volume_normalized_position(KernelGlobals *kg, const ShaderData *sd, float3 P)
|
||||||
|
{
|
||||||
|
/* todo: optimize this so it's just a single matrix multiplication when
|
||||||
|
* possible (not motion blur), or perhaps even just translation + scale */
|
||||||
|
AttributeElement attr_elem;
|
||||||
|
int attr_offset = find_attribute(kg, sd, ATTR_STD_GENERATED_TRANSFORM, &attr_elem);
|
||||||
|
|
||||||
|
object_inverse_position_transform(kg, sd, &P);
|
||||||
|
|
||||||
|
if(attr_offset != ATTR_STD_NOT_FOUND) {
|
||||||
|
Transform tfm = primitive_attribute_matrix(kg, sd, attr_offset);
|
||||||
|
P = transform_point(&tfm, P);
|
||||||
|
}
|
||||||
|
|
||||||
|
return P;
|
||||||
|
}
|
||||||
|
|
||||||
|
ccl_device float volume_attribute_float(KernelGlobals *kg, const ShaderData *sd, AttributeElement elem, int id, float *dx, float *dy)
|
||||||
|
{
|
||||||
|
float3 P = volume_normalized_position(kg, sd, sd->P);
|
||||||
|
float4 r = kernel_tex_image_interp_3d(id, P.x, P.y, P.z);
|
||||||
|
|
||||||
|
if(dx) *dx = 0.0f;
|
||||||
|
if(dx) *dy = 0.0f;
|
||||||
|
|
||||||
|
/* todo: support float textures to lower memory usage for single floats */
|
||||||
|
return average(float4_to_float3(r));
|
||||||
|
}
|
||||||
|
|
||||||
|
ccl_device float3 volume_attribute_float3(KernelGlobals *kg, const ShaderData *sd, AttributeElement elem, int id, float3 *dx, float3 *dy)
|
||||||
|
{
|
||||||
|
float3 P = volume_normalized_position(kg, sd, sd->P);
|
||||||
|
float4 r = kernel_tex_image_interp_3d(id, P.x, P.y, P.z);
|
||||||
|
|
||||||
|
if(dx) *dx = make_float3(0.0f, 0.0f, 0.0f);
|
||||||
|
if(dy) *dy = make_float3(0.0f, 0.0f, 0.0f);
|
||||||
|
|
||||||
|
return float4_to_float3(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
CCL_NAMESPACE_END
|
||||||
|
|
@@ -459,7 +459,8 @@ typedef enum AttributeElement {
|
|||||||
ATTR_ELEMENT_CORNER,
|
ATTR_ELEMENT_CORNER,
|
||||||
ATTR_ELEMENT_CURVE,
|
ATTR_ELEMENT_CURVE,
|
||||||
ATTR_ELEMENT_CURVE_KEY,
|
ATTR_ELEMENT_CURVE_KEY,
|
||||||
ATTR_ELEMENT_CURVE_KEY_MOTION
|
ATTR_ELEMENT_CURVE_KEY_MOTION,
|
||||||
|
ATTR_ELEMENT_VOXEL
|
||||||
} AttributeElement;
|
} AttributeElement;
|
||||||
|
|
||||||
typedef enum AttributeStandard {
|
typedef enum AttributeStandard {
|
||||||
|
@@ -768,9 +768,7 @@ bool OSLRenderServices::get_attribute(void *renderstate, bool derivatives, ustri
|
|||||||
|
|
||||||
if (attr.elem != ATTR_ELEMENT_OBJECT) {
|
if (attr.elem != ATTR_ELEMENT_OBJECT) {
|
||||||
/* triangle and vertex attributes */
|
/* triangle and vertex attributes */
|
||||||
if (prim != PRIM_NONE)
|
if(!get_mesh_element_attribute(kg, sd, attr, type, derivatives, val))
|
||||||
return get_mesh_element_attribute(kg, sd, attr, type, derivatives, val);
|
|
||||||
else
|
|
||||||
return get_mesh_attribute(kg, sd, attr, type, derivatives, val);
|
return get_mesh_attribute(kg, sd, attr, type, derivatives, val);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@@ -22,12 +22,12 @@ ccl_device void svm_node_attr_init(KernelGlobals *kg, ShaderData *sd,
|
|||||||
uint4 node, NodeAttributeType *type,
|
uint4 node, NodeAttributeType *type,
|
||||||
NodeAttributeType *mesh_type, AttributeElement *elem, int *offset, uint *out_offset)
|
NodeAttributeType *mesh_type, AttributeElement *elem, int *offset, uint *out_offset)
|
||||||
{
|
{
|
||||||
if(sd->object != OBJECT_NONE && sd->prim != PRIM_NONE) {
|
if(sd->object != OBJECT_NONE) {
|
||||||
/* find attribute by unique id */
|
/* find attribute by unique id */
|
||||||
uint id = node.y;
|
uint id = node.y;
|
||||||
uint attr_offset = sd->object*kernel_data.bvh.attributes_map_stride;
|
uint attr_offset = sd->object*kernel_data.bvh.attributes_map_stride;
|
||||||
#ifdef __HAIR__
|
#ifdef __HAIR__
|
||||||
attr_offset = (sd->type & PRIMITIVE_ALL_TRIANGLE)? attr_offset: attr_offset + ATTR_PRIM_CURVE;
|
attr_offset = (sd->type & PRIMITIVE_ALL_CURVE)? attr_offset + ATTR_PRIM_CURVE: attr_offset;
|
||||||
#endif
|
#endif
|
||||||
uint4 attr_map = kernel_tex_fetch(__attributes_map, attr_offset);
|
uint4 attr_map = kernel_tex_fetch(__attributes_map, attr_offset);
|
||||||
|
|
||||||
|
@@ -70,17 +70,10 @@ ccl_device void svm_node_tex_coord(KernelGlobals *kg, ShaderData *sd, int path_f
|
|||||||
case NODE_TEXCO_VOLUME_GENERATED: {
|
case NODE_TEXCO_VOLUME_GENERATED: {
|
||||||
data = sd->P;
|
data = sd->P;
|
||||||
|
|
||||||
if(sd->object != OBJECT_NONE) {
|
#ifdef __VOLUME__
|
||||||
AttributeElement attr_elem;
|
if(sd->object != OBJECT_NONE)
|
||||||
int attr_offset = find_attribute(kg, sd, ATTR_STD_GENERATED_TRANSFORM, &attr_elem);
|
data = volume_normalized_position(kg, sd, data);
|
||||||
|
#endif
|
||||||
object_inverse_position_transform(kg, sd, &data);
|
|
||||||
|
|
||||||
if(attr_offset != ATTR_STD_NOT_FOUND) {
|
|
||||||
Transform tfm = primitive_attribute_matrix(kg, sd, attr_offset);
|
|
||||||
data = transform_point(&tfm, data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -141,17 +134,10 @@ ccl_device void svm_node_tex_coord_bump_dx(KernelGlobals *kg, ShaderData *sd, in
|
|||||||
case NODE_TEXCO_VOLUME_GENERATED: {
|
case NODE_TEXCO_VOLUME_GENERATED: {
|
||||||
data = sd->P + sd->dP.dx;
|
data = sd->P + sd->dP.dx;
|
||||||
|
|
||||||
if(sd->object != OBJECT_NONE) {
|
#ifdef __VOLUME__
|
||||||
AttributeElement attr_elem;
|
if(sd->object != OBJECT_NONE)
|
||||||
int attr_offset = find_attribute(kg, sd, ATTR_STD_GENERATED_TRANSFORM, &attr_elem);
|
data = volume_normalized_position(kg, sd, data);
|
||||||
|
#endif
|
||||||
object_inverse_position_transform(kg, sd, &data);
|
|
||||||
|
|
||||||
if(attr_offset != ATTR_STD_NOT_FOUND) {
|
|
||||||
Transform tfm = primitive_attribute_matrix(kg, sd, attr_offset);
|
|
||||||
data = transform_point(&tfm, data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -215,17 +201,10 @@ ccl_device void svm_node_tex_coord_bump_dy(KernelGlobals *kg, ShaderData *sd, in
|
|||||||
case NODE_TEXCO_VOLUME_GENERATED: {
|
case NODE_TEXCO_VOLUME_GENERATED: {
|
||||||
data = sd->P + sd->dP.dy;
|
data = sd->P + sd->dP.dy;
|
||||||
|
|
||||||
if(sd->object != OBJECT_NONE) {
|
#ifdef __VOLUME__
|
||||||
AttributeElement attr_elem;
|
if(sd->object != OBJECT_NONE)
|
||||||
int attr_offset = find_attribute(kg, sd, ATTR_STD_GENERATED_TRANSFORM, &attr_elem);
|
data = volume_normalized_position(kg, sd, data);
|
||||||
|
#endif
|
||||||
object_inverse_position_transform(kg, sd, &data);
|
|
||||||
|
|
||||||
if(attr_offset != ATTR_STD_NOT_FOUND) {
|
|
||||||
Transform tfm = primitive_attribute_matrix(kg, sd, attr_offset);
|
|
||||||
data = transform_point(&tfm, data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -14,6 +14,7 @@
|
|||||||
* limitations under the License
|
* limitations under the License
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "image.h"
|
||||||
#include "mesh.h"
|
#include "mesh.h"
|
||||||
#include "attribute.h"
|
#include "attribute.h"
|
||||||
|
|
||||||
@@ -25,6 +26,17 @@ CCL_NAMESPACE_BEGIN
|
|||||||
|
|
||||||
/* Attribute */
|
/* Attribute */
|
||||||
|
|
||||||
|
Attribute::~Attribute()
|
||||||
|
{
|
||||||
|
/* for voxel data, we need to remove the image from the image manager */
|
||||||
|
if(element == ATTR_ELEMENT_VOXEL) {
|
||||||
|
VoxelAttribute *voxel_data = data_voxel();
|
||||||
|
|
||||||
|
if(voxel_data)
|
||||||
|
voxel_data->manager->remove_image(voxel_data->slot);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Attribute::set(ustring name_, TypeDesc type_, AttributeElement element_)
|
void Attribute::set(ustring name_, TypeDesc type_, AttributeElement element_)
|
||||||
{
|
{
|
||||||
name = name_;
|
name = name_;
|
||||||
@@ -75,9 +87,20 @@ void Attribute::add(const Transform& f)
|
|||||||
buffer.push_back(data[i]);
|
buffer.push_back(data[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Attribute::add(const VoxelAttribute& f)
|
||||||
|
{
|
||||||
|
char *data = (char*)&f;
|
||||||
|
size_t size = sizeof(f);
|
||||||
|
|
||||||
|
for(size_t i = 0; i < size; i++)
|
||||||
|
buffer.push_back(data[i]);
|
||||||
|
}
|
||||||
|
|
||||||
size_t Attribute::data_sizeof() const
|
size_t Attribute::data_sizeof() const
|
||||||
{
|
{
|
||||||
if(type == TypeDesc::TypeFloat)
|
if(element == ATTR_ELEMENT_VOXEL)
|
||||||
|
return sizeof(VoxelAttribute);
|
||||||
|
else if(type == TypeDesc::TypeFloat)
|
||||||
return sizeof(float);
|
return sizeof(float);
|
||||||
else if(type == TypeDesc::TypeMatrix)
|
else if(type == TypeDesc::TypeMatrix)
|
||||||
return sizeof(Transform);
|
return sizeof(Transform);
|
||||||
@@ -92,6 +115,7 @@ size_t Attribute::element_size(int numverts, int numtris, int numsteps, int numc
|
|||||||
switch(element) {
|
switch(element) {
|
||||||
case ATTR_ELEMENT_OBJECT:
|
case ATTR_ELEMENT_OBJECT:
|
||||||
case ATTR_ELEMENT_MESH:
|
case ATTR_ELEMENT_MESH:
|
||||||
|
case ATTR_ELEMENT_VOXEL:
|
||||||
size = 1;
|
size = 1;
|
||||||
break;
|
break;
|
||||||
case ATTR_ELEMENT_VERTEX:
|
case ATTR_ELEMENT_VERTEX:
|
||||||
@@ -147,40 +171,55 @@ bool Attribute::same_storage(TypeDesc a, TypeDesc b)
|
|||||||
|
|
||||||
const char *Attribute::standard_name(AttributeStandard std)
|
const char *Attribute::standard_name(AttributeStandard std)
|
||||||
{
|
{
|
||||||
if(std == ATTR_STD_VERTEX_NORMAL)
|
switch(std) {
|
||||||
|
case ATTR_STD_VERTEX_NORMAL:
|
||||||
return "N";
|
return "N";
|
||||||
else if(std == ATTR_STD_FACE_NORMAL)
|
case ATTR_STD_FACE_NORMAL:
|
||||||
return "Ng";
|
return "Ng";
|
||||||
else if(std == ATTR_STD_UV)
|
case ATTR_STD_UV:
|
||||||
return "uv";
|
return "uv";
|
||||||
else if(std == ATTR_STD_GENERATED)
|
case ATTR_STD_GENERATED:
|
||||||
return "generated";
|
return "generated";
|
||||||
else if(std == ATTR_STD_UV_TANGENT)
|
case ATTR_STD_GENERATED_TRANSFORM:
|
||||||
return "tangent";
|
|
||||||
else if(std == ATTR_STD_UV_TANGENT_SIGN)
|
|
||||||
return "tangent_sign";
|
|
||||||
else if(std == ATTR_STD_POSITION_UNDEFORMED)
|
|
||||||
return "undeformed";
|
|
||||||
else if(std == ATTR_STD_POSITION_UNDISPLACED)
|
|
||||||
return "undisplaced";
|
|
||||||
else if(std == ATTR_STD_MOTION_VERTEX_POSITION)
|
|
||||||
return "motion_P";
|
|
||||||
else if(std == ATTR_STD_MOTION_VERTEX_NORMAL)
|
|
||||||
return "motion_N";
|
|
||||||
else if(std == ATTR_STD_PARTICLE)
|
|
||||||
return "particle";
|
|
||||||
else if(std == ATTR_STD_CURVE_INTERCEPT)
|
|
||||||
return "curve_intercept";
|
|
||||||
else if(std == ATTR_STD_PTEX_FACE_ID)
|
|
||||||
return "ptex_face_id";
|
|
||||||
else if(std == ATTR_STD_PTEX_UV)
|
|
||||||
return "ptex_uv";
|
|
||||||
else if(std == ATTR_STD_GENERATED_TRANSFORM)
|
|
||||||
return "generated_transform";
|
return "generated_transform";
|
||||||
|
case ATTR_STD_UV_TANGENT:
|
||||||
|
return "tangent";
|
||||||
|
case ATTR_STD_UV_TANGENT_SIGN:
|
||||||
|
return "tangent_sign";
|
||||||
|
case ATTR_STD_POSITION_UNDEFORMED:
|
||||||
|
return "undeformed";
|
||||||
|
case ATTR_STD_POSITION_UNDISPLACED:
|
||||||
|
return "undisplaced";
|
||||||
|
case ATTR_STD_MOTION_VERTEX_POSITION:
|
||||||
|
return "motion_P";
|
||||||
|
case ATTR_STD_MOTION_VERTEX_NORMAL:
|
||||||
|
return "motion_N";
|
||||||
|
case ATTR_STD_PARTICLE:
|
||||||
|
return "particle";
|
||||||
|
case ATTR_STD_CURVE_INTERCEPT:
|
||||||
|
return "curve_intercept";
|
||||||
|
case ATTR_STD_PTEX_FACE_ID:
|
||||||
|
return "ptex_face_id";
|
||||||
|
case ATTR_STD_PTEX_UV:
|
||||||
|
return "ptex_uv";
|
||||||
|
case ATTR_STD_NOT_FOUND:
|
||||||
|
case ATTR_STD_NONE:
|
||||||
|
case ATTR_STD_NUM:
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AttributeStandard Attribute::name_standard(const char *name)
|
||||||
|
{
|
||||||
|
for(AttributeStandard std = ATTR_STD_NONE; std < ATTR_STD_NUM; std++)
|
||||||
|
if(strcmp(name, Attribute::standard_name(std)) == 0)
|
||||||
|
return std;
|
||||||
|
|
||||||
|
return ATTR_STD_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
/* Attribute Set */
|
/* Attribute Set */
|
||||||
|
|
||||||
AttributeSet::AttributeSet()
|
AttributeSet::AttributeSet()
|
||||||
|
@@ -27,12 +27,20 @@
|
|||||||
CCL_NAMESPACE_BEGIN
|
CCL_NAMESPACE_BEGIN
|
||||||
|
|
||||||
class Attribute;
|
class Attribute;
|
||||||
class AttributeSet;
|
|
||||||
class AttributeRequest;
|
class AttributeRequest;
|
||||||
class AttributeRequestSet;
|
class AttributeRequestSet;
|
||||||
|
class AttributeSet;
|
||||||
|
class ImageManager;
|
||||||
class Mesh;
|
class Mesh;
|
||||||
struct Transform;
|
struct Transform;
|
||||||
|
|
||||||
|
/* Attributes for voxels are images */
|
||||||
|
|
||||||
|
struct VoxelAttribute {
|
||||||
|
ImageManager *manager;
|
||||||
|
int slot;
|
||||||
|
};
|
||||||
|
|
||||||
/* Attribute
|
/* Attribute
|
||||||
*
|
*
|
||||||
* Arbitrary data layers on meshes.
|
* Arbitrary data layers on meshes.
|
||||||
@@ -48,6 +56,7 @@ public:
|
|||||||
AttributeElement element;
|
AttributeElement element;
|
||||||
|
|
||||||
Attribute() {}
|
Attribute() {}
|
||||||
|
~Attribute();
|
||||||
void set(ustring name, TypeDesc type, AttributeElement element);
|
void set(ustring name, TypeDesc type, AttributeElement element);
|
||||||
void reserve(int numverts, int numfaces, int numsteps, int numcurves, int numkeys, bool resize);
|
void reserve(int numverts, int numfaces, int numsteps, int numcurves, int numkeys, bool resize);
|
||||||
|
|
||||||
@@ -60,19 +69,23 @@ public:
|
|||||||
float4 *data_float4() { return (float4*)data(); }
|
float4 *data_float4() { return (float4*)data(); }
|
||||||
float *data_float() { return (float*)data(); }
|
float *data_float() { return (float*)data(); }
|
||||||
Transform *data_transform() { return (Transform*)data(); }
|
Transform *data_transform() { return (Transform*)data(); }
|
||||||
|
VoxelAttribute *data_voxel() { return ( VoxelAttribute*)data(); }
|
||||||
|
|
||||||
const char *data() const { return (buffer.size())? &buffer[0]: NULL; }
|
const char *data() const { return (buffer.size())? &buffer[0]: NULL; }
|
||||||
const float3 *data_float3() const { return (const float3*)data(); }
|
const float3 *data_float3() const { return (const float3*)data(); }
|
||||||
const float4 *data_float4() const { return (const float4*)data(); }
|
const float4 *data_float4() const { return (const float4*)data(); }
|
||||||
const float *data_float() const { return (const float*)data(); }
|
const float *data_float() const { return (const float*)data(); }
|
||||||
const Transform *data_transform() const { return (const Transform*)data(); }
|
const Transform *data_transform() const { return (const Transform*)data(); }
|
||||||
|
const VoxelAttribute *data_voxel() const { return (const VoxelAttribute*)data(); }
|
||||||
|
|
||||||
void add(const float& f);
|
void add(const float& f);
|
||||||
void add(const float3& f);
|
void add(const float3& f);
|
||||||
void add(const Transform& f);
|
void add(const Transform& f);
|
||||||
|
void add(const VoxelAttribute& f);
|
||||||
|
|
||||||
static bool same_storage(TypeDesc a, TypeDesc b);
|
static bool same_storage(TypeDesc a, TypeDesc b);
|
||||||
static const char *standard_name(AttributeStandard std);
|
static const char *standard_name(AttributeStandard std);
|
||||||
|
static AttributeStandard name_standard(const char *name);
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Attribute Set
|
/* Attribute Set
|
||||||
|
@@ -756,7 +756,12 @@ static void update_attribute_element_offset(Mesh *mesh, vector<float>& attr_floa
|
|||||||
mesh->curves.size(),
|
mesh->curves.size(),
|
||||||
mesh->curve_keys.size());
|
mesh->curve_keys.size());
|
||||||
|
|
||||||
if(mattr->type == TypeDesc::TypeFloat) {
|
if(mattr->element == ATTR_ELEMENT_VOXEL) {
|
||||||
|
/* store slot in offset value */
|
||||||
|
VoxelAttribute *voxel_data = mattr->data_voxel();
|
||||||
|
offset = voxel_data->slot;
|
||||||
|
}
|
||||||
|
else if(mattr->type == TypeDesc::TypeFloat) {
|
||||||
float *data = mattr->data_float();
|
float *data = mattr->data_float();
|
||||||
offset = attr_float.size();
|
offset = attr_float.size();
|
||||||
|
|
||||||
|
@@ -2209,10 +2209,11 @@ void TextureCoordinateNode::attributes(Shader *shader, AttributeRequestSet *attr
|
|||||||
|
|
||||||
if(shader->has_volume) {
|
if(shader->has_volume) {
|
||||||
if(!from_dupli) {
|
if(!from_dupli) {
|
||||||
if(!output("Generated")->links.empty())
|
if(!output("Generated")->links.empty()) {
|
||||||
attributes->add(ATTR_STD_GENERATED_TRANSFORM);
|
attributes->add(ATTR_STD_GENERATED_TRANSFORM);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ShaderNode::attributes(shader, attributes);
|
ShaderNode::attributes(shader, attributes);
|
||||||
}
|
}
|
||||||
@@ -3143,15 +3144,22 @@ AttributeNode::AttributeNode()
|
|||||||
|
|
||||||
void AttributeNode::attributes(Shader *shader, AttributeRequestSet *attributes)
|
void AttributeNode::attributes(Shader *shader, AttributeRequestSet *attributes)
|
||||||
{
|
{
|
||||||
if(shader->has_surface) {
|
|
||||||
ShaderOutput *color_out = output("Color");
|
ShaderOutput *color_out = output("Color");
|
||||||
ShaderOutput *vector_out = output("Vector");
|
ShaderOutput *vector_out = output("Vector");
|
||||||
ShaderOutput *fac_out = output("Fac");
|
ShaderOutput *fac_out = output("Fac");
|
||||||
|
|
||||||
if(!color_out->links.empty() || !vector_out->links.empty() || !fac_out->links.empty())
|
if(!color_out->links.empty() || !vector_out->links.empty() || !fac_out->links.empty()) {
|
||||||
|
AttributeStandard std = Attribute::name_standard(attribute.c_str());
|
||||||
|
|
||||||
|
if(std != ATTR_STD_NONE)
|
||||||
|
attributes->add(std);
|
||||||
|
else
|
||||||
attributes->add(attribute);
|
attributes->add(attribute);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(shader->has_volume)
|
||||||
|
attributes->add(ATTR_STD_GENERATED_TRANSFORM);
|
||||||
|
|
||||||
ShaderNode::attributes(shader, attributes);
|
ShaderNode::attributes(shader, attributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3161,6 +3169,13 @@ void AttributeNode::compile(SVMCompiler& compiler)
|
|||||||
ShaderOutput *vector_out = output("Vector");
|
ShaderOutput *vector_out = output("Vector");
|
||||||
ShaderOutput *fac_out = output("Fac");
|
ShaderOutput *fac_out = output("Fac");
|
||||||
NodeType attr_node = NODE_ATTR;
|
NodeType attr_node = NODE_ATTR;
|
||||||
|
AttributeStandard std = Attribute::name_standard(attribute.c_str());
|
||||||
|
int attr;
|
||||||
|
|
||||||
|
if(std != ATTR_STD_NONE)
|
||||||
|
attr = compiler.attribute(std);
|
||||||
|
else
|
||||||
|
attr = compiler.attribute(attribute);
|
||||||
|
|
||||||
if(bump == SHADER_BUMP_DX)
|
if(bump == SHADER_BUMP_DX)
|
||||||
attr_node = NODE_ATTR_BUMP_DX;
|
attr_node = NODE_ATTR_BUMP_DX;
|
||||||
@@ -3168,8 +3183,6 @@ void AttributeNode::compile(SVMCompiler& compiler)
|
|||||||
attr_node = NODE_ATTR_BUMP_DY;
|
attr_node = NODE_ATTR_BUMP_DY;
|
||||||
|
|
||||||
if(!color_out->links.empty() || !vector_out->links.empty()) {
|
if(!color_out->links.empty() || !vector_out->links.empty()) {
|
||||||
int attr = compiler.attribute(attribute);
|
|
||||||
|
|
||||||
if(!color_out->links.empty()) {
|
if(!color_out->links.empty()) {
|
||||||
compiler.stack_assign(color_out);
|
compiler.stack_assign(color_out);
|
||||||
compiler.add_node(attr_node, attr, color_out->stack_offset, NODE_ATTR_FLOAT3);
|
compiler.add_node(attr_node, attr, color_out->stack_offset, NODE_ATTR_FLOAT3);
|
||||||
@@ -3181,8 +3194,6 @@ void AttributeNode::compile(SVMCompiler& compiler)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(!fac_out->links.empty()) {
|
if(!fac_out->links.empty()) {
|
||||||
int attr = compiler.attribute(attribute);
|
|
||||||
|
|
||||||
compiler.stack_assign(fac_out);
|
compiler.stack_assign(fac_out);
|
||||||
compiler.add_node(attr_node, attr, fac_out->stack_offset, NODE_ATTR_FLOAT);
|
compiler.add_node(attr_node, attr, fac_out->stack_offset, NODE_ATTR_FLOAT);
|
||||||
}
|
}
|
||||||
@@ -3197,7 +3208,11 @@ void AttributeNode::compile(OSLCompiler& compiler)
|
|||||||
else
|
else
|
||||||
compiler.parameter("bump_offset", "center");
|
compiler.parameter("bump_offset", "center");
|
||||||
|
|
||||||
|
if(Attribute::name_standard(attribute.c_str()) != ATTR_STD_NONE)
|
||||||
|
compiler.parameter("name", (string("geom:") + attribute.c_str()).c_str());
|
||||||
|
else
|
||||||
compiler.parameter("name", attribute.c_str());
|
compiler.parameter("name", attribute.c_str());
|
||||||
|
|
||||||
compiler.add(this, "node_attribute");
|
compiler.add(this, "node_attribute");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user