diff options
40 files changed, 1280 insertions, 127 deletions
diff --git a/intern/cycles/blender/blender_mesh.cpp b/intern/cycles/blender/blender_mesh.cpp index 0e13479a761..69b330db483 100644 --- a/intern/cycles/blender/blender_mesh.cpp +++ b/intern/cycles/blender/blender_mesh.cpp @@ -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(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; + if(active_render) + attr = mesh->attributes.add(std, name); + else + attr = mesh->attributes.add(name, TypeDesc::TypePoint, Attribute::CORNER); - 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; + BL::MeshTextureFaceLayer::data_iterator t; + float3 *fdata = attr->data_float3(); + size_t i = 0; - 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); + } } } diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp index 1f8d86a7f70..6dc0bbdb90e 100644 --- a/intern/cycles/blender/blender_shader.cpp +++ b/intern/cycles/blender/blender_shader.cpp @@ -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; } } diff --git a/intern/cycles/kernel/closure/bsdf_ward.h b/intern/cycles/kernel/closure/bsdf_ward.h index 9c81548a2c3..dbddcf20dba 100644 --- a/intern/cycles/kernel/closure/bsdf_ward.h +++ b/intern/cycles/kernel/closure/bsdf_ward.h @@ -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; diff --git a/intern/cycles/kernel/kernel_path.h b/intern/cycles/kernel/kernel_path.h index 817f254a5e5..585068ce8e2 100644 --- a/intern/cycles/kernel/kernel_path.h +++ b/intern/cycles/kernel/kernel_path.h @@ -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); } } diff --git a/intern/cycles/kernel/kernel_shader.h b/intern/cycles/kernel/kernel_shader.h index 86886a6a231..1af5e048ad9 100644 --- a/intern/cycles/kernel/kernel_shader.h +++ b/intern/cycles/kernel/kernel_shader.h @@ -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) diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h index 98d998351a7..d4d88466688 100644 --- a/intern/cycles/kernel/kernel_types.h +++ b/intern/cycles/kernel/kernel_types.h @@ -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 { diff --git a/intern/cycles/kernel/osl/background.cpp b/intern/cycles/kernel/osl/background.cpp index b6e9473b7bf..eed4446cddc 100644 --- a/intern/cycles/kernel/osl/background.cpp +++ b/intern/cycles/kernel/osl/background.cpp @@ -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 diff --git a/intern/cycles/kernel/osl/osl_closures.cpp b/intern/cycles/kernel/osl/osl_closures.cpp index 73e96643df7..de572d0e585 100644 --- a/intern/cycles/kernel/osl/osl_closures.cpp +++ b/intern/cycles/kernel/osl/osl_closures.cpp @@ -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 diff --git a/intern/cycles/kernel/osl/osl_closures.h b/intern/cycles/kernel/osl/osl_closures.h index 574cb685db5..9137bad58d3 100644 --- a/intern/cycles/kernel/osl/osl_closures.h +++ b/intern/cycles/kernel/osl/osl_closures.h @@ -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) \ diff --git a/intern/cycles/kernel/osl/osl_shader.cpp b/intern/cycles/kernel/osl/osl_shader.cpp index 8b71ac30ab6..5d26f543efc 100644 --- a/intern/cycles/kernel/osl/osl_shader.cpp +++ b/intern/cycles/kernel/osl/osl_shader.cpp @@ -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; diff --git a/intern/cycles/kernel/shaders/CMakeLists.txt b/intern/cycles/kernel/shaders/CMakeLists.txt index 00ab52a1d13..4f5a97c1bb6 100644 --- a/intern/cycles/kernel/shaders/CMakeLists.txt +++ b/intern/cycles/kernel/shaders/CMakeLists.txt @@ -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 diff --git a/intern/cycles/kernel/shaders/node_ambient_occlusion.osl b/intern/cycles/kernel/shaders/node_ambient_occlusion.osl new file mode 100644 index 00000000000..57a06f35461 --- /dev/null +++ b/intern/cycles/kernel/shaders/node_ambient_occlusion.osl @@ -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(); +} + diff --git a/intern/cycles/kernel/shaders/node_geometry.osl b/intern/cycles/kernel/shaders/node_geometry.osl index 953c5d1fa2b..3940b98eec1 100644 --- a/intern/cycles/kernel/shaders/node_geometry.osl +++ b/intern/cycles/kernel/shaders/node_geometry.osl @@ -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); } } diff --git a/intern/cycles/kernel/shaders/node_normal_map.osl b/intern/cycles/kernel/shaders/node_normal_map.osl new file mode 100644 index 00000000000..e238313509e --- /dev/null +++ b/intern/cycles/kernel/shaders/node_normal_map.osl @@ -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)); +} + diff --git a/intern/cycles/kernel/shaders/node_refraction_bsdf.osl b/intern/cycles/kernel/shaders/node_refraction_bsdf.osl new file mode 100644 index 00000000000..0cf9d460c6e --- /dev/null +++ b/intern/cycles/kernel/shaders/node_refraction_bsdf.osl @@ -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); +} + diff --git a/intern/cycles/kernel/shaders/node_tangent.osl b/intern/cycles/kernel/shaders/node_tangent.osl new file mode 100644 index 00000000000..731af89231a --- /dev/null +++ b/intern/cycles/kernel/shaders/node_tangent.osl @@ -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))); +} + diff --git a/intern/cycles/kernel/shaders/node_ward_bsdf.osl b/intern/cycles/kernel/shaders/node_ward_bsdf.osl index 03a0477038e..e5c6f0ad705 100644 --- a/intern/cycles/kernel/shaders/node_ward_bsdf.osl +++ b/intern/cycles/kernel/shaders/node_ward_bsdf.osl @@ -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); diff --git a/intern/cycles/kernel/shaders/stdosl.h b/intern/cycles/kernel/shaders/stdosl.h index 4237291c7a4..c55def2b47a 100644 --- a/intern/cycles/kernel/shaders/stdosl.h +++ b/intern/cycles/kernel/shaders/stdosl.h @@ -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; diff --git a/intern/cycles/kernel/svm/svm.h b/intern/cycles/kernel/svm/svm.h index 698ef5016f0..886fce63fd4 100644 --- a/intern/cycles/kernel/svm/svm.h +++ b/intern/cycles/kernel/svm/svm.h @@ -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: diff --git a/intern/cycles/kernel/svm/svm_closure.h b/intern/cycles/kernel/svm/svm_closure.h index 11ce3b7c5d1..f378d24463d 100644 --- a/intern/cycles/kernel/svm/svm_closure.h +++ b/intern/cycles/kernel/svm/svm_closure.h @@ -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; @@ -159,6 +159,31 @@ __device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *st 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); eta = (sd->flag & SD_BACKFACING)? 1.0f/eta: eta; @@ -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) diff --git a/intern/cycles/kernel/svm/svm_geometry.h b/intern/cycles/kernel/svm/svm_geometry.h index 8e772f849c7..68177493f4e 100644 --- a/intern/cycles/kernel/svm/svm_geometry.h +++ b/intern/cycles/kernel/svm/svm_geometry.h @@ -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; diff --git a/intern/cycles/kernel/svm/svm_tex_coord.h b/intern/cycles/kernel/svm/svm_tex_coord.h index 6bd8f2ac69c..2f73f7b9d40 100644 --- a/intern/cycles/kernel/svm/svm_tex_coord.h +++ b/intern/cycles/kernel/svm/svm_tex_coord.h @@ -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 diff --git a/intern/cycles/kernel/svm/svm_types.h b/intern/cycles/kernel/svm/svm_types.h index 77df373a159..54767f3c87f 100644 --- a/intern/cycles/kernel/svm/svm_types.h +++ b/intern/cycles/kernel/svm/svm_types.h @@ -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 diff --git a/intern/cycles/render/attribute.cpp b/intern/cycles/render/attribute.cpp index c7a9ab3e51a..95941c14b6c 100644 --- a/intern/cycles/render/attribute.cpp +++ b/intern/cycles/render/attribute.cpp @@ -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) diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp index d7bf71337f6..4f50de11edf 100644 --- a/intern/cycles/render/nodes.cpp +++ b/intern/cycles/render/nodes.cpp @@ -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 diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h index d90cae5f668..27b07769e28 100644 --- a/intern/cycles/render/nodes.h +++ b/intern/cycles/render/nodes.h @@ -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__ */ diff --git a/intern/cycles/util/util_attribute.cpp b/intern/cycles/util/util_attribute.cpp index 163a92902f3..057fb6213e9 100644 --- a/intern/cycles/util/util_attribute.cpp +++ b/intern/cycles/util/util_attribute.cpp @@ -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) diff --git a/intern/cycles/util/util_types.h b/intern/cycles/util/util_types.h index f2c02cadcbf..fe530d727ad 100644 --- a/intern/cycles/util/util_types.h +++ b/intern/cycles/util/util_types.h @@ -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, diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index 29e03f66bcc..b365d93b246 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -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 diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index 153eb5271c5..2d76484b60a 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -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); diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index 0938562857b..b99842502ec 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -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: diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index c73ba87754f..3437e6dfcf1 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -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 diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index 312469340a7..93f37682aa3 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -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; diff --git a/source/blender/makesrna/intern/rna_nodetree_types.h b/source/blender/makesrna/intern/rna_nodetree_types.h index c45c9b71442..fbbcbae6c12 100644 --- a/source/blender/makesrna/intern/rna_nodetree_types.h +++ b/source/blender/makesrna/intern/rna_nodetree_types.h @@ -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","" ) diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt index 323a534c989..7dca4d07b24 100644 --- a/source/blender/nodes/CMakeLists.txt +++ b/source/blender/nodes/CMakeLists.txt @@ -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 diff --git a/source/blender/nodes/NOD_shader.h b/source/blender/nodes/NOD_shader.h index 66ab15ce29f..e402924c04f 100644 --- a/source/blender/nodes/NOD_shader.h +++ b/source/blender/nodes/NOD_shader.h @@ -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); diff --git a/source/blender/nodes/shader/nodes/node_shader_ambient_occlusion.c b/source/blender/nodes/shader/nodes/node_shader_ambient_occlusion.c new file mode 100644 index 00000000000..7dfefc9ece0 --- /dev/null +++ b/source/blender/nodes/shader/nodes/node_shader_ambient_occlusion.c @@ -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); +} + diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_refraction.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_refraction.c new file mode 100644 index 00000000000..99e66e39002 --- /dev/null +++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_refraction.c @@ -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); +} diff --git a/source/blender/nodes/shader/nodes/node_shader_normal_map.c b/source/blender/nodes/shader/nodes/node_shader_normal_map.c new file mode 100644 index 00000000000..39fd8a5decc --- /dev/null +++ b/source/blender/nodes/shader/nodes/node_shader_normal_map.c @@ -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); +} + diff --git a/source/blender/nodes/shader/nodes/node_shader_tangent.c b/source/blender/nodes/shader/nodes/node_shader_tangent.c new file mode 100644 index 00000000000..6c0d6d7cd9f --- /dev/null +++ b/source/blender/nodes/shader/nodes/node_shader_tangent.c @@ -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); +} + |