Cycles: 4 new nodes.

* Tangent: generate a tangent direction for anisotropic shading. Can be either
  radial around X/Y/Z axis, or from a UV map. The default tangent for the
  anisotropic BSDF and geometry node is now always radial Z, for UV tangent use
  this node now.

http://wiki.blender.org/index.php/Doc:2.6/Manual/Render/Cycles/Nodes/More#Tangent

* Normal Map: generate a perturbed normal from an RGB normal map image. This
  is usually chained with an Image Texture node in the color input, to specify
  the normal map image. For tangent space normal maps, the UV coordinates for
  the image must match, and the image texture should be set to Non-Color mode
  to give correct results.

http://wiki.blender.org/index.php/Doc:2.6/Manual/Render/Cycles/Nodes/More#Normal_Map

* Refraction BSDF: for best results this node should be considered as a building
  block and not be used on its own, but rather mixed with a glossy node using a
  fresnel type factor. Otherwise it will give quite dark results at the edges for
  glossy refraction.

http://wiki.blender.org/index.php/Doc:2.6/Manual/Render/Cycles/Nodes/Shaders#Refraction

* Ambient Occlusion: controls the amount of AO a surface receives, rather than
  having just a global factor in the world. Note that this outputs a shader and
  not a color, that's for another time.

http://wiki.blender.org/index.php/Doc:2.6/Manual/Render/Cycles/Nodes/Shaders#Ambient_Occlusion
This commit is contained in:
Brecht Van Lommel
2012-11-06 19:59:02 +00:00
parent ccffb6811c
commit 27d647dcf8
40 changed files with 1280 additions and 127 deletions

View File

@@ -116,7 +116,7 @@ static void mikk_set_tangent_space(const SMikkTSpaceContext *context, const floa
userdata->tangent[face*4 + vert] = make_float4(T[0], T[1], T[2], sign);
}
static void mikk_compute_tangents(BL::Mesh b_mesh, BL::MeshTextureFaceLayer b_layer, Mesh *mesh, vector<int>& nverts)
static void mikk_compute_tangents(BL::Mesh b_mesh, BL::MeshTextureFaceLayer b_layer, Mesh *mesh, vector<int>& nverts, bool need_sign, bool active_render)
{
/* setup userdata */
MikkUserData userdata(b_mesh, b_layer, nverts.size());
@@ -140,22 +140,57 @@ static void mikk_compute_tangents(BL::Mesh b_mesh, BL::MeshTextureFaceLayer b_la
/* compute tangents */
genTangSpaceDefault(&context);
/* create attribute */
/* todo: create float4 attribute for sign */
Attribute *attr = mesh->attributes.add(ATTR_STD_TANGENT, ustring("tangent"));
/* create tangent attributes */
Attribute *attr;
ustring name = ustring((string(b_layer.name().c_str()) + ".tangent").c_str());
if(active_render)
attr = mesh->attributes.add(ATTR_STD_UV_TANGENT, name);
else
attr = mesh->attributes.add(name, TypeDesc::TypeVector, Attribute::CORNER);
float3 *tangent = attr->data_float3();
for (int i = 0; i < nverts.size(); i++) {
/* create bitangent sign attribute */
float *tangent_sign = NULL;
if(need_sign) {
Attribute *attr_sign;
ustring name_sign = ustring((string(b_layer.name().c_str()) + ".tangent_sign").c_str());
if(active_render)
attr_sign = mesh->attributes.add(ATTR_STD_UV_TANGENT_SIGN, name_sign);
else
attr_sign = mesh->attributes.add(name_sign, TypeDesc::TypeFloat, Attribute::CORNER);
tangent_sign = attr_sign->data_float();
}
for(int i = 0; i < nverts.size(); i++) {
tangent[0] = float4_to_float3(userdata.tangent[i*4 + 0]);
tangent[1] = float4_to_float3(userdata.tangent[i*4 + 1]);
tangent[2] = float4_to_float3(userdata.tangent[i*4 + 2]);
tangent += 3;
if(tangent_sign) {
tangent_sign[0] = userdata.tangent[i*4 + 0].w;
tangent_sign[1] = userdata.tangent[i*4 + 1].w;
tangent_sign[2] = userdata.tangent[i*4 + 2].w;
tangent_sign += 3;
}
if(nverts[i] == 4) {
tangent[0] = float4_to_float3(userdata.tangent[i*4 + 0]);
tangent[1] = float4_to_float3(userdata.tangent[i*4 + 2]);
tangent[2] = float4_to_float3(userdata.tangent[i*4 + 3]);
tangent += 3;
if(tangent_sign) {
tangent_sign[0] = userdata.tangent[i*4 + 0].w;
tangent_sign[1] = userdata.tangent[i*4 + 2].w;
tangent_sign[2] = userdata.tangent[i*4 + 3].w;
tangent_sign += 3;
}
}
}
}
@@ -233,48 +268,49 @@ static void create_mesh(Scene *scene, Mesh *mesh, BL::Mesh b_mesh, const vector<
BL::Mesh::tessface_uv_textures_iterator l;
for(b_mesh.tessface_uv_textures.begin(l); l != b_mesh.tessface_uv_textures.end(); ++l) {
AttributeStandard std = (l->active_render())? ATTR_STD_UV: ATTR_STD_NONE;
bool active_render = l->active_render();
AttributeStandard std = (active_render)? ATTR_STD_UV: ATTR_STD_NONE;
ustring name = ustring(l->name().c_str());
if(!(mesh->need_attribute(scene, name) || mesh->need_attribute(scene, std)))
continue;
/* UV map */
if(mesh->need_attribute(scene, name) || mesh->need_attribute(scene, std)) {
Attribute *attr;
Attribute *attr;
if(active_render)
attr = mesh->attributes.add(std, name);
else
attr = mesh->attributes.add(name, TypeDesc::TypePoint, Attribute::CORNER);
if(l->active_render())
attr = mesh->attributes.add(std, name);
else
attr = mesh->attributes.add(name, TypeDesc::TypePoint, Attribute::CORNER);
BL::MeshTextureFaceLayer::data_iterator t;
float3 *fdata = attr->data_float3();
size_t i = 0;
BL::MeshTextureFaceLayer::data_iterator t;
float3 *fdata = attr->data_float3();
size_t i = 0;
for(l->data.begin(t); t != l->data.end(); ++t, ++i) {
fdata[0] = get_float3(t->uv1());
fdata[1] = get_float3(t->uv2());
fdata[2] = get_float3(t->uv3());
fdata += 3;
if(nverts[i] == 4) {
for(l->data.begin(t); t != l->data.end(); ++t, ++i) {
fdata[0] = get_float3(t->uv1());
fdata[1] = get_float3(t->uv3());
fdata[2] = get_float3(t->uv4());
fdata[1] = get_float3(t->uv2());
fdata[2] = get_float3(t->uv3());
fdata += 3;
if(nverts[i] == 4) {
fdata[0] = get_float3(t->uv1());
fdata[1] = get_float3(t->uv3());
fdata[2] = get_float3(t->uv4());
fdata += 3;
}
}
}
}
}
/* create texcoord-based tangent attributes */
if(mesh->need_attribute(scene, ATTR_STD_TANGENT)) {
BL::Mesh::tessface_uv_textures_iterator l;
/* UV tangent */
std = (active_render)? ATTR_STD_UV_TANGENT: ATTR_STD_NONE;
name = ustring((string(name.c_str()) + ".tangent").c_str());
for(b_mesh.tessface_uv_textures.begin(l); l != b_mesh.tessface_uv_textures.end(); ++l) {
if(!l->active_render())
continue;
if(mesh->need_attribute(scene, name) || mesh->need_attribute(scene, std)) {
std = (active_render)? ATTR_STD_UV_TANGENT_SIGN: ATTR_STD_NONE;
name = ustring((string(name.c_str()) + ".tangent_sign").c_str());
bool need_sign = (mesh->need_attribute(scene, name) || mesh->need_attribute(scene, std));
mikk_compute_tangents(b_mesh, *l, mesh, nverts);
mikk_compute_tangents(b_mesh, *l, mesh, nverts, need_sign, active_render);
}
}
}

View File

@@ -173,6 +173,7 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen
case BL::ShaderNode::type_OUTPUT: break;
case BL::ShaderNode::type_SQUEEZE: break;
case BL::ShaderNode::type_TEXTURE: break;
case BL::ShaderNode::type_FRAME: break;
/* handled outside this function */
case BL::ShaderNode::type_GROUP: break;
/* existing blender nodes */
@@ -366,6 +367,23 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen
node = glass;
break;
}
case BL::ShaderNode::type_BSDF_REFRACTION: {
BL::ShaderNodeBsdfRefraction b_refraction_node(b_node);
RefractionBsdfNode *refraction = new RefractionBsdfNode();
switch(b_refraction_node.distribution()) {
case BL::ShaderNodeBsdfRefraction::distribution_SHARP:
refraction->distribution = ustring("Sharp");
break;
case BL::ShaderNodeBsdfRefraction::distribution_BECKMANN:
refraction->distribution = ustring("Beckmann");
break;
case BL::ShaderNodeBsdfRefraction::distribution_GGX:
refraction->distribution = ustring("GGX");
break;
}
node = refraction;
break;
}
case BL::ShaderNode::type_BSDF_TRANSLUCENT: {
node = new TranslucentBsdfNode();
break;
@@ -382,6 +400,10 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen
node = new EmissionNode();
break;
}
case BL::ShaderNode::type_AMBIENT_OCCLUSION: {
node = new AmbientOcclusionNode();
break;
}
case BL::ShaderNode::type_VOLUME_ISOTROPIC: {
node = new IsotropicVolumeNode();
break;
@@ -573,7 +595,21 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen
node = sky;
break;
}
case BL::ShaderNode::type_FRAME: {
case BL::ShaderNode::type_NORMAL_MAP: {
BL::ShaderNodeNormalMap b_normal_map_node(b_node);
NormalMapNode *nmap = new NormalMapNode();
nmap->space = NormalMapNode::space_enum[(int)b_normal_map_node.space()];
nmap->attribute = b_normal_map_node.uv_map();
node = nmap;
break;
}
case BL::ShaderNode::type_TANGENT: {
BL::ShaderNodeTangent b_tangent_node(b_node);
TangentNode *tangent = new TangentNode();
tangent->direction_type = TangentNode::direction_type_enum[(int)b_tangent_node.direction_type()];
tangent->axis = TangentNode::axis_enum[(int)b_tangent_node.axis()];
tangent->attribute = b_tangent_node.uv_map();
node = tangent;
break;
}
}

View File

@@ -68,7 +68,10 @@ __device float3 bsdf_ward_eval_reflect(const ShaderClosure *sc, const float3 I,
float cosNO = dot(N, I);
float cosNI = dot(N, omega_in);
if(cosNI > 0 && cosNO > 0) {
if(cosNI > 0.0f && cosNO > 0.0f) {
cosNO = max(cosNO, 1e-4f);
cosNI = max(cosNI, 1e-4f);
// get half vector and get x,y basis on the surface for anisotropy
float3 H = normalize(omega_in + I); // normalize needed for pdf
float3 X, Y;
@@ -103,7 +106,7 @@ __device int bsdf_ward_sample(const ShaderClosure *sc, float3 Ng, float3 I, floa
float3 T = sc->T;
float cosNO = dot(N, I);
if(cosNO > 0) {
if(cosNO > 0.0f) {
// get x,y basis on the surface for anisotropy
float3 X, Y;
make_orthonormals_tangent(N, T, &X, &Y);
@@ -165,6 +168,9 @@ __device int bsdf_ward_sample(const ShaderClosure *sc, float3 Ng, float3 I, floa
if(dot(Ng, *omega_in) > 0) {
float cosNI = dot(N, *omega_in);
if(cosNI > 0) {
cosNO = max(cosNO, 1e-4f);
cosNI = max(cosNI, 1e-4f);
// eq. 9
float exp_arg = (dotx * dotx + doty * doty) / (dotn * dotn);
float denom = 4 * M_PI_F * m_ax * m_ay * oh * dotn * dotn * dotn;

View File

@@ -326,7 +326,7 @@ __device float4 kernel_path_progressive(KernelGlobals *kg, RNG *rng, int sample,
#ifdef __AO__
/* ambient occlusion */
if(kernel_data.integrator.use_ambient_occlusion) {
if(kernel_data.integrator.use_ambient_occlusion || (sd.flag & SD_AO)) {
/* todo: solve correlation */
float bsdf_u = path_rng(kg, rng, sample, rng_offset + PRNG_BSDF_U);
float bsdf_v = path_rng(kg, rng, sample, rng_offset + PRNG_BSDF_V);
@@ -349,6 +349,7 @@ __device float4 kernel_path_progressive(KernelGlobals *kg, RNG *rng, int sample,
if(!shadow_blocked(kg, &state, &light_ray, &ao_shadow)) {
float3 ao_bsdf = shader_bsdf_diffuse(kg, &sd)*kernel_data.background.ao_factor;
ao_bsdf += shader_bsdf_ao(kg, &sd);
path_radiance_accum_ao(&L, throughput, ao_bsdf, ao_shadow, state.bounce);
}
}
@@ -503,7 +504,7 @@ __device void kernel_path_indirect(KernelGlobals *kg, RNG *rng, int sample, Ray
#ifdef __AO__
/* ambient occlusion */
if(kernel_data.integrator.use_ambient_occlusion) {
if(kernel_data.integrator.use_ambient_occlusion || (sd.flag & SD_AO)) {
/* todo: solve correlation */
float bsdf_u = path_rng(kg, rng, sample, rng_offset + PRNG_BSDF_U);
float bsdf_v = path_rng(kg, rng, sample, rng_offset + PRNG_BSDF_V);
@@ -526,6 +527,7 @@ __device void kernel_path_indirect(KernelGlobals *kg, RNG *rng, int sample, Ray
if(!shadow_blocked(kg, &state, &light_ray, &ao_shadow)) {
float3 ao_bsdf = shader_bsdf_diffuse(kg, &sd)*kernel_data.background.ao_factor;
ao_bsdf += shader_bsdf_ao(kg, &sd);
path_radiance_accum_ao(L, throughput, ao_bsdf, ao_shadow, state.bounce);
}
}
@@ -706,7 +708,7 @@ __device float4 kernel_path_non_progressive(KernelGlobals *kg, RNG *rng, int sam
#ifdef __AO__
/* ambient occlusion */
if(kernel_data.integrator.use_ambient_occlusion) {
if(kernel_data.integrator.use_ambient_occlusion || (sd.flag & SD_AO)) {
int num_samples = kernel_data.integrator.ao_samples;
float num_samples_inv = 1.0f/num_samples;
float ao_factor = kernel_data.background.ao_factor;
@@ -734,6 +736,7 @@ __device float4 kernel_path_non_progressive(KernelGlobals *kg, RNG *rng, int sam
if(!shadow_blocked(kg, &state, &light_ray, &ao_shadow)) {
float3 ao_bsdf = shader_bsdf_diffuse(kg, &sd)*ao_factor;
ao_bsdf += shader_bsdf_ao(kg, &sd);
path_radiance_accum_ao(&L, throughput*num_samples_inv, ao_bsdf, ao_shadow, state.bounce);
}
}

View File

@@ -599,6 +599,27 @@ __device float3 shader_bsdf_transmission(KernelGlobals *kg, ShaderData *sd)
#endif
}
__device float3 shader_bsdf_ao(KernelGlobals *kg, ShaderData *sd)
{
#ifdef __MULTI_CLOSURE__
float3 eval = make_float3(0.0f, 0.0f, 0.0f);
for(int i = 0; i< sd->num_closure; i++) {
ShaderClosure *sc = &sd->closure[i];
if(CLOSURE_IS_AMBIENT_OCCLUSION(sc->type))
eval += sc->weight;
}
return eval;
#else
if(CLOSURE_IS_AMBIENT_OCCLUSION(sd->closure.type))
return sd->closure.weight;
else
return make_float3(0.0f, 0.0f, 0.0f);
#endif
}
/* Emission */
__device float3 shader_emissive_eval(KernelGlobals *kg, ShaderData *sd)

View File

@@ -393,16 +393,17 @@ enum ShaderDataFlag {
SD_BSDF_GLOSSY = 16, /* have glossy bsdf */
SD_HOLDOUT = 32, /* have holdout closure? */
SD_VOLUME = 64, /* have volume closure? */
SD_AO = 128, /* have ao closure? */
/* shader flags */
SD_SAMPLE_AS_LIGHT = 128, /* direct light sample */
SD_HAS_SURFACE_TRANSPARENT = 256, /* has surface transparency */
SD_HAS_VOLUME = 512, /* has volume shader */
SD_HOMOGENEOUS_VOLUME = 1024, /* has homogeneous volume */
SD_SAMPLE_AS_LIGHT = 256, /* direct light sample */
SD_HAS_SURFACE_TRANSPARENT = 512, /* has surface transparency */
SD_HAS_VOLUME = 1024, /* has volume shader */
SD_HOMOGENEOUS_VOLUME = 2048, /* has homogeneous volume */
/* object flags */
SD_HOLDOUT_MASK = 2048, /* holdout for camera rays */
SD_OBJECT_MOTION = 4096 /* has object motion blur */
SD_HOLDOUT_MASK = 4096, /* holdout for camera rays */
SD_OBJECT_MOTION = 8192 /* has object motion blur */
};
typedef struct ShaderData {

View File

@@ -73,6 +73,22 @@ public:
void print_on(std::ostream &out) const { out << name() << " ()"; }
};
/// ambient occlusion closure
///
/// We only have a ambient occlusion closure for the shaders
/// to return a color in ambient occlusion shaders. No methods,
/// only the weight is taking into account
///
class AmbientOcclusionClosure : public ClosurePrimitive {
public:
AmbientOcclusionClosure () : ClosurePrimitive((ClosurePrimitive::Category)AmbientOcclusion) {}
void setup() {};
size_t memsize() const { return sizeof(*this); }
const char *name() const { return "ambient_occlusion"; }
void print_on(std::ostream &out) const { out << name() << " ()"; }
};
ClosureParam *closure_background_params()
{
static ClosureParam params[] = {
@@ -94,5 +110,16 @@ ClosureParam *closure_holdout_params()
CLOSURE_PREPARE(closure_holdout_prepare, HoldoutClosure)
ClosureParam *closure_ambient_occlusion_params()
{
static ClosureParam params[] = {
CLOSURE_STRING_KEYPARAM("label"),
CLOSURE_FINISH_PARAM(AmbientOcclusionClosure)
};
return params;
}
CLOSURE_PREPARE(closure_ambient_occlusion_prepare, AmbientOcclusionClosure)
CCL_NAMESPACE_END

View File

@@ -190,6 +190,8 @@ void OSLShader::register_closures(OSL::ShadingSystem *ss)
closure_background_params(), closure_background_prepare);
register_closure(ss, "holdout", id++,
closure_holdout_params(), closure_holdout_prepare);
register_closure(ss, "ambient_occlusion", id++,
closure_ambient_occlusion_params(), closure_ambient_occlusion_prepare);
}
CCL_NAMESPACE_END

View File

@@ -46,10 +46,16 @@ CCL_NAMESPACE_BEGIN
OSL::ClosureParam *closure_emission_params();
OSL::ClosureParam *closure_background_params();
OSL::ClosureParam *closure_holdout_params();
OSL::ClosureParam *closure_ambient_occlusion_params();
void closure_emission_prepare(OSL::RendererServices *, int id, void *data);
void closure_background_prepare(OSL::RendererServices *, int id, void *data);
void closure_holdout_prepare(OSL::RendererServices *, int id, void *data);
void closure_ambient_occlusion_prepare(OSL::RendererServices *, int id, void *data);
enum {
AmbientOcclusion = 100
};
#define CLOSURE_PREPARE(name, classname) \
void name(RendererServices *, int id, void *data) \

View File

@@ -159,6 +159,20 @@ static void flatten_surface_closure_tree(ShaderData *sd, bool no_glossy,
sd->closure[sd->num_closure++] = sc;
break;
}
case AmbientOcclusion: {
if (sd->num_closure == MAX_CLOSURE)
return;
/* sample weight */
float sample_weight = fabsf(average(weight));
sc.sample_weight = sample_weight;
sc.type = CLOSURE_AMBIENT_OCCLUSION_ID;
sd->closure[sd->num_closure++] = sc;
sd->flag |= SD_AO;
break;
}
case OSL::ClosurePrimitive::Holdout:
if (sd->num_closure == MAX_CLOSURE)
return;

View File

@@ -3,9 +3,11 @@
set(SRC_OSL
node_add_closure.osl
node_ambient_occlusion.osl
node_attribute.osl
node_background.osl
node_brick_texture.osl
node_brightness.osl
node_bump.osl
node_camera.osl
node_checker_texture.osl
@@ -21,35 +23,37 @@ set(SRC_OSL
node_environment_texture.osl
node_fresnel.osl
node_gamma.osl
node_gradient_texture.osl
node_brightness.osl
node_geometry.osl
node_glass_bsdf.osl
node_glossy_bsdf.osl
node_gradient_texture.osl
node_holdout.osl
node_hsv.osl
node_image_texture.osl
node_invert.osl
node_layer_weight.osl
node_light_path.osl
node_light_falloff.osl
node_light_path.osl
node_magic_texture.osl
node_mapping.osl
node_math.osl
node_mix.osl
node_mix_closure.osl
node_musgrave_texture.osl
node_normal.osl
node_noise_texture.osl
node_normal.osl
node_normal_map.osl
node_object_info.osl
node_output_displacement.osl
node_output_surface.osl
node_output_volume.osl
node_particle_info.osl
node_refraction_bsdf.osl
node_rgb_ramp.osl
node_separate_rgb.osl
node_set_normal.osl
node_sky_texture.osl
node_tangent.osl
node_texture_coordinate.osl
node_translucent_bsdf.osl
node_transparent_bsdf.osl

View File

@@ -0,0 +1,27 @@
/*
* Copyright 2011, Blender Foundation.
*
* 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.
*/
#include "stdosl.h"
shader node_ambient_occlusion(
color Color = color(0.8, 0.8, 0.8),
output closure color AO = ambient_occlusion())
{
AO = Color * ambient_occlusion();
}

View File

@@ -47,26 +47,17 @@ shader node_geometry(
}
/* first try to get tangent attribute */
vector T;
point generated;
if (getattribute("geom:tangent", T)) {
/* ensure orthogonal and normalized (interpolation breaks it) */
/* try to create spherical tangent from generated coordinates */
if (getattribute("geom:generated", generated)) {
vector T = vector(-(generated[1] - 0.5), (generated[0] - 0.5), 0.0);
T = transform("object", "world", T);
Tangent = cross(Normal, normalize(cross(T, Normal)));
}
else {
point generated;
/* try to create spherical tangent from generated coordinates */
if (getattribute("geom:generated", generated)) {
T = vector(-(generated[1] - 0.5), (generated[0] - 0.5), 0.0);
T = transform("object", "world", T);
Tangent = cross(Normal, normalize(cross(T, Normal)));
}
else {
/* otherwise use surface derivatives */
Tangent = normalize(dPdu);
}
/* otherwise use surface derivatives */
Tangent = normalize(dPdu);
}
}

View File

@@ -0,0 +1,48 @@
/*
* Copyright 2011, Blender Foundation.
*
* 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.
*/
#include "stdosl.h"
shader node_normal_map(
normal NormalIn = N,
color Color = color(0.5, 0.5, 1.0),
string space = "Tangent",
string attr_name = "geom:tangent",
string attr_sign_name = "geom:tangent_sign",
output normal Normal = NormalIn)
{
color mcolor = 2.0*color(Color[0] - 0.5, Color[1] - 0.5, Color[2] - 0.5);
if (space == "Tangent") {
vector tangent;
float tangent_sign;
getattribute(attr_name, tangent);
getattribute(attr_sign_name, tangent_sign);
tangent = transform("object", "world", tangent);
vector B = tangent_sign * cross(NormalIn, tangent);
Normal = normalize(mcolor[0] * tangent + mcolor[1] * B + mcolor[2] * NormalIn);
}
else if (space == "Object")
Normal = normalize(transform("object", "world", vector(mcolor)));
else if (space == "World")
Normal = normalize(vector(mcolor));
}

View File

@@ -0,0 +1,39 @@
/*
* Copyright 2011, Blender Foundation.
*
* 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.
*/
#include "stdosl.h"
shader node_refraction_bsdf(
color Color = color(0.8, 0.8, 0.8),
string distribution = "Sharp",
float Roughness = 0.2,
float IOR = 1.45,
normal Normal = N,
output closure color BSDF = diffuse(Normal))
{
float f = max(IOR, 1.0 + 1e-5);
float eta = backfacing() ? 1.0 / f: f;
if (distribution == "Sharp")
BSDF = Color * refraction(Normal, eta);
else if (distribution == "Beckmann")
BSDF = Color * microfacet_beckmann_refraction(Normal, Roughness, eta);
else if (distribution == "GGX")
BSDF = Color * microfacet_ggx_refraction(Normal, Roughness, eta);
}

View File

@@ -0,0 +1,50 @@
/*
* Copyright 2011, Blender Foundation.
*
* 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.
*/
#include "stdosl.h"
shader node_tangent(
normal NormalIn = N,
string attr_name = "geom:tangent",
string direction_type = "Radial",
string axis = "Z",
output normal Tangent = normalize(dPdu))
{
vector T;
if (direction_type == "UV Map") {
getattribute(attr_name, T);
}
else if (direction_type == "Radial") {
point generated;
if (!getattribute("geom:generated", generated))
generated = P;
if (axis == "X")
T = vector(0.0, -(generated[2] - 0.5), (generated[1] - 0.5));
else if (axis == "Y")
T = vector(-(generated[2] - 0.5), 0.0, (generated[0] - 0.5));
else
T = vector(-(generated[1] - 0.5), (generated[0] - 0.5), 0.0);
}
T = transform("object", "world", T);
Tangent = cross(NormalIn, normalize(cross(T, NormalIn)));
}

View File

@@ -38,12 +38,12 @@ shader node_ward_bsdf(
float aniso = clamp(Anisotropy, -0.99, 0.99);
if(aniso < 0.0) {
RoughnessU = Roughness*(1.0 + aniso);
RoughnessV = Roughness/(1.0 + aniso);
RoughnessU = Roughness/(1.0 + aniso);
RoughnessV = Roughness*(1.0 + aniso);
}
else {
RoughnessU = Roughness/(1.0 - aniso);
RoughnessV = Roughness*(1.0 - aniso);
RoughnessU = Roughness*(1.0 - aniso);
RoughnessV = Roughness/(1.0 - aniso);
}
BSDF = Color * ward(Normal, T, RoughnessU, RoughnessV);

View File

@@ -446,6 +446,7 @@ closure color ashikhmin_velvet(normal N, float sigma) BUILTIN;
closure color emission() BUILTIN;
closure color background() BUILTIN;
closure color holdout() BUILTIN;
closure color ambient_occlusion() BUILTIN;
// Renderer state
int raytype (string typename) BUILTIN;

View File

@@ -215,6 +215,9 @@ __device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, ShaderT
case NODE_CLOSURE_HOLDOUT:
svm_node_closure_holdout(sd, stack, node);
break;
case NODE_CLOSURE_AMBIENT_OCCLUSION:
svm_node_closure_ambient_occlusion(sd, stack, node);
break;
case NODE_CLOSURE_VOLUME:
svm_node_closure_volume(kg, sd, stack, node, path_flag);
break;
@@ -398,6 +401,12 @@ __device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, ShaderT
case NODE_LIGHT_FALLOFF:
svm_node_light_falloff(sd, stack, node);
break;
case NODE_TANGENT:
svm_node_tangent(kg, sd, stack, node);
break;
case NODE_NORMAL_MAP:
svm_node_normal_map(kg, sd, stack, node);
break;
#endif
case NODE_END:
default:

View File

@@ -20,9 +20,9 @@ CCL_NAMESPACE_BEGIN
/* Closure Nodes */
__device void svm_node_glossy_setup(ShaderData *sd, ShaderClosure *sc, int type, float eta, float roughness, bool refract)
__device void svm_node_glass_setup(ShaderData *sd, ShaderClosure *sc, int type, float eta, float roughness, bool refract)
{
if(type == CLOSURE_BSDF_REFRACTION_ID) {
if(type == CLOSURE_BSDF_SHARP_GLASS_ID) {
if(refract) {
sc->data0 = eta;
sd->flag |= bsdf_refraction_setup(sc);
@@ -30,7 +30,7 @@ __device void svm_node_glossy_setup(ShaderData *sd, ShaderClosure *sc, int type,
else
sd->flag |= bsdf_reflection_setup(sc);
}
else if(type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID) {
else if(type == CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID) {
sc->data0 = roughness;
sc->data1 = eta;
@@ -158,6 +158,31 @@ __device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *st
#ifdef __CAUSTICS_TRICKS__
if(kernel_data.integrator.no_caustics && (path_flag & PATH_RAY_DIFFUSE))
break;
#endif
ShaderClosure *sc = svm_node_closure_get(sd);
sc->N = N;
sc->data0 = param1;
svm_node_closure_set_mix_weight(sc, mix_weight);
float eta = fmaxf(param2, 1.0f + 1e-5f);
sc->data1 = (sd->flag & SD_BACKFACING)? 1.0f/eta: eta;
/* setup bsdf */
if(type == CLOSURE_BSDF_REFRACTION_ID)
sd->flag |= bsdf_refraction_setup(sc);
else if(type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID)
sd->flag |= bsdf_microfacet_beckmann_refraction_setup(sc);
else
sd->flag |= bsdf_microfacet_ggx_refraction_setup(sc);
break;
}
case CLOSURE_BSDF_SHARP_GLASS_ID:
case CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID:
case CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID: {
#ifdef __CAUSTICS_TRICKS__
if(kernel_data.integrator.no_caustics && (path_flag & PATH_RAY_DIFFUSE))
break;
#endif
/* index of refraction */
float eta = fmaxf(param2, 1.0f + 1e-5f);
@@ -177,7 +202,7 @@ __device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *st
float sample_weight = sc->sample_weight;
svm_node_closure_set_mix_weight(sc, mix_weight*fresnel);
svm_node_glossy_setup(sd, sc, type, eta, roughness, false);
svm_node_glass_setup(sd, sc, type, eta, roughness, false);
/* refraction */
sc = svm_node_closure_get(sd);
@@ -187,7 +212,7 @@ __device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *st
sc->sample_weight = sample_weight;
svm_node_closure_set_mix_weight(sc, mix_weight*(1.0f - fresnel));
svm_node_glossy_setup(sd, sc, type, eta, roughness, true);
svm_node_glass_setup(sd, sc, type, eta, roughness, true);
#else
ShaderClosure *sc = svm_node_closure_get(sd);
sc->N = N;
@@ -195,7 +220,7 @@ __device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *st
bool refract = (randb > fresnel);
svm_node_closure_set_mix_weight(sc, mix_weight);
svm_node_glossy_setup(sd, sc, type, eta, roughness, refract);
svm_node_glass_setup(sd, sc, type, eta, roughness, refract);
#endif
break;
@@ -222,12 +247,12 @@ __device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *st
float anisotropy = clamp(param2, -0.99f, 0.99f);
if(anisotropy < 0.0f) {
sc->data0 = roughness*(1.0f + anisotropy);
sc->data1 = roughness/(1.0f + anisotropy);
sc->data0 = roughness/(1.0f + anisotropy);
sc->data1 = roughness*(1.0f + anisotropy);
}
else {
sc->data0 = roughness/(1.0f - anisotropy);
sc->data1 = roughness*(1.0f - anisotropy);
sc->data0 = roughness*(1.0f - anisotropy);
sc->data1 = roughness/(1.0f - anisotropy);
}
sd->flag |= bsdf_ward_setup(sc);
@@ -372,6 +397,34 @@ __device void svm_node_closure_holdout(ShaderData *sd, float *stack, uint4 node)
sd->flag |= SD_HOLDOUT;
}
__device void svm_node_closure_ambient_occlusion(ShaderData *sd, float *stack, uint4 node)
{
#ifdef __MULTI_CLOSURE__
uint mix_weight_offset = node.y;
if(stack_valid(mix_weight_offset)) {
float mix_weight = stack_load_float(stack, mix_weight_offset);
if(mix_weight == 0.0f)
return;
ShaderClosure *sc = svm_node_closure_get(sd);
sc->weight *= mix_weight;
sc->type = CLOSURE_AMBIENT_OCCLUSION_ID;
}
else {
ShaderClosure *sc = svm_node_closure_get(sd);
sc->type = CLOSURE_AMBIENT_OCCLUSION_ID;
}
#else
ShaderClosure *sc = &sd->closure;
sc->type = CLOSURE_AMBIENT_OCCLUSION_ID;
#endif
sd->flag |= SD_AO;
}
/* Closure Nodes */
__device_inline void svm_node_closure_store_weight(ShaderData *sd, float3 weight)

View File

@@ -29,29 +29,18 @@ __device void svm_node_geometry(KernelGlobals *kg, ShaderData *sd, float *stack,
case NODE_GEOM_N: data = sd->N; break;
#ifdef __DPDU__
case NODE_GEOM_T: {
/* first try to get tangent attribute */
int attr_offset = (sd->object != ~0)? find_attribute(kg, sd, ATTR_STD_TANGENT): ATTR_STD_NOT_FOUND;
/* try to create spherical tangent from generated coordinates */
int attr_offset = (sd->object != ~0)? find_attribute(kg, sd, ATTR_STD_GENERATED): ATTR_STD_NOT_FOUND;
if(attr_offset != ATTR_STD_NOT_FOUND) {
/* ensure orthogonal and normalized (interpolation breaks it) */
data = triangle_attribute_float3(kg, sd, ATTR_ELEMENT_CORNER, attr_offset, NULL, NULL);
data = triangle_attribute_float3(kg, sd, ATTR_ELEMENT_VERTEX, attr_offset, NULL, NULL);
data = make_float3(-(data.y - 0.5), (data.x - 0.5), 0.0f);
object_normal_transform(kg, sd, &data);
data = cross(sd->N, normalize(cross(data, sd->N)));;
}
else {
/* try to create spherical tangent from generated coordinates */
int attr_offset = (sd->object != ~0)? find_attribute(kg, sd, ATTR_STD_GENERATED): ATTR_STD_NOT_FOUND;
if(attr_offset != ATTR_STD_NOT_FOUND) {
data = triangle_attribute_float3(kg, sd, ATTR_ELEMENT_VERTEX, attr_offset, NULL, NULL);
data = make_float3(-(data.y - 0.5), (data.x - 0.5), 0.0f);
object_normal_transform(kg, sd, &data);
data = cross(sd->N, normalize(cross(data, sd->N)));;
}
else {
/* otherwise use surface derivatives */
data = normalize(sd->dPdu);
}
/* otherwise use surface derivatives */
data = normalize(sd->dPdu);
}
break;

View File

@@ -225,5 +225,91 @@ __device void svm_node_tex_coord_bump_dy(KernelGlobals *kg, ShaderData *sd, floa
#endif
}
__device void svm_node_normal_map(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node)
{
uint color_offset, normal_offset, space;
decode_node_uchar4(node.y, &color_offset, &normal_offset, &space, NULL);
float3 color = stack_load_float3(stack, color_offset);
color = 2.0f*make_float3(color.x - 0.5f, color.y - 0.5f, color.z - 0.5f);
if(space == NODE_NORMAL_MAP_TANGENT) {
/* tangent space */
if(sd->object == ~0) {
stack_store_float3(stack, normal_offset, make_float3(0.0f, 0.0f, 0.0f));
return;
}
/* first try to get tangent attribute */
int attr_offset = find_attribute(kg, sd, node.z);
int attr_sign_offset = find_attribute(kg, sd, node.w);
if(attr_offset == ATTR_STD_NOT_FOUND || attr_offset == ATTR_STD_NOT_FOUND) {
stack_store_float3(stack, normal_offset, make_float3(0.0f, 0.0f, 0.0f));
return;
}
/* ensure orthogonal and normalized (interpolation breaks it) */
float3 tangent = triangle_attribute_float3(kg, sd, ATTR_ELEMENT_CORNER, attr_offset, NULL, NULL);
float sign = triangle_attribute_float(kg, sd, ATTR_ELEMENT_CORNER, attr_sign_offset, NULL, NULL);
object_normal_transform(kg, sd, &tangent);
tangent = cross(sd->N, normalize(cross(tangent, sd->N)));;
float3 B = sign * cross(sd->N, tangent);
float3 N = color.x * tangent + color.y * B + color.z * sd->N;
stack_store_float3(stack, normal_offset, normalize(N));
}
else {
/* object, world space */
float3 N = color;
if(space == NODE_NORMAL_MAP_OBJECT)
object_normal_transform(kg, sd, &N);
stack_store_float3(stack, normal_offset, normalize(N));
}
}
__device void svm_node_tangent(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node)
{
uint tangent_offset, direction_type, axis;
decode_node_uchar4(node.y, &tangent_offset, &direction_type, &axis, NULL);
float3 tangent;
if(direction_type == NODE_TANGENT_UVMAP) {
/* UV map */
int attr_offset = find_attribute(kg, sd, node.z);
if(attr_offset == ATTR_STD_NOT_FOUND)
tangent = make_float3(0.0f, 0.0f, 0.0f);
else
tangent = triangle_attribute_float3(kg, sd, ATTR_ELEMENT_CORNER, attr_offset, NULL, NULL);
}
else {
/* radial */
int attr_offset = find_attribute(kg, sd, node.z);
float3 generated;
if(attr_offset == ATTR_STD_NOT_FOUND)
generated = sd->P;
else
generated = triangle_attribute_float3(kg, sd, ATTR_ELEMENT_VERTEX, attr_offset, NULL, NULL);
if(axis == NODE_TANGENT_AXIS_X)
tangent = make_float3(0.0f, -(generated.z - 0.5f), (generated.y - 0.5f));
else if(axis == NODE_TANGENT_AXIS_Y)
tangent = make_float3(-(generated.z - 0.5f), 0.0f, (generated.x - 0.5f));
else
tangent = make_float3(-(generated.y - 0.5f), (generated.x - 0.5f), 0.0f);
}
object_normal_transform(kg, sd, &tangent);
tangent = cross(sd->N, normalize(cross(tangent, sd->N)));
stack_store_float3(stack, tangent_offset, tangent);
}
CCL_NAMESPACE_END

View File

@@ -94,6 +94,9 @@ typedef enum NodeType {
NODE_PARTICLE_INFO,
NODE_TEX_BRICK,
NODE_CLOSURE_SET_NORMAL,
NODE_CLOSURE_AMBIENT_OCCLUSION,
NODE_TANGENT,
NODE_NORMAL_MAP
} NodeType;
typedef enum NodeAttributeType {
@@ -279,6 +282,23 @@ typedef enum NodeBlendWeightType {
NODE_LAYER_WEIGHT_FACING
} NodeBlendWeightType;
typedef enum NodeTangentDirectionType {
NODE_TANGENT_RADIAL,
NODE_TANGENT_UVMAP
} NodeTangentDirectionType;
typedef enum NodeTangentAxis {
NODE_TANGENT_AXIS_X,
NODE_TANGENT_AXIS_Y,
NODE_TANGENT_AXIS_Z
} NodeTangentAxis;
typedef enum NodeNormalMapSpace {
NODE_NORMAL_MAP_TANGENT,
NODE_NORMAL_MAP_OBJECT,
NODE_NORMAL_MAP_WORLD
} NodeNormalMapSpace;
typedef enum ShaderType {
SHADER_TYPE_SURFACE,
SHADER_TYPE_VOLUME,
@@ -307,7 +327,9 @@ typedef enum ClosureType {
CLOSURE_BSDF_WESTIN_BACKSCATTER_ID,
CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID,
CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID,
CLOSURE_BSDF_GLASS_ID,
CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID,
CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID,
CLOSURE_BSDF_SHARP_GLASS_ID,
CLOSURE_BSDF_TRANSPARENT_ID,
@@ -317,6 +339,7 @@ typedef enum ClosureType {
CLOSURE_BACKGROUND_ID,
CLOSURE_HOLDOUT_ID,
CLOSURE_SUBSURFACE_ID,
CLOSURE_AMBIENT_OCCLUSION_ID,
CLOSURE_VOLUME_ID,
CLOSURE_VOLUME_TRANSPARENT_ID,
@@ -329,11 +352,12 @@ typedef enum ClosureType {
#define CLOSURE_IS_BSDF(type) (type <= CLOSURE_BSDF_TRANSPARENT_ID)
#define CLOSURE_IS_BSDF_DIFFUSE(type) (type >= CLOSURE_BSDF_DIFFUSE_ID && type <= CLOSURE_BSDF_OREN_NAYAR_ID)
#define CLOSURE_IS_BSDF_GLOSSY(type) (type >= CLOSURE_BSDF_GLOSSY_ID && type <= CLOSURE_BSDF_WESTIN_SHEEN_ID)
#define CLOSURE_IS_BSDF_TRANSMISSION(type) (type >= CLOSURE_BSDF_TRANSMISSION_ID && type <= CLOSURE_BSDF_GLASS_ID)
#define CLOSURE_IS_BSDF_TRANSMISSION(type) (type >= CLOSURE_BSDF_TRANSMISSION_ID && type <= CLOSURE_BSDF_SHARP_GLASS_ID)
#define CLOSURE_IS_VOLUME(type) (type >= CLOSURE_VOLUME_ID && type <= CLOSURE_VOLUME_ISOTROPIC_ID)
#define CLOSURE_IS_EMISSION(type) (type == CLOSURE_EMISSION_ID)
#define CLOSURE_IS_HOLDOUT(type) (type == CLOSURE_HOLDOUT_ID)
#define CLOSURE_IS_BACKGROUND(type) (type == CLOSURE_BACKGROUND_ID)
#define CLOSURE_IS_AMBIENT_OCCLUSION(type) (type == CLOSURE_AMBIENT_OCCLUSION_ID)
CCL_NAMESPACE_END

View File

@@ -162,8 +162,10 @@ Attribute *AttributeSet::add(AttributeStandard std, ustring name)
attr = add(name, TypeDesc::TypeNormal, Attribute::FACE);
else if(std == ATTR_STD_UV)
attr = add(name, TypeDesc::TypePoint, Attribute::CORNER);
else if(std == ATTR_STD_TANGENT)
else if(std == ATTR_STD_UV_TANGENT)
attr = add(name, TypeDesc::TypeVector, Attribute::CORNER);
else if(std == ATTR_STD_UV_TANGENT_SIGN)
attr = add(name, TypeDesc::TypeFloat, Attribute::CORNER);
else if(std == ATTR_STD_GENERATED)
attr = add(name, TypeDesc::TypePoint, Attribute::VERTEX);
else if(std == ATTR_STD_POSITION_UNDEFORMED)

View File

@@ -1284,10 +1284,8 @@ void WardBsdfNode::attributes(AttributeRequestSet *attributes)
{
ShaderInput *tangent_in = input("Tangent");
if(!tangent_in->link) {
attributes->add(ATTR_STD_TANGENT);
if(!tangent_in->link)
attributes->add(ATTR_STD_GENERATED);
}
ShaderNode::attributes(attributes);
}
@@ -1346,9 +1344,9 @@ static ShaderEnum glass_distribution_init()
{
ShaderEnum enm;
enm.insert("Sharp", CLOSURE_BSDF_REFRACTION_ID);
enm.insert("Beckmann", CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID);
enm.insert("GGX", CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID);
enm.insert("Sharp", CLOSURE_BSDF_SHARP_GLASS_ID);
enm.insert("Beckmann", CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID);
enm.insert("GGX", CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID);
return enm;
}
@@ -1367,7 +1365,7 @@ void GlassBsdfNode::compile(SVMCompiler& compiler)
{
closure = (ClosureType)distribution_enum[distribution];
if(closure == CLOSURE_BSDF_REFRACTION_ID)
if(closure == CLOSURE_BSDF_SHARP_GLASS_ID)
BsdfNode::compile(compiler, NULL, input("IOR"));
else
BsdfNode::compile(compiler, input("Roughness"), input("IOR"));
@@ -1379,6 +1377,45 @@ void GlassBsdfNode::compile(OSLCompiler& compiler)
compiler.add(this, "node_glass_bsdf");
}
/* Refraction BSDF Closure */
static ShaderEnum refraction_distribution_init()
{
ShaderEnum enm;
enm.insert("Sharp", CLOSURE_BSDF_REFRACTION_ID);
enm.insert("Beckmann", CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID);
enm.insert("GGX", CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID);
return enm;
}
ShaderEnum RefractionBsdfNode::distribution_enum = refraction_distribution_init();
RefractionBsdfNode::RefractionBsdfNode()
{
distribution = ustring("Sharp");
add_input("Roughness", SHADER_SOCKET_FLOAT, 0.0f);
add_input("IOR", SHADER_SOCKET_FLOAT, 0.3f);
}
void RefractionBsdfNode::compile(SVMCompiler& compiler)
{
closure = (ClosureType)distribution_enum[distribution];
if(closure == CLOSURE_BSDF_REFRACTION_ID)
BsdfNode::compile(compiler, NULL, input("IOR"));
else
BsdfNode::compile(compiler, input("Roughness"), input("IOR"));
}
void RefractionBsdfNode::compile(OSLCompiler& compiler)
{
compiler.parameter("distribution", distribution);
compiler.add(this, "node_refraction_bsdf");
}
/* Velvet BSDF Closure */
VelvetBsdfNode::VelvetBsdfNode()
@@ -1536,6 +1573,34 @@ void HoldoutNode::compile(OSLCompiler& compiler)
compiler.add(this, "node_holdout");
}
/* Ambient Occlusion */
AmbientOcclusionNode::AmbientOcclusionNode()
: ShaderNode("ambient_occlusion")
{
add_input("Color", SHADER_SOCKET_COLOR, make_float3(0.8f, 0.8f, 0.8f));
add_output("AO", SHADER_SOCKET_CLOSURE);
}
void AmbientOcclusionNode::compile(SVMCompiler& compiler)
{
ShaderInput *color_in = input("Color");
if(color_in->link) {
compiler.stack_assign(color_in);
compiler.add_node(NODE_CLOSURE_WEIGHT, color_in->stack_offset);
}
else
compiler.add_node(NODE_CLOSURE_SET_WEIGHT, color_in->value);
compiler.add_node(NODE_CLOSURE_AMBIENT_OCCLUSION, compiler.closure_mix_weight_offset());
}
void AmbientOcclusionNode::compile(OSLCompiler& compiler)
{
compiler.add(this, "node_ambient_occlusion");
}
/* Volume Closure */
VolumeNode::VolumeNode()
@@ -1635,10 +1700,8 @@ GeometryNode::GeometryNode()
void GeometryNode::attributes(AttributeRequestSet *attributes)
{
if(!output("Tangent")->links.empty()) {
attributes->add(ATTR_STD_TANGENT);
if(!output("Tangent")->links.empty())
attributes->add(ATTR_STD_GENERATED);
}
ShaderNode::attributes(attributes);
}
@@ -2075,13 +2138,14 @@ void ParticleInfoNode::compile(SVMCompiler& compiler)
compiler.add_node(NODE_PARTICLE_INFO, NODE_INFO_PAR_LOCATION, out->stack_offset);
}
#if 0 /* XXX Quaternion data is not yet supported by Cycles */
/* quaternion data is not yet supported by Cycles */
#if 0
out = output("Rotation");
if(!out->links.empty()) {
compiler.stack_assign(out);
compiler.add_node(NODE_PARTICLE_INFO, NODE_INFO_PAR_ROTATION, out->stack_offset);
}
#endif
#endif
out = output("Size");
if(!out->links.empty()) {
@@ -2946,5 +3010,181 @@ void OSLScriptNode::compile(OSLCompiler& compiler)
compiler.add(this, bytecode_hash.c_str(), false);
}
/* Normal Map */
static ShaderEnum normal_map_space_init()
{
ShaderEnum enm;
enm.insert("Tangent", NODE_NORMAL_MAP_TANGENT);
enm.insert("Object", NODE_NORMAL_MAP_OBJECT);
enm.insert("World", NODE_NORMAL_MAP_WORLD);
return enm;
}
ShaderEnum NormalMapNode::space_enum = normal_map_space_init();
NormalMapNode::NormalMapNode()
: ShaderNode("normal_map")
{
space = ustring("Tangent");
attribute = ustring("");
add_input("NormalIn", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL, true);
add_input("Color", SHADER_SOCKET_COLOR);
add_output("Normal", SHADER_SOCKET_NORMAL);
}
void NormalMapNode::attributes(AttributeRequestSet *attributes)
{
if(space == ustring("Tangent")) {
if(attribute == ustring("")) {
attributes->add(ATTR_STD_UV_TANGENT);
attributes->add(ATTR_STD_UV_TANGENT_SIGN);
}
else {
attributes->add(ustring((string(attribute.c_str()) + ".tangent").c_str()));
attributes->add(ustring((string(attribute.c_str()) + ".tangent_sign").c_str()));
}
}
ShaderNode::attributes(attributes);
}
void NormalMapNode::compile(SVMCompiler& compiler)
{
ShaderInput *color_in = input("Color");
ShaderOutput *normal_out = output("Normal");
int attr = 0, attr_sign = 0;
if(space == ustring("Tangent")) {
if(attribute == ustring("")) {
attr = compiler.attribute(ATTR_STD_UV_TANGENT);
attr_sign = compiler.attribute(ATTR_STD_UV_TANGENT_SIGN);
}
else {
attr = compiler.attribute(ustring((string(attribute.c_str()) + ".tangent").c_str()));
attr_sign = compiler.attribute(ustring((string(attribute.c_str()) + ".tangent_sign").c_str()));
}
}
compiler.stack_assign(color_in);
compiler.stack_assign(normal_out);
compiler.add_node(NODE_NORMAL_MAP,
compiler.encode_uchar4(
color_in->stack_offset,
normal_out->stack_offset,
space_enum[space]),
attr, attr_sign);
}
void NormalMapNode::compile(OSLCompiler& compiler)
{
if(space == ustring("Tangent")) {
if(attribute == ustring("")) {
compiler.parameter("attr_name", ustring("geom:tangent"));
compiler.parameter("attr_sign_name", ustring("geom:tangent_sign"));
}
else {
compiler.parameter("attr_name", ustring((string(attribute.c_str()) + ".tangent").c_str()));
compiler.parameter("attr_sign_name", ustring((string(attribute.c_str()) + ".tangent_sign").c_str()));
}
}
compiler.parameter("space", space);
compiler.add(this, "node_normal_map");
}
/* Tangent */
static ShaderEnum tangent_direction_type_init()
{
ShaderEnum enm;
enm.insert("Radial", NODE_TANGENT_RADIAL);
enm.insert("UV Map", NODE_TANGENT_UVMAP);
return enm;
}
static ShaderEnum tangent_axis_init()
{
ShaderEnum enm;
enm.insert("X", NODE_TANGENT_AXIS_X);
enm.insert("Y", NODE_TANGENT_AXIS_Y);
enm.insert("Z", NODE_TANGENT_AXIS_Z);
return enm;
}
ShaderEnum TangentNode::direction_type_enum = tangent_direction_type_init();
ShaderEnum TangentNode::axis_enum = tangent_axis_init();
TangentNode::TangentNode()
: ShaderNode("normal_map")
{
direction_type = ustring("Radial");
axis = ustring("X");
attribute = ustring("");
add_input("NormalIn", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL, true);
add_output("Tangent", SHADER_SOCKET_NORMAL);
}
void TangentNode::attributes(AttributeRequestSet *attributes)
{
if(direction_type == ustring("UV Map")) {
if(attribute == ustring(""))
attributes->add(ATTR_STD_UV_TANGENT);
else
attributes->add(ustring((string(attribute.c_str()) + ".tangent").c_str()));
}
else
attributes->add(ATTR_STD_GENERATED);
ShaderNode::attributes(attributes);
}
void TangentNode::compile(SVMCompiler& compiler)
{
ShaderOutput *tangent_out = output("Tangent");
int attr;
if(direction_type == ustring("UV Map")) {
if(attribute == ustring(""))
attr = compiler.attribute(ATTR_STD_UV_TANGENT);
else
attr = compiler.attribute(ustring((string(attribute.c_str()) + ".tangent").c_str()));
}
else
attr = compiler.attribute(ATTR_STD_GENERATED);
compiler.stack_assign(tangent_out);
compiler.add_node(NODE_TANGENT,
compiler.encode_uchar4(
tangent_out->stack_offset,
direction_type_enum[direction_type],
axis_enum[axis]), attr);
}
void TangentNode::compile(OSLCompiler& compiler)
{
if(direction_type == ustring("UV Map")) {
if(attribute == ustring(""))
compiler.parameter("attr_name", ustring("geom:tangent"));
else
compiler.parameter("attr_name", ustring((string(attribute.c_str()) + ".tangent").c_str()));
}
compiler.parameter("direction_type", direction_type);
compiler.parameter("axis", axis);
compiler.add(this, "node_tangent");
}
CCL_NAMESPACE_END

View File

@@ -240,6 +240,14 @@ public:
static ShaderEnum distribution_enum;
};
class RefractionBsdfNode : public BsdfNode {
public:
SHADER_NODE_CLASS(RefractionBsdfNode)
ustring distribution;
static ShaderEnum distribution_enum;
};
class EmissionNode : public ShaderNode {
public:
SHADER_NODE_CLASS(EmissionNode)
@@ -257,6 +265,11 @@ public:
SHADER_NODE_CLASS(HoldoutNode)
};
class AmbientOcclusionNode : public ShaderNode {
public:
SHADER_NODE_CLASS(AmbientOcclusionNode)
};
class VolumeNode : public ShaderNode {
public:
SHADER_NODE_CLASS(VolumeNode)
@@ -457,6 +470,31 @@ public:
vector<ustring> output_names;
};
class NormalMapNode : public ShaderNode {
public:
SHADER_NODE_CLASS(NormalMapNode)
void attributes(AttributeRequestSet *attributes);
ustring space;
static ShaderEnum space_enum;
ustring attribute;
};
class TangentNode : public ShaderNode {
public:
SHADER_NODE_CLASS(TangentNode)
void attributes(AttributeRequestSet *attributes);
ustring direction_type;
static ShaderEnum direction_type_enum;
ustring axis;
static ShaderEnum axis_enum;
ustring attribute;
};
CCL_NAMESPACE_END
#endif /* __NODES_H__ */

View File

@@ -30,8 +30,10 @@ const char *attribute_standard_name(AttributeStandard std)
return "uv";
else if(std == ATTR_STD_GENERATED)
return "generated";
else if(std == ATTR_STD_TANGENT)
else if(std == ATTR_STD_UV_TANGENT)
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)

View File

@@ -449,7 +449,8 @@ typedef enum AttributeStandard {
ATTR_STD_VERTEX_NORMAL,
ATTR_STD_FACE_NORMAL,
ATTR_STD_UV,
ATTR_STD_TANGENT,
ATTR_STD_UV_TANGENT,
ATTR_STD_UV_TANGENT_SIGN,
ATTR_STD_GENERATED,
ATTR_STD_POSITION_UNDEFORMED,
ATTR_STD_POSITION_UNDISPLACED,

View File

@@ -553,6 +553,10 @@ struct ShadeResult;
#define SH_NODE_TEX_BRICK 169
#define SH_NODE_BUMP 170
#define SH_NODE_SCRIPT 171
#define SH_NODE_AMBIENT_OCCLUSION 172
#define SH_NODE_BSDF_REFRACTION 173
#define SH_NODE_TANGENT 174
#define SH_NODE_NORMAL_MAP 175
/* custom defines options for Material node */
#define SH_NODE_MAT_DIFF 1

View File

@@ -2293,17 +2293,21 @@ static void registerShaderNodes(bNodeTreeType *ttype)
register_node_type_sh_particle_info(ttype);
register_node_type_sh_bump(ttype);
register_node_type_sh_script(ttype);
register_node_type_sh_tangent(ttype);
register_node_type_sh_normal_map(ttype);
register_node_type_sh_background(ttype);
register_node_type_sh_bsdf_anisotropic(ttype);
register_node_type_sh_bsdf_diffuse(ttype);
register_node_type_sh_bsdf_glossy(ttype);
register_node_type_sh_bsdf_glass(ttype);
register_node_type_sh_bsdf_refraction(ttype);
register_node_type_sh_bsdf_translucent(ttype);
register_node_type_sh_bsdf_transparent(ttype);
register_node_type_sh_bsdf_velvet(ttype);
register_node_type_sh_emission(ttype);
register_node_type_sh_holdout(ttype);
register_node_type_sh_ambient_occlusion(ttype);
//register_node_type_sh_volume_transparent(ttype);
//register_node_type_sh_volume_isotropic(ttype);
register_node_type_sh_mix_shader(ttype);

View File

@@ -1379,6 +1379,30 @@ static void node_shader_buts_tex_coord(uiLayout *layout, bContext *UNUSED(C), Po
uiItemR(layout, ptr, "from_dupli", 0, NULL, 0);
}
static void node_shader_buts_normal_map(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiItemR(layout, ptr, "space", 0, "", 0);
if(RNA_enum_get(ptr, "space") == SHD_NORMAL_MAP_TANGENT)
uiItemR(layout, ptr, "uv_map", 0, NULL, 0);
}
static void node_shader_buts_tangent(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiLayout *split, *row;
split = uiLayoutSplit(layout, 0.0f, FALSE);
uiItemR(split, ptr, "direction_type", 0, "", 0);
row = uiLayoutRow(split, FALSE);
if(RNA_enum_get(ptr, "direction_type") == SHD_TANGENT_UVMAP)
uiItemR(row, ptr, "uv_map", 0, "", 0);
else
uiItemR(row, ptr, "axis", UI_ITEM_R_EXPAND, NULL, 0);
}
static void node_shader_buts_glossy(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiItemR(layout, ptr, "distribution", 0, "", ICON_NONE);
@@ -1491,8 +1515,15 @@ static void node_shader_set_butfunc(bNodeType *ntype)
case SH_NODE_TEX_COORD:
ntype->uifunc = node_shader_buts_tex_coord;
break;
case SH_NODE_NORMAL_MAP:
ntype->uifunc = node_shader_buts_normal_map;
break;
case SH_NODE_TANGENT:
ntype->uifunc = node_shader_buts_tangent;
break;
case SH_NODE_BSDF_GLOSSY:
case SH_NODE_BSDF_GLASS:
case SH_NODE_BSDF_REFRACTION:
ntype->uifunc = node_shader_buts_glossy;
break;
case SH_NODE_SCRIPT:

View File

@@ -716,6 +716,17 @@ typedef struct NodeShaderScript {
IDProperty *prop;
} NodeShaderScript;
typedef struct NodeShaderTangent {
int direction_type;
int axis;
char uv_map[64];
} NodeShaderTangent;
typedef struct NodeShaderNormalMap {
int space;
char uv_map[64];
} NodeShaderNormalMap;
/* script node mode */
#define NODE_SCRIPT_INTERNAL 0
#define NODE_SCRIPT_EXTERNAL 1
@@ -800,6 +811,20 @@ typedef struct NodeShaderScript {
#define SHD_PROJ_FLAT 0
#define SHD_PROJ_BOX 1
/* tangent */
#define SHD_TANGENT_RADIAL 0
#define SHD_TANGENT_UVMAP 1
/* tangent */
#define SHD_TANGENT_AXIS_X 0
#define SHD_TANGENT_AXIS_Y 1
#define SHD_TANGENT_AXIS_Z 2
/* normal map space */
#define SHD_NORMAL_MAP_TANGENT 0
#define SHD_NORMAL_MAP_OBJECT 1
#define SHD_NORMAL_MAP_WORLD 2
/* blur node */
#define CMP_NODE_BLUR_ASPECT_NONE 0
#define CMP_NODE_BLUR_ASPECT_Y 1

View File

@@ -1850,6 +1850,67 @@ static void def_glossy(StructRNA *srna)
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
}
static void def_sh_normal_map(StructRNA *srna)
{
static EnumPropertyItem prop_space_items[] = {
{SHD_NORMAL_MAP_TANGENT, "TANGENT", 0, "Tangent Space", "Tangent space normal mapping"},
{SHD_NORMAL_MAP_OBJECT, "OBJECT", 0, "Object Space", "Object space normal mapping"},
{SHD_NORMAL_MAP_WORLD, "WORLD", 0, "World Space", "World space normal mapping"},
{0, NULL, 0, NULL, NULL}
};
PropertyRNA *prop;
RNA_def_struct_sdna_from(srna, "NodeShaderNormalMap", "storage");
prop = RNA_def_property(srna, "space", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, prop_space_items);
RNA_def_property_ui_text(prop, "Space", "Space of the input normal");
RNA_def_property_update(prop, 0, "rna_Node_update");
prop = RNA_def_property(srna, "uv_map", PROP_STRING, PROP_NONE);
RNA_def_property_ui_text(prop, "UV Map", "Name of the UV Map for for tangent space maps");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
RNA_def_struct_sdna_from(srna, "bNode", NULL);
}
static void def_sh_tangent(StructRNA *srna)
{
static EnumPropertyItem prop_direction_type_items[] = {
{SHD_TANGENT_RADIAL, "RADIAL", 0, "Radial", "Radial tangent around the X, Y or Z axis"},
{SHD_TANGENT_UVMAP, "UV_MAP", 0, "UV Map", "Tangent from UV map"},
{0, NULL, 0, NULL, NULL}
};
static EnumPropertyItem prop_axis_items[] = {
{SHD_TANGENT_AXIS_X, "X", 0, "X", "X axis"},
{SHD_TANGENT_AXIS_Y, "Y", 0, "Y", "Y axis"},
{SHD_TANGENT_AXIS_Z, "Z", 0, "Z", "Z axis"},
{0, NULL, 0, NULL, NULL}
};
PropertyRNA *prop;
RNA_def_struct_sdna_from(srna, "NodeShaderTangent", "storage");
prop = RNA_def_property(srna, "direction_type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, prop_direction_type_items);
RNA_def_property_ui_text(prop, "Direction", "Method to use for the tangent");
RNA_def_property_update(prop, 0, "rna_Node_update");
prop = RNA_def_property(srna, "axis", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, prop_axis_items);
RNA_def_property_ui_text(prop, "Axis", "Axis for radial tangents");
RNA_def_property_update(prop, 0, "rna_Node_update");
prop = RNA_def_property(srna, "uv_map", PROP_STRING, PROP_NONE);
RNA_def_property_ui_text(prop, "UV Map", "Name of the UV Map for for tangent generated from UV");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
RNA_def_struct_sdna_from(srna, "bNode", NULL);
}
static void def_sh_script(StructRNA *srna)
{
FunctionRNA *func;

View File

@@ -65,12 +65,14 @@ DefNode( ShaderNode, SH_NODE_LAYER_WEIGHT, 0, "LA
DefNode( ShaderNode, SH_NODE_MIX_SHADER, 0, "MIX_SHADER", MixShader, "Mix Shader", "" )
DefNode( ShaderNode, SH_NODE_ADD_SHADER, 0, "ADD_SHADER", AddShader, "Add Shader", "" )
DefNode( ShaderNode, SH_NODE_ATTRIBUTE, def_sh_attribute, "ATTRIBUTE", Attribute, "Attribute", "" )
DefNode( ShaderNode, SH_NODE_AMBIENT_OCCLUSION, 0, "AMBIENT_OCCLUSION", AmbientOcclusion, "Ambient Occlusion", "" )
DefNode( ShaderNode, SH_NODE_BACKGROUND, 0, "BACKGROUND", Background, "Background", "" )
DefNode( ShaderNode, SH_NODE_HOLDOUT, 0, "HOLDOUT", Holdout, "Holdout", "" )
DefNode( ShaderNode, SH_NODE_BSDF_ANISOTROPIC, 0, "BSDF_ANISOTROPIC", BsdfAnisotropic, "Anisotropic Bsdf", "" )
DefNode( ShaderNode, SH_NODE_BSDF_DIFFUSE, 0, "BSDF_DIFFUSE", BsdfDiffuse, "Diffuse Bsdf", "" )
DefNode( ShaderNode, SH_NODE_BSDF_GLOSSY, def_glossy, "BSDF_GLOSSY", BsdfGlossy, "Glossy Bsdf", "" )
DefNode( ShaderNode, SH_NODE_BSDF_GLASS, def_glossy, "BSDF_GLASS", BsdfGlass, "Glass Bsdf", "" )
DefNode( ShaderNode, SH_NODE_BSDF_REFRACTION, def_glossy, "BSDF_REFRACTION", BsdfRefraction, "Refraction Bsdf", "" )
DefNode( ShaderNode, SH_NODE_BSDF_TRANSLUCENT, 0, "BSDF_TRANSLUCENT", BsdfTranslucent, "Translucent Bsdf", "" )
DefNode( ShaderNode, SH_NODE_BSDF_TRANSPARENT, 0, "BSDF_TRANSPARENT", BsdfTransparent, "Transparent Bsdf", "" )
DefNode( ShaderNode, SH_NODE_BSDF_VELVET, 0, "BSDF_VELVET", BsdfVelvet, "Velvet Bsdf", "" )
@@ -82,7 +84,9 @@ DefNode( ShaderNode, SH_NODE_LIGHT_PATH, 0, "LI
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_PARTICLE_INFO, 0, "PARTICLE_INFO", ParticleInfo, "Particle Info", "" )
DefNode( ShaderNode, SH_NODE_BUMP, 0, "BUMP", BumpNode, "Bump", "" )
DefNode( ShaderNode, SH_NODE_BUMP, 0, "BUMP", Bump, "Bump", "" )
DefNode( ShaderNode, SH_NODE_NORMAL_MAP, def_sh_normal_map, "NORMAL_MAP", NormalMap, "Normal Map", "" )
DefNode( ShaderNode, SH_NODE_TANGENT, def_sh_tangent, "TANGENT", Tangent, "Tangent", "" )
DefNode( ShaderNode, SH_NODE_SCRIPT, def_sh_script, "SCRIPT", Script, "Script", "" )
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","" )

View File

@@ -145,36 +145,40 @@ set(SRC
shader/nodes/node_shader_valToRgb.c
shader/nodes/node_shader_value.c
shader/nodes/node_shader_vectMath.c
shader/nodes/node_shader_add_shader.c
shader/nodes/node_shader_ambient_occlusion.c
shader/nodes/node_shader_attribute.c
shader/nodes/node_shader_background.c
shader/nodes/node_shader_bsdf_anisotropic.c
shader/nodes/node_shader_bsdf_diffuse.c
shader/nodes/node_shader_bsdf_glossy.c
shader/nodes/node_shader_bsdf_glass.c
shader/nodes/node_shader_bsdf_glossy.c
shader/nodes/node_shader_bsdf_refraction.c
shader/nodes/node_shader_bsdf_translucent.c
shader/nodes/node_shader_bsdf_transparent.c
shader/nodes/node_shader_bsdf_velvet.c
shader/nodes/node_shader_bump.c
shader/nodes/node_shader_emission.c
shader/nodes/node_shader_fresnel.c
shader/nodes/node_shader_layer_weight.c
shader/nodes/node_shader_geometry.c
shader/nodes/node_shader_holdout.c
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_layer_weight.c
shader/nodes/node_shader_light_falloff.c
shader/nodes/node_shader_object_info.c
shader/nodes/node_shader_script.c
shader/nodes/node_shader_particle_info.c
shader/nodes/node_shader_light_path.c
shader/nodes/node_shader_mix_shader.c
shader/nodes/node_shader_add_shader.c
shader/nodes/node_shader_normal_map.c
shader/nodes/node_shader_object_info.c
shader/nodes/node_shader_output_lamp.c
shader/nodes/node_shader_output_material.c
shader/nodes/node_shader_output_world.c
shader/nodes/node_shader_tex_gradient.c
shader/nodes/node_shader_particle_info.c
shader/nodes/node_shader_script.c
shader/nodes/node_shader_tangent.c
shader/nodes/node_shader_tex_brick.c
shader/nodes/node_shader_tex_checker.c
shader/nodes/node_shader_tex_coord.c
shader/nodes/node_shader_tex_environment.c
shader/nodes/node_shader_tex_gradient.c
shader/nodes/node_shader_tex_image.c
shader/nodes/node_shader_tex_magic.c
shader/nodes/node_shader_tex_musgrave.c
@@ -182,8 +186,8 @@ set(SRC
shader/nodes/node_shader_tex_sky.c
shader/nodes/node_shader_tex_voronoi.c
shader/nodes/node_shader_tex_wave.c
shader/nodes/node_shader_tex_checker.c
shader/nodes/node_shader_tex_brick.c
shader/nodes/node_shader_volume_isotropic.c
shader/nodes/node_shader_volume_transparent.c
shader/node_shader_tree.c
shader/node_shader_util.c

View File

@@ -81,11 +81,15 @@ void register_node_type_sh_layer_weight(struct bNodeTreeType *ttype);
void register_node_type_sh_tex_coord(struct bNodeTreeType *ttype);
void register_node_type_sh_particle_info(struct bNodeTreeType *ttype);
void register_node_type_sh_script(struct bNodeTreeType *ttype);
void register_node_type_sh_normal_map(struct bNodeTreeType *ttype);
void register_node_type_sh_tangent(struct bNodeTreeType *ttype);
void register_node_type_sh_ambient_occlusion(struct bNodeTreeType *ttype);
void register_node_type_sh_background(struct bNodeTreeType *ttype);
void register_node_type_sh_bsdf_diffuse(struct bNodeTreeType *ttype);
void register_node_type_sh_bsdf_glossy(struct bNodeTreeType *ttype);
void register_node_type_sh_bsdf_glass(struct bNodeTreeType *ttype);
void register_node_type_sh_bsdf_refraction(struct bNodeTreeType *ttype);
void register_node_type_sh_bsdf_translucent(struct bNodeTreeType *ttype);
void register_node_type_sh_bsdf_transparent(struct bNodeTreeType *ttype);
void register_node_type_sh_bsdf_velvet(struct bNodeTreeType *ttype);

View File

@@ -0,0 +1,63 @@
/*
* ***** 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_ambient_occlusion_in[] = {
{ SOCK_RGBA, 1, N_("Color"), 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
{ -1, 0, "" }
};
static bNodeSocketTemplate sh_node_ambient_occlusion_out[] = {
{ SOCK_SHADER, 0, N_("AO")},
{ -1, 0, "" }
};
static int node_shader_gpu_ambient_occlusion(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out)
{
return GPU_stack_link(mat, "node_ambient_occlusion", in, out, GPU_builtin(GPU_VIEW_NORMAL));
}
/* node type definition */
void register_node_type_sh_ambient_occlusion(bNodeTreeType *ttype)
{
static bNodeType ntype;
node_type_base(ttype, &ntype, SH_NODE_AMBIENT_OCCLUSION, "Ambient Occlusion", NODE_CLASS_SHADER, 0);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_ambient_occlusion_in, sh_node_ambient_occlusion_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_ambient_occlusion);
nodeRegisterType(ttype, &ntype);
}

View File

@@ -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"
/* **************** OUTPUT ******************** */
static bNodeSocketTemplate sh_node_bsdf_refraction_in[] = {
{ SOCK_RGBA, 1, N_("Color"), 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
{ SOCK_FLOAT, 1, N_("Roughness"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_FLOAT, 1, N_("IOR"), 1.45f, 0.0f, 0.0f, 0.0f, 1.0f, 1000.0f},
{ SOCK_VECTOR, 1, N_("Normal"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE},
{ -1, 0, "" }
};
static bNodeSocketTemplate sh_node_bsdf_refraction_out[] = {
{ SOCK_SHADER, 0, N_("BSDF")},
{ -1, 0, "" }
};
static int node_shader_gpu_bsdf_refraction(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out)
{
if (!in[3].link)
in[3].link = GPU_builtin(GPU_VIEW_NORMAL);
return GPU_stack_link(mat, "node_bsdf_refraction", in, out);
}
/* node type definition */
void register_node_type_sh_bsdf_refraction(bNodeTreeType *ttype)
{
static bNodeType ntype;
node_type_base(ttype, &ntype, SH_NODE_BSDF_REFRACTION, "Refraction BSDF", NODE_CLASS_SHADER, NODE_OPTIONS);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_bsdf_refraction_in, sh_node_bsdf_refraction_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_bsdf_refraction);
nodeRegisterType(ttype, &ntype);
}

View File

@@ -0,0 +1,69 @@
/*
* ***** 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_normal_map_in[] = {
{ SOCK_RGBA, 0, N_("Color"), 0.5f, 0.5f, 1.0f, 1.0f, 0.0f, 1.0f},
{ -1, 0, "" }
};
static bNodeSocketTemplate sh_node_normal_map_out[] = {
{ SOCK_VECTOR, 0, N_("Normal"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ -1, 0, "" }
};
static void node_shader_init_normal_map(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
{
NodeShaderNormalMap *attr = MEM_callocN(sizeof(NodeShaderNormalMap), "NodeShaderNormalMap");
node->storage = attr;
}
static int gpu_shader_normal_map(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out)
{
return GPU_stack_link(mat, "node_normal_map", in, out, GPU_builtin(GPU_VIEW_NORMAL));
}
/* node type definition */
void register_node_type_sh_normal_map(bNodeTreeType *ttype)
{
static bNodeType ntype;
node_type_base(ttype, &ntype, SH_NODE_NORMAL_MAP, "Normal Map", NODE_CLASS_OP_VECTOR, NODE_OPTIONS);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, sh_node_normal_map_in, sh_node_normal_map_out);
node_type_size(&ntype, 250, 60, 250);
node_type_init(&ntype, node_shader_init_normal_map);
node_type_storage(&ntype, "NodeShaderNormalMap", node_free_standard_storage, node_copy_standard_storage);
node_type_exec(&ntype, NULL);
node_type_gpu(&ntype, gpu_shader_normal_map);
nodeRegisterType(ttype, &ntype);
}

View File

@@ -0,0 +1,60 @@
/*
* ***** 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_tangent_out[] = {
{ SOCK_VECTOR, 0, N_("Tangent"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ -1, 0, "" }
};
static void node_shader_init_tangent(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
{
NodeShaderTangent *attr = MEM_callocN(sizeof(NodeShaderTangent), "NodeShaderTangent");
attr->axis = SHD_TANGENT_AXIS_Z;
node->storage = attr;
}
/* node type definition */
void register_node_type_sh_tangent(bNodeTreeType *ttype)
{
static bNodeType ntype;
node_type_base(ttype, &ntype, SH_NODE_TANGENT, "Tangent", NODE_CLASS_INPUT, NODE_OPTIONS);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, NULL, sh_node_tangent_out);
node_type_size(&ntype, 150, 60, 200);
node_type_init(&ntype, node_shader_init_tangent);
node_type_storage(&ntype, "NodeShaderTangent", node_free_standard_storage, node_copy_standard_storage);
node_type_exec(&ntype, NULL);
node_type_gpu(&ntype, NULL);
nodeRegisterType(ttype, &ntype);
}