Merge branch 'master' into blender2.8

This commit is contained in:
Campbell Barton 2017-08-21 15:41:03 +10:00
commit 3e555d3d78
Notes: blender-bot 2023-02-14 06:39:29 +01:00
Referenced by issue #52482, Eevee: Regression in visuals on Ember forest sample file
33 changed files with 394 additions and 243 deletions

View File

@ -67,6 +67,7 @@ class AddPresetSampling(AddPresetBase, Operator):
"cycles.mesh_light_samples",
"cycles.subsurface_samples",
"cycles.volume_samples",
"cycles.use_square_samples",
"cycles.progressive",
"cycles.seed",
"cycles.sample_clamp_direct",

View File

@ -172,6 +172,12 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
default='PATH',
)
cls.use_square_samples = BoolProperty(
name="Square Samples",
description="Square sampling values for easier artist control",
default=False,
)
cls.samples = IntProperty(
name="Samples",
description="Number of samples to render for each pixel",

View File

@ -101,6 +101,8 @@ def draw_samples_info(layout, context):
# Calculate sample values
if integrator == 'PATH':
aa = cscene.samples
if cscene.use_square_samples:
aa = aa * aa
else:
aa = cscene.aa_samples
d = cscene.diffuse_samples
@ -111,9 +113,19 @@ def draw_samples_info(layout, context):
sss = cscene.subsurface_samples
vol = cscene.volume_samples
if cscene.use_square_samples:
aa = aa * aa
d = d * d
g = g * g
t = t * t
ao = ao * ao
ml = ml * ml
sss = sss * sss
vol = vol * vol
# Draw interface
# Do not draw for progressive, when Square Samples are disabled
if use_branched_path(context):
if use_branched_path(context) or (cscene.use_square_samples and integrator == 'PATH'):
col = layout.column(align=True)
col.scale_y = 0.6
col.label("Total Samples:")
@ -146,7 +158,7 @@ class CyclesRender_PT_sampling(CyclesButtonsPanel, Panel):
row = layout.row()
sub = row.row()
sub.prop(cscene, "progressive", text="")
sub.label()
row.prop(cscene, "use_square_samples")
split = layout.split()

View File

@ -315,23 +315,3 @@ def do_versions(self):
cscene.blur_glossy = 0.0
if not cscene.is_property_set("sample_clamp_indirect"):
cscene.sample_clamp_indirect = 0.0
# Remove and apply square samples
use_square_samples = cscene.get("use_square_samples", False)
if use_square_samples:
del cscene["use_square_samples"]
cscene.samples *= cscene.samples
cscene.preview_samples *= cscene.preview_samples
cscene.aa_samples *= cscene.aa_samples
cscene.preview_aa_samples *= cscene.preview_aa_samples
cscene.diffuse_samples *= cscene.diffuse_samples
cscene.glossy_samples *= cscene.glossy_samples
cscene.transmission_samples *= cscene.transmission_samples
cscene.ao_samples *= cscene.ao_samples
cscene.mesh_light_samples *= cscene.mesh_light_samples
cscene.subsurface_samples *= cscene.subsurface_samples
cscene.volume_samples *= cscene.volume_samples
for layer in scene.render.layers:
layer.samples *= layer.samples

View File

@ -163,11 +163,16 @@ void BlenderSync::sync_light(BL::Object& b_parent,
light->shader = used_shaders[0];
/* shadow */
PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
PointerRNA clamp = RNA_pointer_get(&b_lamp.ptr, "cycles");
light->cast_shadow = get_boolean(clamp, "cast_shadow");
light->use_mis = get_boolean(clamp, "use_multiple_importance_sampling");
light->samples = get_int(clamp, "samples");
int samples = get_int(clamp, "samples");
if(get_boolean(cscene, "use_square_samples"))
light->samples = samples * samples;
else
light->samples = samples;
light->max_bounces = get_int(clamp, "max_bounces");
@ -195,6 +200,7 @@ void BlenderSync::sync_background_light(bool use_portal)
BL::World b_world = b_scene.world();
if(b_world) {
PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
PointerRNA cworld = RNA_pointer_get(&b_world.ptr, "cycles");
bool sample_as_light = get_boolean(cworld, "sample_as_light");
@ -213,7 +219,11 @@ void BlenderSync::sync_background_light(bool use_portal)
light->use_mis = sample_as_light;
light->max_bounces = get_int(cworld, "max_bounces");
light->samples = get_int(cworld, "samples");
int samples = get_int(cworld, "samples");
if(get_boolean(cscene, "use_square_samples"))
light->samples = samples * samples;
else
light->samples = samples;
light->tag_update(scene);
light_map.set_recalc(b_world);

View File

@ -294,13 +294,32 @@ void BlenderSync::sync_integrator()
integrator->sample_all_lights_indirect = get_boolean(cscene, "sample_all_lights_indirect");
integrator->light_sampling_threshold = get_float(cscene, "light_sampling_threshold");
integrator->diffuse_samples = get_int(cscene, "diffuse_samples");
integrator->glossy_samples = get_int(cscene, "glossy_samples");
integrator->transmission_samples = get_int(cscene, "transmission_samples");
integrator->ao_samples = get_int(cscene, "ao_samples");
integrator->mesh_light_samples = get_int(cscene, "mesh_light_samples");
integrator->subsurface_samples = get_int(cscene, "subsurface_samples");
integrator->volume_samples = get_int(cscene, "volume_samples");
int diffuse_samples = get_int(cscene, "diffuse_samples");
int glossy_samples = get_int(cscene, "glossy_samples");
int transmission_samples = get_int(cscene, "transmission_samples");
int ao_samples = get_int(cscene, "ao_samples");
int mesh_light_samples = get_int(cscene, "mesh_light_samples");
int subsurface_samples = get_int(cscene, "subsurface_samples");
int volume_samples = get_int(cscene, "volume_samples");
if(get_boolean(cscene, "use_square_samples")) {
integrator->diffuse_samples = diffuse_samples * diffuse_samples;
integrator->glossy_samples = glossy_samples * glossy_samples;
integrator->transmission_samples = transmission_samples * transmission_samples;
integrator->ao_samples = ao_samples * ao_samples;
integrator->mesh_light_samples = mesh_light_samples * mesh_light_samples;
integrator->subsurface_samples = subsurface_samples * subsurface_samples;
integrator->volume_samples = volume_samples * volume_samples;
}
else {
integrator->diffuse_samples = diffuse_samples;
integrator->glossy_samples = glossy_samples;
integrator->transmission_samples = transmission_samples;
integrator->ao_samples = ao_samples;
integrator->mesh_light_samples = mesh_light_samples;
integrator->subsurface_samples = subsurface_samples;
integrator->volume_samples = volume_samples;
}
if(b_scene.render().use_simplify()) {
if(preview) {
@ -400,7 +419,11 @@ void BlenderSync::sync_render_layers(BL::SpaceView3D& b_v3d, const char *layer)
render_layer.bound_samples = (use_layer_samples == 1);
if(use_layer_samples != 2) {
render_layer.samples = b_rlay->samples();
int samples = b_rlay->samples();
if(get_boolean(cscene, "use_square_samples"))
render_layer.samples = samples * samples;
else
render_layer.samples = samples;
}
}
@ -715,6 +738,14 @@ SessionParams BlenderSync::get_session_params(BL::RenderEngine& b_engine,
int preview_samples = get_int(cscene, "preview_samples");
int preview_aa_samples = get_int(cscene, "preview_aa_samples");
if(get_boolean(cscene, "use_square_samples")) {
aa_samples = aa_samples * aa_samples;
preview_aa_samples = preview_aa_samples * preview_aa_samples;
samples = samples * samples;
preview_samples = preview_samples * preview_samples;
}
if(get_enum(cscene, "progressive") == 0) {
if(background) {
params.samples = aa_samples;

View File

@ -2144,18 +2144,34 @@ Device *device_cuda_create(DeviceInfo& info, Stats &stats, bool background)
return new CUDADevice(info, stats, background);
}
static CUresult device_cuda_safe_init()
{
#ifdef _WIN32
__try {
return cuInit(0);
}
__except(EXCEPTION_EXECUTE_HANDLER) {
/* Ignore crashes inside the CUDA driver and hope we can
* survive even with corrupted CUDA installs. */
fprintf(stderr, "Cycles CUDA: driver crashed, continuing without CUDA.\n");
}
return CUDA_ERROR_NO_DEVICE;
#else
return cuInit(0);
#endif
}
void device_cuda_info(vector<DeviceInfo>& devices)
{
CUresult result;
int count = 0;
result = cuInit(0);
CUresult result = device_cuda_safe_init();
if(result != CUDA_SUCCESS) {
if(result != CUDA_ERROR_NO_DEVICE)
fprintf(stderr, "CUDA cuInit: %s\n", cuewErrorString(result));
return;
}
int count = 0;
result = cuDeviceGetCount(&count);
if(result != CUDA_SUCCESS) {
fprintf(stderr, "CUDA cuDeviceGetCount: %s\n", cuewErrorString(result));
@ -2212,7 +2228,7 @@ void device_cuda_info(vector<DeviceInfo>& devices)
string device_cuda_capabilities(void)
{
CUresult result = cuInit(0);
CUresult result = device_cuda_safe_init();
if(result != CUDA_SUCCESS) {
if(result != CUDA_ERROR_NO_DEVICE) {
return string("Error initializing CUDA: ") + cuewErrorString(result);

View File

@ -73,8 +73,34 @@ bool device_opencl_init(void)
return result;
}
static cl_int device_opencl_get_num_platforms_safe(cl_uint *num_platforms)
{
#ifdef _WIN32
__try {
return clGetPlatformIDs(0, NULL, num_platforms);
}
__except(EXCEPTION_EXECUTE_HANDLER) {
/* Ignore crashes inside the OpenCL driver and hope we can
* survive even with corrupted OpenCL installs. */
fprintf(stderr, "Cycles OpenCL: driver crashed, continuing without OpenCL.\n");
}
*num_platforms = 0;
return CL_DEVICE_NOT_FOUND;
#else
return clGetPlatformIDs(0, NULL, num_platforms);
#endif
}
void device_opencl_info(vector<DeviceInfo>& devices)
{
cl_uint num_platforms = 0;
device_opencl_get_num_platforms_safe(&num_platforms);
if(num_platforms == 0) {
return;
}
vector<OpenCLPlatformDevice> usable_devices;
OpenCLInfo::get_usable_devices(&usable_devices);
/* Devices are numbered consecutively across platforms. */
@ -113,7 +139,7 @@ string device_opencl_capabilities(void)
* it could also be nicely reported to the console.
*/
cl_uint num_platforms = 0;
opencl_assert(clGetPlatformIDs(0, NULL, &num_platforms));
opencl_assert(device_opencl_get_num_platforms_safe(&num_platforms));
if(num_platforms == 0) {
return "No OpenCL platforms found\n";
}

View File

@ -342,8 +342,8 @@ ccl_device void kernel_bake_evaluate(KernelGlobals *kg, ccl_global uint4 *input,
shader_eval_surface(kg, &sd, &state, 0.f, 0, SHADER_CONTEXT_MAIN);
}
/* compression: normal = (2 * color) - 1 */
out = sd.N * 0.5f + make_float3(0.5f, 0.5f, 0.5f);
/* encoding: normal = (2 * color) - 1 */
out = shader_bsdf_average_normal(kg, &sd) * 0.5f + make_float3(0.5f, 0.5f, 0.5f);
break;
}
case SHADER_EVAL_UV:

View File

@ -260,7 +260,7 @@ ccl_device_inline void kernel_write_data_passes(KernelGlobals *kg, ccl_global fl
}
if(flag & PASS_NORMAL) {
float3 normal = sd->N;
float3 normal = shader_bsdf_average_normal(kg, sd);
kernel_write_pass_float3(buffer + kernel_data.film.pass_normal, sample, normal);
}
if(flag & PASS_UV) {

View File

@ -46,7 +46,7 @@ bool kernel_path_subsurface_scatter(
*/
kernel_assert(!ss_indirect->tracing);
uint lcg_state = lcg_state_init(state, 0x68bc21eb);
uint lcg_state = lcg_state_init_addrspace(state, 0x68bc21eb);
SubsurfaceIntersection ss_isect;
float bssrdf_u, bssrdf_v;

View File

@ -307,12 +307,19 @@ ccl_device_inline void path_state_branch(ccl_addr_space PathState *state,
state->num_samples = state->num_samples*num_branches;
}
ccl_device_inline uint lcg_state_init(ccl_addr_space PathState *state,
ccl_device_inline uint lcg_state_init(PathState *state,
uint scramble)
{
return lcg_init(state->rng_hash + state->rng_offset + state->sample*scramble);
}
ccl_device_inline uint lcg_state_init_addrspace(ccl_addr_space PathState *state,
uint scramble)
{
return lcg_init(state->rng_hash + state->rng_offset + state->sample*scramble);
}
ccl_device float lcg_step_float_addrspace(ccl_addr_space uint *rng)
{
/* Implicit mod 2^32 */

View File

@ -764,6 +764,19 @@ ccl_device float3 shader_bsdf_subsurface(KernelGlobals *kg, ShaderData *sd)
return eval;
}
ccl_device float3 shader_bsdf_average_normal(KernelGlobals *kg, ShaderData *sd)
{
float3 N = 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_BSDF_OR_BSSRDF(sc->type))
N += sc->N*average(sc->weight);
}
return (is_zero(N))? sd->N : normalize(N);
}
ccl_device float3 shader_bsdf_ao(KernelGlobals *kg, ShaderData *sd, float ao_factor, float3 *N_)
{
float3 eval = make_float3(0.0f, 0.0f, 0.0f);
@ -783,12 +796,7 @@ ccl_device float3 shader_bsdf_ao(KernelGlobals *kg, ShaderData *sd, float ao_fac
}
}
if(is_zero(N))
N = sd->N;
else
N = normalize(N);
*N_ = N;
*N_ = (is_zero(N))? sd->N : normalize(N);
return eval;
}
@ -888,7 +896,7 @@ ccl_device void shader_eval_surface(KernelGlobals *kg, ShaderData *sd,
}
if(sd->flag & SD_BSDF_NEEDS_LCG) {
sd->lcg_state = lcg_state_init(state, 0xb4bc3953);
sd->lcg_state = lcg_state_init_addrspace(state, 0xb4bc3953);
}
}

View File

@ -878,7 +878,7 @@ enum ShaderDataFlag {
SD_VOLUME_MIS = (1 << 23),
/* Use cubic interpolation for voxels. */
SD_VOLUME_CUBIC = (1 << 24),
/* Has data connected to the displacement input. */
/* Has data connected to the displacement input or uses bump map. */
SD_HAS_BUMP = (1 << 25),
/* Has true displacement. */
SD_HAS_DISPLACEMENT = (1 << 26),

View File

@ -51,8 +51,8 @@ ccl_device_noinline bool kernel_split_branched_path_subsurface_indirect_light_it
if(branched_state->ss_next_sample == 0 && branched_state->next_hit == 0 &&
branched_state->next_closure == 0 && branched_state->next_sample == 0)
{
branched_state->lcg_state = lcg_state_init(&branched_state->path_state,
0x68bc21eb);
branched_state->lcg_state = lcg_state_init_addrspace(&branched_state->path_state,
0x68bc21eb);
}
int num_samples = kernel_data.integrator.subsurface_samples;
float num_samples_inv = 1.0f/num_samples;
@ -258,7 +258,7 @@ ccl_device void kernel_subsurface_scatter(KernelGlobals *kg)
/* do bssrdf scatter step if we picked a bssrdf closure */
if(sc) {
uint lcg_state = lcg_state_init(state, 0x68bc21eb);
uint lcg_state = lcg_state_init_addrspace(state, 0x68bc21eb);
float bssrdf_u, bssrdf_v;
path_state_rng_2D(kg,
state,

View File

@ -221,28 +221,6 @@ OutputNode *ShaderGraph::output()
return (OutputNode*)nodes.front();
}
ShaderGraph *ShaderGraph::copy()
{
ShaderGraph *newgraph = new ShaderGraph();
/* copy nodes */
ShaderNodeSet nodes_all;
foreach(ShaderNode *node, nodes)
nodes_all.insert(node);
ShaderNodeMap nodes_copy;
copy_nodes(nodes_all, nodes_copy);
/* add nodes (in same order, so output is still first) */
newgraph->clear_nodes();
foreach(ShaderNode *node, nodes)
newgraph->add(nodes_copy[node]);
newgraph->simplified = simplified;
return newgraph;
}
void ShaderGraph::connect(ShaderOutput *from, ShaderInput *to)
{
assert(!finalized);

View File

@ -151,6 +151,7 @@ public:
virtual bool has_surface_emission() { return false; }
virtual bool has_surface_transparent() { return false; }
virtual bool has_surface_bssrdf() { return false; }
virtual bool has_bump() { return false; }
virtual bool has_bssrdf_bump() { return false; }
virtual bool has_spatial_varying() { return false; }
virtual bool has_object_dependency() { return false; }
@ -245,8 +246,6 @@ public:
ShaderGraph();
~ShaderGraph();
ShaderGraph *copy();
ShaderNode *add(ShaderNode *node);
OutputNode *output();

View File

@ -1801,6 +1801,14 @@ BsdfBaseNode::BsdfBaseNode(const NodeType *node_type)
special_type = SHADER_SPECIAL_TYPE_CLOSURE;
}
bool BsdfBaseNode::has_bump()
{
/* detect if anything is plugged into the normal input besides the default */
ShaderInput *normal_in = input("Normal");
return (normal_in && normal_in->link &&
normal_in->link->parent->special_type != SHADER_SPECIAL_TYPE_GEOMETRY);
}
/* BSDF Closure */
BsdfNode::BsdfNode(const NodeType *node_type)
@ -2439,9 +2447,7 @@ void PrincipledBsdfNode::compile(OSLCompiler& compiler)
bool PrincipledBsdfNode::has_bssrdf_bump()
{
/* detect if anything is plugged into the normal input besides the default */
ShaderInput *normal_in = input("Normal");
return (normal_in->link && normal_in->link->parent->special_type != SHADER_SPECIAL_TYPE_GEOMETRY);
return has_surface_bssrdf() && has_bump();
}
/* Translucent BSDF Closure */

View File

@ -326,6 +326,16 @@ class BsdfBaseNode : public ShaderNode {
public:
BsdfBaseNode(const NodeType *node_type);
bool has_spatial_varying() { return true; }
virtual ClosureType get_closure_type() { return closure; }
virtual bool has_bump();
virtual bool equals(const ShaderNode& /*other*/)
{
/* TODO(sergey): With some care BSDF nodes can be de-duplicated. */
return false;
}
ClosureType closure;
};
@ -334,19 +344,11 @@ public:
explicit BsdfNode(const NodeType *node_type);
SHADER_NODE_BASE_CLASS(BsdfNode)
bool has_spatial_varying() { return true; }
void compile(SVMCompiler& compiler, ShaderInput *param1, ShaderInput *param2, ShaderInput *param3 = NULL, ShaderInput *param4 = NULL);
virtual ClosureType get_closure_type() { return closure; }
float3 color;
float3 normal;
float surface_mix_weight;
virtual bool equals(const ShaderNode& /*other*/)
{
/* TODO(sergey): With some care BSDF nodes can be de-duplicated. */
return false;
}
};
class AnisotropicBsdfNode : public BsdfNode {
@ -373,7 +375,6 @@ class PrincipledBsdfNode : public BsdfBaseNode {
public:
SHADER_NODE_CLASS(PrincipledBsdfNode)
bool has_spatial_varying() { return true; }
bool has_surface_bssrdf();
bool has_bssrdf_bump();
void compile(SVMCompiler& compiler, ShaderInput *metallic, ShaderInput *subsurface, ShaderInput *subsurface_radius,
@ -390,13 +391,6 @@ public:
float surface_mix_weight;
ClosureType distribution, distribution_orig;
virtual bool equals(const ShaderNode * /*other*/)
{
/* TODO(sergey): With some care BSDF nodes can be de-duplicated. */
return false;
}
ClosureType get_closure_type() { return closure; }
bool has_integrator_dependency();
void attributes(Shader *shader, AttributeRequestSet *attributes);
};

View File

@ -721,6 +721,7 @@ void OSLCompiler::add(ShaderNode *node, const char *name, bool isfilepath)
current_shader->has_surface_bssrdf = true;
current_shader->has_bssrdf_bump = true; /* can't detect yet */
}
current_shader->has_bump = true; /* can't detect yet */
}
if(node->has_spatial_varying()) {
@ -1029,6 +1030,9 @@ void OSLCompiler::generate_nodes(const ShaderNodeSet& nodes)
if(node->has_bssrdf_bump())
current_shader->has_bssrdf_bump = true;
}
if(node->has_bump()) {
current_shader->has_bump = true;
}
}
else if(current_type == SHADER_TYPE_VOLUME) {
if(node->has_spatial_varying())
@ -1091,21 +1095,14 @@ void OSLCompiler::compile(Scene *scene, OSLGlobals *og, Shader *shader)
ShaderGraph *graph = shader->graph;
ShaderNode *output = (graph)? graph->output(): NULL;
/* copy graph for shader with bump mapping */
if(output->input("Surface")->link && output->input("Displacement")->link)
if(!shader->graph_bump)
shader->graph_bump = shader->graph->copy();
bool has_bump = (shader->displacement_method != DISPLACE_TRUE) &&
output->input("Surface")->link && output->input("Displacement")->link;
/* finalize */
shader->graph->finalize(scene,
false,
shader->has_integrator_dependency);
if(shader->graph_bump) {
shader->graph_bump->finalize(scene,
true,
shader->has_integrator_dependency,
shader->displacement_method == DISPLACE_BOTH);
}
has_bump,
shader->has_integrator_dependency,
shader->displacement_method == DISPLACE_BOTH);
current_shader = shader;
@ -1113,7 +1110,8 @@ void OSLCompiler::compile(Scene *scene, OSLGlobals *og, Shader *shader)
shader->has_surface_emission = false;
shader->has_surface_transparent = false;
shader->has_surface_bssrdf = false;
shader->has_bssrdf_bump = false;
shader->has_bump = has_bump;
shader->has_bssrdf_bump = has_bump;
shader->has_volume = false;
shader->has_displacement = false;
shader->has_surface_spatial_varying = false;
@ -1125,8 +1123,8 @@ void OSLCompiler::compile(Scene *scene, OSLGlobals *og, Shader *shader)
if(shader->used && graph && output->input("Surface")->link) {
shader->osl_surface_ref = compile_type(shader, shader->graph, SHADER_TYPE_SURFACE);
if(shader->graph_bump && shader->displacement_method != DISPLACE_TRUE)
shader->osl_surface_bump_ref = compile_type(shader, shader->graph_bump, SHADER_TYPE_BUMP);
if(has_bump)
shader->osl_surface_bump_ref = compile_type(shader, shader->graph, SHADER_TYPE_BUMP);
else
shader->osl_surface_bump_ref = OSL::ShaderGroupRef();

View File

@ -177,7 +177,6 @@ Shader::Shader()
pass_id = 0;
graph = NULL;
graph_bump = NULL;
has_surface = false;
has_surface_transparent = false;
@ -185,6 +184,7 @@ Shader::Shader()
has_surface_bssrdf = false;
has_volume = false;
has_displacement = false;
has_bump = false;
has_bssrdf_bump = false;
has_surface_spatial_varying = false;
has_volume_spatial_varying = false;
@ -204,7 +204,6 @@ Shader::Shader()
Shader::~Shader()
{
delete graph;
delete graph_bump;
}
bool Shader::is_constant_emission(float3 *emission)
@ -239,9 +238,7 @@ void Shader::set_graph(ShaderGraph *graph_)
/* assign graph */
delete graph;
delete graph_bump;
graph = graph_;
graph_bump = NULL;
/* Store info here before graph optimization to make sure that
* nodes that get optimized away still count. */
@ -458,15 +455,11 @@ void ShaderManager::device_update_common(Device *device,
flag |= SD_VOLUME_MIS;
if(shader->volume_interpolation_method == VOLUME_INTERPOLATION_CUBIC)
flag |= SD_VOLUME_CUBIC;
if(shader->graph_bump)
if(shader->has_bump)
flag |= SD_HAS_BUMP;
if(shader->displacement_method != DISPLACE_BUMP)
flag |= SD_HAS_DISPLACEMENT;
/* shader with bump mapping */
if(shader->displacement_method != DISPLACE_TRUE && shader->graph_bump)
flag |= SD_HAS_BSSRDF_BUMP;
/* constant emission check */
float3 constant_emission = make_float3(0.0f, 0.0f, 0.0f);
if(shader->is_constant_emission(&constant_emission))
@ -608,11 +601,6 @@ void ShaderManager::get_requested_features(Scene *scene,
Shader *shader = scene->shaders[i];
/* Gather requested features from all the nodes from the graph nodes. */
get_requested_graph_features(shader->graph, requested_features);
/* Gather requested features from the graph itself. */
if(shader->graph_bump) {
get_requested_graph_features(shader->graph_bump,
requested_features);
}
ShaderNode *output_node = shader->graph->output();
if(output_node->input("Displacement")->link != NULL) {
requested_features->nodes_features |= NODE_FEATURE_BUMP;

View File

@ -89,11 +89,6 @@ public:
/* shader graph */
ShaderGraph *graph;
/* shader graph with auto bump mapping included, we compile two shaders,
* with and without bump, because the displacement method is a mesh
* level setting, so we need to handle both */
ShaderGraph *graph_bump;
/* sampling */
bool use_mis;
bool use_transparent_shadow;
@ -121,6 +116,7 @@ public:
bool has_volume;
bool has_displacement;
bool has_surface_bssrdf;
bool has_bump;
bool has_bssrdf_bump;
bool has_surface_spatial_varying;
bool has_volume_spatial_varying;

View File

@ -521,6 +521,9 @@ void SVMCompiler::generate_closure_node(ShaderNode *node,
if(node->has_bssrdf_bump())
current_shader->has_bssrdf_bump = true;
}
if(node->has_bump()) {
current_shader->has_bump = true;
}
}
}
@ -799,29 +802,21 @@ void SVMCompiler::compile(Scene *scene,
Summary *summary)
{
/* copy graph for shader with bump mapping */
ShaderNode *node = shader->graph->output();
ShaderNode *output = shader->graph->output();
int start_num_svm_nodes = svm_nodes.size();
const double time_start = time_dt();
if(node->input("Surface")->link && node->input("Displacement")->link)
if(!shader->graph_bump)
shader->graph_bump = shader->graph->copy();
bool has_bump = (shader->displacement_method != DISPLACE_TRUE) &&
output->input("Surface")->link && output->input("Displacement")->link;
/* finalize */
{
scoped_timer timer((summary != NULL)? &summary->time_finalize: NULL);
shader->graph->finalize(scene,
false,
shader->has_integrator_dependency);
}
if(shader->graph_bump) {
scoped_timer timer((summary != NULL)? &summary->time_finalize_bump: NULL);
shader->graph_bump->finalize(scene,
true,
shader->has_integrator_dependency,
shader->displacement_method == DISPLACE_BOTH);
has_bump,
shader->has_integrator_dependency,
shader->displacement_method == DISPLACE_BOTH);
}
current_shader = shader;
@ -830,7 +825,8 @@ void SVMCompiler::compile(Scene *scene,
shader->has_surface_emission = false;
shader->has_surface_transparent = false;
shader->has_surface_bssrdf = false;
shader->has_bssrdf_bump = false;
shader->has_bump = has_bump;
shader->has_bssrdf_bump = has_bump;
shader->has_volume = false;
shader->has_displacement = false;
shader->has_surface_spatial_varying = false;
@ -839,9 +835,9 @@ void SVMCompiler::compile(Scene *scene,
shader->has_integrator_dependency = false;
/* generate bump shader */
if(shader->displacement_method != DISPLACE_TRUE && shader->graph_bump) {
if(has_bump) {
scoped_timer timer((summary != NULL)? &summary->time_generate_bump: NULL);
compile_type(shader, shader->graph_bump, SHADER_TYPE_BUMP);
compile_type(shader, shader->graph, SHADER_TYPE_BUMP);
svm_nodes[index].y = svm_nodes.size();
svm_nodes.insert(svm_nodes.end(),
current_svm_nodes.begin(),
@ -853,7 +849,7 @@ void SVMCompiler::compile(Scene *scene,
scoped_timer timer((summary != NULL)? &summary->time_generate_surface: NULL);
compile_type(shader, shader->graph, SHADER_TYPE_SURFACE);
/* only set jump offset if there's no bump shader, as the bump shader will fall thru to this one if it exists */
if(shader->displacement_method == DISPLACE_TRUE || !shader->graph_bump) {
if(!has_bump) {
svm_nodes[index].y = svm_nodes.size();
}
svm_nodes.insert(svm_nodes.end(),
@ -895,7 +891,6 @@ SVMCompiler::Summary::Summary()
: num_svm_nodes(0),
peak_stack_usage(0),
time_finalize(0.0),
time_finalize_bump(0.0),
time_generate_surface(0.0),
time_generate_bump(0.0),
time_generate_volume(0.0),
@ -911,10 +906,7 @@ string SVMCompiler::Summary::full_report() const
report += string_printf("Peak stack usage: %d\n", peak_stack_usage);
report += string_printf("Time (in seconds):\n");
report += string_printf(" Finalize: %f\n", time_finalize);
report += string_printf(" Bump finalize: %f\n", time_finalize_bump);
report += string_printf("Finalize: %f\n", time_finalize +
time_finalize_bump);
report += string_printf("Finalize: %f\n", time_finalize);
report += string_printf(" Surface: %f\n", time_generate_surface);
report += string_printf(" Bump: %f\n", time_generate_bump);
report += string_printf(" Volume: %f\n", time_generate_volume);

View File

@ -74,9 +74,6 @@ public:
/* Time spent on surface graph finalization. */
double time_finalize;
/* Time spent on bump graph finalization. */
double time_finalize_bump;
/* Time spent on generating SVM nodes for surface shader. */
double time_generate_surface;

106
make.bat
View File

@ -71,28 +71,28 @@ if NOT "%1" == "" (
-C"%BLENDER_DIR%\build_files\cmake\config\bpy_module.cmake"
) else if "%1" == "release" (
set TARGET=Release
) else if "%1" == "x86" (
) else if "%1" == "x86" (
set BUILD_ARCH=x86
) else if "%1" == "x64" (
) else if "%1" == "x64" (
set BUILD_ARCH=x64
) else if "%1" == "2017" (
) else if "%1" == "2017" (
set BUILD_VS_VER=15
set BUILD_VS_YEAR=2017
set BUILD_VS_LIBDIRPOST=vc14
) else if "%1" == "2015" (
) else if "%1" == "2015" (
set BUILD_VS_VER=14
set BUILD_VS_YEAR=2015
set BUILD_VS_LIBDIRPOST=vc14
) else if "%1" == "2013" (
) else if "%1" == "2013" (
set BUILD_VS_VER=12
set BUILD_VS_YEAR=2013
set BUILD_VS_LIBDIRPOST=vc12
) else if "%1" == "packagename" (
) else if "%1" == "packagename" (
set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% -DCPACK_OVERRIDE_PACKAGENAME="%2"
shift /1
) else if "%1" == "nobuild" (
) else if "%1" == "nobuild" (
set NOBUILD=1
) else if "%1" == "showhash" (
) else if "%1" == "showhash" (
for /f "delims=" %%i in ('git rev-parse HEAD') do echo Branch_hash=%%i
cd release/datafiles/locale
for /f "delims=" %%i in ('git rev-parse HEAD') do echo Locale_hash=%%i
@ -129,10 +129,10 @@ if "%BUILD_ARCH%"=="" (
set BUILD_ARCH=x86
)
) else if "%BUILD_ARCH%"=="x64" (
set WINDOWS_ARCH= Win64
) else if "%BUILD_ARCH%"=="x86" (
set WINDOWS_ARCH=
)
set WINDOWS_ARCH= Win64
) else if "%BUILD_ARCH%"=="x86" (
set WINDOWS_ARCH=
)
if "%BUILD_VS_VER%"=="" (
set BUILD_VS_VER=12
@ -142,19 +142,19 @@ if "%BUILD_VS_VER%"=="" (
if "%BUILD_ARCH%"=="x64" (
set MSBUILD_PLATFORM=x64
) else if "%BUILD_ARCH%"=="x86" (
set MSBUILD_PLATFORM=win32
) else if "%BUILD_ARCH%"=="x86" (
set MSBUILD_PLATFORM=win32
)
if "%target%"=="Release" (
rem for vc12 check for both cuda 7.5 and 8
if "%CUDA_PATH%"=="" (
echo Cuda Not found, aborting!
goto EOF
)
set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% ^
-C"%BLENDER_DIR%\build_files\cmake\config\blender_release.cmake"
rem for vc12 check for both cuda 7.5 and 8
if "%CUDA_PATH%"=="" (
echo Cuda Not found, aborting!
goto EOF
)
set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% ^
-C"%BLENDER_DIR%\build_files\cmake\config\blender_release.cmake"
)
:DetectMSVC
@ -193,7 +193,7 @@ if %ERRORLEVEL% NEQ 0 (
set BUILD_VS_YEAR=2015
set BUILD_VS_LIBDIRPOST=vc14
goto DetectMSVC
) else (
) else (
echo Error: "MSBuild" command not in the PATH.
echo You must have MSVC installed and run this from the "Developer Command Prompt"
echo ^(available from Visual Studio's Start menu entry^), aborting!
@ -216,8 +216,8 @@ if %ERRORLEVEL% NEQ 0 (
if "%BUILD_ARCH%"=="x64" (
set BUILD_VS_SVNDIR=win64_%BUILD_VS_LIBDIRPOST%
) else if "%BUILD_ARCH%"=="x86" (
set BUILD_VS_SVNDIR=windows_%BUILD_VS_LIBDIRPOST%
) else if "%BUILD_ARCH%"=="x86" (
set BUILD_VS_SVNDIR=windows_%BUILD_VS_LIBDIRPOST%
)
set BUILD_VS_LIBDIR="%BLENDER_DIR%..\lib\%BUILD_VS_SVNDIR%"
@ -238,9 +238,9 @@ if NOT EXIST %BUILD_VS_LIBDIR% (
)
if NOT EXIST %BUILD_VS_LIBDIR% (
echo Error: Path to libraries not found "%BUILD_VS_LIBDIR%"
echo This is needed for building, aborting!
goto EOF
echo Error: Path to libraries not found "%BUILD_VS_LIBDIR%"
echo This is needed for building, aborting!
goto EOF
)
if "%TARGET%"=="" (
@ -331,31 +331,31 @@ echo Blender successfully built, run from: "%BUILD_DIR%\bin\%BUILD_TYPE%\blender
echo.
goto EOF
:HELP
echo.
echo Convenience targets
echo - release ^(identical to the official blender.org builds^)
echo - full ^(same as release minus the cuda kernels^)
echo - lite
echo - headless
echo - cycles
echo - bpy
echo.
echo Utilities ^(not associated with building^)
echo - clean ^(Target must be set^)
echo - update
echo - nobuild ^(only generate project files^)
echo - showhash ^(Show git hashes of source tree^)
echo.
echo Configuration options
echo - with_tests ^(enable building unit tests^)
echo - noge ^(disable building game enginge and player^)
echo - debug ^(Build an unoptimized debuggable build^)
echo - packagename [newname] ^(override default cpack package name^)
echo - buildir [newdir] ^(override default build folder^)
echo - x86 ^(override host auto-detect and build 32 bit code^)
echo - x64 ^(override host auto-detect and build 64 bit code^)
echo - 2013 ^(build with visual studio 2013^)
echo - 2015 ^(build with visual studio 2015^) [EXPERIMENTAL]
echo.
echo.
echo Convenience targets
echo - release ^(identical to the official blender.org builds^)
echo - full ^(same as release minus the cuda kernels^)
echo - lite
echo - headless
echo - cycles
echo - bpy
echo.
echo Utilities ^(not associated with building^)
echo - clean ^(Target must be set^)
echo - update
echo - nobuild ^(only generate project files^)
echo - showhash ^(Show git hashes of source tree^)
echo.
echo Configuration options
echo - with_tests ^(enable building unit tests^)
echo - noge ^(disable building game enginge and player^)
echo - debug ^(Build an unoptimized debuggable build^)
echo - packagename [newname] ^(override default cpack package name^)
echo - buildir [newdir] ^(override default build folder^)
echo - x86 ^(override host auto-detect and build 32 bit code^)
echo - x64 ^(override host auto-detect and build 64 bit code^)
echo - 2013 ^(build with visual studio 2013^)
echo - 2015 ^(build with visual studio 2015^) [EXPERIMENTAL]
echo.
:EOF

View File

@ -294,7 +294,8 @@ class VIEW3D_MT_transform_object(VIEW3D_MT_transform_base):
layout.operator("object.origin_set", text="Geometry to Origin").type = 'GEOMETRY_ORIGIN'
layout.operator("object.origin_set", text="Origin to Geometry").type = 'ORIGIN_GEOMETRY'
layout.operator("object.origin_set", text="Origin to 3D Cursor").type = 'ORIGIN_CURSOR'
layout.operator("object.origin_set", text="Origin to Center of Mass").type = 'ORIGIN_CENTER_OF_MASS'
layout.operator("object.origin_set", text="Origin to Center of Mass (Surface)").type = 'ORIGIN_CENTER_OF_MASS'
layout.operator("object.origin_set", text="Origin to Center of Mass (Volume)").type = 'ORIGIN_CENTER_OF_VOLUME'
layout.separator()
layout.operator("object.randomize_transform")

View File

@ -278,7 +278,8 @@ void BKE_mesh_poly_edgebitmap_insert(
bool BKE_mesh_center_median(const struct Mesh *me, float r_cent[3]);
bool BKE_mesh_center_bounds(const struct Mesh *me, float r_cent[3]);
bool BKE_mesh_center_centroid(const struct Mesh *me, float r_cent[3]);
bool BKE_mesh_center_of_surface(const struct Mesh *me, float r_cent[3]);
bool BKE_mesh_center_of_volume(const struct Mesh *me, float r_cent[3]);
void BKE_mesh_calc_volume(
const struct MVert *mverts, const int mverts_num,

View File

@ -1856,11 +1856,14 @@ float BKE_mesh_calc_poly_area(
* - http://forums.cgsociety.org/archive/index.php?t-756235.html
* - http://www.globalspec.com/reference/52702/203279/4-8-the-centroid-of-a-tetrahedron
*
* \note volume is 6x actual volume, and centroid is 4x actual volume-weighted centroid
* (so division can be done once at the end)
* \note results will have bias if polygon is non-planar.
* \note
* - Volume is 6x actual volume, and centroid is 4x actual volume-weighted centroid
* (so division can be done once at the end).
* - Results will have bias if polygon is non-planar.
* - The resulting volume will only be correct if the mesh is manifold and has consistent face winding
* (non-contiguous face normals or holes in the mesh surface).
*/
static float mesh_calc_poly_volume_and_weighted_centroid(
static float mesh_calc_poly_volume_centroid(
const MPoly *mpoly, const MLoop *loopstart, const MVert *mvarray,
float r_cent[3])
{
@ -1897,6 +1900,43 @@ static float mesh_calc_poly_volume_and_weighted_centroid(
return total_volume;
}
/**
* \note
* - Results won't be correct if polygon is non-planar.
* - This has the advantage over #mesh_calc_poly_volume_centroid
* that it doesn't depend on solid geometry, instead it weights the surface by volume.
*/
static float mesh_calc_poly_area_centroid(
const MPoly *mpoly, const MLoop *loopstart, const MVert *mvarray,
float r_cent[3])
{
int i;
float tri_area;
float total_area = 0.0f;
float v1[3], v2[3], v3[3], normal[3], tri_cent[3];
BKE_mesh_calc_poly_normal(mpoly, loopstart, mvarray, normal);
copy_v3_v3(v1, mvarray[loopstart[0].v].co);
copy_v3_v3(v2, mvarray[loopstart[1].v].co);
zero_v3(r_cent);
for (i = 2; i < mpoly->totloop; i++) {
copy_v3_v3(v3, mvarray[loopstart[i].v].co);
tri_area = area_tri_signed_v3(v1, v2, v3, normal);
total_area += tri_area;
mid_v3_v3v3v3(tri_cent, v1, v2, v3);
madd_v3_v3fl(r_cent, tri_cent, tri_area);
copy_v3_v3(v2, v3);
}
mul_v3_fl(r_cent, 1.0f / total_area);
return total_area;
}
#if 0 /* slow version of the function below */
void BKE_mesh_calc_poly_angles(MPoly *mpoly, MLoop *loopstart,
MVert *mvarray, float angles[])
@ -2011,7 +2051,40 @@ bool BKE_mesh_center_bounds(const Mesh *me, float r_cent[3])
return false;
}
bool BKE_mesh_center_centroid(const Mesh *me, float r_cent[3])
bool BKE_mesh_center_of_surface(const Mesh *me, float r_cent[3])
{
int i = me->totpoly;
MPoly *mpoly;
float poly_area;
float total_area = 0.0f;
float poly_cent[3];
zero_v3(r_cent);
/* calculate a weighted average of polygon centroids */
for (mpoly = me->mpoly; i--; mpoly++) {
poly_area = mesh_calc_poly_area_centroid(mpoly, me->mloop + mpoly->loopstart, me->mvert, poly_cent);
madd_v3_v3fl(r_cent, poly_cent, poly_area);
total_area += poly_area;
}
/* otherwise we get NAN for 0 polys */
if (me->totpoly) {
mul_v3_fl(r_cent, 1.0f / total_area);
}
/* zero area faces cause this, fallback to median */
if (UNLIKELY(!is_finite_v3(r_cent))) {
return BKE_mesh_center_median(me, r_cent);
}
return (me->totpoly != 0);
}
/**
* \note Mesh must be manifold with consistent face-winding, see #mesh_calc_poly_volume_centroid for details.
*/
bool BKE_mesh_center_of_volume(const Mesh *me, float r_cent[3])
{
int i = me->totpoly;
MPoly *mpoly;
@ -2023,7 +2096,7 @@ bool BKE_mesh_center_centroid(const Mesh *me, float r_cent[3])
/* calculate a weighted average of polyhedron centroids */
for (mpoly = me->mpoly; i--; mpoly++) {
poly_volume = mesh_calc_poly_volume_and_weighted_centroid(mpoly, me->mloop + mpoly->loopstart, me->mvert, poly_cent);
poly_volume = mesh_calc_poly_volume_centroid(mpoly, me->mloop + mpoly->loopstart, me->mvert, poly_cent);
/* poly_cent is already volume-weighted, so no need to multiply by the volume */
add_v3_v3(r_cent, poly_cent);
@ -2043,6 +2116,7 @@ bool BKE_mesh_center_centroid(const Mesh *me, float r_cent[3])
return (me->totpoly != 0);
}
/** \} */

View File

@ -429,7 +429,6 @@ static void distribute_from_verts_exec(ParticleTask *thread, ParticleData *pa, i
ParticleThreadContext *ctx= thread->ctx;
MFace *mface;
DM_ensure_tessface(ctx->dm);
mface = ctx->dm->getTessFaceDataArray(ctx->dm, CD_MFACE);
int rng_skip_tot = PSYS_RND_DIST_SKIP; /* count how many rng_* calls wont need skipping */
@ -899,10 +898,7 @@ static int psys_thread_context_init_distribute(ParticleThreadContext *ctx, Parti
else
dm= CDDM_from_mesh((Mesh*)ob->data);
/* BMESH ONLY, for verts we don't care about tessfaces */
if (from != PART_FROM_VERT) {
DM_ensure_tessface(dm);
}
DM_ensure_tessface(dm);
/* we need orco for consistent distributions */
if (!CustomData_has_layer(&dm->vertData, CD_ORCO))

View File

@ -734,7 +734,8 @@ enum {
GEOMETRY_TO_ORIGIN = 0,
ORIGIN_TO_GEOMETRY,
ORIGIN_TO_CURSOR,
ORIGIN_TO_CENTER_OF_MASS
ORIGIN_TO_CENTER_OF_MASS_SURFACE,
ORIGIN_TO_CENTER_OF_MASS_VOLUME,
};
static int object_origin_set_exec(bContext *C, wmOperator *op)
@ -891,10 +892,21 @@ static int object_origin_set_exec(bContext *C, wmOperator *op)
if (obedit == NULL && ob->type == OB_MESH) {
Mesh *me = ob->data;
if (centermode == ORIGIN_TO_CURSOR) { /* done */ }
else if (centermode == ORIGIN_TO_CENTER_OF_MASS) { BKE_mesh_center_centroid(me, cent); }
else if (around == V3D_AROUND_CENTER_MEAN) { BKE_mesh_center_median(me, cent); }
else { BKE_mesh_center_bounds(me, cent); }
if (centermode == ORIGIN_TO_CURSOR) {
/* done */
}
else if (centermode == ORIGIN_TO_CENTER_OF_MASS_SURFACE) {
BKE_mesh_center_of_surface(me, cent);
}
else if (centermode == ORIGIN_TO_CENTER_OF_MASS_VOLUME) {
BKE_mesh_center_of_volume(me, cent);
}
else if (around == V3D_AROUND_CENTER_MEAN) {
BKE_mesh_center_median(me, cent);
}
else {
BKE_mesh_center_bounds(me, cent);
}
negate_v3_v3(cent_neg, cent);
BKE_mesh_translate(me, cent_neg, 1);
@ -1105,11 +1117,14 @@ void OBJECT_OT_origin_set(wmOperatorType *ot)
static EnumPropertyItem prop_set_center_types[] = {
{GEOMETRY_TO_ORIGIN, "GEOMETRY_ORIGIN", 0, "Geometry to Origin", "Move object geometry to object origin"},
{ORIGIN_TO_GEOMETRY, "ORIGIN_GEOMETRY", 0, "Origin to Geometry",
"Move object origin to center of object geometry"},
"Calculate the center of geometry based on the current pivot point (median, otherwise bounding-box)"},
{ORIGIN_TO_CURSOR, "ORIGIN_CURSOR", 0, "Origin to 3D Cursor",
"Move object origin to position of the 3D cursor"},
{ORIGIN_TO_CENTER_OF_MASS, "ORIGIN_CENTER_OF_MASS", 0, "Origin to Center of Mass",
"Move object origin to the object center of mass (assuming uniform density)"},
"Move object origin to position of the 3D cursor"},
/* Intentional naming mismatch since some scripts refer to this. */
{ORIGIN_TO_CENTER_OF_MASS_SURFACE, "ORIGIN_CENTER_OF_MASS", 0, "Origin to Center of Mass (Surface)",
"Calculate the center of mass from the surface area"},
{ORIGIN_TO_CENTER_OF_MASS_VOLUME, "ORIGIN_CENTER_OF_VOLUME", 0, "Origin to Center of Mass (Volume)",
"Calculate the center of mass from the volume (must be manifold geometry with consistent normals)"},
{0, NULL, 0, NULL, NULL}
};

View File

@ -51,14 +51,23 @@ static int node_shader_gpu_fresnel(GPUMaterial *mat, bNode *node, bNodeExecData
return GPU_stack_link(mat, node, "node_fresnel", in, out, GPU_builtin(GPU_VIEW_POSITION));
}
static void node_shader_exec_fresnel(void *data, int UNUSED(thread), bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), bNodeStack **in, bNodeStack **out)
static void node_shader_exec_fresnel(void *data, int UNUSED(thread), bNode *node, bNodeExecData *UNUSED(execdata), bNodeStack **in, bNodeStack **out)
{
ShadeInput *shi = ((ShaderCallData *)data)->shi;
float eta = max_ff(in[0]->vec[0], 0.00001);
/* Compute IOR. */
float eta;
nodestack_get_vec(&eta, SOCK_FLOAT, in[0]);
eta = max_ff(eta, 0.00001);
eta = shi->flippednor ? 1 / eta : eta;
/* Get normal from socket, but only if linked. */
bNodeSocket *sock_normal = node->inputs.first;
sock_normal = sock_normal->next;
float n[3];
if (in[1]->hasinput) {
copy_v3_v3(n, in[1]->vec);
if (sock_normal->link) {
nodestack_get_vec(n, SOCK_VECTOR, in[1]);
}
else {
copy_v3_v3(n, shi->vn);
@ -68,7 +77,7 @@ static void node_shader_exec_fresnel(void *data, int UNUSED(thread), bNode *UNUS
mul_mat3_m4_v3((float (*)[4])RE_render_current_get_matrix(RE_VIEW_MATRIX), n);
}
out[0]->vec[0] = RE_fresnel_dielectric(shi->view, n, shi->flippednor ? 1 / eta : eta);
out[0]->vec[0] = RE_fresnel_dielectric(shi->view, n, eta);
}
/* node type definition */

View File

@ -52,24 +52,33 @@ static int node_shader_gpu_layer_weight(GPUMaterial *mat, bNode *node, bNodeExec
return GPU_stack_link(mat, node, "node_layer_weight", in, out, GPU_builtin(GPU_VIEW_POSITION));
}
static void node_shader_exec_layer_weight(void *data, int UNUSED(thread), bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), bNodeStack **in, bNodeStack **out)
static void node_shader_exec_layer_weight(void *data, int UNUSED(thread), bNode *node, bNodeExecData *UNUSED(execdata), bNodeStack **in, bNodeStack **out)
{
ShadeInput *shi = ((ShaderCallData *)data)->shi;
float blend = in[0]->vec[0];
/* Compute IOR. */
float blend;
nodestack_get_vec(&blend, SOCK_FLOAT, in[0]);
float eta = max_ff(1 - blend, 0.00001);
eta = shi->flippednor ? eta : 1 / eta;
/* Get normal from socket, but only if linked. */
bNodeSocket *sock_normal = node->inputs.first;
sock_normal = sock_normal->next;
float n[3];
if (in[1]->hasinput) {
copy_v3_v3(n, in[1]->vec);
if (sock_normal->link) {
nodestack_get_vec(n, SOCK_VECTOR, in[1]);
}
else {
copy_v3_v3(n, shi->vn);
}
if (shi->use_world_space_shading)
mul_mat3_m4_v3((float (*)[4])RE_render_current_get_matrix(RE_VIEW_MATRIX), n);
out[0]->vec[0] = RE_fresnel_dielectric(shi->view, n, shi->flippednor ? eta : 1 / eta);
out[0]->vec[0] = RE_fresnel_dielectric(shi->view, n, eta);
float facing = fabs(dot_v3v3(shi->view, n));
if (blend != 0.5) {

View File

@ -44,7 +44,8 @@
#include "STR_String.h"
#include "MT_Vector3.h"
#include "SG_QList.h"
#include <stddef.h>
#include <cstddef>
#include <cstdint>
#ifdef WITH_PYTHON
#ifdef USE_MATHUTILS