Merge branch 'master' into blender2.8
This commit is contained in:
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
|
@ -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",
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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()
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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";
|
||||
}
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
106
make.bat
|
@ -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
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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}
|
||||
};
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue