1
1

Compare commits

...

4 Commits

Author SHA1 Message Date
Dalai Felinto
27b3ea622f Merge remote-tracking branch 'origin/master' into cycles_camera_nodes
Note: the branch currently crashes in blender_camera_nodes.cpp:
BL::NodeTree b_ntree = b_data.node_groups[nodes_tree_name];

The crash was introduced in:
cb7cf523e5

Conflicts:
	intern/cycles/SConscript
	intern/cycles/blender/addon/__init__.py
	intern/cycles/blender/addon/properties.py
	intern/cycles/blender/blender_camera.cpp
	intern/cycles/kernel/kernel_types.h
	intern/cycles/kernel/svm/svm.h
	intern/cycles/kernel/svm/svm_types.h
	intern/cycles/render/camera.cpp
	intern/cycles/render/camera.h
2015-09-24 12:24:20 -03:00
Dalai Felinto
372dff8d1d Silence double promotion error/warnings 2015-09-21 19:56:14 -03:00
Dalai Felinto
91d64cbf0f CMake build support 2015-09-16 17:09:40 -03:00
0e1f34a0c8 Cycles; Camera ray nodes initial commit
This commit lays down an initial playground for the camera ray nodes.

The idea of this nodes is to be able to have a control over the rays
which are being casted from the camera in order to gain several use
case scenarios:

- Panorama cameras with custom mapping (kinda generalized way doing
  what Daniel Basso tried to address in T35428).

- Distortion rendering, to produce renders which matches the footage
  precisely, improving motrack work flow in general.

- Some possible artistic scenarios.

It's the very beginning and loads of stuff to be done, but it's
already possible to render a distorted images on CPU using the same
exact distortion model as used by the motion tracker.

Committing the stuff in order to be able to gather early feedback
about how exactly this nodes are expected to work from the artists
point of view, and hopefully someone will pick the work up and help
finishing it all up.

Some technical details:

- Camera nodes are using pynodes, so no changes to the blender itself
  is to be done. This leads some limitations and corners on the usage,
  but that's probably something to be addressed for pynodes in general.

  That said, current annoyance is:

  * Modifying node declaration in the cycles addon doesn't update the
    files, leading to wrong render results. Not sure how it's expected
    to be handled actually.

  * Some operators like Ctrl-X are not re-linking noodles correctly.

  * Muting is impossible.

  * Some major update issues, mainly in cycles viewport. This also
    involves dependency graph stupidness into here.

- Nodes are implemented using SVM, which is really easy to use and
  extend. Would also make it possible to have custom socket types, for
  example in SVM we can have socket type named "Ray" which would pass
  all the origin, direction length via a single noodle.

  In OSL it's not so trivial by the looks of it, so for now we stick
  to a stupid regular socket types.

- Supporting OSL could be a rather tricky business via pynodes and
  could involve quite some work in here. Also it'll stress OSL with
  something it wasn't really designed to do, but it might just work.

- Since inverting the distortion is an optimization problem which is
  rather tricky to implement on GPU, only CPU supports camera ray
  nodes at this moment.

- The above thing might be solved if we bake distortion into a grid
  and use as a lookup table from the kernel. Would also help performance
  by avoiding solving optimization problem for each single camera ray
  at each sample.

- Some stuff might be totally broken at this moment, use with care
  and don't forget to back your files up before doing experiments.

Real quick example: ftp://ftp.blender.org/sergey/camera_nodes.blend.png
2014-09-26 18:23:18 +06:00
29 changed files with 1246 additions and 8 deletions

View File

@@ -195,6 +195,13 @@ if(WITH_CYCLES_DEBUG)
add_definitions(-DWITH_CYCLES_DEBUG)
endif()
if(WITH_LIBMV)
add_definitions(-DWITH_CYCLES_DISTORTION)
include_directories(
../../extern/libmv
)
endif()
include_directories(
SYSTEM
${BOOST_INCLUDE_DIR}

View File

@@ -67,6 +67,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')
if env['WITH_BF_CYCLES_DEBUG']:
defs.append('WITH_CYCLES_DEBUG')

View File

@@ -22,6 +22,7 @@ set(INC_SYS
set(SRC
blender_camera.cpp
blender_camera_nodes.cpp
blender_mesh.cpp
blender_object.cpp
blender_particles.cpp
@@ -42,6 +43,7 @@ set(SRC
set(ADDON_FILES
addon/__init__.py
addon/camera_nodes.py
addon/engine.py
addon/osl.py
addon/presets.py

View File

@@ -30,10 +30,7 @@ bl_info = {
import bpy
from . import (
engine,
version_update,
)
from . import engine
class CyclesRender(bpy.types.RenderEngine):
@@ -89,28 +86,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__)

View File

@@ -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)

View File

@@ -21,7 +21,8 @@ from bpy.props import (BoolProperty,
EnumProperty,
FloatProperty,
IntProperty,
PointerProperty)
PointerProperty,
StringProperty)
# enums
@@ -625,6 +626,9 @@ class CyclesCameraSettings(bpy.types.PropertyGroup):
subtype='ANGLE',
default=math.pi,
)
cls.nodes = StringProperty(
name="nodes",
description="Camera ray nodes")
@classmethod
def unregister(cls):

View File

@@ -547,6 +547,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"

View File

@@ -335,6 +335,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 */
@@ -370,6 +372,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;
@@ -377,6 +382,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;
@@ -455,6 +461,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);
}
void BlenderSync::sync_camera_motion(BL::RenderSettings b_render,
@@ -687,6 +694,7 @@ void BlenderSync::sync_view(BL::SpaceView3D b_v3d, BL::RegionView3D b_rv3d, int
blender_camera_border(&bcam, b_engine, b_scene.render(), b_scene, b_v3d, b_rv3d, width, height);
blender_camera_sync(scene->camera, &bcam, width, height);
sync_view_nodes(b_rv3d);
}
BufferParams BlenderSync::get_buffer_params(BL::RenderSettings b_render, BL::SpaceView3D b_v3d, BL::RegionView3D b_rv3d, Camera *cam, int width, int height)

View File

@@ -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

View File

@@ -62,7 +62,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; }

View File

@@ -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)
@@ -296,6 +298,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);

View File

@@ -21,6 +21,7 @@
#include "util_math.h"
#include "util_math_fast.h"
#include "util_transform.h"
#include "util_distort.h"
#endif /* __KERNEL_MATH_H__ */

View File

@@ -74,6 +74,7 @@ CCL_NAMESPACE_BEGIN
#define __VOLUME_SCATTER__
#define __SHADOW_RECORD_ALL__
#define __VOLUME_RECORD_ALL__
#define __CAMERA_RAY_NODES__
#endif
#ifdef __KERNEL_CUDA__
@@ -795,6 +796,10 @@ typedef struct KernelCamera {
float inv_aperture_ratio;
int is_inside_volume;
int shader;
float focal_length;
float pad[2];
/* more matrices */
Transform screentoworld;
@@ -999,6 +1004,13 @@ typedef struct KernelData {
KernelTables tables;
} KernelData;
typedef struct CameraData {
float2 raster;
float2 lens;
Ray ray;
int shader;
} CameraData;
#ifdef __KERNEL_DEBUG__
typedef ccl_addr_space struct DebugData {
// Total number of BVH node traversal steps and primitives intersections

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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);
@@ -467,5 +482,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__ */

View File

@@ -127,6 +127,11 @@ typedef enum NodeType {
NODE_HAIR_INFO,
NODE_UVMAP,
NODE_TEX_VOXEL,
NODE_CAMERA_PATH_ATTRIBUTE,
NODE_CAMERA_SAMPLE_PERSPECTIVE,
NODE_CAMERA_RAY_OUTPUT,
NODE_CAMERA_POLYNOMIAL_DISTORTION,
} NodeType;
typedef enum NodeAttributeType {
@@ -358,7 +363,8 @@ typedef enum NodeTexVoxelSpace {
typedef enum ShaderType {
SHADER_TYPE_SURFACE,
SHADER_TYPE_VOLUME,
SHADER_TYPE_DISPLACEMENT
SHADER_TYPE_DISPLACEMENT,
SHADER_TYPE_CAMERA_RAY,
} ShaderType;
/* Closure */
@@ -419,6 +425,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)

View File

@@ -20,6 +20,7 @@ set(SRC
bake.cpp
buffers.cpp
camera.cpp
camera_nodes.cpp
film.cpp
graph.cpp
image.cpp
@@ -48,6 +49,7 @@ set(SRC_HEADERS
background.h
buffers.h
camera.h
camera_nodes.h
film.h
graph.h
image.h

View File

@@ -15,7 +15,9 @@
*/
#include "camera.h"
#include "graph.h"
#include "mesh.h"
#include "nodes.h"
#include "object.h"
#include "scene.h"
@@ -84,10 +86,13 @@ Camera::Camera()
need_device_update = true;
need_flags_update = true;
previous_need_motion = -1;
graph = NULL;
}
Camera::~Camera()
{
delete graph;
}
void Camera::compute_auto_viewplane()
@@ -316,6 +321,17 @@ void Camera::device_update(Device *device, DeviceScene *dscene, Scene *scene)
kcam->is_inside_volume = 0;
previous_need_motion = need_motion;
/* focal length */
kcam->focal_length = focal_length;
/* 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_update_volume(Device * /*device*/,
@@ -355,6 +371,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) &&
@@ -444,4 +461,14 @@ BoundBox Camera::viewplane_bounds_get()
return bounds;
}
void Camera::set_graph(CameraNodesGraph *graph_)
{
if(graph_) {
graph_->remove_unneeded_nodes();
}
delete graph;
graph = graph_;
}
CCL_NAMESPACE_END

View File

@@ -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;
@@ -110,12 +112,17 @@ public:
bool need_flags_update;
int previous_need_motion;
/* Camera ray nodes. */
CameraNodesGraph *graph;
/* functions */
Camera();
~Camera();
void compute_auto_viewplane();
void set_graph(CameraNodesGraph *graph);
void update();
void device_update(Device *device, DeviceScene *dscene, Scene *scene);

View File

@@ -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

View File

@@ -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__ */

View File

@@ -17,6 +17,7 @@
#include "attribute.h"
#include "graph.h"
#include "nodes.h"
#include "camera_nodes.h"
#include "shader.h"
#include "util_algorithm.h"
@@ -968,5 +969,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

View File

@@ -37,6 +37,7 @@ class ShaderGraph;
class SVMCompiler;
class OSLCompiler;
class OutputNode;
class RayOutputNode;
/* Socket Type
*
@@ -292,6 +293,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__ */

View File

@@ -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"
@@ -65,7 +67,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];
@@ -81,6 +88,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);
@@ -691,6 +704,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 */
@@ -742,5 +785,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

View File

@@ -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;

View File

@@ -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 * (double)focal_length + (double)principal_point.x;
result->y = normalized_y * (double)focal_length + (double)principal_point.y;
#else
*result = image;
#endif
}
CCL_NAMESPACE_END
#endif /* __UTIL_DISTORT_H__ */