diff options
29 files changed, 1247 insertions, 9 deletions
diff --git a/intern/cycles/CMakeLists.txt b/intern/cycles/CMakeLists.txt index bfd29dcf606..ae38fbb2934 100644 --- a/intern/cycles/CMakeLists.txt +++ b/intern/cycles/CMakeLists.txt @@ -146,6 +146,13 @@ if(WITH_CYCLES_LOGGING) endif() endif() +if(WITH_LIBMV) + add_definitions(-DWITH_CYCLES_DISTORTION) + include_directories( + ../../extern/libmv + ) +endif() + include_directories( SYSTEM ${BOOST_INCLUDE_DIR} diff --git a/intern/cycles/SConscript b/intern/cycles/SConscript index a6c947bfca8..58685f599a5 100644 --- a/intern/cycles/SConscript +++ b/intern/cycles/SConscript @@ -59,6 +59,10 @@ if env['WITH_BF_CYCLES_OSL']: defs.append('OSL_STATIC_LIBRARY') incs.append(cycles['BF_OSL_INC']) +if env['WITH_BF_LIBMV']: + defs.append('WITH_CYCLES_DISTORTION') + incs.append('#extern/libmv') + incs.extend('. bvh render device kernel kernel/osl kernel/svm util subd'.split()) incs.extend('#intern/guardedalloc #source/blender/makesrna #source/blender/makesdna #source/blender/blenlib'.split()) incs.extend('#source/blender/blenloader ../../source/blender/makesrna/intern'.split()) diff --git a/intern/cycles/blender/CMakeLists.txt b/intern/cycles/blender/CMakeLists.txt index 13ac0be0562..0b1c161574a 100644 --- a/intern/cycles/blender/CMakeLists.txt +++ b/intern/cycles/blender/CMakeLists.txt @@ -21,6 +21,7 @@ set(INC_SYS set(SRC blender_camera.cpp + blender_camera_nodes.cpp blender_mesh.cpp blender_object.cpp blender_particles.cpp diff --git a/intern/cycles/blender/addon/__init__.py b/intern/cycles/blender/addon/__init__.py index 8c60ea31053..415f6e81be8 100644 --- a/intern/cycles/blender/addon/__init__.py +++ b/intern/cycles/blender/addon/__init__.py @@ -31,7 +31,6 @@ bl_info = { import bpy from . import engine -from . import version_update class CyclesRender(bpy.types.RenderEngine): @@ -90,28 +89,34 @@ class CyclesRender(bpy.types.RenderEngine): def register(): + from . import camera_nodes from . import ui from . import properties from . import presets + from . import version_update engine.init() properties.register() ui.register() presets.register() + camera_nodes.register() bpy.utils.register_module(__name__) bpy.app.handlers.version_update.append(version_update.do_versions) def unregister(): + from . import camera_nodes from . import ui from . import properties from . import presets + from . import version_update bpy.app.handlers.version_update.remove(version_update.do_versions) ui.unregister() properties.unregister() presets.unregister() + camera_nodes.unregister() bpy.utils.unregister_module(__name__) diff --git a/intern/cycles/blender/addon/camera_nodes.py b/intern/cycles/blender/addon/camera_nodes.py new file mode 100644 index 00000000000..76050fe7951 --- /dev/null +++ b/intern/cycles/blender/addon/camera_nodes.py @@ -0,0 +1,165 @@ +# +# Copyright 2011-2014 Blender Foundation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License +# + +# <pep8 compliant> + +import bpy +import nodeitems_utils +from bpy.types import NodeTree, Node, NodeSocket +from bpy.props import EnumProperty, FloatProperty +from nodeitems_utils import NodeCategory, NodeItem + + +class CameraRaysTree(NodeTree): + '''Camera rays node tree''' + bl_idname = 'CameraRaysTreeType' + bl_label = 'Camera Rays' + bl_icon = 'CAMERA_DATA' + + +class CameraRaysTreeNode: + @classmethod + def poll(cls, ntree): + return ntree.bl_idname == 'CameraRaysTreeType' + + +class PathAttributeNode(Node, CameraRaysTreeNode): + '''Path attribute input node''' + bl_idname = 'PathAttributeNodeType' + bl_label = 'Attribute' + + def init(self, context): + self.outputs.new('NodeSocketVector', "Raster") + self.outputs.new('NodeSocketVector', "Lens") + self.outputs.new('NodeSocketFloat', "Time") + + def draw_buttons(self, context, layout): + pass + + +class CameraSamplePerspectiveNode(Node, CameraRaysTreeNode): + '''Sample perspective camera ray''' + bl_idname = 'CameraSamplePerspectiveNodeType' + bl_label = 'Sample Perspective' + + def init(self, context): + self.inputs.new('NodeSocketVector', "Raster") + self.inputs.new('NodeSocketVector', "Lens") + self.inputs.new('NodeSocketFloat', "Time") + self.outputs.new('NodeSocketVector', "Ray Origin") + self.outputs.new('NodeSocketVector', "Ray Direction") + self.outputs.new('NodeSocketFloat', "Ray Length") + + def draw_buttons(self, context, layout): + pass + + +class CameraRayOutputNode(Node, CameraRaysTreeNode): + '''Camera ray output node''' + bl_idname = 'CameraRayOutputNodeType' + bl_label = 'Ray Output' + + def init(self, context): + self.inputs.new('NodeSocketVector', "Ray Origin") + self.inputs.new('NodeSocketVector', "Ray Direction") + self.inputs.new('NodeSocketFloat', "Ray Length") + self.inputs.new('NodeSocketFloat', "Time") + + def draw_buttons(self, context, layout): + pass + + +class PolynomialDistortionNode(Node, CameraRaysTreeNode): + '''Ray distortion node type''' + bl_idname = 'PolynomialDistortionNodeType' + bl_label = 'Polynomial Distortion' + + mode = EnumProperty(name="Mode", + description="Mode of the distortion", + items=(('APPLY', 'Apply', + "Apply the radial distortion on the input"), + ('INVERT', "Invert", + "Invert the radial distortion from the input")), + default='INVERT') + + k1 = FloatProperty(name="K1", + description="First coefficient of third " + "order polynomial radial distortion", + default=0.0) + + k2 = FloatProperty(name="K2", + description="Second coefficient of third " + "order polynomial radial distortion", + default=0.0) + + k3 = FloatProperty(name="K3", + description="Third coefficient of third " + "order polynomial radial distortion", + default=0.0) + + def init(self, context): + self.inputs.new('NodeSocketVector', "Raster") + self.outputs.new('NodeSocketVector', "Raster") + + def draw_buttons(self, context, layout): + col = layout.column() + col.prop(self, "mode", text="") + + col = layout.column(align=True) + col.prop(self, "k1") + col.prop(self, "k2") + col.prop(self, "k3") + + +class CameraRaysNodeCategory(NodeCategory): + @classmethod + def poll(cls, context): + return context.space_data.tree_type == 'CameraRaysTreeType' + +node_categories = [ + CameraRaysNodeCategory("INPUT", "Input", items=[ + NodeItem("PathAttributeNodeType"), + ]), + CameraRaysNodeCategory("OUTPUT", "Output", items=[ + NodeItem("CameraRayOutputNodeType"), + ]), + CameraRaysNodeCategory("SAMPLE", "Sample", items=[ + NodeItem("CameraSamplePerspectiveNodeType"), + ]), + CameraRaysNodeCategory("DISTORTION", "Distortion", items=[ + NodeItem("PolynomialDistortionNodeType"), + ]), + ] + + +def register(): + bpy.utils.register_class(CameraRaysTree) + bpy.utils.register_class(PathAttributeNode) + bpy.utils.register_class(CameraSamplePerspectiveNode) + bpy.utils.register_class(CameraRayOutputNode) + bpy.utils.register_class(PolynomialDistortionNode) + + nodeitems_utils.register_node_categories("CAMERA_NODES", node_categories) + + +def unregister(): + nodeitems_utils.unregister_node_categories("CAMERA_NODES") + + bpy.utils.unregister_class(CameraRaysTree) + bpy.utils.unregister_class(PathAttributeNode) + bpy.utils.unregister_class(CameraSamplePerspectiveNode) + bpy.utils.unregister_class(CameraRayOutputNode) + bpy.utils.unregister_class(PolynomialDistortionNode) diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py index 597ac1a9ce0..12c1cd820be 100644 --- a/intern/cycles/blender/addon/properties.py +++ b/intern/cycles/blender/addon/properties.py @@ -21,7 +21,8 @@ from bpy.props import (BoolProperty, EnumProperty, FloatProperty, IntProperty, - PointerProperty) + PointerProperty, + StringProperty) # enums @@ -577,6 +578,9 @@ class CyclesCameraSettings(bpy.types.PropertyGroup): min=0.01, soft_max=15.0, max=100.0, default=10.5, ) + cls.nodes = StringProperty( + name="nodes", + description="Camera ray nodes") @classmethod def unregister(cls): diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index 9632b12c414..b544c476c11 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -472,6 +472,24 @@ class CyclesCamera_PT_dof(CyclesButtonsPanel, Panel): sub.prop(ccam, "aperture_ratio", text="Ratio") +class CyclesCamera_PT_ray_nodes(CyclesButtonsPanel, Panel): + bl_label = "Ray Nodes" + bl_context = "data" + + @classmethod + def poll(cls, context): + return context.camera and CyclesButtonsPanel.poll(context) + + def draw(self, context): + layout = self.layout + + cam = context.camera + ccam = cam.cycles + + col = layout.column() + col.prop_search(ccam, "nodes", bpy.data, "node_groups", text="") + + class Cycles_PT_context_material(CyclesButtonsPanel, Panel): bl_label = "" bl_context = "material" diff --git a/intern/cycles/blender/blender_camera.cpp b/intern/cycles/blender/blender_camera.cpp index 016f6637b3c..d26317b6e32 100644 --- a/intern/cycles/blender/blender_camera.cpp +++ b/intern/cycles/blender/blender_camera.cpp @@ -283,6 +283,8 @@ static void blender_camera_sync(Camera *cam, BlenderCamera *bcam, int width, int { /* copy camera to compare later */ Camera prevcam = *cam; + prevcam.graph = NULL; + float aspectratio, sensor_size; /* viewplane */ @@ -318,6 +320,9 @@ static void blender_camera_sync(Camera *cam, BlenderCamera *bcam, int width, int cam->sensorheight = sensor_size; } } + else { + cam->sensorwidth = sensor_size; + } /* clipping distances */ cam->nearclip = bcam->nearclip; @@ -325,6 +330,7 @@ static void blender_camera_sync(Camera *cam, BlenderCamera *bcam, int width, int /* type */ cam->type = bcam->type; + cam->focal_length = bcam->lens; /* panorama */ cam->panorama_type = bcam->panorama_type; @@ -390,6 +396,7 @@ void BlenderSync::sync_camera(BL::RenderSettings b_render, BL::Object b_override /* sync */ Camera *cam = scene->camera; blender_camera_sync(cam, &bcam, width, height); + sync_camera_nodes(b_ob); scene->camera->use_camera_in_volume = experimental; } @@ -555,6 +562,7 @@ void BlenderSync::sync_view(BL::SpaceView3D b_v3d, BL::RegionView3D b_rv3d, int blender_camera_border(&bcam, b_scene.render(), b_scene, b_v3d, b_rv3d, width, height); blender_camera_sync(scene->camera, &bcam, width, height); + sync_view_nodes(b_rv3d); scene->camera->use_camera_in_volume = experimental; } diff --git a/intern/cycles/blender/blender_camera_nodes.cpp b/intern/cycles/blender/blender_camera_nodes.cpp new file mode 100644 index 00000000000..9595a511e47 --- /dev/null +++ b/intern/cycles/blender/blender_camera_nodes.cpp @@ -0,0 +1,267 @@ +/* + * Copyright 2011-2014 Blender Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +#include "camera.h" +#include "graph.h" +#include "nodes.h" +#include "camera_nodes.h" +#include "scene.h" + +#include "blender_sync.h" +#include "blender_util.h" + +CCL_NAMESPACE_BEGIN + +typedef map<void*, ShaderInput*> PtrInputMap; +typedef map<void*, ShaderOutput*> PtrOutputMap; + +static void set_default_value(ShaderInput *input, BL::Node b_node, BL::NodeSocket b_sock, BL::BlendData b_data, BL::ID b_id) +{ + /* copy values for non linked inputs */ + switch(input->type) { + case SHADER_SOCKET_FLOAT: { + input->set(get_float(b_sock.ptr, "default_value")); + break; + } + case SHADER_SOCKET_INT: { + input->set((float)get_int(b_sock.ptr, "default_value")); + break; + } + case SHADER_SOCKET_COLOR: { + input->set(float4_to_float3(get_float4(b_sock.ptr, "default_value"))); + break; + } + case SHADER_SOCKET_NORMAL: + case SHADER_SOCKET_POINT: + case SHADER_SOCKET_VECTOR: { + input->set(get_float3(b_sock.ptr, "default_value")); + break; + } + case SHADER_SOCKET_STRING: { + input->set((ustring)blender_absolute_path(b_data, b_id, get_string(b_sock.ptr, "default_value"))); + break; + } + + case SHADER_SOCKET_CLOSURE: + case SHADER_SOCKET_UNDEFINED: + break; + } +} + +static bool node_use_modified_socket_name(ShaderNode *node) +{ + if (node->special_type == SHADER_SPECIAL_TYPE_SCRIPT) + return false; + + return true; +} + +static ShaderInput *node_find_input_by_name(ShaderNode *node, BL::Node b_node, BL::NodeSocket b_socket) +{ + string name = b_socket.name(); + + if (node_use_modified_socket_name(node)) { + BL::Node::inputs_iterator b_input; + bool found = false; + int counter = 0, total = 0; + + for (b_node.inputs.begin(b_input); b_input != b_node.inputs.end(); ++b_input) { + if (b_input->name() == name) { + if (!found) + counter++; + total++; + } + + if(b_input->ptr.data == b_socket.ptr.data) + found = true; + } + + /* rename if needed */ + if (name == "Shader") + name = "Closure"; + + if (total > 1) + name = string_printf("%s%d", name.c_str(), counter); + } + + return node->input(name.c_str()); +} + +static ShaderOutput *node_find_output_by_name(ShaderNode *node, BL::Node b_node, BL::NodeSocket b_socket) +{ + string name = b_socket.name(); + + if (node_use_modified_socket_name(node)) { + BL::Node::outputs_iterator b_output; + bool found = false; + int counter = 0, total = 0; + + for (b_node.outputs.begin(b_output); b_output != b_node.outputs.end(); ++b_output) { + if (b_output->name() == name) { + if (!found) + counter++; + total++; + } + + if(b_output->ptr.data == b_socket.ptr.data) + found = true; + } + + /* rename if needed */ + if (name == "Shader") + name = "Closure"; + + if (total > 1) + name = string_printf("%s%d", name.c_str(), counter); + } + + return node->output(name.c_str()); +} + +static void add_nodes(BL::BlendData b_data, BL::NodeTree b_ntree, CameraNodesGraph *graph) +{ + PtrInputMap input_map; + PtrOutputMap output_map; + + /* Synchronize nodes themselves. */ + BL::NodeTree::nodes_iterator b_node; + for(b_ntree.nodes.begin(b_node); b_node != b_ntree.nodes.end(); ++b_node) { + ShaderNode *node = NULL; + string type = b_node->bl_idname(); + /* TODO(sergey): Support node groups. */ + if(type == "PathAttributeNodeType") { + node = new PathAttributeNode(); + } + else if(type == "CameraSamplePerspectiveNodeType") { + node = new SamplePerspectiveNode(); + } + else if(type == "PolynomialDistortionNodeType") { + PolynomialDistortionNode *distortion_node; + node = distortion_node = new PolynomialDistortionNode(); + + distortion_node->k1 = get_float(b_node->ptr, "k1"); + distortion_node->k2 = get_float(b_node->ptr, "k2"); + distortion_node->k3 = get_float(b_node->ptr, "k3"); + distortion_node->invert = get_enum(b_node->ptr, "mode") == 1; + } + else if(type == "CameraRayOutputNodeType") { + node = graph->output(); + } + else { + printf("Uknown camera node type: %s\n", type.c_str()); + /* Unknown node type, could happen when opening newer file in older + * blender or the node has been deprecated/removed. + */ + } + + if(node != NULL) { + if(node != graph->output()) + graph->add(node); + + /* Map node sockets for linking */ + BL::Node::inputs_iterator b_input; + for(b_node->inputs.begin(b_input); + b_input != b_node->inputs.end(); + ++b_input) + { + ShaderInput *input = node_find_input_by_name(node, + *b_node, + *b_input); + if(!input) { + /* XXX should not happen, report error? */ + continue; + } + input_map[b_input->ptr.data] = input; + + set_default_value(input, *b_node, *b_input, b_data, b_ntree); + } + + BL::Node::outputs_iterator b_output; + for(b_node->outputs.begin(b_output); + b_output != b_node->outputs.end(); + ++b_output) + { + ShaderOutput *output = node_find_output_by_name(node, + *b_node, + *b_output); + if(!output) { + /* XXX should not happen, report error? */ + continue; + } + output_map[b_output->ptr.data] = output; + } + + } + } + + /* Connect nodes with noodles. */ + BL::NodeTree::links_iterator b_link; + for(b_ntree.links.begin(b_link); b_link != b_ntree.links.end(); ++b_link) { + BL::NodeSocket b_from_sock = b_link->from_socket(); + BL::NodeSocket b_to_sock = b_link->to_socket(); + + ShaderOutput *output = 0; + ShaderInput *input = 0; + + PtrOutputMap::iterator output_it = output_map.find(b_from_sock.ptr.data); + if(output_it != output_map.end()) + output = output_it->second; + PtrInputMap::iterator input_it = input_map.find(b_to_sock.ptr.data); + if(input_it != input_map.end()) + input = input_it->second; + + /* Either node may be NULL when the node was not exported, typically + * because the node type is not supported */ + if(output && input) + graph->connect(output, input); + } +} + +void BlenderSync::sync_camera_nodes(BL::Object b_ob) +{ + if(!b_ob) { + return; + } + + BL::ID b_ob_data = b_ob.data(); + assert(b_ob_data.is_a(&RNA_Camera)); + + BL::Camera b_camera(b_ob_data); + PointerRNA ccamera = RNA_pointer_get(&b_ob_data.ptr, "cycles"); + string nodes_tree_name = get_string(ccamera, "nodes"); + + if(nodes_tree_name != "") { + BL::NodeTree b_ntree = b_data.node_groups[nodes_tree_name]; + if (b_ntree) { + progress.set_status("Synchronizing camera nodes", b_ntree.name()); + CameraNodesGraph *graph = new CameraNodesGraph(); + add_nodes(b_data, b_ntree, graph); + scene->camera->set_graph(graph); + progress.set_status(""); + } + } +} + +void BlenderSync::sync_view_nodes(BL::RegionView3D b_rv3d) +{ + if(b_rv3d.view_perspective() == + BL::RegionView3D::view_perspective_CAMERA) + { + sync_camera_nodes(b_scene.camera()); + } +} + +CCL_NAMESPACE_END diff --git a/intern/cycles/blender/blender_sync.h b/intern/cycles/blender/blender_sync.h index 9c4175ef690..bb8e9c31b1d 100644 --- a/intern/cycles/blender/blender_sync.h +++ b/intern/cycles/blender/blender_sync.h @@ -57,7 +57,9 @@ public: void sync_render_layers(BL::SpaceView3D b_v3d, const char *layer); void sync_integrator(); void sync_camera(BL::RenderSettings b_render, BL::Object b_override, int width, int height); + void sync_camera_nodes(BL::Object b_ob); void sync_view(BL::SpaceView3D b_v3d, BL::RegionView3D b_rv3d, int width, int height); + void sync_view_nodes(BL::RegionView3D b_rv3d); int get_layer_samples() { return render_layer.samples; } int get_layer_bound_samples() { return render_layer.bound_samples; } diff --git a/intern/cycles/kernel/kernel_camera.h b/intern/cycles/kernel/kernel_camera.h index 5c83358a56d..d1217ae0abc 100644 --- a/intern/cycles/kernel/kernel_camera.h +++ b/intern/cycles/kernel/kernel_camera.h @@ -16,6 +16,8 @@ CCL_NAMESPACE_BEGIN +ccl_device_noinline void svm_eval_camera_nodes(KernelGlobals *kg, CameraData *cd, ShaderType type); + /* Perspective Camera */ ccl_device float2 camera_sample_aperture(KernelGlobals *kg, float u, float v) @@ -239,6 +241,20 @@ ccl_device void camera_sample(KernelGlobals *kg, int x, int y, float filter_u, f ray->time = time; #endif +#ifdef __CAMERA_RAY_NODES__ + /* TODO(sergey): Add proper check for nodes tree here. */ + if(kernel_data.cam.shader != 0) { + CameraData cd; + cd.raster = make_float2(raster_x, raster_y); + cd.lens = make_float2(lens_u, lens_v); + cd.shader = kernel_data.cam.shader; + cd.ray = *ray; + svm_eval_camera_nodes(kg, &cd, SHADER_TYPE_CAMERA_RAY); + *ray = cd.ray; + return; + } +#endif + /* sample */ if(kernel_data.cam.type == CAMERA_PERSPECTIVE) camera_sample_perspective(kg, raster_x, raster_y, lens_u, lens_v, ray); diff --git a/intern/cycles/kernel/kernel_math.h b/intern/cycles/kernel/kernel_math.h index 97621db1cf3..d95a5c76309 100644 --- a/intern/cycles/kernel/kernel_math.h +++ b/intern/cycles/kernel/kernel_math.h @@ -20,6 +20,7 @@ #include "util_color.h" #include "util_math.h" #include "util_transform.h" +#include "util_distort.h" #endif /* __KERNEL_MATH_H__ */ diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h index 3e9e260794d..0ec34dae87a 100644 --- a/intern/cycles/kernel/kernel_types.h +++ b/intern/cycles/kernel/kernel_types.h @@ -69,6 +69,7 @@ CCL_NAMESPACE_BEGIN #define __VOLUME_DECOUPLED__ #define __VOLUME_SCATTER__ #define __SHADOW_RECORD_ALL__ +#define __CAMERA_RAY_NODES__ #endif #ifdef __KERNEL_CUDA__ @@ -785,7 +786,10 @@ typedef struct KernelCamera { float inv_aperture_ratio; int is_inside_volume; - int pad2; + int shader; + + float focal_length; + float pad[3]; /* more matrices */ Transform screentoworld; @@ -972,6 +976,13 @@ typedef struct KernelData { KernelTables tables; } KernelData; +typedef struct CameraData { + float2 raster; + float2 lens; + Ray ray; + int shader; +} CameraData; + CCL_NAMESPACE_END #endif /* __KERNEL_TYPES_H__ */ diff --git a/intern/cycles/kernel/svm/camera_nodes/svm_camera_distortion.h b/intern/cycles/kernel/svm/camera_nodes/svm_camera_distortion.h new file mode 100644 index 00000000000..f64d2362cd9 --- /dev/null +++ b/intern/cycles/kernel/svm/camera_nodes/svm_camera_distortion.h @@ -0,0 +1,62 @@ +/* + * Copyright 2011-2013 Blender Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +CCL_NAMESPACE_BEGIN + +/* Polynomial distortion */ + +ccl_device void svm_node_camera_polynomial_distortion(KernelGlobals *kg, + CameraData *cd, + uint4 node, + float *stack, + int *offset) +{ + /* Read extra data. */ + uint4 node1 = read_node(kg, offset); + const float k1 = __int_as_float(node.y); + const float k2 = __int_as_float(node.z); + const float k3 = __int_as_float(node.w); + const int invert = __float_as_int(node1.y); + const int raster_in_offset = node1.z; + const int raster_out_offset =node1.w; + const float focal_length = kernel_data.cam.focal_length * + kernel_data.cam.width / kernel_data.cam.sensorwidth; + + float2 raster_in, raster_out; + raster_in = stack_load_float2(stack, raster_in_offset); + + float2 principal_point = make_float2(kernel_data.cam.width * 0.5f, + kernel_data.cam.height * 0.5f); + + if(invert) { + util_invert_polynomial_distortion(raster_in, + focal_length, + principal_point, + k1, k2, k3, + &raster_out); + } + else { + util_apply_polynomial_distortion(raster_in, + focal_length, + principal_point, + k1, k2, k3, + &raster_out); + } + + stack_store_float2(stack, raster_out_offset, raster_out); +} + +CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/svm/camera_nodes/svm_camera_path_attribute.h b/intern/cycles/kernel/svm/camera_nodes/svm_camera_path_attribute.h new file mode 100644 index 00000000000..549a82b5143 --- /dev/null +++ b/intern/cycles/kernel/svm/camera_nodes/svm_camera_path_attribute.h @@ -0,0 +1,41 @@ +/* + * Copyright 2011-2014 Blender Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +CCL_NAMESPACE_BEGIN + +/* Path attribute node */ + +ccl_device void svm_camera_node_path_attribute(KernelGlobals *kg, + CameraData *cd, + float *stack, + uint type, + uint out_offset) +{ + switch(type) { + case NODE_CAMERA_PATH_ATTRIBUTE_RASTER: + stack_store_float2(stack, out_offset, cd->raster); + break; + case NODE_CAMERA_PATH_ATTRIBUTE_LENS: + stack_store_float2(stack, out_offset, cd->lens); + break; + case NODE_CAMERA_PATH_ATTRIBUTE_TIME: + stack_store_float(stack, out_offset, cd->ray.time); + break; + } + +} + +CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/svm/camera_nodes/svm_camera_ray_output.h b/intern/cycles/kernel/svm/camera_nodes/svm_camera_ray_output.h new file mode 100644 index 00000000000..92828701d39 --- /dev/null +++ b/intern/cycles/kernel/svm/camera_nodes/svm_camera_ray_output.h @@ -0,0 +1,41 @@ +/* + * Copyright 2011-2014 Blender Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +CCL_NAMESPACE_BEGIN + +/* Ray output node */ + +ccl_device void svm_camera_node_ray_output(KernelGlobals *kg, + CameraData *cd, + float *stack, + uint4 node) +{ + uint ray_origin_offset, ray_direction_offset, ray_length_offset; + uint time_offset; + + decode_node_uchar4(node.y, + &ray_origin_offset, + &ray_direction_offset, + &ray_length_offset, + &time_offset); + + cd->ray.P = stack_load_float3(stack, ray_origin_offset); + cd->ray.D = stack_load_float3(stack, ray_direction_offset); + cd->ray.t = stack_load_float(stack, ray_length_offset); + cd->ray.time = stack_load_float(stack, time_offset); +} + +CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/svm/camera_nodes/svm_camera_sample_perspective.h b/intern/cycles/kernel/svm/camera_nodes/svm_camera_sample_perspective.h new file mode 100644 index 00000000000..8b1f884aa85 --- /dev/null +++ b/intern/cycles/kernel/svm/camera_nodes/svm_camera_sample_perspective.h @@ -0,0 +1,59 @@ +/* + * Copyright 2011-2014 Blender Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +CCL_NAMESPACE_BEGIN + +/* Sample perspective node */ + +ccl_device void svm_camera_node_sample_perspective(KernelGlobals *kg, + CameraData *cd, + float *stack, + uint4 node) +{ + uint raster_offset, lens_offset, time_offset; + decode_node_uchar4(node.y, &raster_offset, &lens_offset, &time_offset, NULL); + + /* TODO(sergey): Make sure unconnected sockets are fine here. */ + float2 raster = stack_load_float2(stack, raster_offset); + float2 lens = stack_load_float2(stack, lens_offset); + Ray ray; + if(stack_valid(time_offset)) { + ray.time = stack_load_float(stack, time_offset); + } + else { + ray.time = TIME_INVALID; + } + camera_sample_perspective(kg, raster.x, raster.y, lens.x, lens.y, &ray); + + uint ray_origin_offset, ray_direction_offset, ray_length_offset; + decode_node_uchar4(node.z, + &ray_origin_offset, + &ray_direction_offset, + &ray_length_offset, + NULL); + + if(stack_valid(ray_origin_offset)) { + stack_store_float3(stack, ray_origin_offset, ray.P); + } + if(stack_valid(ray_direction_offset)) { + stack_store_float3(stack, ray_direction_offset, ray.D); + } + if(stack_valid(ray_length_offset)) { + stack_store_float(stack, ray_length_offset, ray.t); + } +} + +CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/svm/svm.h b/intern/cycles/kernel/svm/svm.h index c13eae813d6..efbffacf375 100644 --- a/intern/cycles/kernel/svm/svm.h +++ b/intern/cycles/kernel/svm/svm.h @@ -61,6 +61,21 @@ ccl_device_inline void stack_store_float3(float *stack, uint a, float3 f) stack[a+2] = f.z; } +ccl_device_inline float2 stack_load_float2(float *stack, uint a) +{ + kernel_assert(a+1 < SVM_STACK_SIZE); + + return make_float2(stack[a+0], stack[a+1]); +} + +ccl_device_inline void stack_store_float2(float *stack, uint a, float2 f) +{ + kernel_assert(a+1 < SVM_STACK_SIZE); + + stack[a+0] = f.x; + stack[a+1] = f.y; +} + ccl_device_inline float stack_load_float(float *stack, uint a) { kernel_assert(a < SVM_STACK_SIZE); @@ -424,7 +439,7 @@ ccl_device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, Shade break; case NODE_NORMAL_MAP: svm_node_normal_map(kg, sd, stack, node); - break; + break; case NODE_END: default: return; @@ -434,5 +449,60 @@ ccl_device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, Shade CCL_NAMESPACE_END -#endif /* __SVM_H__ */ +#ifdef __CAMERA_RAY_NODES__ +# include "camera_nodes/svm_camera_distortion.h" +# include "camera_nodes/svm_camera_path_attribute.h" +# include "camera_nodes/svm_camera_ray_output.h" +# include "camera_nodes/svm_camera_sample_perspective.h" + +CCL_NAMESPACE_BEGIN + +ccl_device_noinline void svm_eval_camera_nodes(KernelGlobals *kg, + CameraData *cd, + ShaderType type) +{ + float stack[SVM_STACK_SIZE]; + int offset = cd->shader & SHADER_MASK; + + kernel_assert(type == SHADER_TYPE_CAMERA_RAY); + + while(1) { + uint4 node = read_node(kg, &offset); + + switch(node.x) { + case NODE_SHADER_JUMP: { + if(type == SHADER_TYPE_CAMERA_RAY) offset = node.y; + else return; + break; + } + case NODE_CAMERA_PATH_ATTRIBUTE: + svm_camera_node_path_attribute(kg, cd, stack, node.y, node.z); + break; + case NODE_CAMERA_SAMPLE_PERSPECTIVE: + svm_camera_node_sample_perspective(kg, cd, stack, node); + break; + case NODE_CAMERA_RAY_OUTPUT: + svm_camera_node_ray_output(kg, cd, stack, node); + break; + case NODE_CAMERA_POLYNOMIAL_DISTORTION: + svm_node_camera_polynomial_distortion(kg, cd, node, + stack, &offset); + break; + case NODE_VALUE_F: + svm_node_value_f(kg, NULL, stack, node.y, node.z); + break; + case NODE_VALUE_V: + svm_node_value_v(kg, NULL, stack, node.y, &offset); + break; + case NODE_END: + default: + return; + } + } +} +CCL_NAMESPACE_END + +#endif + +#endif /* __SVM_H__ */ diff --git a/intern/cycles/kernel/svm/svm_types.h b/intern/cycles/kernel/svm/svm_types.h index 103f562ed60..cd38ce4ba9b 100644 --- a/intern/cycles/kernel/svm/svm_types.h +++ b/intern/cycles/kernel/svm/svm_types.h @@ -102,7 +102,13 @@ typedef enum NodeType { NODE_TANGENT, NODE_NORMAL_MAP, NODE_HAIR_INFO, - NODE_UVMAP + NODE_UVMAP, + + /* Camera ray nodes. */ + NODE_CAMERA_PATH_ATTRIBUTE, + NODE_CAMERA_SAMPLE_PERSPECTIVE, + NODE_CAMERA_RAY_OUTPUT, + NODE_CAMERA_POLYNOMIAL_DISTORTION, } NodeType; typedef enum NodeAttributeType { @@ -337,7 +343,8 @@ typedef enum NodeNormalMapSpace { typedef enum ShaderType { SHADER_TYPE_SURFACE, SHADER_TYPE_VOLUME, - SHADER_TYPE_DISPLACEMENT + SHADER_TYPE_DISPLACEMENT, + SHADER_TYPE_CAMERA_RAY, } ShaderType; /* Closure */ @@ -400,6 +407,12 @@ typedef enum ClosureType { NBUILTIN_CLOSURES } ClosureType; +typedef enum NodePathAttribute { + NODE_CAMERA_PATH_ATTRIBUTE_RASTER, + NODE_CAMERA_PATH_ATTRIBUTE_LENS, + NODE_CAMERA_PATH_ATTRIBUTE_TIME, +} NodePathAttribute; + /* watch this, being lazy with memory usage */ #define CLOSURE_IS_BSDF(type) (type <= CLOSURE_BSDF_TRANSPARENT_ID) #define CLOSURE_IS_BSDF_DIFFUSE(type) (type >= CLOSURE_BSDF_DIFFUSE_ID && type <= CLOSURE_BSDF_DIFFUSE_TOON_ID) diff --git a/intern/cycles/render/CMakeLists.txt b/intern/cycles/render/CMakeLists.txt index 449c1391980..e4f847a783a 100644 --- a/intern/cycles/render/CMakeLists.txt +++ b/intern/cycles/render/CMakeLists.txt @@ -20,6 +20,7 @@ set(SRC blackbody.cpp buffers.cpp camera.cpp + camera_nodes.cpp film.cpp graph.cpp image.cpp @@ -49,6 +50,7 @@ set(SRC_HEADERS blackbody.h buffers.h camera.h + camera_nodes.h film.h graph.h image.h diff --git a/intern/cycles/render/camera.cpp b/intern/cycles/render/camera.cpp index 4c73726ba33..71442d490ee 100644 --- a/intern/cycles/render/camera.cpp +++ b/intern/cycles/render/camera.cpp @@ -15,7 +15,9 @@ */ #include "camera.h" +#include "graph.h" #include "mesh.h" +#include "nodes.h" #include "object.h" #include "scene.h" @@ -103,10 +105,13 @@ Camera::Camera() need_update = true; need_device_update = true; previous_need_motion = -1; + + graph = NULL; } Camera::~Camera() { + delete graph; } void Camera::compute_auto_viewplane() @@ -297,6 +302,9 @@ void Camera::device_update(Device *device, DeviceScene *dscene, Scene *scene) kcam->nearclip = nearclip; kcam->cliplength = (farclip == FLT_MAX)? FLT_MAX: farclip - nearclip; + /* focal length */ + kcam->focal_length = focal_length; + need_device_update = false; previous_need_motion = need_motion; @@ -333,6 +341,14 @@ void Camera::device_update(Device *device, DeviceScene *dscene, Scene *scene) } } } + + /* TODO(sergey): Make sure shaders are fully synced at this point. */ + if(graph != NULL) { + kcam->shader = scene->shader_manager->get_shader_id(scene->shaders.size()); + } + else { + kcam->shader = 0; + } } void Camera::device_free(Device *device, DeviceScene *dscene) @@ -349,6 +365,7 @@ bool Camera::modified(const Camera& cam) (focaldistance == cam.focaldistance) && (type == cam.type) && (fov == cam.fov) && + (focal_length == cam.focal_length) && (nearclip == cam.nearclip) && (farclip == cam.farclip) && (sensorwidth == cam.sensorwidth) && @@ -427,5 +444,14 @@ BoundBox Camera::viewplane_bounds_get() return bounds; } -CCL_NAMESPACE_END +void Camera::set_graph(CameraNodesGraph *graph_) +{ + if(graph_) { + graph_->remove_unneeded_nodes(); + } + delete graph; + graph = graph_; +} + +CCL_NAMESPACE_END diff --git a/intern/cycles/render/camera.h b/intern/cycles/render/camera.h index 3054137309d..ff93420bccc 100644 --- a/intern/cycles/render/camera.h +++ b/intern/cycles/render/camera.h @@ -28,6 +28,7 @@ CCL_NAMESPACE_BEGIN class Device; class DeviceScene; class Scene; +class CameraNodesGraph; /* Camera * @@ -48,6 +49,7 @@ public: /* type */ CameraType type; float fov; + float focal_length; /* panorama */ PanoramaType panorama_type; @@ -109,6 +111,9 @@ public: */ bool use_camera_in_volume; + /* Camera ray nodes. */ + CameraNodesGraph *graph; + /* functions */ Camera(); ~Camera(); @@ -126,6 +131,8 @@ public: BoundBox viewplane_bounds_get(); float3 transform_raster_to_world(float raster_x, float raster_y); + + void set_graph(CameraNodesGraph *graph); }; CCL_NAMESPACE_END diff --git a/intern/cycles/render/camera_nodes.cpp b/intern/cycles/render/camera_nodes.cpp new file mode 100644 index 00000000000..348ae49a93b --- /dev/null +++ b/intern/cycles/render/camera_nodes.cpp @@ -0,0 +1,187 @@ +/* + * Copyright 2011-2014 Blender Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +#include "nodes.h" +#include "camera_nodes.h" +#include "svm.h" +#include "osl.h" + +CCL_NAMESPACE_BEGIN + +/* Path attribute */ + +PathAttributeNode::PathAttributeNode() +: ShaderNode("path_attribute") +{ + add_output("Raster", SHADER_SOCKET_VECTOR); + add_output("Lens", SHADER_SOCKET_VECTOR); + add_output("Time", SHADER_SOCKET_FLOAT); +} + +void PathAttributeNode::compile(SVMCompiler& compiler) +{ + ShaderOutput *out; + + out = output("Raster"); + if(!out->links.empty()) { + compiler.stack_assign(out); + compiler.add_node(NODE_CAMERA_PATH_ATTRIBUTE, + NODE_CAMERA_PATH_ATTRIBUTE_RASTER, + out->stack_offset); + } + + out = output("Lens"); + if(!out->links.empty()) { + compiler.stack_assign(out); + compiler.add_node(NODE_CAMERA_PATH_ATTRIBUTE, + NODE_CAMERA_PATH_ATTRIBUTE_LENS, + out->stack_offset); + } + + out = output("Time"); + if(!out->links.empty()) { + compiler.stack_assign(out); + compiler.add_node(NODE_CAMERA_PATH_ATTRIBUTE, + NODE_CAMERA_PATH_ATTRIBUTE_TIME, + out->stack_offset); + } +} + +void PathAttributeNode::compile(OSLCompiler& compiler) +{ +} + +/* Sample perspective */ + +SamplePerspectiveNode::SamplePerspectiveNode() +: ShaderNode("sample_perspective") +{ + add_input("Raster", SHADER_SOCKET_VECTOR); + add_input("Lens", SHADER_SOCKET_VECTOR); + add_input("Time", SHADER_SOCKET_FLOAT); + add_output("Ray Origin", SHADER_SOCKET_VECTOR); + add_output("Ray Direction", SHADER_SOCKET_VECTOR); + add_output("Ray Length", SHADER_SOCKET_FLOAT); +} + +void SamplePerspectiveNode::compile(SVMCompiler& compiler) +{ + ShaderInput *raster_in = input("Raster"); + ShaderInput *lens_in = input("Lens"); + ShaderInput *time_in = input("Time"); + ShaderOutput *ray_origin_out = output("Ray Origin"); + ShaderOutput *ray_direction_out = output("Ray Direction"); + ShaderOutput *ray_length_out = output("Ray Length"); + + if(raster_in->link) { + compiler.stack_assign(raster_in); + } + if(lens_in->link) { + compiler.stack_assign(lens_in); + } + if(time_in->link) { + compiler.stack_assign(time_in); + } + if(!ray_origin_out->links.empty()) { + compiler.stack_assign(ray_origin_out); + } + if(!ray_direction_out->links.empty()) { + compiler.stack_assign(ray_direction_out); + } + if(!ray_length_out->links.empty()) { + compiler.stack_assign(ray_length_out); + } + + compiler.add_node(NODE_CAMERA_SAMPLE_PERSPECTIVE, + compiler.encode_uchar4(raster_in->stack_offset, + lens_in->stack_offset, + time_in->stack_offset, 0), + compiler.encode_uchar4(ray_origin_out->stack_offset, + ray_direction_out->stack_offset, + ray_length_out->stack_offset, + 0)); +} + +void SamplePerspectiveNode::compile(OSLCompiler& compiler) +{ +} + +/* Polynomial distortion node. */ + +PolynomialDistortionNode::PolynomialDistortionNode() + : ShaderNode("polynomial_distortion"), + k1(0.0f), k2(0.0f), k3(0.0f), + invert(false) +{ + add_input("Raster", SHADER_SOCKET_VECTOR); + add_output("Raster", SHADER_SOCKET_VECTOR); +} + +void PolynomialDistortionNode::compile(SVMCompiler& compiler) +{ + ShaderInput *raster_in = input("Raster"); + ShaderOutput *raster_out = output("Raster"); + + compiler.stack_assign(raster_in); + compiler.stack_assign(raster_out); + + float3 encoded_distortion = make_float3(k1, k2, k3); + compiler.add_node(NODE_CAMERA_POLYNOMIAL_DISTORTION, encoded_distortion); + compiler.add_node(NODE_CAMERA_POLYNOMIAL_DISTORTION, + (int)invert, + raster_in->stack_offset, + raster_out->stack_offset); +} + +void PolynomialDistortionNode::compile(OSLCompiler& compiler) +{ +} + +/* Camera Ray Output */ + +RayOutputNode::RayOutputNode() +: ShaderNode("ray_output") +{ + add_input("Ray Origin", SHADER_SOCKET_VECTOR); + add_input("Ray Direction", SHADER_SOCKET_VECTOR); + add_input("Ray Length", SHADER_SOCKET_FLOAT); + add_input("Time", SHADER_SOCKET_FLOAT); +} + +void RayOutputNode::compile(SVMCompiler& compiler) +{ + ShaderInput *ray_origin_in = input("Ray Origin"); + ShaderInput *ray_direction_in = input("Ray Direction"); + ShaderInput *ray_length_in = input("Ray Length"); + ShaderInput *time_in = input("Time"); + + compiler.stack_assign(ray_origin_in); + compiler.stack_assign(ray_direction_in); + compiler.stack_assign(ray_length_in); + compiler.stack_assign(time_in); + + compiler.add_node(NODE_CAMERA_RAY_OUTPUT, + compiler.encode_uchar4(ray_origin_in->stack_offset, + ray_direction_in->stack_offset, + ray_length_in->stack_offset, + time_in->stack_offset)); +} + +void RayOutputNode::compile(OSLCompiler& compiler) +{ +} + +CCL_NAMESPACE_END diff --git a/intern/cycles/render/camera_nodes.h b/intern/cycles/render/camera_nodes.h new file mode 100644 index 00000000000..c473826cdf3 --- /dev/null +++ b/intern/cycles/render/camera_nodes.h @@ -0,0 +1,49 @@ +/* + * Copyright 2011-2014 Blender Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +#ifndef __CAMERA_NODES_H__ +#define __CAMERA_NODES_H__ + +CCL_NAMESPACE_BEGIN + +/* TODO(sergey): Add a petter suitable name. */ +class PathAttributeNode : public ShaderNode { +public: + SHADER_NODE_CLASS(PathAttributeNode) +}; + +class SamplePerspectiveNode : public ShaderNode { +public: + SHADER_NODE_CLASS(SamplePerspectiveNode) +}; + +class PolynomialDistortionNode : public ShaderNode { +public: + SHADER_NODE_CLASS(PolynomialDistortionNode) + + /* Third order polynomial distortion coefficients. */ + float k1, k2, k3; + bool invert; +}; + +class RayOutputNode : public ShaderNode { +public: + SHADER_NODE_CLASS(RayOutputNode) +}; + +CCL_NAMESPACE_END + +#endif /* __CAMERA_NODES_H__ */ diff --git a/intern/cycles/render/graph.cpp b/intern/cycles/render/graph.cpp index 45b08832fea..d6c6d019b03 100644 --- a/intern/cycles/render/graph.cpp +++ b/intern/cycles/render/graph.cpp @@ -17,6 +17,7 @@ #include "attribute.h" #include "graph.h" #include "nodes.h" +#include "camera_nodes.h" #include "shader.h" #include "util_algorithm.h" @@ -877,5 +878,27 @@ void ShaderGraph::dump_graph(const char *filename) fclose(fd); } +/* CameraNodesGraph */ + +CameraNodesGraph::CameraNodesGraph() +{ + finalized = false; + num_node_ids = 0; + + /* TODO(sergey): Ideally we just don't want parent constructor + * to be called from this class. + */ + foreach(ShaderNode *node, nodes) + delete node; + nodes.clear(); + + add(new RayOutputNode()); +} + +RayOutputNode *CameraNodesGraph::output() +{ + return (RayOutputNode*)nodes.front(); +} + CCL_NAMESPACE_END diff --git a/intern/cycles/render/graph.h b/intern/cycles/render/graph.h index 7b95703d3aa..29fa1403597 100644 --- a/intern/cycles/render/graph.h +++ b/intern/cycles/render/graph.h @@ -37,6 +37,7 @@ class ShaderGraph; class SVMCompiler; class OSLCompiler; class OutputNode; +class RayOutputNode; /* Socket Type * @@ -266,6 +267,13 @@ protected: void transform_multi_closure(ShaderNode *node, ShaderOutput *weight_out, bool volume); }; +/* Graph of camera ray nodes. */ +class CameraNodesGraph : public ShaderGraph { +public: + CameraNodesGraph(); + RayOutputNode *output(); +}; + CCL_NAMESPACE_END #endif /* __GRAPH_H__ */ diff --git a/intern/cycles/render/svm.cpp b/intern/cycles/render/svm.cpp index 13c63d9420c..204c8fa2ce7 100644 --- a/intern/cycles/render/svm.cpp +++ b/intern/cycles/render/svm.cpp @@ -14,11 +14,13 @@ * limitations under the License */ +#include "camera.h" #include "device.h" #include "graph.h" #include "light.h" #include "mesh.h" #include "nodes.h" +#include "camera_nodes.h" #include "scene.h" #include "shader.h" #include "svm.h" @@ -62,7 +64,12 @@ void SVMShaderManager::device_update(Device *device, DeviceScene *dscene, Scene svm_nodes.push_back(make_int4(NODE_SHADER_JUMP, 0, 0, 0)); svm_nodes.push_back(make_int4(NODE_SHADER_JUMP, 0, 0, 0)); } - + + if(scene->camera->graph != NULL) { + svm_nodes.push_back(make_int4(NODE_SHADER_JUMP, 0, 0, 0)); + svm_nodes.push_back(make_int4(NODE_SHADER_JUMP, 0, 0, 0)); + } + for(i = 0; i < scene->shaders.size(); i++) { Shader *shader = scene->shaders[i]; @@ -78,6 +85,12 @@ void SVMShaderManager::device_update(Device *device, DeviceScene *dscene, Scene compiler.compile(shader, svm_nodes, i); } + if(scene->camera->graph != NULL) { + SVMCompiler compiler(scene->shader_manager, scene->image_manager); + compiler.background = false; + compiler.compile(scene->camera, svm_nodes, scene->shaders.size()); + } + dscene->svm_nodes.copy((uint4*)&svm_nodes[0], svm_nodes.size()); device->tex_alloc("__svm_nodes", dscene->svm_nodes); @@ -688,6 +701,36 @@ void SVMCompiler::compile_type(Shader *shader, ShaderGraph *graph, ShaderType ty add_node(NODE_END, 0, 0, 0); } +void SVMCompiler::compile_type(Camera *camera, + CameraNodesGraph *graph) +{ + current_type = SHADER_TYPE_CAMERA_RAY; + current_graph = graph; + + /* Clear all compiler state. */ + memset(&active_stack, 0, sizeof(active_stack)); + svm_nodes.clear(); + + foreach(ShaderNode *node_iter, graph->nodes) { + foreach(ShaderInput *input, node_iter->inputs) + input->stack_offset = SVM_STACK_INVALID; + foreach(ShaderOutput *output, node_iter->outputs) + output->stack_offset = SVM_STACK_INVALID; + } + + RayOutputNode *node = graph->output(); + set<ShaderNode*> done, closure_done; + generate_multi_closure(node, node, done, closure_done); + + /* If compile failed, generate empty shader. */ + if(compile_failed) { + svm_nodes.clear(); + compile_failed = false; + } + + add_node(NODE_END, 0, 0, 0); +} + void SVMCompiler::compile(Shader *shader, vector<int4>& global_svm_nodes, int index) { /* copy graph for shader with bump mapping */ @@ -739,5 +782,22 @@ void SVMCompiler::compile(Shader *shader, vector<int4>& global_svm_nodes, int in global_svm_nodes.insert(global_svm_nodes.end(), svm_nodes.begin(), svm_nodes.end()); } +void SVMCompiler::compile(Camera *camera, + vector<int4>& global_svm_nodes, + int index) +{ + /* Finalize the graph. */ + /* TODO(sergey): Finalization is currently working for shader nodes only. */ + /* camera->graph->finalize(false, false); */ + + /* Generate camera nodes to SVM nodes. */ + compile_type(camera, camera->graph); + global_svm_nodes[index*2 + 0].y = global_svm_nodes.size(); + global_svm_nodes[index*2 + 1].y = global_svm_nodes.size(); + global_svm_nodes.insert(global_svm_nodes.end(), + svm_nodes.begin(), + svm_nodes.end()); +} + CCL_NAMESPACE_END diff --git a/intern/cycles/render/svm.h b/intern/cycles/render/svm.h index c1dd96e4d80..4a666bade55 100644 --- a/intern/cycles/render/svm.h +++ b/intern/cycles/render/svm.h @@ -26,6 +26,8 @@ CCL_NAMESPACE_BEGIN +class Camera; +class CameraNodesGraph; class Device; class DeviceScene; class ImageManager; @@ -54,6 +56,7 @@ class SVMCompiler { public: SVMCompiler(ShaderManager *shader_manager, ImageManager *image_manager); void compile(Shader *shader, vector<int4>& svm_nodes, int index); + void compile(Camera *camera, vector<int4>& svm_nodes, int index); void stack_assign(ShaderOutput *output); void stack_assign(ShaderInput *input); @@ -141,6 +144,7 @@ protected: /* compile */ void compile_type(Shader *shader, ShaderGraph *graph, ShaderType type); + void compile_type(Camera *camera, CameraNodesGraph *graph); vector<int4> svm_nodes; ShaderType current_type; diff --git a/intern/cycles/util/util_distort.h b/intern/cycles/util/util_distort.h new file mode 100644 index 00000000000..6f8d4f259ff --- /dev/null +++ b/intern/cycles/util/util_distort.h @@ -0,0 +1,77 @@ +/* + * Copyright 2011-2014 Blender Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +#ifndef __UTIL_DISTORT_H__ +#define __UTIL_DISTORT_H__ + +#ifdef WITH_CYCLES_DISTORTION +# include "libmv/simple_pipeline/distortion_models.h" +#endif + +CCL_NAMESPACE_BEGIN + +ccl_device void util_apply_polynomial_distortion(const float2 image, + const float focal_length, + const float2 principal_point, + const float k1, + const float k2, + const float k3, + float2 *result) +{ +#if defined(WITH_CYCLES_DISTORTION) && !defined(__KERNEL_GPU__) + double normalized_x = (image.x - principal_point.x) / focal_length; + double normalized_y = (image.y - principal_point.y) / focal_length; + double image_x, image_y; + libmv::InvertPolynomialDistortionModel(focal_length, focal_length, + normalized_x, normalized_y, + k1, k2, k3, + 0.0, 0.0, + image.x, image.y, + &image_x, &image_y); + result->x = image_x; + result->y = image_y; +#else + *result = image; +#endif +} + +ccl_device void util_invert_polynomial_distortion(const float2 image, + const float focal_length, + const float2 principal_point, + const float k1, + const float k2, + const float k3, + float2 *result) +{ +#if defined(WITH_CYCLES_DISTORTION) && !defined(__KERNEL_GPU__) + double normalized_x, normalized_y; + libmv::InvertPolynomialDistortionModel(focal_length, focal_length, + principal_point.x, principal_point.y, + k1, k2, k3, + 0.0, 0.0, + image.x, image.y, + &normalized_x, + &normalized_y); + result->x = normalized_x * focal_length + principal_point.x; + result->y = normalized_y * focal_length + principal_point.y; +#else + *result = image; +#endif +} + +CCL_NAMESPACE_END + +#endif /* __UTIL_DISTORT_H__ */ |