diff options
Diffstat (limited to 'intern/cycles')
51 files changed, 548 insertions, 319 deletions
diff --git a/intern/cycles/app/cycles_test.cpp b/intern/cycles/app/cycles_test.cpp index c16f6f4e99a..27e53ded6db 100644 --- a/intern/cycles/app/cycles_test.cpp +++ b/intern/cycles/app/cycles_test.cpp @@ -66,26 +66,26 @@ static void session_print(const string& str) static void session_print_status() { - int pass; - double total_time, pass_time; + int sample; + double total_time, sample_time; string status, substatus; /* get status */ - options.session->progress.get_pass(pass, total_time, pass_time); + options.session->progress.get_sample(sample, total_time, sample_time); options.session->progress.get_status(status, substatus); if(substatus != "") status += ": " + substatus; /* print status */ - status = string_printf("Pass %d %s", pass, status.c_str()); + status = string_printf("Sample %d %s", sample, status.c_str()); session_print(status); } static void session_init() { options.session = new Session(options.session_params); - options.session->reset(options.width, options.height, options.session_params.passes); + options.session->reset(options.width, options.height, options.session_params.samples); options.session->scene = options.scene; if(options.session_params.background && !options.quiet) @@ -133,18 +133,18 @@ static void display_info(Progress& progress) latency = (elapsed - last); last = elapsed; - int pass; - double total_time, pass_time; + int sample; + double total_time, sample_time; string status, substatus; - progress.get_pass(pass, total_time, pass_time); + progress.get_sample(sample, total_time, sample_time); progress.get_status(status, substatus); if(substatus != "") status += ": " + substatus; - str = string_printf("latency: %.4f pass: %d total: %.4f average: %.4f %s", - latency, pass, total_time, pass_time, status.c_str()); + str = string_printf("latency: %.4f sample: %d total: %.4f average: %.4f %s", + latency, sample, total_time, sample_time, status.c_str()); view_display_info(str.c_str()); } @@ -162,13 +162,13 @@ static void resize(int width, int height) options.height= height; if(options.session) - options.session->reset(options.width, options.height, options.session_params.passes); + options.session->reset(options.width, options.height, options.session_params.samples); } void keyboard(unsigned char key) { if(key == 'r') - options.session->reset(options.width, options.height, options.session_params.passes); + options.session->reset(options.width, options.height, options.session_params.samples); else if(key == 27) // escape options.session->progress.set_cancel("Cancelled"); } @@ -220,7 +220,7 @@ static void options_parse(int argc, const char **argv) "--shadingsys %s", &ssname, "Shading system to use: svm, osl", "--background", &options.session_params.background, "Render in background, without user interface", "--quiet", &options.quiet, "In background mode, don't print progress messages", - "--passes %d", &options.session_params.passes, "Number of passes to render", + "--samples %d", &options.session_params.samples, "Number of samples to render", "--output %s", &options.session_params.output_path, "File path to write output image", "--threads %d", &options.session_params.threads, "CPU Rendering Threads", "--help", &help, "Print help message", @@ -266,8 +266,8 @@ static void options_parse(int argc, const char **argv) fprintf(stderr, "OSL shading system only works with CPU device\n"); exit(EXIT_FAILURE); } - else if(options.session_params.passes < 0) { - fprintf(stderr, "Invalid number of passes: %d\n", options.session_params.passes); + else if(options.session_params.samples < 0) { + fprintf(stderr, "Invalid number of samples: %d\n", options.session_params.samples); exit(EXIT_FAILURE); } else if(options.filepath == "") { diff --git a/intern/cycles/app/cycles_xml.cpp b/intern/cycles/app/cycles_xml.cpp index 7c3fb0b3625..c7580642c43 100644 --- a/intern/cycles/app/cycles_xml.cpp +++ b/intern/cycles/app/cycles_xml.cpp @@ -272,7 +272,7 @@ static void xml_read_camera(const XMLReadState& state, pugi::xml_node node) xml_read_float(&cam->nearclip, node, "nearclip"); xml_read_float(&cam->farclip, node, "farclip"); - xml_read_float(&cam->lensradius, node, "lensradius"); // 0.5*focallength/fstop + xml_read_float(&cam->aperturesize, node, "aperturesize"); // 0.5*focallength/fstop xml_read_float(&cam->focaldistance, node, "focaldistance"); xml_read_float(&cam->shutteropen, node, "shutteropen"); xml_read_float(&cam->shutterclose, node, "shutterclose"); diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py index 5d90223032f..89c2829175c 100644 --- a/intern/cycles/blender/addon/properties.py +++ b/intern/cycles/blender/addon/properties.py @@ -19,6 +19,8 @@ import bpy from bpy.props import * +import math + from cycles import enums class CyclesRenderSettings(bpy.types.PropertyGroup): @@ -35,9 +37,9 @@ class CyclesRenderSettings(bpy.types.PropertyGroup): cls.shading_system = EnumProperty(name="Shading System", description="Shading system to use for rendering", items=enums.shading_systems, default="GPU_COMPATIBLE") - cls.passes = IntProperty(name="Passes", description="Number of passes to render", + cls.samples = IntProperty(name="Samples", description="Number of samples to render for each pixel", default=10, min=1, max=2147483647) - cls.preview_passes = IntProperty(name="Preview Passes", description="Number of passes to render in the viewport, unlimited if 0", + cls.preview_samples = IntProperty(name="Preview Samples", description="Number of samples to render in the viewport, unlimited if 0", default=0, min=0, max=2147483647) cls.preview_pause = BoolProperty(name="Pause Preview", description="Pause all viewport preview renders", default=False) @@ -99,8 +101,12 @@ class CyclesCameraSettings(bpy.types.PropertyGroup): def register(cls): bpy.types.Camera.cycles = PointerProperty(type=cls, name="Cycles Camera Settings", description="Cycles camera settings") - cls.lens_radius = FloatProperty(name="Lens radius", description="Lens radius for depth of field", + cls.aperture_size = FloatProperty(name="Aperture Size", description="Radius of the aperture for depth of field", default=0.0, min=0.0, max=10.0) + cls.aperture_blades = IntProperty(name="Aperture Blades", description="Number of blades in aperture for polygonal bokeh (need 3 or more)", + default=0, min=0, max=100) + cls.aperture_rotation = FloatProperty(name="Aperture Rotation", description="Rotation of blades in aperture", + default=0, soft_min=-math.pi, soft_max=math.pi, subtype='ANGLE') @classmethod def unregister(cls): diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index 992a698bbdd..86d1f19d096 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -59,9 +59,9 @@ class CyclesRender_PT_integrator(CyclesButtonsPanel, Panel): col = split.column() sub = col.column(align=True) - sub.label(text="Passes:") - sub.prop(cscene, "passes", text="Render") - sub.prop(cscene, "preview_passes", text="Preview") + sub.label(text="Samples:") + sub.prop(cscene, "samples", text="Render") + sub.prop(cscene, "preview_samples", text="Preview") sub = col.column(align=True) sub.label("Tranparency:") @@ -194,21 +194,38 @@ class Cycles_PT_post_processing(CyclesButtonsPanel, Panel): col = split.column() col.prop(rd, "dither_intensity", text="Dither", slider=True) -class Cycles_PT_camera(CyclesButtonsPanel, Panel): - bl_label = "Cycles" +class CyclesCamera_PT_dof(CyclesButtonsPanel, Panel): + bl_label = "Depth of Field" bl_context = "data" @classmethod def poll(cls, context): - return context.camera + return context.camera and CyclesButtonsPanel.poll(context) def draw(self, context): layout = self.layout - camera = context.camera - ccamera = camera.cycles + cam = context.camera + ccam = cam.cycles - layout.prop(ccamera, "lens_radius") + split = layout.split() + + col = split.column() + col.label("Focus:") + col.prop(cam, "dof_object", text="") + + sub = col.row() + sub.active = cam.dof_object is None + sub.prop(cam, "dof_distance", text="Distance") + + col = split.column() + + col.label("Aperture:") + col.prop(ccam, "aperture_size", text="Size") + + sub = col.column(align=True) + sub.prop(ccam, "aperture_blades", text="Blades") + sub.prop(ccam, "aperture_rotation", text="Rotation") class Cycles_PT_context_material(CyclesButtonsPanel, Panel): bl_label = "Surface" @@ -550,7 +567,7 @@ class CyclesTexture_PT_color(CyclesButtonsPanel, Panel): layout = self.layout layout.label("Color modification options go here."); layout.label("Ramp, brightness, contrast, saturation.") - + def draw_device(self, context): scene = context.scene layout = self.layout diff --git a/intern/cycles/blender/blender_camera.cpp b/intern/cycles/blender/blender_camera.cpp index 530193247ae..e3b0fbd0a25 100644 --- a/intern/cycles/blender/blender_camera.cpp +++ b/intern/cycles/blender/blender_camera.cpp @@ -35,7 +35,10 @@ struct BlenderCamera { float ortho_scale; float lens; - float lensradius; + + float aperturesize; + uint apertureblades; + float aperturerotation; float focaldistance; float2 shift; @@ -90,7 +93,9 @@ static void blender_camera_from_object(BlenderCamera *bcam, BL::Object b_ob) bcam->ortho_scale = b_camera.ortho_scale(); bcam->lens = b_camera.lens(); - bcam->lensradius = RNA_float_get(&ccamera, "lens_radius"); + bcam->aperturesize = RNA_float_get(&ccamera, "aperture_size"); + bcam->apertureblades = RNA_int_get(&ccamera, "aperture_blades"); + bcam->aperturerotation = RNA_float_get(&ccamera, "aperture_rotation"); bcam->focaldistance = blender_camera_focal_distance(b_ob, b_camera); bcam->shift.x = b_camera.shift_x(); @@ -162,7 +167,9 @@ static void blender_camera_sync(Camera *cam, BlenderCamera *bcam, int width, int /* perspective */ cam->fov = 2.0f*atan(16.0f/bcam->lens/aspectratio); cam->focaldistance = bcam->focaldistance; - cam->lensradius = bcam->lensradius; + cam->aperturesize = bcam->aperturesize; + cam->blades = bcam->apertureblades; + cam->bladesrotation = bcam->aperturerotation; /* transform, note the blender camera points along the negative z-axis */ cam->matrix = bcam->matrix * transform_scale(1.0f, 1.0f, -1.0f); diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp index 62721b7cf10..c6f016b7971 100644 --- a/intern/cycles/blender/blender_session.cpp +++ b/intern/cycles/blender/blender_session.cpp @@ -96,7 +96,7 @@ void BlenderSession::create_session() session->set_pause(BlenderSync::get_session_pause(b_scene, background)); /* start rendering */ - session->reset(width, height, session_params.passes); + session->reset(width, height, session_params.samples); session->start(); } @@ -122,11 +122,11 @@ void BlenderSession::write_render_result() /* get result */ RenderBuffers *buffers = session->buffers; float exposure = scene->film->exposure; - double total_time, pass_time; - int pass; - session->progress.get_pass(pass, total_time, pass_time); + double total_time, sample_time; + int sample; + session->progress.get_sample(sample, total_time, sample_time); - float4 *pixels = buffers->copy_from_device(exposure, pass); + float4 *pixels = buffers->copy_from_device(exposure, sample); if(!pixels) return; @@ -158,8 +158,8 @@ void BlenderSession::synchronize() return; } - /* increase passes, but never decrease */ - session->set_passes(session_params.passes); + /* increase samples, but never decrease */ + session->set_samples(session_params.samples); session->set_pause(BlenderSync::get_session_pause(b_scene, background)); /* copy recalc flags, outside of mutex so we can decide to do the real @@ -185,7 +185,7 @@ void BlenderSession::synchronize() /* reset if needed */ if(scene->need_reset()) - session->reset(width, height, session_params.passes); + session->reset(width, height, session_params.samples); } bool BlenderSession::draw(int w, int h) @@ -221,7 +221,7 @@ bool BlenderSession::draw(int w, int h) /* reset if requested */ if(reset) { SessionParams session_params = BlenderSync::get_session_params(b_scene, background); - session->reset(width, height, session_params.passes); + session->reset(width, height, session_params.samples); } } @@ -239,11 +239,11 @@ void BlenderSession::get_status(string& status, string& substatus) void BlenderSession::get_progress(float& progress, double& total_time) { - double pass_time; - int pass; + double sample_time; + int sample; - session->progress.get_pass(pass, total_time, pass_time); - progress = ((float)pass/(float)session->params.passes); + session->progress.get_sample(sample, total_time, sample_time); + progress = ((float)sample/(float)session->params.samples); } void BlenderSession::update_status_progress() diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp index 362c765b399..cba093edbad 100644 --- a/intern/cycles/blender/blender_shader.cpp +++ b/intern/cycles/blender/blender_shader.cpp @@ -190,11 +190,15 @@ static ShaderNode *add_node(BL::BlendData b_data, ShaderGraph *graph, BL::Node * node = new FresnelNode(); break; } - case BL::ShaderNode::type_ADD_CLOSURE: { + case BL::ShaderNode::type_BLEND_WEIGHT: { + node = new BlendWeightNode(); + break; + } + case BL::ShaderNode::type_ADD_SHADER: { node = new AddClosureNode(); break; } - case BL::ShaderNode::type_MIX_CLOSURE: { + case BL::ShaderNode::type_MIX_SHADER: { node = new MixClosureNode(); break; } @@ -402,6 +406,20 @@ static ShaderNode *add_node(BL::BlendData b_data, ShaderGraph *graph, BL::Node * return node; } +static const char *node_socket_map_name(const char *name) +{ + if(strstr(name, "Shader")) { + if(strcmp(name, "Shader") == 0) + return "Closure"; + if(strcmp(name, "Shader1") == 0) + return "Closure1"; + if(strcmp(name, "Shader2") == 0) + return "Closure2"; + } + + return name; +} + static void add_nodes(BL::BlendData b_data, ShaderGraph *graph, BL::ShaderNodeTree b_ntree, BL::Node *b_group_node, PtrSockMap& sockets_map) { /* add nodes */ @@ -427,7 +445,7 @@ static void add_nodes(BL::BlendData b_data, ShaderGraph *graph, BL::ShaderNodeTr node_map[b_node->ptr.data] = node; for(b_node->inputs.begin(b_input); b_input != b_node->inputs.end(); ++b_input) { - ShaderInput *input = node->input(b_input->name().c_str()); + ShaderInput *input = node->input(node_socket_map_name(b_input->name().c_str())); BL::NodeSocket sock(get_node_input(b_group_node, *b_node, b_input->name())); assert(input); @@ -522,7 +540,7 @@ static void add_nodes(BL::BlendData b_data, ShaderGraph *graph, BL::ShaderNodeTr /* in case of groups there may not actually be a node inside the group that the group socket connects to, so from_node or to_node may be NULL */ if(from_node && to_node) - graph->connect(from_node->output(from_name.c_str()), to_node->input(to_name.c_str())); + graph->connect(from_node->output(node_socket_map_name(from_name.c_str())), to_node->input(node_socket_map_name(to_name.c_str()))); } } diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp index b9d35a02a78..9bb7cb45e35 100644 --- a/intern/cycles/blender/blender_sync.cpp +++ b/intern/cycles/blender/blender_sync.cpp @@ -185,13 +185,17 @@ void BlenderSync::sync_render_layer(BL::SpaceView3D b_v3d) else { BL::RenderSettings r = b_scene.render(); BL::RenderSettings::layers_iterator b_rlay; + bool first = true; for(r.layers.begin(b_rlay); b_rlay != r.layers.end(); ++b_rlay) { - render_layer.scene_layer = get_layer(b_scene.layers()); - render_layer.layer = get_layer(b_rlay->layers()); - render_layer.material_override = b_rlay->material_override(); + /* single layer for now */ + if(first) { + render_layer.scene_layer = get_layer(b_scene.layers()); + render_layer.layer = get_layer(b_rlay->layers()); + render_layer.material_override = b_rlay->material_override(); - break; /* single layer for now */ + first = false; + } } } } @@ -255,14 +259,14 @@ SessionParams BlenderSync::get_session_params(BL::Scene b_scene, bool background /* Background */ params.background = background; - /* passes */ + /* samples */ if(background) { - params.passes = get_int(cscene, "passes"); + params.samples = get_int(cscene, "samples"); } else { - params.passes = get_int(cscene, "preview_passes"); - if(params.passes == 0) - params.passes = INT_MAX; + params.samples = get_int(cscene, "preview_samples"); + if(params.samples == 0) + params.samples = INT_MAX; } /* other parameters */ diff --git a/intern/cycles/device/device.cpp b/intern/cycles/device/device.cpp index 6ba50154dac..f43ccffe461 100644 --- a/intern/cycles/device/device.cpp +++ b/intern/cycles/device/device.cpp @@ -36,7 +36,7 @@ CCL_NAMESPACE_BEGIN DeviceTask::DeviceTask(Type type_) : type(type_), x(0), y(0), w(0), h(0), rng_state(0), rgba(0), buffer(0), - pass(0), resolution(0), + sample(0), resolution(0), displace_input(0), displace_offset(0), displace_x(0), displace_w(0) { } diff --git a/intern/cycles/device/device.h b/intern/cycles/device/device.h index aa9cb9eb8f4..0b3c66dbb2c 100644 --- a/intern/cycles/device/device.h +++ b/intern/cycles/device/device.h @@ -58,7 +58,7 @@ public: device_ptr rng_state; device_ptr rgba; device_ptr buffer; - int pass; + int sample; int resolution; device_ptr displace_input; diff --git a/intern/cycles/device/device_cpu.cpp b/intern/cycles/device/device_cpu.cpp index 3a3ae685395..2409cc65998 100644 --- a/intern/cycles/device/device_cpu.cpp +++ b/intern/cycles/device/device_cpu.cpp @@ -152,7 +152,7 @@ public: for(int y = task.y; y < task.y + task.h; y++) { for(int x = task.x; x < task.x + task.w; x++) - kernel_cpu_path_trace(kg, (float4*)task.buffer, (unsigned int*)task.rng_state, task.pass, x, y); + kernel_cpu_path_trace(kg, (float4*)task.buffer, (unsigned int*)task.rng_state, task.sample, x, y); if(tasks.worker_cancel()) break; @@ -168,7 +168,7 @@ public: { for(int y = task.y; y < task.y + task.h; y++) { for(int x = task.x; x < task.x + task.w; x++) - kernel_cpu_tonemap(kg, (uchar4*)task.rgba, (float4*)task.buffer, task.pass, task.resolution, x, y); + kernel_cpu_tonemap(kg, (uchar4*)task.rgba, (float4*)task.buffer, task.sample, task.resolution, x, y); } } diff --git a/intern/cycles/device/device_cuda.cpp b/intern/cycles/device/device_cuda.cpp index 7fc0afce1ac..3773dda7631 100644 --- a/intern/cycles/device/device_cuda.cpp +++ b/intern/cycles/device/device_cuda.cpp @@ -455,11 +455,11 @@ public: cuda_assert(cuParamSetv(cuPathTrace, offset, &d_rng_state, sizeof(d_rng_state))) offset += sizeof(d_rng_state); - int pass = task.pass; - offset = cuda_align_up(offset, __alignof(pass)); + int sample = task.sample; + offset = cuda_align_up(offset, __alignof(sample)); - cuda_assert(cuParamSeti(cuPathTrace, offset, task.pass)) - offset += sizeof(task.pass); + cuda_assert(cuParamSeti(cuPathTrace, offset, task.sample)) + offset += sizeof(task.sample); cuda_assert(cuParamSeti(cuPathTrace, offset, task.x)) offset += sizeof(task.x); @@ -513,11 +513,11 @@ public: cuda_assert(cuParamSetv(cuFilmConvert, offset, &d_buffer, sizeof(d_buffer))) offset += sizeof(d_buffer); - int pass = task.pass; - offset = cuda_align_up(offset, __alignof(pass)); + int sample = task.sample; + offset = cuda_align_up(offset, __alignof(sample)); - cuda_assert(cuParamSeti(cuFilmConvert, offset, task.pass)) - offset += sizeof(task.pass); + cuda_assert(cuParamSeti(cuFilmConvert, offset, task.sample)) + offset += sizeof(task.sample); cuda_assert(cuParamSeti(cuFilmConvert, offset, task.resolution)) offset += sizeof(task.resolution); diff --git a/intern/cycles/device/device_network.cpp b/intern/cycles/device/device_network.cpp index 0feba34f713..af7d90478cf 100644 --- a/intern/cycles/device/device_network.cpp +++ b/intern/cycles/device/device_network.cpp @@ -178,22 +178,22 @@ public: #endif } - void path_trace(int x, int y, int w, int h, device_ptr buffer, device_ptr rng_state, int pass) + void path_trace(int x, int y, int w, int h, device_ptr buffer, device_ptr rng_state, int sample) { #if 0 RPCSend snd(socket, "path_trace"); - snd.archive & x & y & w & h & buffer & rng_state & pass; + snd.archive & x & y & w & h & buffer & rng_state & sample; snd.write(); #endif } - void tonemap(int x, int y, int w, int h, device_ptr rgba, device_ptr buffer, int pass, int resolution) + void tonemap(int x, int y, int w, int h, device_ptr rgba, device_ptr buffer, int sample, int resolution) { #if 0 RPCSend snd(socket, "tonemap"); - snd.archive & x & y & w & h & rgba & buffer & pass & resolution; + snd.archive & x & y & w & h & rgba & buffer & sample & resolution; snd.write(); #endif } @@ -201,9 +201,9 @@ public: void task_add(DeviceTask& task) { if(task.type == DeviceTask::TONEMAP) - tonemap(task.x, task.y, task.w, task.h, task.rgba, task.buffer, task.pass, task.resolution); + tonemap(task.x, task.y, task.w, task.h, task.rgba, task.buffer, task.sample, task.resolution); else if(task.type == DeviceTask::PATH_TRACE) - path_trace(task.x, task.y, task.w, task.h, task.buffer, task.rng_state, task.pass); + path_trace(task.x, task.y, task.w, task.h, task.buffer, task.rng_state, task.sample); } void task_wait() @@ -355,20 +355,20 @@ void Device::server_run() #if 0 device_ptr buffer, rng_state; int x, y, w, h; - int pass; + int sample; - *rcv.archive & x & y & w & h & buffer & rng_state & pass; - path_trace(x, y, w, h, buffer, rng_state, pass); + *rcv.archive & x & y & w & h & buffer & rng_state & sample; + path_trace(x, y, w, h, buffer, rng_state, sample); #endif } else if(rcv.name == "tonemap") { #if 0 device_ptr rgba, buffer; int x, y, w, h; - int pass, resolution; + int sample, resolution; - *rcv.archive & x & y & w & h & rgba & buffer & pass & resolution; - tonemap(x, y, w, h, rgba, buffer, pass, resolution); + *rcv.archive & x & y & w & h & rgba & buffer & sample & resolution; + tonemap(x, y, w, h, rgba, buffer, sample, resolution); #endif } } diff --git a/intern/cycles/device/device_opencl.cpp b/intern/cycles/device/device_opencl.cpp index a41238ffe09..a87b12786b1 100644 --- a/intern/cycles/device/device_opencl.cpp +++ b/intern/cycles/device/device_opencl.cpp @@ -502,9 +502,9 @@ public: cl_int d_y = task.y; cl_int d_w = task.w; cl_int d_h = task.h; - cl_int d_pass = task.pass; + cl_int d_sample = task.sample; - /* pass arguments */ + /* sample arguments */ int narg = 0; ciErr = 0; @@ -516,7 +516,7 @@ public: ciErr |= set_kernel_arg_mem(ckPathTraceKernel, &narg, #name); #include "kernel_textures.h" - ciErr |= clSetKernelArg(ckPathTraceKernel, narg++, sizeof(d_pass), (void*)&d_pass); + ciErr |= clSetKernelArg(ckPathTraceKernel, narg++, sizeof(d_sample), (void*)&d_sample); ciErr |= clSetKernelArg(ckPathTraceKernel, narg++, sizeof(d_x), (void*)&d_x); ciErr |= clSetKernelArg(ckPathTraceKernel, narg++, sizeof(d_y), (void*)&d_y); ciErr |= clSetKernelArg(ckPathTraceKernel, narg++, sizeof(d_w), (void*)&d_w); @@ -575,10 +575,10 @@ public: cl_int d_y = task.y; cl_int d_w = task.w; cl_int d_h = task.h; - cl_int d_pass = task.pass; + cl_int d_sample = task.sample; cl_int d_resolution = task.resolution; - /* pass arguments */ + /* sample arguments */ int narg = 0; ciErr = 0; @@ -590,7 +590,7 @@ public: ciErr |= set_kernel_arg_mem(ckFilmConvertKernel, &narg, #name); #include "kernel_textures.h" - ciErr |= clSetKernelArg(ckFilmConvertKernel, narg++, sizeof(d_pass), (void*)&d_pass); + ciErr |= clSetKernelArg(ckFilmConvertKernel, narg++, sizeof(d_sample), (void*)&d_sample); ciErr |= clSetKernelArg(ckFilmConvertKernel, narg++, sizeof(d_resolution), (void*)&d_resolution); ciErr |= clSetKernelArg(ckFilmConvertKernel, narg++, sizeof(d_x), (void*)&d_x); ciErr |= clSetKernelArg(ckFilmConvertKernel, narg++, sizeof(d_y), (void*)&d_y); diff --git a/intern/cycles/kernel/kernel.cl b/intern/cycles/kernel/kernel.cl index 007a5f6de6a..48bee8eef97 100644 --- a/intern/cycles/kernel/kernel.cl +++ b/intern/cycles/kernel/kernel.cl @@ -37,7 +37,7 @@ __kernel void kernel_ocl_path_trace( int name##_width, #include "kernel_textures.h" - int pass, + int sample, int sx, int sy, int sw, int sh) { KernelGlobals kglobals, *kg = &kglobals; @@ -53,7 +53,7 @@ __kernel void kernel_ocl_path_trace( int y = sy + get_global_id(1); if(x < sx + sw && y < sy + sh) - kernel_path_trace(kg, buffer, rng_state, pass, x, y); + kernel_path_trace(kg, buffer, rng_state, sample, x, y); } __kernel void kernel_ocl_tonemap( @@ -66,7 +66,7 @@ __kernel void kernel_ocl_tonemap( int name##_width, #include "kernel_textures.h" - int pass, int resolution, + int sample, int resolution, int sx, int sy, int sw, int sh) { KernelGlobals kglobals, *kg = &kglobals; @@ -82,7 +82,7 @@ __kernel void kernel_ocl_tonemap( int y = sy + get_global_id(1); if(x < sx + sw && y < sy + sh) - kernel_film_tonemap(kg, rgba, buffer, pass, resolution, x, y); + kernel_film_tonemap(kg, rgba, buffer, sample, resolution, x, y); } /*__kernel void kernel_ocl_displace(__global uint4 *input, __global float3 *offset, int sx) diff --git a/intern/cycles/kernel/kernel.cpp b/intern/cycles/kernel/kernel.cpp index 01682d11f33..7e5fa25c662 100644 --- a/intern/cycles/kernel/kernel.cpp +++ b/intern/cycles/kernel/kernel.cpp @@ -269,16 +269,16 @@ void kernel_tex_copy(KernelGlobals *kg, const char *name, device_ptr mem, size_t /* Path Tracing */ -void kernel_cpu_path_trace(KernelGlobals *kg, float4 *buffer, unsigned int *rng_state, int pass, int x, int y) +void kernel_cpu_path_trace(KernelGlobals *kg, float4 *buffer, unsigned int *rng_state, int sample, int x, int y) { - kernel_path_trace(kg, buffer, rng_state, pass, x, y); + kernel_path_trace(kg, buffer, rng_state, sample, x, y); } /* Tonemapping */ -void kernel_cpu_tonemap(KernelGlobals *kg, uchar4 *rgba, float4 *buffer, int pass, int resolution, int x, int y) +void kernel_cpu_tonemap(KernelGlobals *kg, uchar4 *rgba, float4 *buffer, int sample, int resolution, int x, int y) { - kernel_film_tonemap(kg, rgba, buffer, pass, resolution, x, y); + kernel_film_tonemap(kg, rgba, buffer, sample, resolution, x, y); } /* Displacement */ diff --git a/intern/cycles/kernel/kernel.cu b/intern/cycles/kernel/kernel.cu index 5e5b445ac2c..75415a00b00 100644 --- a/intern/cycles/kernel/kernel.cu +++ b/intern/cycles/kernel/kernel.cu @@ -26,22 +26,22 @@ #include "kernel_path.h" #include "kernel_displace.h" -extern "C" __global__ void kernel_cuda_path_trace(float4 *buffer, uint *rng_state, int pass, int sx, int sy, int sw, int sh) +extern "C" __global__ void kernel_cuda_path_trace(float4 *buffer, uint *rng_state, int sample, int sx, int sy, int sw, int sh) { int x = sx + blockDim.x*blockIdx.x + threadIdx.x; int y = sy + blockDim.y*blockIdx.y + threadIdx.y; if(x < sx + sw && y < sy + sh) - kernel_path_trace(NULL, buffer, rng_state, pass, x, y); + kernel_path_trace(NULL, buffer, rng_state, sample, x, y); } -extern "C" __global__ void kernel_cuda_tonemap(uchar4 *rgba, float4 *buffer, int pass, int resolution, int sx, int sy, int sw, int sh) +extern "C" __global__ void kernel_cuda_tonemap(uchar4 *rgba, float4 *buffer, int sample, int resolution, int sx, int sy, int sw, int sh) { int x = sx + blockDim.x*blockIdx.x + threadIdx.x; int y = sy + blockDim.y*blockIdx.y + threadIdx.y; if(x < sx + sw && y < sy + sh) - kernel_film_tonemap(NULL, rgba, buffer, pass, resolution, x, y); + kernel_film_tonemap(NULL, rgba, buffer, sample, resolution, x, y); } extern "C" __global__ void kernel_cuda_displace(uint4 *input, float3 *offset, int sx) diff --git a/intern/cycles/kernel/kernel.h b/intern/cycles/kernel/kernel.h index 2bab585c6e6..7f60730e8bf 100644 --- a/intern/cycles/kernel/kernel.h +++ b/intern/cycles/kernel/kernel.h @@ -36,8 +36,8 @@ bool kernel_osl_use(KernelGlobals *kg); void kernel_const_copy(KernelGlobals *kg, const char *name, void *host, size_t size); void kernel_tex_copy(KernelGlobals *kg, const char *name, device_ptr mem, size_t width, size_t height); -void kernel_cpu_path_trace(KernelGlobals *kg, float4 *buffer, unsigned int *rng_state, int pass, int x, int y); -void kernel_cpu_tonemap(KernelGlobals *kg, uchar4 *rgba, float4 *buffer, int pass, int resolution, int x, int y); +void kernel_cpu_path_trace(KernelGlobals *kg, float4 *buffer, unsigned int *rng_state, int sample, int x, int y); +void kernel_cpu_tonemap(KernelGlobals *kg, uchar4 *rgba, float4 *buffer, int sample, int resolution, int x, int y); void kernel_cpu_displace(KernelGlobals *kg, uint4 *input, float3 *offset, int i); diff --git a/intern/cycles/kernel/kernel_camera.h b/intern/cycles/kernel/kernel_camera.h index 1f93394e078..c2828c20eee 100644 --- a/intern/cycles/kernel/kernel_camera.h +++ b/intern/cycles/kernel/kernel_camera.h @@ -20,6 +20,21 @@ CCL_NAMESPACE_BEGIN /* Perspective Camera */ +__device float2 camera_sample_aperture(KernelGlobals *kg, float u, float v) +{ + float blades = kernel_data.cam.blades; + + if(blades == 0.0f) { + /* sample disk */ + return concentric_sample_disk(u, v); + } + else { + /* sample polygon */ + float rotation = kernel_data.cam.bladesrotation; + return regular_polygon_sample(blades, rotation, u, v); + } +} + __device void camera_sample_perspective(KernelGlobals *kg, float raster_x, float raster_y, float lens_u, float lens_v, Ray *ray) { /* create ray form raster position */ @@ -30,14 +45,11 @@ __device void camera_sample_perspective(KernelGlobals *kg, float raster_x, float ray->D = Pcamera; /* modify ray for depth of field */ - float lensradius = kernel_data.cam.lensradius; - - if(lensradius > 0.0f) { - /* sample point on lens */ - float2 lensuv; + float aperturesize = kernel_data.cam.aperturesize; - lensuv = concentric_sample_disk(lens_u, lens_v); - lensuv *= lensradius; + if(aperturesize > 0.0f) { + /* sample point on aperture */ + float2 lensuv = camera_sample_aperture(kg, lens_u, lens_v)*aperturesize; /* compute point on plane of focus */ float ft = kernel_data.cam.focaldistance/ray->D.z; diff --git a/intern/cycles/kernel/kernel_film.h b/intern/cycles/kernel/kernel_film.h index f6351a73295..4373701452e 100644 --- a/intern/cycles/kernel/kernel_film.h +++ b/intern/cycles/kernel/kernel_film.h @@ -18,9 +18,9 @@ CCL_NAMESPACE_BEGIN -__device float4 film_map(KernelGlobals *kg, float4 irradiance, int pass) +__device float4 film_map(KernelGlobals *kg, float4 irradiance, int sample) { - float scale = 1.0f/(float)(pass+1); + float scale = 1.0f/(float)(sample+1); float exposure = kernel_data.film.exposure; float4 result = irradiance*scale; @@ -48,13 +48,13 @@ __device uchar4 film_float_to_byte(float4 color) return result; } -__device void kernel_film_tonemap(KernelGlobals *kg, __global uchar4 *rgba, __global float4 *buffer, int pass, int resolution, int x, int y) +__device void kernel_film_tonemap(KernelGlobals *kg, __global uchar4 *rgba, __global float4 *buffer, int sample, int resolution, int x, int y) { int w = kernel_data.cam.width; int index = x + y*w; float4 irradiance = buffer[index]; - float4 float_result = film_map(kg, irradiance, pass); + float4 float_result = film_map(kg, irradiance, sample); uchar4 byte_result = film_float_to_byte(float_result); rgba[index] = byte_result; diff --git a/intern/cycles/kernel/kernel_montecarlo.h b/intern/cycles/kernel/kernel_montecarlo.h index 6f3a3dd3421..5d9afb6418f 100644 --- a/intern/cycles/kernel/kernel_montecarlo.h +++ b/intern/cycles/kernel/kernel_montecarlo.h @@ -172,6 +172,30 @@ __device float2 concentric_sample_disk(float u1, float u2) return make_float2(r * cosf(theta), r * sinf(theta)); } +__device float2 regular_polygon_sample(float corners, float rotation, float u, float v) +{ + /* sample corner number and reuse u */ + float corner = floorf(u*corners); + u = u*corners - corner; + + /* uniform sampled triangle weights */ + u = sqrtf(u); + v = v*u; + u = 1.0f - u; + + /* point in triangle */ + float angle = M_PI_F/corners; + float2 p = make_float2((u + v)*cosf(angle), (u - v)*sinf(angle)); + + /* rotate */ + rotation += corner*2.0f*angle; + + float cr = cosf(rotation); + float sr = sinf(rotation); + + return make_float2(cr*p.x - sr*p.y, sr*p.x + cr*p.y); +} + /* Spherical coordinates <-> Cartesion direction */ __device float2 direction_to_spherical(float3 dir) diff --git a/intern/cycles/kernel/kernel_path.h b/intern/cycles/kernel/kernel_path.h index 815eb4a1d53..d6977c24c53 100644 --- a/intern/cycles/kernel/kernel_path.h +++ b/intern/cycles/kernel/kernel_path.h @@ -34,22 +34,22 @@ CCL_NAMESPACE_BEGIN #ifdef __MODIFY_TP__ -__device float3 path_terminate_modified_throughput(KernelGlobals *kg, __global float3 *buffer, int x, int y, int pass) +__device float3 path_terminate_modified_throughput(KernelGlobals *kg, __global float3 *buffer, int x, int y, int sample) { /* modify throughput to influence path termination probability, to avoid darker regions receiving fewer samples than lighter regions. also RGB are weighted differently. proper validation still remains to be done. */ const float3 weights = make_float3(1.0f, 1.33f, 0.66f); const float3 one = make_float3(1.0f, 1.0f, 1.0f); - const int minpass = 5; + const int minsample = 5; const float minL = 0.1f; - if(pass >= minpass) { + if(sample >= minsample) { float3 L = buffer[x + y*kernel_data.cam.width]; float3 Lmin = make_float3(minL, minL, minL); - float correct = (float)(pass+1)/(float)pass; + float correct = (float)(sample+1)/(float)sample; - L = film_map(L*correct, pass); + L = film_map(L*correct, sample); return weights/clamp(L, Lmin, one); } @@ -242,7 +242,7 @@ __device_inline bool shadow_blocked(KernelGlobals *kg, PathState *state, Ray *ra return result; } -__device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int pass, Ray ray, float3 throughput) +__device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample, Ray ray, float3 throughput) { /* initialize */ float3 L = make_float3(0.0f, 0.0f, 0.0f); @@ -284,7 +284,7 @@ __device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int pass, Ray /* setup shading */ ShaderData sd; shader_setup_from_ray(kg, &sd, &isect, &ray); - float rbsdf = path_rng(kg, rng, pass, rng_offset + PRNG_BSDF); + float rbsdf = path_rng(kg, rng, sample, rng_offset + PRNG_BSDF); shader_eval_surface(kg, &sd, rbsdf, state.flag); #ifdef __HOLDOUT__ @@ -308,7 +308,7 @@ __device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int pass, Ray mainly due to the mixed in MIS that we use. gives too many unneeded shader evaluations, only need emission if we are going to terminate */ float probability = path_state_terminate_probability(kg, &state, throughput); - float terminate = path_rng(kg, rng, pass, rng_offset + PRNG_TERMINATE); + float terminate = path_rng(kg, rng, sample, rng_offset + PRNG_TERMINATE); if(terminate >= probability) break; @@ -319,10 +319,10 @@ __device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int pass, Ray if(kernel_data.integrator.use_emission) { /* sample illumination from lights to find path contribution */ if(sd.flag & SD_BSDF_HAS_EVAL) { - float light_t = path_rng(kg, rng, pass, rng_offset + PRNG_LIGHT); - float light_o = path_rng(kg, rng, pass, rng_offset + PRNG_LIGHT_F); - float light_u = path_rng(kg, rng, pass, rng_offset + PRNG_LIGHT_U); - float light_v = path_rng(kg, rng, pass, rng_offset + PRNG_LIGHT_V); + float light_t = path_rng(kg, rng, sample, rng_offset + PRNG_LIGHT); + float light_o = path_rng(kg, rng, sample, rng_offset + PRNG_LIGHT_F); + float light_u = path_rng(kg, rng, sample, rng_offset + PRNG_LIGHT_U); + float light_v = path_rng(kg, rng, sample, rng_offset + PRNG_LIGHT_V); Ray light_ray; float3 light_L; @@ -356,8 +356,8 @@ __device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int pass, Ray float3 bsdf_eval; float3 bsdf_omega_in; differential3 bsdf_domega_in; - float bsdf_u = path_rng(kg, rng, pass, rng_offset + PRNG_BSDF_U); - float bsdf_v = path_rng(kg, rng, pass, rng_offset + PRNG_BSDF_V); + float bsdf_u = path_rng(kg, rng, sample, rng_offset + PRNG_BSDF_U); + float bsdf_v = path_rng(kg, rng, sample, rng_offset + PRNG_BSDF_V); int label; label = shader_bsdf_sample(kg, &sd, bsdf_u, bsdf_v, &bsdf_eval, @@ -392,7 +392,7 @@ __device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int pass, Ray return make_float4(L.x, L.y, L.z, 1.0f - Ltransparent); } -__device void kernel_path_trace(KernelGlobals *kg, __global float4 *buffer, __global uint *rng_state, int pass, int x, int y) +__device void kernel_path_trace(KernelGlobals *kg, __global float4 *buffer, __global uint *rng_state, int sample, int x, int y) { /* initialize random numbers */ RNG rng; @@ -400,29 +400,29 @@ __device void kernel_path_trace(KernelGlobals *kg, __global float4 *buffer, __gl float filter_u; float filter_v; - path_rng_init(kg, rng_state, pass, &rng, x, y, &filter_u, &filter_v); + path_rng_init(kg, rng_state, sample, &rng, x, y, &filter_u, &filter_v); /* sample camera ray */ Ray ray; - float lens_u = path_rng(kg, &rng, pass, PRNG_LENS_U); - float lens_v = path_rng(kg, &rng, pass, PRNG_LENS_V); + float lens_u = path_rng(kg, &rng, sample, PRNG_LENS_U); + float lens_v = path_rng(kg, &rng, sample, PRNG_LENS_V); camera_sample(kg, x, y, filter_u, filter_v, lens_u, lens_v, &ray); /* integrate */ #ifdef __MODIFY_TP__ - float3 throughput = path_terminate_modified_throughput(kg, buffer, x, y, pass); - float4 L = kernel_path_integrate(kg, &rng, pass, ray, throughput)/throughput; + float3 throughput = path_terminate_modified_throughput(kg, buffer, x, y, sample); + float4 L = kernel_path_integrate(kg, &rng, sample, ray, throughput)/throughput; #else float3 throughput = make_float3(1.0f, 1.0f, 1.0f); - float4 L = kernel_path_integrate(kg, &rng, pass, ray, throughput); + float4 L = kernel_path_integrate(kg, &rng, sample, ray, throughput); #endif /* accumulate result in output buffer */ int index = x + y*kernel_data.cam.width; - if(pass == 0) + if(sample == 0) buffer[index] = L; else buffer[index] += L; diff --git a/intern/cycles/kernel/kernel_random.h b/intern/cycles/kernel/kernel_random.h index 6c2daafb061..13cf4df8b8c 100644 --- a/intern/cycles/kernel/kernel_random.h +++ b/intern/cycles/kernel/kernel_random.h @@ -95,7 +95,7 @@ __device uint sobol_lookup(const uint m, const uint frame, const uint ex, const return index; } -__device_inline float path_rng(KernelGlobals *kg, RNG *rng, int pass, int dimension) +__device_inline float path_rng(KernelGlobals *kg, RNG *rng, int sample, int dimension) { #ifdef __SOBOL_FULL_SCREEN__ uint result = sobol_dimension(kg, *rng, dimension); @@ -103,7 +103,7 @@ __device_inline float path_rng(KernelGlobals *kg, RNG *rng, int pass, int dimens return r; #else /* compute sobol sequence value using direction vectors */ - uint result = sobol_dimension(kg, pass, dimension); + uint result = sobol_dimension(kg, sample, dimension); float r = (float)result * (1.0f/(float)0xFFFFFFFF); /* Cranly-Patterson rotation using rng seed */ @@ -118,13 +118,13 @@ __device_inline float path_rng(KernelGlobals *kg, RNG *rng, int pass, int dimens #endif } -__device_inline void path_rng_init(KernelGlobals *kg, __global uint *rng_state, int pass, RNG *rng, int x, int y, float *fx, float *fy) +__device_inline void path_rng_init(KernelGlobals *kg, __global uint *rng_state, int sample, RNG *rng, int x, int y, float *fx, float *fy) { #ifdef __SOBOL_FULL_SCREEN__ uint px, py; uint bits = 16; /* limits us to 65536x65536 and 65536 samples */ uint size = 1 << bits; - uint frame = pass; + uint frame = sample; *rng = sobol_lookup(bits, frame, x, y, &px, &py); @@ -133,8 +133,8 @@ __device_inline void path_rng_init(KernelGlobals *kg, __global uint *rng_state, #else *rng = rng_state[x + y*kernel_data.cam.width]; - *fx = path_rng(kg, rng, pass, PRNG_FILTER_U); - *fy = path_rng(kg, rng, pass, PRNG_FILTER_V); + *fx = path_rng(kg, rng, sample, PRNG_FILTER_U); + *fy = path_rng(kg, rng, sample, PRNG_FILTER_V); #endif } @@ -147,25 +147,25 @@ __device void path_rng_end(KernelGlobals *kg, __global uint *rng_state, RNG rng, /* Linear Congruential Generator */ -__device float path_rng(KernelGlobals *kg, RNG *rng, int pass, int dimension) +__device float path_rng(KernelGlobals *kg, RNG *rng, int sample, int dimension) { /* implicit mod 2^32 */ *rng = (1103515245*(*rng) + 12345); return (float)*rng * (1.0f/(float)0xFFFFFFFF); } -__device void path_rng_init(KernelGlobals *kg, __global uint *rng_state, int pass, RNG *rng, int x, int y, float *fx, float *fy) +__device void path_rng_init(KernelGlobals *kg, __global uint *rng_state, int sample, RNG *rng, int x, int y, float *fx, float *fy) { /* load state */ *rng = rng_state[x + y*kernel_data.cam.width]; - *fx = path_rng(kg, rng, pass, PRNG_FILTER_U); - *fy = path_rng(kg, rng, pass, PRNG_FILTER_V); + *fx = path_rng(kg, rng, sample, PRNG_FILTER_U); + *fy = path_rng(kg, rng, sample, PRNG_FILTER_V); } __device void path_rng_end(KernelGlobals *kg, __global uint *rng_state, RNG rng, int x, int y) { - /* store state for next pass */ + /* store state for next sample */ rng_state[x + y*kernel_data.cam.width] = rng; } diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h index d3012324739..8083da971ed 100644 --- a/intern/cycles/kernel/kernel_types.h +++ b/intern/cycles/kernel/kernel_types.h @@ -288,14 +288,6 @@ typedef struct KernelCamera { Transform cameratoworld; Transform rastertocamera; - /* depth of field */ - float lensradius; - float focaldistance; - - /* motion blur */ - float shutteropen; - float shutterclose; - /* differentials */ float3 dx; #ifndef WITH_OPENCL @@ -306,10 +298,19 @@ typedef struct KernelCamera { float pad2; #endif + /* depth of field */ + float aperturesize; + float blades; + float bladesrotation; + float focaldistance; + + /* motion blur */ + float shutteropen; + float shutterclose; + /* clipping */ float nearclip; float cliplength; - float pad3, pad4; /* more matrices */ Transform screentoworld; diff --git a/intern/cycles/kernel/osl/nodes/CMakeLists.txt b/intern/cycles/kernel/osl/nodes/CMakeLists.txt index 365cc42ad6b..7d37bb09d71 100644 --- a/intern/cycles/kernel/osl/nodes/CMakeLists.txt +++ b/intern/cycles/kernel/osl/nodes/CMakeLists.txt @@ -30,6 +30,7 @@ set(osl_sources node_mix.osl node_mix_closure.osl node_musgrave_texture.osl + node_blend_weight_texture.osl node_noise_texture.osl node_output_displacement.osl node_output_surface.osl diff --git a/intern/cycles/kernel/osl/nodes/node_blend_weight.osl b/intern/cycles/kernel/osl/nodes/node_blend_weight.osl new file mode 100644 index 00000000000..d834819ef3a --- /dev/null +++ b/intern/cycles/kernel/osl/nodes/node_blend_weight.osl @@ -0,0 +1,42 @@ +/* + * Copyright 2011, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "stdosl.h" +#include "node_fresnel.h" + +shader node_blend_weight( + float Blend = 0.3, + normal Normal = N, + output float Fresnel = 0.0, + output float Facing = 0.0) +{ + float f = max(1.0 - Blend, 1e-5); + Fresnel = fresnel_dielectric(I, Normal, backfacing()? f: 1.0/f); + + Facing = abs(dot(I, Normal)); + + if(Blend != 0.5) { + Blend = clamp(Blend, 0.0, 1.0); + Blend = (Blend < 0.5)? 2.0*Blend: 0.5/(1.0 - Blend); + + Facing = powf(Facing, Blend); + } + + Facing = 1.0 - Facing; +} + diff --git a/intern/cycles/kernel/osl/nodes/node_environment_texture.osl b/intern/cycles/kernel/osl/nodes/node_environment_texture.osl index 267db7bad2d..3ad806781eb 100644 --- a/intern/cycles/kernel/osl/nodes/node_environment_texture.osl +++ b/intern/cycles/kernel/osl/nodes/node_environment_texture.osl @@ -23,9 +23,10 @@ shader node_environment_texture( vector Vector = P, string filename = "", string color_space = "sRGB", - output color Color = color(0.0, 0.0, 0.0)) + output color Color = color(0.0, 0.0, 0.0), + output float Alpha = 1.0) { - Color = (color)environment(filename, Vector); + Color = (color)environment(filename, Vector, "alpha", Alpha); if(color_space == "sRGB") Color = color_srgb_to_scene_linear(Color); diff --git a/intern/cycles/kernel/osl/nodes/node_fresnel.osl b/intern/cycles/kernel/osl/nodes/node_fresnel.osl index ddc86db130f..3af4448b43f 100644 --- a/intern/cycles/kernel/osl/nodes/node_fresnel.osl +++ b/intern/cycles/kernel/osl/nodes/node_fresnel.osl @@ -20,11 +20,12 @@ #include "node_fresnel.h" shader node_fresnel( - float Fresnel = 0.3, + float IOR = 1.45, normal Normal = N, output float Fac = 0.0) { - float f = max(1.0 - Fresnel, 0.00001); - Fac = fresnel_dielectric(I, Normal, backfacing()? f: 1.0/f); + float f = max(IOR, 1.0 + 1e-5); + float eta = backfacing()? 1.0/f: f; + Fac = fresnel_dielectric(I, Normal, eta); } diff --git a/intern/cycles/kernel/osl/nodes/node_glass_bsdf.osl b/intern/cycles/kernel/osl/nodes/node_glass_bsdf.osl index af946048011..cc2104af56f 100644 --- a/intern/cycles/kernel/osl/nodes/node_glass_bsdf.osl +++ b/intern/cycles/kernel/osl/nodes/node_glass_bsdf.osl @@ -23,12 +23,12 @@ shader node_glass_bsdf( color Color = color(0.8, 0.8, 0.8), string distribution = "Sharp", float Roughness = 0.2, - float Fresnel = 0.3, + float IOR = 1.45, normal Normal = N, output closure color BSDF = diffuse(Normal)) { - float f = clamp(1.0 - Fresnel, 1e-5, 1.0 - 1e-5); - float eta = backfacing()? f: 1.0/f; + float f = max(IOR, 1.0 + 1e-5); + float eta = backfacing()? 1.0/f: f; float Fr = fresnel_dielectric(I, Normal, eta); if(distribution == "Sharp") diff --git a/intern/cycles/kernel/osl/nodes/node_glossy_bsdf.osl b/intern/cycles/kernel/osl/nodes/node_glossy_bsdf.osl index ca6bee74b38..aa446b66cfb 100644 --- a/intern/cycles/kernel/osl/nodes/node_glossy_bsdf.osl +++ b/intern/cycles/kernel/osl/nodes/node_glossy_bsdf.osl @@ -23,23 +23,15 @@ shader node_glossy_bsdf( color Color = color(0.8, 0.8, 0.8), string distribution = "Beckmann", float Roughness = 0.2, - float Fresnel = 1.0, normal Normal = N, output closure color BSDF = diffuse(Normal)) { - float Fr = 1.0; - - if(Fresnel < 1.0) { - float eta = 1.0/clamp(1.0 - Fresnel, 1e-5, 1.0 - 1e-5); - Fr = fresnel_dielectric(I, Normal, eta); - } - if(distribution == "Sharp") - BSDF = (Fr*Color)*reflection(Normal); + BSDF = Color*reflection(Normal); else if(distribution == "Beckmann") - BSDF = (Fr*Color)*microfacet_beckmann(Normal, Roughness); + BSDF = Color*microfacet_beckmann(Normal, Roughness); else if(distribution == "GGX") - BSDF = (Fr*Color)*microfacet_ggx(Normal, Roughness); + BSDF = Color*microfacet_ggx(Normal, Roughness); } diff --git a/intern/cycles/kernel/osl/nodes/node_image_texture.osl b/intern/cycles/kernel/osl/nodes/node_image_texture.osl index 85025db7c74..38126401d76 100644 --- a/intern/cycles/kernel/osl/nodes/node_image_texture.osl +++ b/intern/cycles/kernel/osl/nodes/node_image_texture.osl @@ -23,9 +23,10 @@ shader node_image_texture( point Vector = P, string filename = "", string color_space = "sRGB", - output color Color = color(0.0, 0.0, 0.0)) + output color Color = color(0.0, 0.0, 0.0), + output float Alpha = 1.0) { - Color = (color)texture(filename, Vector[0], 1.0-Vector[1], "wrap", "periodic"); + Color = (color)texture(filename, Vector[0], 1.0-Vector[1], "wrap", "periodic", "alpha", Alpha); if(color_space == "sRGB") Color = color_srgb_to_scene_linear(Color); diff --git a/intern/cycles/kernel/osl/nodes/node_velvet_bsdf.osl b/intern/cycles/kernel/osl/nodes/node_velvet_bsdf.osl index 2b6219f6325..7a336c148db 100644 --- a/intern/cycles/kernel/osl/nodes/node_velvet_bsdf.osl +++ b/intern/cycles/kernel/osl/nodes/node_velvet_bsdf.osl @@ -22,19 +22,11 @@ shader node_velvet_bsdf( color Color = color(0.8, 0.8, 0.8), float Sigma = 0.0, - float Fresnel = 0.3, normal Normal = N, output closure color BSDF = diffuse(Normal)) { - float Fr = 1.0; - - if(Fresnel < 1.0) { - float eta = 1.0/clamp(1.0 - Fresnel, 1e-5, 1.0 - 1e-5); - Fr = fresnel_dielectric(I, Normal, eta); - } - float sigma = clamp(Sigma, 0.0, 1.0); - BSDF = (Fr*Color)*ashikhmin_velvet(Normal, sigma); + BSDF = Color*ashikhmin_velvet(Normal, sigma); } diff --git a/intern/cycles/kernel/svm/svm.h b/intern/cycles/kernel/svm/svm.h index a5d95c1b394..65d92a91df9 100644 --- a/intern/cycles/kernel/svm/svm.h +++ b/intern/cycles/kernel/svm/svm.h @@ -282,6 +282,9 @@ __device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, ShaderT case NODE_FRESNEL: svm_node_fresnel(sd, stack, node.y, node.z, node.w); break; + case NODE_BLEND_WEIGHT: + svm_node_blend_weight(sd, stack, node); + break; case NODE_SET_DISPLACEMENT: svm_node_set_displacement(sd, stack, node.y); break; diff --git a/intern/cycles/kernel/svm/svm_closure.h b/intern/cycles/kernel/svm/svm_closure.h index aaf2926f60d..68f91408f1f 100644 --- a/intern/cycles/kernel/svm/svm_closure.h +++ b/intern/cycles/kernel/svm/svm_closure.h @@ -102,23 +102,19 @@ __device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *st if(kernel_data.integrator.no_caustics && (path_flag & PATH_RAY_DIFFUSE)) break; #endif - ShaderClosure *sc = svm_node_closure_get(sd); svm_node_closure_set_mix_weight(sc, mix_weight); - /* index of refraction */ - float eta = clamp(1.0f-param2, 1e-5f, 1.0f - 1e-5f); - eta = 1.0f/eta; - - /* fresnel */ - float cosNO = dot(sd->N, sd->I); - float fresnel = fresnel_dielectric_cos(cosNO, eta); float roughness = param1; - sc->weight *= fresnel; - /* setup bsdf */ - svm_node_glossy_setup(sd, sc, type, eta, roughness, false); + if(type == CLOSURE_BSDF_REFLECTION_ID) + bsdf_reflection_setup(sd, sc); + else if(type == CLOSURE_BSDF_MICROFACET_BECKMANN_ID) + bsdf_microfacet_beckmann_setup(sd, sc, roughness, 1.0f, false); + else + bsdf_microfacet_ggx_setup(sd, sc, roughness, 1.0f, false); + break; } case CLOSURE_BSDF_REFRACTION_ID: @@ -128,10 +124,9 @@ __device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *st if(kernel_data.integrator.no_caustics && (path_flag & PATH_RAY_DIFFUSE)) break; #endif - /* index of refraction */ - float eta = clamp(1.0f-param2, 1e-5f, 1.0f - 1e-5f); - eta = (sd->flag & SD_BACKFACING)? eta: 1.0f/eta; + float eta = fmaxf(param2, 1.0f + 1e-5f); + eta = (sd->flag & SD_BACKFACING)? 1.0f/eta: eta; /* fresnel */ float cosNO = dot(sd->N, sd->I); @@ -173,7 +168,6 @@ __device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *st if(kernel_data.integrator.no_caustics && (path_flag & PATH_RAY_DIFFUSE)) break; #endif - ShaderClosure *sc = svm_node_closure_get(sd); svm_node_closure_set_mix_weight(sc, mix_weight); @@ -190,17 +184,6 @@ __device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *st /* sigma */ float sigma = clamp(param1, 0.0f, 1.0f); - - /* index of refraction */ - float eta = clamp(1.0f-param2, 1e-5f, 1.0f - 1e-5f); - eta = 1.0f/eta; - - /* fresnel */ - float cosNO = dot(sd->N, sd->I); - float fresnel = fresnel_dielectric_cos(cosNO, eta); - - sc->weight *= fresnel; - bsdf_ashikhmin_velvet_setup(sd, sc, sigma); break; } @@ -308,7 +291,8 @@ __device void svm_node_emission_weight(KernelGlobals *kg, ShaderData *sd, float uint strength_offset = node.z; uint total_power = node.w; - float3 weight = stack_load_float3(stack, color_offset)*stack_load_float(stack, strength_offset); + float strength = stack_load_float(stack, strength_offset); + float3 weight = stack_load_float3(stack, color_offset)*strength; if(total_power && sd->object != ~0) weight /= object_surface_area(kg, sd->object); diff --git a/intern/cycles/kernel/svm/svm_fresnel.h b/intern/cycles/kernel/svm/svm_fresnel.h index f6122fa3071..1b9d99506e3 100644 --- a/intern/cycles/kernel/svm/svm_fresnel.h +++ b/intern/cycles/kernel/svm/svm_fresnel.h @@ -20,12 +20,48 @@ CCL_NAMESPACE_BEGIN /* Fresnel Node */ -__device void svm_node_fresnel(ShaderData *sd, float *stack, uint fresnel_offset, uint fresnel_value, uint out_offset) +__device void svm_node_fresnel(ShaderData *sd, float *stack, uint ior_offset, uint ior_value, uint out_offset) { - float fresnel = (stack_valid(fresnel_offset))? stack_load_float(stack, fresnel_offset): __int_as_float(fresnel_value); - fresnel = fmaxf(1.0f - fresnel, 0.00001f); + float eta = (stack_valid(ior_offset))? stack_load_float(stack, ior_offset): __int_as_float(ior_value); + eta = fmaxf(eta, 1.0f + 1e-5f); + eta = (sd->flag & SD_BACKFACING)? 1.0f/eta: eta; - float f = fresnel_dielectric_cos(dot(sd->I, sd->N), (sd->flag & SD_BACKFACING)? fresnel: 1.0f/fresnel); + float f = fresnel_dielectric_cos(dot(sd->I, sd->N), eta); + + stack_store_float(stack, out_offset, f); +} + +/* Blend Weight Node */ + +__device void svm_node_blend_weight(ShaderData *sd, float *stack, uint4 node) +{ + uint blend_offset = node.y; + uint blend_value = node.z; + float blend = (stack_valid(blend_offset))? stack_load_float(stack, blend_offset): __int_as_float(blend_value); + + uint type, out_offset; + decode_node_uchar4(node.w, &type, &out_offset, NULL, NULL); + + float f; + + if(type == NODE_BLEND_WEIGHT_FRESNEL) { + float eta = fmaxf(1.0f - blend, 1e-5f); + eta = (sd->flag & SD_BACKFACING)? eta: 1.0f/eta; + + f = fresnel_dielectric_cos(dot(sd->I, sd->N), eta); + } + else { + f = fabsf(dot(sd->I, sd->N)); + + if(blend != 0.5f) { + blend = clamp(blend, 0.0f, 1.0f); + blend = (blend < 0.5f)? 2.0f*blend: 0.5f/(1.0f - blend); + + f = powf(f, blend); + } + + f = 1.0f - f; + } stack_store_float(stack, out_offset, f); } diff --git a/intern/cycles/kernel/svm/svm_image.h b/intern/cycles/kernel/svm/svm_image.h index 586e35c6465..62e24166970 100644 --- a/intern/cycles/kernel/svm/svm_image.h +++ b/intern/cycles/kernel/svm/svm_image.h @@ -147,9 +147,9 @@ __device float4 svm_image_texture(KernelGlobals *kg, int id, float x, float y) __device void svm_node_tex_image(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node) { uint id = node.y; - uint co_offset, out_offset, srgb; + uint co_offset, out_offset, alpha_offset, srgb; - decode_node_uchar4(node.z, &co_offset, &out_offset, &srgb, NULL); + decode_node_uchar4(node.z, &co_offset, &out_offset, &alpha_offset, &srgb); float3 co = stack_load_float3(stack, co_offset); float4 f = svm_image_texture(kg, id, co.x, co.y); @@ -161,15 +161,18 @@ __device void svm_node_tex_image(KernelGlobals *kg, ShaderData *sd, float *stack r.z = color_srgb_to_scene_linear(r.z); } - stack_store_float3(stack, out_offset, r); + if(stack_valid(out_offset)) + stack_store_float3(stack, out_offset, r); + if(stack_valid(alpha_offset)) + stack_store_float(stack, alpha_offset, f.w); } __device void svm_node_tex_environment(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node) { uint id = node.y; - uint co_offset, out_offset, srgb; + uint co_offset, out_offset, alpha_offset, srgb; - decode_node_uchar4(node.z, &co_offset, &out_offset, &srgb, NULL); + decode_node_uchar4(node.z, &co_offset, &out_offset, &alpha_offset, &srgb); float3 co = stack_load_float3(stack, co_offset); float u = (atan2f(co.y, co.x) + M_PI_F)/(2*M_PI_F); @@ -183,7 +186,10 @@ __device void svm_node_tex_environment(KernelGlobals *kg, ShaderData *sd, float r.z = color_srgb_to_scene_linear(r.z); } - stack_store_float3(stack, out_offset, r); + if(stack_valid(out_offset)) + stack_store_float3(stack, out_offset, r); + if(stack_valid(alpha_offset)) + stack_store_float(stack, alpha_offset, f.w); } CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/svm/svm_types.h b/intern/cycles/kernel/svm/svm_types.h index 98e4a5ee583..483f3c76f3c 100644 --- a/intern/cycles/kernel/svm/svm_types.h +++ b/intern/cycles/kernel/svm/svm_types.h @@ -82,7 +82,8 @@ typedef enum NodeType { NODE_ATTR_BUMP_DX = 4400, NODE_ATTR_BUMP_DY = 4500, NODE_TEX_ENVIRONMENT = 4600, - NODE_CLOSURE_HOLDOUT = 4700 + NODE_CLOSURE_HOLDOUT = 4700, + NODE_BLEND_WEIGHT = 4800 } NodeType; typedef enum NodeAttributeType { @@ -249,6 +250,11 @@ typedef enum NodeVoronoiColoring { NODE_VORONOI_POSITION_OUTLINE_INTENSITY } NodeVoronoiColoring; +typedef enum NodeBlendWeightType { + NODE_BLEND_WEIGHT_FRESNEL, + NODE_BLEND_WEIGHT_FACING +} NodeBlendWeightType; + typedef enum ShaderType { SHADER_TYPE_SURFACE, SHADER_TYPE_VOLUME, diff --git a/intern/cycles/render/buffers.cpp b/intern/cycles/render/buffers.cpp index 62dc17960ae..acdddb475d0 100644 --- a/intern/cycles/render/buffers.cpp +++ b/intern/cycles/render/buffers.cpp @@ -85,7 +85,7 @@ void RenderBuffers::reset(Device *device, int width_, int height_) device->mem_copy_to(rng_state); } -float4 *RenderBuffers::copy_from_device(float exposure, int pass) +float4 *RenderBuffers::copy_from_device(float exposure, int sample) { if(!buffer.device_pointer) return NULL; @@ -94,7 +94,7 @@ float4 *RenderBuffers::copy_from_device(float exposure, int pass) float4 *out = new float4[width*height]; float4 *in = (float4*)buffer.data_pointer; - float scale = 1.0f/(float)pass; + float scale = 1.0f/(float)sample; for(int i = width*height - 1; i >= 0; i--) { float4 rgba = in[i]*scale; diff --git a/intern/cycles/render/buffers.h b/intern/cycles/render/buffers.h index e99fedb0dff..d5eb8d7fa2f 100644 --- a/intern/cycles/render/buffers.h +++ b/intern/cycles/render/buffers.h @@ -47,7 +47,7 @@ public: ~RenderBuffers(); void reset(Device *device, int width, int height); - float4 *copy_from_device(float exposure, int pass); + float4 *copy_from_device(float exposure, int sample); protected: void device_free(); diff --git a/intern/cycles/render/camera.cpp b/intern/cycles/render/camera.cpp index 74469c738c7..e88c0a388bc 100644 --- a/intern/cycles/render/camera.cpp +++ b/intern/cycles/render/camera.cpp @@ -28,8 +28,10 @@ Camera::Camera() shutteropen = 0.0f; shutterclose = 1.0f; - lensradius = 0.0f; + aperturesize = 0.0f; focaldistance = 10.0f; + blades = 0; + bladesrotation = 0.0f; matrix = transform_identity(); @@ -134,8 +136,10 @@ void Camera::device_update(Device *device, DeviceScene *dscene) kcam->worldtocamera = transform_inverse(cameratoworld); /* depth of field */ - kcam->lensradius = lensradius; + kcam->aperturesize = aperturesize; kcam->focaldistance = focaldistance; + kcam->blades = (blades < 3)? 0.0f: blades; + kcam->bladesrotation = bladesrotation; /* motion blur */ kcam->shutteropen = shutteropen; @@ -168,7 +172,9 @@ bool Camera::modified(const Camera& cam) { return !((shutteropen == cam.shutteropen) && (shutterclose == cam.shutterclose) && - (lensradius == cam.lensradius) && + (aperturesize == cam.aperturesize) && + (blades == cam.blades) && + (bladesrotation == cam.bladesrotation) && (focaldistance == cam.focaldistance) && (ortho == cam.ortho) && (fov == cam.fov) && diff --git a/intern/cycles/render/camera.h b/intern/cycles/render/camera.h index d385aa274f4..43537ce8c3c 100644 --- a/intern/cycles/render/camera.h +++ b/intern/cycles/render/camera.h @@ -39,8 +39,10 @@ public: float shutterclose; /* depth of field */ - float lensradius; float focaldistance; + float aperturesize; + uint blades; + float bladesrotation; /* orthographic/perspective */ bool ortho; diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp index f2030256814..038a6c45b97 100644 --- a/intern/cycles/render/nodes.cpp +++ b/intern/cycles/render/nodes.cpp @@ -49,6 +49,7 @@ ImageTextureNode::ImageTextureNode() add_input("Vector", SHADER_SOCKET_POINT, ShaderInput::TEXTURE_COORDINATE); add_output("Color", SHADER_SOCKET_COLOR); + add_output("Alpha", SHADER_SOCKET_FLOAT); } ImageTextureNode::~ImageTextureNode() @@ -69,12 +70,16 @@ void ImageTextureNode::compile(SVMCompiler& compiler) { ShaderInput *vector_in = input("Vector"); ShaderOutput *color_out = output("Color"); + ShaderOutput *alpha_out = output("Alpha"); image_manager = compiler.image_manager; if(slot == -1) slot = image_manager->add_image(filename); - compiler.stack_assign(color_out); + if(!color_out->links.empty()) + compiler.stack_assign(color_out); + if(!alpha_out->links.empty()) + compiler.stack_assign(alpha_out); if(slot != -1) { compiler.stack_assign(vector_in); @@ -83,12 +88,17 @@ void ImageTextureNode::compile(SVMCompiler& compiler) compiler.encode_uchar4( vector_in->stack_offset, color_out->stack_offset, + alpha_out->stack_offset, color_space_enum[color_space])); } else { /* image not found */ - compiler.add_node(NODE_VALUE_V, color_out->stack_offset); - compiler.add_node(NODE_VALUE_V, make_float3(0, 0, 0)); + if(!color_out->links.empty()) { + compiler.add_node(NODE_VALUE_V, color_out->stack_offset); + compiler.add_node(NODE_VALUE_V, make_float3(0, 0, 0)); + } + if(!alpha_out->links.empty()) + compiler.add_node(NODE_VALUE_F, __float_as_int(0.0f), alpha_out->stack_offset); } } @@ -113,6 +123,7 @@ EnvironmentTextureNode::EnvironmentTextureNode() add_input("Vector", SHADER_SOCKET_VECTOR, ShaderInput::POSITION); add_output("Color", SHADER_SOCKET_COLOR); + add_output("Alpha", SHADER_SOCKET_FLOAT); } EnvironmentTextureNode::~EnvironmentTextureNode() @@ -133,12 +144,16 @@ void EnvironmentTextureNode::compile(SVMCompiler& compiler) { ShaderInput *vector_in = input("Vector"); ShaderOutput *color_out = output("Color"); + ShaderOutput *alpha_out = output("Alpha"); image_manager = compiler.image_manager; if(slot == -1) slot = image_manager->add_image(filename); - compiler.stack_assign(color_out); + if(!color_out->links.empty()) + compiler.stack_assign(color_out); + if(!alpha_out->links.empty()) + compiler.stack_assign(alpha_out); if(slot != -1) { compiler.stack_assign(vector_in); @@ -147,12 +162,17 @@ void EnvironmentTextureNode::compile(SVMCompiler& compiler) compiler.encode_uchar4( vector_in->stack_offset, color_out->stack_offset, + alpha_out->stack_offset, color_space_enum[color_space])); } else { /* image not found */ - compiler.add_node(NODE_VALUE_V, color_out->stack_offset); - compiler.add_node(NODE_VALUE_V, make_float3(0, 0, 0)); + if(!color_out->links.empty()) { + compiler.add_node(NODE_VALUE_V, color_out->stack_offset); + compiler.add_node(NODE_VALUE_V, make_float3(0, 0, 0)); + } + if(!alpha_out->links.empty()) + compiler.add_node(NODE_VALUE_F, __float_as_int(0.0f), alpha_out->stack_offset); } } @@ -1080,7 +1100,6 @@ GlossyBsdfNode::GlossyBsdfNode() distribution = ustring("Beckmann"); add_input("Roughness", SHADER_SOCKET_FLOAT, 0.2f); - add_input("Fresnel", SHADER_SOCKET_FLOAT, 1.0f); } void GlossyBsdfNode::compile(SVMCompiler& compiler) @@ -1088,9 +1107,9 @@ void GlossyBsdfNode::compile(SVMCompiler& compiler) closure = (ClosureType)distribution_enum[distribution]; if(closure == CLOSURE_BSDF_REFLECTION_ID) - BsdfNode::compile(compiler, NULL, input("Fresnel")); + BsdfNode::compile(compiler, NULL, NULL); else - BsdfNode::compile(compiler, input("Roughness"), input("Fresnel")); + BsdfNode::compile(compiler, input("Roughness"), NULL); } void GlossyBsdfNode::compile(OSLCompiler& compiler) @@ -1119,7 +1138,7 @@ GlassBsdfNode::GlassBsdfNode() distribution = ustring("Sharp"); add_input("Roughness", SHADER_SOCKET_FLOAT, 0.0f); - add_input("Fresnel", SHADER_SOCKET_FLOAT, 0.3f); + add_input("IOR", SHADER_SOCKET_FLOAT, 0.3f); } void GlassBsdfNode::compile(SVMCompiler& compiler) @@ -1127,9 +1146,9 @@ void GlassBsdfNode::compile(SVMCompiler& compiler) closure = (ClosureType)distribution_enum[distribution]; if(closure == CLOSURE_BSDF_REFRACTION_ID) - BsdfNode::compile(compiler, NULL, input("Fresnel")); + BsdfNode::compile(compiler, NULL, input("IOR")); else - BsdfNode::compile(compiler, input("Roughness"), input("Fresnel")); + BsdfNode::compile(compiler, input("Roughness"), input("IOR")); } void GlassBsdfNode::compile(OSLCompiler& compiler) @@ -1145,12 +1164,11 @@ VelvetBsdfNode::VelvetBsdfNode() closure = CLOSURE_BSDF_ASHIKHMIN_VELVET_ID; add_input("Sigma", SHADER_SOCKET_FLOAT, 1.0f); - add_input("Fresnel", SHADER_SOCKET_FLOAT, 1.0f); } void VelvetBsdfNode::compile(SVMCompiler& compiler) { - BsdfNode::compile(compiler, input("Sigma"), input("Fresnel")); + BsdfNode::compile(compiler, input("Sigma"), NULL); } void VelvetBsdfNode::compile(OSLCompiler& compiler) @@ -1781,18 +1799,18 @@ FresnelNode::FresnelNode() : ShaderNode("Fresnel") { add_input("Normal", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL, true); - add_input("Fresnel", SHADER_SOCKET_FLOAT, 0.3f); + add_input("IOR", SHADER_SOCKET_FLOAT, 1.45f); add_output("Fac", SHADER_SOCKET_FLOAT); } void FresnelNode::compile(SVMCompiler& compiler) { - ShaderInput *fresnel_in = input("Fresnel"); + ShaderInput *ior_in = input("IOR"); ShaderOutput *fac_out = output("Fac"); - compiler.stack_assign(fresnel_in); + compiler.stack_assign(ior_in); compiler.stack_assign(fac_out); - compiler.add_node(NODE_FRESNEL, fresnel_in->stack_offset, __float_as_int(fresnel_in->value.x), fac_out->stack_offset); + compiler.add_node(NODE_FRESNEL, ior_in->stack_offset, __float_as_int(ior_in->value.x), fac_out->stack_offset); } void FresnelNode::compile(OSLCompiler& compiler) @@ -1800,6 +1818,45 @@ void FresnelNode::compile(OSLCompiler& compiler) compiler.add(this, "node_fresnel"); } +/* Blend Weight */ + +BlendWeightNode::BlendWeightNode() +: ShaderNode("BlendWeight") +{ + add_input("Normal", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL, true); + add_input("Blend", SHADER_SOCKET_FLOAT, 0.5f); + + add_output("Fresnel", SHADER_SOCKET_FLOAT); + add_output("Facing", SHADER_SOCKET_FLOAT); +} + +void BlendWeightNode::compile(SVMCompiler& compiler) +{ + ShaderInput *blend_in = input("Blend"); + + if(blend_in->link) + compiler.stack_assign(blend_in); + + ShaderOutput *fresnel_out = output("Fresnel"); + if(!fresnel_out->links.empty()) { + compiler.stack_assign(fresnel_out); + compiler.add_node(NODE_BLEND_WEIGHT, blend_in->stack_offset, __float_as_int(blend_in->value.x), + compiler.encode_uchar4(NODE_BLEND_WEIGHT_FRESNEL, fresnel_out->stack_offset)); + } + + ShaderOutput *facing_out = output("Facing"); + if(!facing_out->links.empty()) { + compiler.stack_assign(facing_out); + compiler.add_node(NODE_BLEND_WEIGHT, blend_in->stack_offset, __float_as_int(blend_in->value.x), + compiler.encode_uchar4(NODE_BLEND_WEIGHT_FACING, facing_out->stack_offset)); + } +} + +void BlendWeightNode::compile(OSLCompiler& compiler) +{ + compiler.add(this, "node_blend_weight"); +} + /* Output */ OutputNode::OutputNode() diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h index 2afe585c3ac..f11f34778e3 100644 --- a/intern/cycles/render/nodes.h +++ b/intern/cycles/render/nodes.h @@ -323,6 +323,11 @@ public: SHADER_NODE_CLASS(FresnelNode) }; +class BlendWeightNode : public ShaderNode { +public: + SHADER_NODE_CLASS(BlendWeightNode) +}; + class MathNode : public ShaderNode { public: SHADER_NODE_CLASS(MathNode) diff --git a/intern/cycles/render/scene.h b/intern/cycles/render/scene.h index 5772a9d7268..93d8ebf1301 100644 --- a/intern/cycles/render/scene.h +++ b/intern/cycles/render/scene.h @@ -99,6 +99,7 @@ public: class SceneParams { public: enum { OSL, SVM } shadingsystem; + bool use_multi_closure; enum BVHType { BVH_DYNAMIC, BVH_STATIC } bvh_type; bool use_bvh_cache; bool use_bvh_spatial_split; @@ -107,6 +108,7 @@ public: SceneParams() { shadingsystem = SVM; + use_multi_closure = false; bvh_type = BVH_DYNAMIC; use_bvh_cache = false; use_bvh_spatial_split = false; diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp index 5eb8d51a816..50f7017bacf 100644 --- a/intern/cycles/render/session.cpp +++ b/intern/cycles/render/session.cpp @@ -33,7 +33,7 @@ CCL_NAMESPACE_BEGIN Session::Session(const SessionParams& params_) : params(params_), - tile_manager(params.progressive, params.passes, params.tile_size, params.min_size) + tile_manager(params.progressive, params.samples, params.tile_size, params.min_size) { device_use_gl = ((params.device_type != DEVICE_CPU) && !params.background); @@ -48,12 +48,12 @@ Session::Session(const SessionParams& params_) reset_time = 0.0; preview_time = 0.0; paused_time = 0.0; - pass = 0; + sample = 0; delayed_reset.do_reset = false; delayed_reset.w = 0; delayed_reset.h = 0; - delayed_reset.passes = 0; + delayed_reset.samples = 0; display_outdated = false; gpu_draw_ready = false; @@ -108,7 +108,7 @@ bool Session::ready_to_reset() /* GPU Session */ -void Session::reset_gpu(int w, int h, int passes) +void Session::reset_gpu(int w, int h, int samples) { /* block for buffer acces and reset immediately. we can't do this in the thread, because we need to allocate an OpenGL buffer, and @@ -119,7 +119,7 @@ void Session::reset_gpu(int w, int h, int passes) display_outdated = true; reset_time = time_dt(); - reset_(w, h, passes); + reset_(w, h, samples); gpu_need_tonemap = false; gpu_need_tonemap_cond.notify_all(); @@ -207,7 +207,7 @@ void Session::run_gpu() if(!no_tiles) { /* buffers mutex is locked entirely while rendering each - pass, and released/reacquired on each iteration to allow + sample, and released/reacquired on each iteration to allow reset and draw in between */ thread_scoped_lock buffers_lock(buffers->mutex); @@ -249,7 +249,7 @@ void Session::run_gpu() /* CPU Session */ -void Session::reset_cpu(int w, int h, int passes) +void Session::reset_cpu(int w, int h, int samples) { thread_scoped_lock reset_lock(delayed_reset.mutex); @@ -258,7 +258,7 @@ void Session::reset_cpu(int w, int h, int passes) delayed_reset.w = w; delayed_reset.h = h; - delayed_reset.passes = passes; + delayed_reset.samples = samples; delayed_reset.do_reset = true; device->task_cancel(); @@ -294,7 +294,7 @@ void Session::run_cpu() thread_scoped_lock buffers_lock(buffers->mutex); thread_scoped_lock display_lock(display->mutex); - reset_(delayed_reset.w, delayed_reset.h, delayed_reset.passes); + reset_(delayed_reset.w, delayed_reset.h, delayed_reset.samples); delayed_reset.do_reset = false; } @@ -335,7 +335,7 @@ void Session::run_cpu() if(!no_tiles) { /* buffers mutex is locked entirely while rendering each - pass, and released/reacquired on each iteration to allow + sample, and released/reacquired on each iteration to allow reset and draw in between */ thread_scoped_lock buffers_lock(buffers->mutex); @@ -368,11 +368,11 @@ void Session::run_cpu() if(delayed_reset.do_reset) { /* reset rendering if request from main thread */ delayed_reset.do_reset = false; - reset_(delayed_reset.w, delayed_reset.h, delayed_reset.passes); + reset_(delayed_reset.w, delayed_reset.h, delayed_reset.samples); } else if(need_tonemap) { /* tonemap only if we do not reset, we don't we don't - want to show the result of an incomplete pass*/ + want to show the result of an incomplete sample*/ tonemap(); } } @@ -418,7 +418,7 @@ bool Session::draw(int w, int h) return draw_cpu(w, h); } -void Session::reset_(int w, int h, int passes) +void Session::reset_(int w, int h, int samples) { if(w != buffers->width || h != buffers->height) { gpu_draw_ready = false; @@ -426,27 +426,27 @@ void Session::reset_(int w, int h, int passes) display->reset(device, w, h); } - tile_manager.reset(w, h, passes); + tile_manager.reset(w, h, samples); start_time = time_dt(); preview_time = 0.0; paused_time = 0.0; - pass = 0; + sample = 0; } -void Session::reset(int w, int h, int passes) +void Session::reset(int w, int h, int samples) { if(device_use_gl) - reset_gpu(w, h, passes); + reset_gpu(w, h, samples); else - reset_cpu(w, h, passes); + reset_cpu(w, h, samples); } -void Session::set_passes(int passes) +void Session::set_samples(int samples) { - if(passes != params.passes) { - params.passes = passes; - tile_manager.set_passes(passes); + if(samples != params.samples) { + params.samples = samples; + tile_manager.set_samples(samples); { thread_scoped_lock pause_lock(pause_mutex); @@ -504,7 +504,7 @@ void Session::update_scene() void Session::update_status_time(bool show_pause, bool show_done) { - int pass = tile_manager.state.pass; + int sample = tile_manager.state.sample; int resolution = tile_manager.state.resolution; /* update status */ @@ -512,10 +512,10 @@ void Session::update_status_time(bool show_pause, bool show_done) if(!params.progressive) substatus = "Path Tracing"; - else if(params.passes == INT_MAX) - substatus = string_printf("Path Tracing Pass %d", pass+1); + else if(params.samples == INT_MAX) + substatus = string_printf("Path Tracing Sample %d", sample+1); else - substatus = string_printf("Path Tracing Pass %d/%d", pass+1, params.passes); + substatus = string_printf("Path Tracing Sample %d/%d", sample+1, params.samples); if(show_pause) status = "Paused"; @@ -531,13 +531,13 @@ void Session::update_status_time(bool show_pause, bool show_done) preview_time = time_dt(); double total_time = time_dt() - start_time - paused_time; - double pass_time = (pass == 0)? 0.0: (time_dt() - preview_time - paused_time)/(pass); + double sample_time = (sample == 0)? 0.0: (time_dt() - preview_time - paused_time)/(sample); /* negative can happen when we pause a bit before rendering, can discard that */ if(total_time < 0.0) total_time = 0.0; if(preview_time < 0.0) preview_time = 0.0; - progress.set_pass(pass + 1, total_time, pass_time); + progress.set_sample(sample + 1, total_time, sample_time); } void Session::path_trace(Tile& tile) @@ -551,7 +551,7 @@ void Session::path_trace(Tile& tile) task.h = tile.h; task.buffer = buffers->buffer.device_pointer; task.rng_state = buffers->rng_state.device_pointer; - task.pass = tile_manager.state.pass; + task.sample = tile_manager.state.sample; task.resolution = tile_manager.state.resolution; device->task_add(task); @@ -568,7 +568,7 @@ void Session::tonemap() task.h = tile_manager.state.height; task.rgba = display->rgba.device_pointer; task.buffer = buffers->buffer.device_pointer; - task.pass = tile_manager.state.pass; + task.sample = tile_manager.state.sample; task.resolution = tile_manager.state.resolution; if(task.w > 0 && task.h > 0) { diff --git a/intern/cycles/render/session.h b/intern/cycles/render/session.h index 4d5cf434098..82c14227d03 100644 --- a/intern/cycles/render/session.h +++ b/intern/cycles/render/session.h @@ -43,7 +43,7 @@ public: string output_path; bool progressive; - int passes; + int samples; int tile_size; int min_size; int threads; @@ -59,7 +59,7 @@ public: output_path = ""; progressive = false; - passes = INT_MAX; + samples = INT_MAX; tile_size = 64; min_size = 64; threads = 0; @@ -73,7 +73,7 @@ public: { return !(device_type == params.device_type && background == params.background && output_path == params.output_path - /* && passes == params.passes */ + /* && samples == params.samples */ && progressive == params.progressive && tile_size == params.tile_size && min_size == params.min_size @@ -97,7 +97,7 @@ public: DisplayBuffer *display; Progress progress; SessionParams params; - int pass; + int sample; Session(const SessionParams& params); ~Session(); @@ -107,8 +107,8 @@ public: void wait(); bool ready_to_reset(); - void reset(int w, int h, int passes); - void set_passes(int passes); + void reset(int w, int h, int samples); + void set_samples(int samples); void set_pause(bool pause); protected: @@ -116,7 +116,7 @@ protected: thread_mutex mutex; bool do_reset; int w, h; - int passes; + int samples; } delayed_reset; void run(); @@ -126,15 +126,15 @@ protected: void tonemap(); void path_trace(Tile& tile); - void reset_(int w, int h, int passes); + void reset_(int w, int h, int samples); void run_cpu(); bool draw_cpu(int w, int h); - void reset_cpu(int w, int h, int passes); + void reset_cpu(int w, int h, int samples); void run_gpu(); bool draw_gpu(int w, int h); - void reset_gpu(int w, int h, int passes); + void reset_gpu(int w, int h, int samples); TileManager tile_manager; bool device_use_gl; diff --git a/intern/cycles/render/svm.cpp b/intern/cycles/render/svm.cpp index 8f3682cc349..c9bbeecc3a4 100644 --- a/intern/cycles/render/svm.cpp +++ b/intern/cycles/render/svm.cpp @@ -69,7 +69,8 @@ void SVMShaderManager::device_update(Device *device, DeviceScene *dscene, Scene if(shader->has_surface_emission) scene->light_manager->need_update = true; - SVMCompiler compiler(scene->shader_manager, scene->image_manager); + SVMCompiler compiler(scene->shader_manager, scene->image_manager, + scene->params.use_multi_closure); compiler.sunsky = (sunsky_done)? NULL: &dscene->data.sunsky; compiler.background = ((int)i == scene->default_background); compiler.compile(shader, svm_nodes, i); @@ -96,7 +97,7 @@ void SVMShaderManager::device_free(Device *device, DeviceScene *dscene) /* Graph Compiler */ -SVMCompiler::SVMCompiler(ShaderManager *shader_manager_, ImageManager *image_manager_) +SVMCompiler::SVMCompiler(ShaderManager *shader_manager_, ImageManager *image_manager_, bool use_multi_closure_) { shader_manager = shader_manager_; image_manager = image_manager_; @@ -106,6 +107,7 @@ SVMCompiler::SVMCompiler(ShaderManager *shader_manager_, ImageManager *image_man current_shader = NULL; background = false; mix_weight_offset = SVM_STACK_INVALID; + use_multi_closure = use_multi_closure_; } int SVMCompiler::stack_size(ShaderSocketType type) @@ -573,9 +575,8 @@ void SVMCompiler::compile_type(Shader *shader, ShaderGraph *graph, ShaderType ty if(generate) { set<ShaderNode*> done; - bool multi_closure = false; /* __MULTI_CLOSURE__ */ - if(multi_closure) { + if(use_multi_closure) { generate_multi_closure(clin->link->parent, done, SVM_STACK_INVALID); } else { diff --git a/intern/cycles/render/svm.h b/intern/cycles/render/svm.h index dfd78cf3c40..4c23e931e09 100644 --- a/intern/cycles/render/svm.h +++ b/intern/cycles/render/svm.h @@ -53,7 +53,8 @@ public: class SVMCompiler { public: - SVMCompiler(ShaderManager *shader_manager, ImageManager *image_manager); + SVMCompiler(ShaderManager *shader_manager, ImageManager *image_manager, + bool use_multi_closure_); void compile(Shader *shader, vector<int4>& svm_nodes, int index); void stack_assign(ShaderOutput *output); @@ -123,6 +124,7 @@ protected: Stack active_stack; int max_stack_use; uint mix_weight_offset; + bool use_multi_closure; }; CCL_NAMESPACE_END diff --git a/intern/cycles/render/tile.cpp b/intern/cycles/render/tile.cpp index 450090c42f8..ba437e74874 100644 --- a/intern/cycles/render/tile.cpp +++ b/intern/cycles/render/tile.cpp @@ -22,7 +22,7 @@ CCL_NAMESPACE_BEGIN -TileManager::TileManager(bool progressive_, int passes_, int tile_size_, int min_size_) +TileManager::TileManager(bool progressive_, int samples_, int tile_size_, int min_size_) { progressive = progressive_; tile_size = tile_size_; @@ -35,7 +35,7 @@ TileManager::~TileManager() { } -void TileManager::reset(int width_, int height_, int passes_) +void TileManager::reset(int width_, int height_, int samples_) { full_width = width_; full_height = height_; @@ -53,18 +53,18 @@ void TileManager::reset(int width_, int height_, int passes_) } } - passes = passes_; + samples = samples_; state.width = 0; state.height = 0; - state.pass = -1; + state.sample = -1; state.resolution = start_resolution; state.tiles.clear(); } -void TileManager::set_passes(int passes_) +void TileManager::set_samples(int samples_) { - passes = passes_; + samples = samples_; } void TileManager::set_tiles() @@ -96,7 +96,7 @@ void TileManager::set_tiles() bool TileManager::done() { - return (state.pass+1 >= passes); + return (state.sample+1 >= samples && state.resolution == 1); } bool TileManager::next() @@ -105,12 +105,12 @@ bool TileManager::next() return false; if(progressive && state.resolution > 1) { - state.pass = 0; + state.sample = 0; state.resolution /= 2; set_tiles(); } else { - state.pass++; + state.sample++; state.resolution = 1; set_tiles(); } diff --git a/intern/cycles/render/tile.h b/intern/cycles/render/tile.h index 56c69cdce88..5cd16eb8afa 100644 --- a/intern/cycles/render/tile.h +++ b/intern/cycles/render/tile.h @@ -42,16 +42,16 @@ public: struct State { int width; int height; - int pass; + int sample; int resolution; list<Tile> tiles; } state; - TileManager(bool progressive, int passes, int tile_size, int min_size); + TileManager(bool progressive, int samples, int tile_size, int min_size); ~TileManager(); - void reset(int width, int height, int passes); - void set_passes(int passes); + void reset(int width, int height, int samples); + void set_samples(int samples); bool next(); bool done(); @@ -59,7 +59,7 @@ protected: void set_tiles(); bool progressive; - int passes; + int samples; int tile_size; int min_size; diff --git a/intern/cycles/util/util_progress.h b/intern/cycles/util/util_progress.h index c9e0a6ab713..fc2e4af5ead 100644 --- a/intern/cycles/util/util_progress.h +++ b/intern/cycles/util/util_progress.h @@ -35,9 +35,9 @@ class Progress { public: Progress() { - pass = 0; + sample = 0; total_time = 0.0f; - pass_time = 0.0f; + sample_time = 0.0f; status = "Initializing"; substatus = ""; update_cb = NULL; @@ -55,7 +55,7 @@ public: { thread_scoped_lock lock(progress.progress_mutex); - progress.get_pass(pass, total_time, pass_time); + progress.get_sample(sample, total_time, sample_time); progress.get_status(status, substatus); return *this; @@ -88,24 +88,24 @@ public: cancel_cb = function; } - /* pass and timing information */ + /* sample and timing information */ - void set_pass(int pass_, double total_time_, double pass_time_) + void set_sample(int sample_, double total_time_, double sample_time_) { thread_scoped_lock lock(progress_mutex); - pass = pass_; + sample = sample_; total_time = total_time_; - pass_time = pass_time_; + sample_time = sample_time_; } - void get_pass(int& pass_, double& total_time_, double& pass_time_) + void get_sample(int& sample_, double& total_time_, double& sample_time_) { thread_scoped_lock lock(progress_mutex); - pass_ = pass; + sample_ = sample; total_time_ = total_time; - pass_time_ = pass_time; + sample_time_ = sample_time; } /* status messages */ @@ -156,10 +156,10 @@ protected: boost::function<void(void)> update_cb; boost::function<void(void)> cancel_cb; - int pass; + int sample; double total_time; - double pass_time; + double sample_time; string status; string substatus; |