forked from bartvdbraak/blender
Cycles: add Object Info node, with outputs object location, object/material
pass index, and a random number unique to the instance of the object. This can be useful to give some variation to a single material assigned to multiple instances, either manually controlled through the object index, based on the object location, or randomized for each instance. http://wiki.blender.org/index.php/Doc:2.6/Manual/Render/Cycles/Nodes/More#Object_Info
This commit is contained in:
parent
ea11bc980a
commit
c3e1fce775
@ -245,6 +245,7 @@ void BlenderSync::sync_object(BL::Object b_parent, int b_index, BL::Object b_ob,
|
||||
/* object sync */
|
||||
if(object_updated || (object->mesh && object->mesh->need_update)) {
|
||||
object->name = b_ob.name().c_str();
|
||||
object->instance_id = b_index;
|
||||
object->pass_id = b_ob.pass_index();
|
||||
object->tfm = tfm;
|
||||
object->motion.pre = tfm;
|
||||
|
@ -334,6 +334,10 @@ static ShaderNode *add_node(BL::BlendData b_data, ShaderGraph *graph, BL::Shader
|
||||
node = new LightFalloffNode();
|
||||
break;
|
||||
}
|
||||
case BL::ShaderNode::type_OBJECT_INFO: {
|
||||
node = new ObjectInfoNode();
|
||||
break;
|
||||
}
|
||||
case BL::ShaderNode::type_TEX_IMAGE: {
|
||||
BL::ShaderNodeTexImage b_image_node(b_node);
|
||||
BL::Image b_image(b_image_node.image());
|
||||
|
@ -117,6 +117,16 @@ __device_inline void object_dir_transform(KernelGlobals *kg, ShaderData *sd, flo
|
||||
#endif
|
||||
}
|
||||
|
||||
__device_inline float3 object_location(KernelGlobals *kg, ShaderData *sd)
|
||||
{
|
||||
#ifdef __MOTION__
|
||||
return make_float3(sd->ob_tfm.x.w, sd->ob_tfm.y.w, sd->ob_tfm.z.w);
|
||||
#else
|
||||
Transform tfm = object_fetch_transform(kg, sd->object, 0.0f, OBJECT_TRANSFORM);
|
||||
return make_float3(tfm.x.w, tfm.y.w, tfm.z.w);
|
||||
#endif
|
||||
}
|
||||
|
||||
__device_inline float object_surface_area(KernelGlobals *kg, int object)
|
||||
{
|
||||
int offset = object*OBJECT_SIZE + OBJECT_PROPERTIES;
|
||||
@ -134,5 +144,20 @@ __device_inline float object_pass_id(KernelGlobals *kg, int object)
|
||||
return f.y;
|
||||
}
|
||||
|
||||
__device_inline float object_random_number(KernelGlobals *kg, int object)
|
||||
{
|
||||
if(object == ~0)
|
||||
return 0.0f;
|
||||
|
||||
int offset = object*OBJECT_SIZE + OBJECT_PROPERTIES;
|
||||
float4 f = kernel_tex_fetch(__objects, offset);
|
||||
return f.z;
|
||||
}
|
||||
|
||||
__device int shader_pass_id(KernelGlobals *kg, ShaderData *sd)
|
||||
{
|
||||
return kernel_tex_fetch(__shader_flag, (sd->shader & SHADER_MASK)*2 + 1);
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
|
@ -679,11 +679,6 @@ __device bool shader_transparent_shadow(KernelGlobals *kg, Intersection *isect)
|
||||
}
|
||||
#endif
|
||||
|
||||
__device int shader_pass_id(KernelGlobals *kg, ShaderData *sd)
|
||||
{
|
||||
return kernel_tex_fetch(__shader_flag, (sd->shader & SHADER_MASK)*2 + 1);
|
||||
}
|
||||
|
||||
/* Free ShaderData */
|
||||
|
||||
__device void shader_release(KernelGlobals *kg, ShaderData *sd)
|
||||
|
@ -266,6 +266,9 @@ __device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, ShaderT
|
||||
case NODE_LIGHT_PATH:
|
||||
svm_node_light_path(sd, stack, node.y, node.z, path_flag);
|
||||
break;
|
||||
case NODE_OBJECT_INFO:
|
||||
svm_node_object_info(kg, sd, stack, node.y, node.z);
|
||||
break;
|
||||
#endif
|
||||
case NODE_CONVERT:
|
||||
svm_node_convert(sd, stack, node.y, node.z, node.w);
|
||||
|
@ -74,5 +74,25 @@ __device void svm_node_geometry_bump_dy(ShaderData *sd, float *stack, uint type,
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Object Info */
|
||||
|
||||
__device void svm_node_object_info(KernelGlobals *kg, ShaderData *sd, float *stack, uint type, uint out_offset)
|
||||
{
|
||||
float data;
|
||||
|
||||
switch(type) {
|
||||
case NODE_INFO_OB_LOCATION: {
|
||||
stack_store_float3(stack, out_offset, object_location(kg, sd));
|
||||
return;
|
||||
}
|
||||
case NODE_INFO_OB_INDEX: data = object_pass_id(kg, sd->object); break;
|
||||
case NODE_INFO_MAT_INDEX: data = shader_pass_id(kg, sd); break;
|
||||
case NODE_INFO_OB_RANDOM: data = object_random_number(kg, sd->object); break;
|
||||
default: data = 0.0f; break;
|
||||
}
|
||||
|
||||
stack_store_float(stack, out_offset, data);
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
|
@ -92,7 +92,8 @@ typedef enum NodeType {
|
||||
NODE_RGB_RAMP = 5900,
|
||||
NODE_RGB_CURVES = 6000,
|
||||
NODE_MIN_MAX = 6100,
|
||||
NODE_LIGHT_FALLOFF = 6200
|
||||
NODE_LIGHT_FALLOFF = 6200,
|
||||
NODE_OBJECT_INFO = 6300
|
||||
} NodeType;
|
||||
|
||||
typedef enum NodeAttributeType {
|
||||
@ -109,6 +110,13 @@ typedef enum NodeGeometry {
|
||||
NODE_GEOM_uv
|
||||
} NodeGeometry;
|
||||
|
||||
typedef enum NodeObjectInfo {
|
||||
NODE_INFO_OB_LOCATION,
|
||||
NODE_INFO_OB_INDEX,
|
||||
NODE_INFO_MAT_INDEX,
|
||||
NODE_INFO_OB_RANDOM
|
||||
} NodeObjectInfo;
|
||||
|
||||
typedef enum NodeLightPath {
|
||||
NODE_LP_camera = 0,
|
||||
NODE_LP_shadow,
|
||||
|
@ -1699,7 +1699,7 @@ void LightPathNode::compile(OSLCompiler& compiler)
|
||||
compiler.add(this, "node_light_path");
|
||||
}
|
||||
|
||||
/* Light Path */
|
||||
/* Light Falloff */
|
||||
|
||||
LightFalloffNode::LightFalloffNode()
|
||||
: ShaderNode("light_path")
|
||||
@ -1746,6 +1746,49 @@ void LightFalloffNode::compile(OSLCompiler& compiler)
|
||||
compiler.add(this, "node_light_falloff");
|
||||
}
|
||||
|
||||
/* Object Info */
|
||||
|
||||
ObjectInfoNode::ObjectInfoNode()
|
||||
: ShaderNode("object_info")
|
||||
{
|
||||
add_output("Location", SHADER_SOCKET_VECTOR);
|
||||
add_output("Object Index", SHADER_SOCKET_FLOAT);
|
||||
add_output("Material Index", SHADER_SOCKET_FLOAT);
|
||||
add_output("Random", SHADER_SOCKET_FLOAT);
|
||||
}
|
||||
|
||||
void ObjectInfoNode::compile(SVMCompiler& compiler)
|
||||
{
|
||||
ShaderOutput *out = output("Location");
|
||||
if(!out->links.empty()) {
|
||||
compiler.stack_assign(out);
|
||||
compiler.add_node(NODE_OBJECT_INFO, NODE_INFO_OB_LOCATION, out->stack_offset);
|
||||
}
|
||||
|
||||
out = output("Object Index");
|
||||
if(!out->links.empty()) {
|
||||
compiler.stack_assign(out);
|
||||
compiler.add_node(NODE_OBJECT_INFO, NODE_INFO_OB_INDEX, out->stack_offset);
|
||||
}
|
||||
|
||||
out = output("Material Index");
|
||||
if(!out->links.empty()) {
|
||||
compiler.stack_assign(out);
|
||||
compiler.add_node(NODE_OBJECT_INFO, NODE_INFO_MAT_INDEX, out->stack_offset);
|
||||
}
|
||||
|
||||
out = output("Random");
|
||||
if(!out->links.empty()) {
|
||||
compiler.stack_assign(out);
|
||||
compiler.add_node(NODE_OBJECT_INFO, NODE_INFO_OB_RANDOM, out->stack_offset);
|
||||
}
|
||||
}
|
||||
|
||||
void ObjectInfoNode::compile(OSLCompiler& compiler)
|
||||
{
|
||||
compiler.add(this, "node_object_info");
|
||||
}
|
||||
|
||||
/* Value */
|
||||
|
||||
ValueNode::ValueNode()
|
||||
|
@ -285,6 +285,11 @@ public:
|
||||
SHADER_NODE_CLASS(LightFalloffNode)
|
||||
};
|
||||
|
||||
class ObjectInfoNode : public ShaderNode {
|
||||
public:
|
||||
SHADER_NODE_CLASS(ObjectInfoNode)
|
||||
};
|
||||
|
||||
class ValueNode : public ShaderNode {
|
||||
public:
|
||||
SHADER_NODE_CLASS(ValueNode)
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "scene.h"
|
||||
|
||||
#include "util_foreach.h"
|
||||
#include "util_hash.h"
|
||||
#include "util_map.h"
|
||||
#include "util_progress.h"
|
||||
|
||||
@ -36,6 +37,7 @@ Object::Object()
|
||||
mesh = NULL;
|
||||
tfm = transform_identity();
|
||||
visibility = ~0;
|
||||
instance_id = 0;
|
||||
pass_id = 0;
|
||||
bounds = BoundBox::empty;
|
||||
motion.pre = transform_identity();
|
||||
@ -164,6 +166,9 @@ void ObjectManager::device_update_transforms(Device *device, DeviceScene *dscene
|
||||
float surface_area = 0.0f;
|
||||
float pass_id = ob->pass_id;
|
||||
|
||||
uint ob_hash = hash_int_2d(hash_string(ob->name.c_str()), ob->instance_id);
|
||||
float random_number = (float)ob_hash * (1.0f/(float)0xFFFFFFFF);
|
||||
|
||||
if(transform_uniform_scale(tfm, uniform_scale)) {
|
||||
map<Mesh*, float>::iterator it = surface_area_map.find(mesh);
|
||||
|
||||
@ -198,7 +203,7 @@ void ObjectManager::device_update_transforms(Device *device, DeviceScene *dscene
|
||||
|
||||
memcpy(&objects[offset], &tfm, sizeof(float4)*3);
|
||||
memcpy(&objects[offset+3], &itfm, sizeof(float4)*3);
|
||||
objects[offset+6] = make_float4(surface_area, pass_id, 0.0f, 0.0f);
|
||||
objects[offset+6] = make_float4(surface_area, pass_id, random_number, 0.0f);
|
||||
|
||||
if(need_motion == Scene::MOTION_PASS) {
|
||||
/* motion transformations, is world/object space depending if mesh
|
||||
|
@ -41,6 +41,7 @@ public:
|
||||
Transform tfm;
|
||||
BoundBox bounds;
|
||||
ustring name;
|
||||
int instance_id;
|
||||
int pass_id;
|
||||
vector<ParamValue> attributes;
|
||||
uint visibility;
|
||||
|
@ -19,13 +19,15 @@
|
||||
#ifndef __UTIL_HASH_H__
|
||||
#define __UTIL_HASH_H__
|
||||
|
||||
#include "util_types.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
static inline unsigned int hash_int_2d(unsigned int kx, unsigned int ky)
|
||||
static inline uint hash_int_2d(uint kx, uint ky)
|
||||
{
|
||||
#define rot(x,k) (((x)<<(k)) | ((x)>>(32-(k))))
|
||||
|
||||
unsigned int a, b, c;
|
||||
uint a, b, c;
|
||||
|
||||
a = b = c = 0xdeadbeef + (2 << 2) + 13;
|
||||
a += kx;
|
||||
@ -44,11 +46,21 @@ static inline unsigned int hash_int_2d(unsigned int kx, unsigned int ky)
|
||||
#undef rot
|
||||
}
|
||||
|
||||
static inline unsigned int hash_int(unsigned int k)
|
||||
static inline uint hash_int(uint k)
|
||||
{
|
||||
return hash_int_2d(k, 0);
|
||||
}
|
||||
|
||||
static inline uint hash_string(const char *str)
|
||||
{
|
||||
uint i = 0, c;
|
||||
|
||||
while ((c = *str++))
|
||||
i = i * 37 + c;
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
#endif /* __UTIL_HASH_H__ */
|
||||
|
@ -516,6 +516,7 @@ struct ShadeResult;
|
||||
#define SH_NODE_TEX_CHECKER 164
|
||||
#define SH_NODE_BRIGHTCONTRAST 165
|
||||
#define SH_NODE_LIGHT_FALLOFF 166
|
||||
#define SH_NODE_OBJECT_INFO 167
|
||||
|
||||
/* custom defines options for Material node */
|
||||
#define SH_NODE_MAT_DIFF 1
|
||||
|
@ -1977,6 +1977,7 @@ static void registerShaderNodes(bNodeTreeType *ttype)
|
||||
register_node_type_sh_geometry(ttype);
|
||||
register_node_type_sh_light_path(ttype);
|
||||
register_node_type_sh_light_falloff(ttype);
|
||||
register_node_type_sh_object_info(ttype);
|
||||
register_node_type_sh_fresnel(ttype);
|
||||
register_node_type_sh_layer_weight(ttype);
|
||||
register_node_type_sh_tex_coord(ttype);
|
||||
|
@ -2206,6 +2206,15 @@ void node_light_falloff(float strength, float tsmooth, out float quadratic, out
|
||||
constant = strength;
|
||||
}
|
||||
|
||||
void node_object_info(out vec3 location, out float object_index, out float material_index, out float random)
|
||||
{
|
||||
location = vec3(0.0);
|
||||
object_index = 0.0;
|
||||
material_index = 0.0;
|
||||
random = 0.0;
|
||||
}
|
||||
|
||||
|
||||
/* output */
|
||||
|
||||
void node_output_material(vec4 surface, vec4 volume, float displacement, out vec4 result)
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -79,6 +79,7 @@ DefNode( ShaderNode, SH_NODE_EMISSION, 0, "EM
|
||||
DefNode( ShaderNode, SH_NODE_NEW_GEOMETRY, 0, "NEW_GEOMETRY", NewGeometry, "Geometry", "" )
|
||||
DefNode( ShaderNode, SH_NODE_LIGHT_PATH, 0, "LIGHT_PATH", LightPath, "Light Path", "" )
|
||||
DefNode( ShaderNode, SH_NODE_LIGHT_FALLOFF, 0, "LIGHT_FALLOFF", LightFalloff, "Light Falloff", "" )
|
||||
DefNode( ShaderNode, SH_NODE_OBJECT_INFO, 0, "OBJECT_INFO", ObjectInfo, "Object Info", "" )
|
||||
DefNode( ShaderNode, SH_NODE_TEX_IMAGE, def_sh_tex_image, "TEX_IMAGE", TexImage, "Image Texture", "" )
|
||||
DefNode( ShaderNode, SH_NODE_TEX_ENVIRONMENT, def_sh_tex_environment, "TEX_ENVIRONMENT", TexEnvironment, "Environment Texture","" )
|
||||
DefNode( ShaderNode, SH_NODE_TEX_SKY, def_sh_tex_sky, "TEX_SKY", TexSky, "Sky Texture", "" )
|
||||
|
@ -158,6 +158,7 @@ set(SRC
|
||||
shader/nodes/node_shader_volume_isotropic.c
|
||||
shader/nodes/node_shader_light_path.c
|
||||
shader/nodes/node_shader_light_falloff.c
|
||||
shader/nodes/node_shader_object_info.c
|
||||
shader/nodes/node_shader_mix_shader.c
|
||||
shader/nodes/node_shader_add_shader.c
|
||||
shader/nodes/node_shader_output_lamp.c
|
||||
|
@ -74,6 +74,7 @@ void register_node_type_sh_attribute(struct bNodeTreeType *ttype);
|
||||
void register_node_type_sh_geometry(struct bNodeTreeType *ttype);
|
||||
void register_node_type_sh_light_path(struct bNodeTreeType *ttype);
|
||||
void register_node_type_sh_light_falloff(struct bNodeTreeType *ttype);
|
||||
void register_node_type_sh_object_info(struct bNodeTreeType *ttype);
|
||||
void register_node_type_sh_fresnel(struct bNodeTreeType *ttype);
|
||||
void register_node_type_sh_layer_weight(struct bNodeTreeType *ttype);
|
||||
void register_node_type_sh_tex_coord(struct bNodeTreeType *ttype);
|
||||
|
61
source/blender/nodes/shader/nodes/node_shader_object_info.c
Normal file
61
source/blender/nodes/shader/nodes/node_shader_object_info.c
Normal file
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2005 Blender Foundation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* The Original Code is: all of this file.
|
||||
*
|
||||
* Contributor(s): none yet.
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
#include "../node_shader_util.h"
|
||||
|
||||
/* **************** OUTPUT ******************** */
|
||||
|
||||
static bNodeSocketTemplate sh_node_object_info_out[]= {
|
||||
{ SOCK_VECTOR, 0, "Location", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
|
||||
{ SOCK_FLOAT, 0, "Object Index", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
|
||||
{ SOCK_FLOAT, 0, "Material Index", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
|
||||
{ SOCK_FLOAT, 0, "Random", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
|
||||
{ -1, 0, "" }
|
||||
};
|
||||
|
||||
static int node_shader_gpu_object_info(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out)
|
||||
{
|
||||
return GPU_stack_link(mat, "node_object_info", in, out);
|
||||
}
|
||||
|
||||
/* node type definition */
|
||||
void register_node_type_sh_object_info(bNodeTreeType *ttype)
|
||||
{
|
||||
static bNodeType ntype;
|
||||
|
||||
node_type_base(ttype, &ntype, SH_NODE_OBJECT_INFO, "Object Info", NODE_CLASS_INPUT, 0);
|
||||
node_type_compatibility(&ntype, NODE_NEW_SHADING);
|
||||
node_type_socket_templates(&ntype, NULL, sh_node_object_info_out);
|
||||
node_type_size(&ntype, 150, 60, 200);
|
||||
node_type_init(&ntype, NULL);
|
||||
node_type_storage(&ntype, "", NULL, NULL);
|
||||
node_type_exec(&ntype, NULL);
|
||||
node_type_gpu(&ntype, node_shader_gpu_object_info);
|
||||
|
||||
nodeRegisterType(ttype, &ntype);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user