Cycles: add light falloff node, with quadratic/linear/constant falloff and a

smoothing factor to reduce high values near the light.
http://wiki.blender.org/index.php/Doc:2.6/Manual/Render/Cycles/Nodes/More#Light_Falloff

Note that this was already possible to do manually with the Ray Length, but
this adds a convenient node for it. This commit also makes the mapping node
min/max option work, fixing #31348.
This commit is contained in:
Brecht Van Lommel 2012-05-07 20:24:38 +00:00
parent f44e80e638
commit e6a84eb1b5
15 changed files with 1785 additions and 1636 deletions

@ -97,6 +97,13 @@ static void get_tex_mapping(TextureMapping *mapping, BL::ShaderNodeMapping b_map
mapping->translation = get_float3(b_mapping.translation());
mapping->rotation = get_float3(b_mapping.rotation());
mapping->scale = get_float3(b_mapping.scale());
mapping->use_minmax = b_mapping.use_min() || b_mapping.use_max();
if(b_mapping.use_min())
mapping->min = get_float3(b_mapping.min());
if(b_mapping.use_max())
mapping->max = get_float3(b_mapping.max());
}
static ShaderNode *add_node(BL::BlendData b_data, ShaderGraph *graph, BL::ShaderNode b_node)
@ -323,6 +330,10 @@ static ShaderNode *add_node(BL::BlendData b_data, ShaderGraph *graph, BL::Shader
node = new LightPathNode();
break;
}
case BL::ShaderNode::type_LIGHT_FALLOFF: {
node = new LightFalloffNode();
break;
}
case BL::ShaderNode::type_TEX_IMAGE: {
BL::ShaderNodeTexImage b_image_node(b_node);
BL::Image b_image(b_image_node.image());

@ -326,6 +326,9 @@ __device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, ShaderT
case NODE_MAPPING:
svm_node_mapping(kg, sd, stack, node.y, node.z, &offset);
break;
case NODE_MIN_MAX:
svm_node_min_max(kg, sd, stack, node.y, node.z, &offset);
break;
case NODE_TEX_COORD:
svm_node_tex_coord(kg, sd, stack, node.y, node.z);
break;
@ -344,6 +347,9 @@ __device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, ShaderT
case NODE_RGB_CURVES:
svm_node_rgb_curves(kg, sd, stack, node, &offset);
break;
case NODE_LIGHT_FALLOFF:
svm_node_light_falloff(sd, stack, node);
break;
case NODE_END:
default:
#ifndef __MULTI_CLOSURE__

@ -39,5 +39,32 @@ __device void svm_node_light_path(ShaderData *sd, float *stack, uint type, uint
stack_store_float(stack, out_offset, info);
}
/* Light Falloff Node */
__device void svm_node_light_falloff(ShaderData *sd, float *stack, uint4 node)
{
uint strength_offset, out_offset, smooth_offset;
decode_node_uchar4(node.z, &strength_offset, &smooth_offset, &out_offset, NULL);
float strength = stack_load_float(stack, strength_offset);
uint type = node.y;
switch(type) {
case NODE_LIGHT_FALLOFF_QUADRATIC: break;
case NODE_LIGHT_FALLOFF_LINEAR: strength *= sd->ray_length; break;
case NODE_LIGHT_FALLOFF_CONSTANT: strength *= sd->ray_length*sd->ray_length; break;
}
float smooth = stack_load_float(stack, smooth_offset);
if(smooth > 0.0f) {
float squared = sd->ray_length*sd->ray_length;
strength *= squared/(smooth + squared);
}
stack_store_float(stack, out_offset, strength);
}
CCL_NAMESPACE_END

@ -34,5 +34,16 @@ __device void svm_node_mapping(KernelGlobals *kg, ShaderData *sd, float *stack,
stack_store_float3(stack, out_offset, r);
}
__device void svm_node_min_max(KernelGlobals *kg, ShaderData *sd, float *stack, uint vec_offset, uint out_offset, int *offset)
{
float3 v = stack_load_float3(stack, vec_offset);
float3 mn = float4_to_float3(read_node_float(kg, offset));
float3 mx = float4_to_float3(read_node_float(kg, offset));
float3 r = min(max(mn, v), mx);
stack_store_float3(stack, out_offset, r);
}
CCL_NAMESPACE_END

@ -90,7 +90,9 @@ typedef enum NodeType {
NODE_TEX_CHECKER = 5700,
NODE_BRIGHTCONTRAST = 5800,
NODE_RGB_RAMP = 5900,
NODE_RGB_CURVES = 6000
NODE_RGB_CURVES = 6000,
NODE_MIN_MAX = 6100,
NODE_LIGHT_FALLOFF = 6200
} NodeType;
typedef enum NodeAttributeType {
@ -119,6 +121,12 @@ typedef enum NodeLightPath {
NODE_LP_ray_length
} NodeLightPath;
typedef enum NodeLightFalloff {
NODE_LIGHT_FALLOFF_QUADRATIC,
NODE_LIGHT_FALLOFF_LINEAR,
NODE_LIGHT_FALLOFF_CONSTANT
} NodeLightFalloff;
typedef enum NodeTexCoord {
NODE_TEXCO_NORMAL,
NODE_TEXCO_OBJECT,

@ -33,6 +33,11 @@ TextureMapping::TextureMapping()
rotation = make_float3(0.0f, 0.0f, 0.0f);
scale = make_float3(1.0f, 1.0f, 1.0f);
min = make_float3(-FLT_MAX, -FLT_MAX, -FLT_MAX);
max = make_float3(FLT_MAX, FLT_MAX, FLT_MAX);
use_minmax = false;
x_mapping = X;
y_mapping = Y;
z_mapping = Z;
@ -69,6 +74,8 @@ bool TextureMapping::skip()
if(x_mapping != X || y_mapping != Y || z_mapping != Z)
return false;
if(use_minmax)
return false;
return true;
}
@ -85,6 +92,12 @@ void TextureMapping::compile(SVMCompiler& compiler, int offset_in, int offset_ou
compiler.add_node(tfm.y);
compiler.add_node(tfm.z);
compiler.add_node(tfm.w);
if(use_minmax) {
compiler.add_node(NODE_MIN_MAX, offset_out, offset_out);
compiler.add_node(float3_to_float4(min));
compiler.add_node(float3_to_float4(max));
}
}
/* Image Texture */
@ -1686,6 +1699,54 @@ void LightPathNode::compile(OSLCompiler& compiler)
compiler.add(this, "node_light_path");
}
/* Light Path */
LightFalloffNode::LightFalloffNode()
: ShaderNode("light_path")
{
add_input("Strength", SHADER_SOCKET_FLOAT, 100.0f);
add_input("Smooth", SHADER_SOCKET_FLOAT, 0.0f);
add_output("Quadratic", SHADER_SOCKET_FLOAT);
add_output("Linear", SHADER_SOCKET_FLOAT);
add_output("Constant", SHADER_SOCKET_FLOAT);
}
void LightFalloffNode::compile(SVMCompiler& compiler)
{
ShaderInput *strength_in = input("Strength");
ShaderInput *smooth_in = input("Smooth");
compiler.stack_assign(strength_in);
compiler.stack_assign(smooth_in);
ShaderOutput *out = output("Quadratic");
if(!out->links.empty()) {
compiler.stack_assign(out);
compiler.add_node(NODE_LIGHT_FALLOFF, NODE_LIGHT_FALLOFF_QUADRATIC,
compiler.encode_uchar4(strength_in->stack_offset, smooth_in->stack_offset, out->stack_offset));
}
out = output("Linear");
if(!out->links.empty()) {
compiler.stack_assign(out);
compiler.add_node(NODE_LIGHT_FALLOFF, NODE_LIGHT_FALLOFF_LINEAR,
compiler.encode_uchar4(strength_in->stack_offset, smooth_in->stack_offset, out->stack_offset));
compiler.add_node(NODE_LIGHT_FALLOFF, NODE_LIGHT_FALLOFF_LINEAR, out->stack_offset);
}
out = output("Constant");
if(!out->links.empty()) {
compiler.stack_assign(out);
compiler.add_node(NODE_LIGHT_FALLOFF, NODE_LIGHT_FALLOFF_CONSTANT,
compiler.encode_uchar4(strength_in->stack_offset, smooth_in->stack_offset, out->stack_offset));
}
}
void LightFalloffNode::compile(OSLCompiler& compiler)
{
compiler.add(this, "node_light_falloff");
}
/* Value */
ValueNode::ValueNode()

@ -41,6 +41,9 @@ public:
float3 rotation;
float3 scale;
float3 min, max;
bool use_minmax;
enum Mapping { NONE=0, X=1, Y=2, Z=3 };
Mapping x_mapping, y_mapping, z_mapping;
@ -277,6 +280,11 @@ public:
SHADER_NODE_CLASS(LightPathNode)
};
class LightFalloffNode : public ShaderNode {
public:
SHADER_NODE_CLASS(LightFalloffNode)
};
class ValueNode : public ShaderNode {
public:
SHADER_NODE_CLASS(ValueNode)

@ -508,9 +508,10 @@ struct ShadeResult;
#define SH_NODE_LAYER_WEIGHT 160
#define SH_NODE_VOLUME_TRANSPARENT 161
#define SH_NODE_VOLUME_ISOTROPIC 162
#define SH_NODE_GAMMA 163
#define SH_NODE_TEX_CHECKER 164
#define SH_NODE_GAMMA 163
#define SH_NODE_TEX_CHECKER 164
#define SH_NODE_BRIGHTCONTRAST 165
#define SH_NODE_LIGHT_FALLOFF 166
/* custom defines options for Material node */
#define SH_NODE_MAT_DIFF 1

@ -1969,6 +1969,7 @@ static void registerShaderNodes(bNodeTreeType *ttype)
register_node_type_sh_attribute(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_fresnel(ttype);
register_node_type_sh_layer_weight(ttype);
register_node_type_sh_tex_coord(ttype);

@ -2188,6 +2188,13 @@ void node_light_path(
is_transmission_ray = 0.0;
}
void node_light_falloff(float strength, float smooth, out float quadratic, out float linear, out float constant)
{
quadratic = strength;
linear = strength;
constant = strength;
}
/* output */
void node_output_material(vec4 surface, vec4 volume, float displacement, out vec4 result)

File diff suppressed because it is too large Load Diff

@ -77,7 +77,8 @@ DefNode( ShaderNode, SH_NODE_VOLUME_TRANSPARENT, 0, "VO
DefNode( ShaderNode, SH_NODE_VOLUME_ISOTROPIC, 0, "VOLUME_ISOTROPIC", VolumeIsotropic, "Isotropic Volume", "" )
DefNode( ShaderNode, SH_NODE_EMISSION, 0, "EMISSION", Emission, "Emission", "" )
DefNode( ShaderNode, SH_NODE_NEW_GEOMETRY, 0, "NEW_GEOMETRY", NewGeometry, "Geometry", "" )
DefNode( ShaderNode, SH_NODE_LIGHT_PATH, 0, "LIGHT_PATH", Light_path, "Light Path", "" )
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_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", "" )

@ -149,6 +149,7 @@ set(SRC
shader/nodes/node_shader_volume_transparent.c
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_mix_shader.c
shader/nodes/node_shader_add_shader.c
shader/nodes/node_shader_output_lamp.c

@ -73,6 +73,7 @@ void register_node_type_sh_hue_sat(struct bNodeTreeType *ttype);
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_fresnel(struct bNodeTreeType *ttype);
void register_node_type_sh_layer_weight(struct bNodeTreeType *ttype);
void register_node_type_sh_tex_coord(struct bNodeTreeType *ttype);

@ -0,0 +1,68 @@
/*
* ***** 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"
/* **************** INPUT ********************* */
static bNodeSocketTemplate sh_node_light_falloff_in[]= {
{ SOCK_FLOAT, 0, "Strength", 100.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_FLOAT, 0, "Smooth", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ -1, 0, "" }
};
/* **************** OUTPUT ******************** */
static bNodeSocketTemplate sh_node_light_falloff_out[]= {
{ SOCK_FLOAT, 0, "Quadratic", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_FLOAT, 0, "Linear", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_FLOAT, 0, "Constant", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ -1, 0, "" }
};
static int node_shader_gpu_light_falloff(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out)
{
return GPU_stack_link(mat, "node_light_falloff", in, out);
}
/* node type definition */
void register_node_type_sh_light_falloff(bNodeTreeType *ttype)
{
static bNodeType ntype;
node_type_base(ttype, &ntype, SH_NODE_LIGHT_FALLOFF, "Light Falloff", NODE_CLASS_OP_COLOR, 0);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_light_falloff_in, sh_node_light_falloff_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_light_falloff);
nodeRegisterType(ttype, &ntype);
}