Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--intern/cycles/CMakeLists.txt7
-rw-r--r--intern/cycles/SConscript4
-rw-r--r--intern/cycles/blender/CMakeLists.txt1
-rw-r--r--intern/cycles/blender/addon/__init__.py7
-rw-r--r--intern/cycles/blender/addon/camera_nodes.py165
-rw-r--r--intern/cycles/blender/addon/properties.py6
-rw-r--r--intern/cycles/blender/addon/ui.py18
-rw-r--r--intern/cycles/blender/blender_camera.cpp8
-rw-r--r--intern/cycles/blender/blender_camera_nodes.cpp267
-rw-r--r--intern/cycles/blender/blender_sync.h2
-rw-r--r--intern/cycles/kernel/kernel_camera.h16
-rw-r--r--intern/cycles/kernel/kernel_math.h1
-rw-r--r--intern/cycles/kernel/kernel_types.h13
-rw-r--r--intern/cycles/kernel/svm/camera_nodes/svm_camera_distortion.h62
-rw-r--r--intern/cycles/kernel/svm/camera_nodes/svm_camera_path_attribute.h41
-rw-r--r--intern/cycles/kernel/svm/camera_nodes/svm_camera_ray_output.h41
-rw-r--r--intern/cycles/kernel/svm/camera_nodes/svm_camera_sample_perspective.h59
-rw-r--r--intern/cycles/kernel/svm/svm.h74
-rw-r--r--intern/cycles/kernel/svm/svm_types.h17
-rw-r--r--intern/cycles/render/CMakeLists.txt2
-rw-r--r--intern/cycles/render/camera.cpp28
-rw-r--r--intern/cycles/render/camera.h7
-rw-r--r--intern/cycles/render/camera_nodes.cpp187
-rw-r--r--intern/cycles/render/camera_nodes.h49
-rw-r--r--intern/cycles/render/graph.cpp23
-rw-r--r--intern/cycles/render/graph.h8
-rw-r--r--intern/cycles/render/svm.cpp62
-rw-r--r--intern/cycles/render/svm.h4
-rw-r--r--intern/cycles/util/util_distort.h77
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__ */