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:
authorDalai Felinto <dfelinto@gmail.com>2014-01-03 01:05:07 +0400
committerDalai Felinto <dfelinto@gmail.com>2014-05-03 04:19:09 +0400
commiteec3eaba084725a978f4aefb773a16ae9c0420db (patch)
tree68e34c3e8ff42af5263c010895b6649961f82eb6
parent97641a0ec946005d9a042f075697109c6590a28d (diff)
Cycles Bake
Expand Cycles to use the new baking API in Blender. It works on the selected object, and the panel can be accessed in the Render panel (similar to where it is for the Blender Internal). It bakes for the active texture of each material of the object. The active texture is currently defined as the active Image Texture node present in the material nodetree. If you don't want the baking to override an existent material, make sure the active Image Texture node is not connected to the nodetree. The active texture is also the texture shown in the viewport in the rendered mode. Remember to save your images after the baking is complete. Note: Bake currently only works in the CPU Note: This is not supported by Cycles standalone because a lot of the work is done in Blender as part of the operator only, not the engine (Cycles). Documentation: http://wiki.blender.org/index.php/Doc:2.6/Manual/Render/Cycles/Bake Supported Passes: ----------------- Data Passes * Normal * UV * Diffuse/Glossy/Transmission/Subsurface/Emit Color Light Passes * AO * Combined * Shadow * Diffuse/Glossy/Transmission/Subsurface/Emit Direct/Indirect * Environment Review: D421 Reviewed by: Campbell Barton, Brecht van Lommel, Sergey Sharybin, Thomas Dinge Original design by Brecht van Lommel. The entire commit history can be found on the branch: bake-cycles
-rw-r--r--intern/cycles/blender/addon/__init__.py3
-rw-r--r--intern/cycles/blender/addon/engine.py6
-rw-r--r--intern/cycles/blender/addon/properties.py27
-rw-r--r--intern/cycles/blender/addon/ui.py48
-rw-r--r--intern/cycles/blender/blender_python.cpp33
-rw-r--r--intern/cycles/blender/blender_session.cpp155
-rw-r--r--intern/cycles/blender/blender_session.h3
-rw-r--r--intern/cycles/device/device_cpu.cpp10
-rw-r--r--intern/cycles/kernel/kernel_accumulate.h21
-rw-r--r--intern/cycles/kernel/kernel_displace.h267
-rw-r--r--intern/cycles/kernel/kernel_path.h80
-rw-r--r--intern/cycles/kernel/kernel_types.h33
-rw-r--r--intern/cycles/render/CMakeLists.txt2
-rw-r--r--intern/cycles/render/bake.cpp183
-rw-r--r--intern/cycles/render/bake.h72
-rw-r--r--intern/cycles/render/film.cpp7
-rw-r--r--intern/cycles/render/light.cpp5
-rw-r--r--intern/cycles/render/mesh_displace.cpp10
-rw-r--r--intern/cycles/render/scene.cpp13
-rw-r--r--intern/cycles/render/scene.h3
-rw-r--r--intern/cycles/render/session.cpp9
-rw-r--r--intern/cycles/render/session.h2
22 files changed, 937 insertions, 55 deletions
diff --git a/intern/cycles/blender/addon/__init__.py b/intern/cycles/blender/addon/__init__.py
index 9f42cc9bb00..27d986900c8 100644
--- a/intern/cycles/blender/addon/__init__.py
+++ b/intern/cycles/blender/addon/__init__.py
@@ -67,6 +67,9 @@ class CyclesRender(bpy.types.RenderEngine):
def render(self, scene):
engine.render(self)
+ def bake(self, scene, obj, pass_type, pixel_array, num_pixels, depth, result):
+ engine.bake(self, obj, pass_type, pixel_array, num_pixels, depth, result)
+
# viewport render
def view_update(self, context):
if not self.session:
diff --git a/intern/cycles/blender/addon/engine.py b/intern/cycles/blender/addon/engine.py
index b9ce65588df..25a9e97a99b 100644
--- a/intern/cycles/blender/addon/engine.py
+++ b/intern/cycles/blender/addon/engine.py
@@ -59,6 +59,12 @@ def render(engine):
_cycles.render(engine.session)
+def bake(engine, obj, pass_type, pixel_array, num_pixels, depth, result):
+ import _cycles
+ session = getattr(engine, "session", None)
+ if session is not None:
+ _cycles.bake(engine.session, obj.as_pointer(), pass_type, pixel_array.as_pointer(), num_pixels, depth, result.as_pointer())
+
def reset(engine, data, scene):
import _cycles
data = data.as_pointer()
diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py
index 2b05c2148eb..7205a272395 100644
--- a/intern/cycles/blender/addon/properties.py
+++ b/intern/cycles/blender/addon/properties.py
@@ -471,6 +471,33 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
default=False,
)
+ cls.bake_type = EnumProperty(
+ name="Bake Type",
+ default='COMBINED',
+ description="Type of pass to bake",
+ items = (
+ ('COMBINED', "Combined", ""),
+ ('AO', "Ambient Occlusion", ""),
+ ('SHADOW', "Shadow", ""),
+ ('NORMAL', "Normal", ""),
+ ('UV', "UV", ""),
+ ('EMIT', "Emit", ""),
+ ('ENVIRONMENT', "Environment", ""),
+ ('DIFFUSE_DIRECT', "Diffuse Direct", ""),
+ ('DIFFUSE_INDIRECT', "Diffuse Indirect", ""),
+ ('DIFFUSE_COLOR', "Diffuse Color", ""),
+ ('GLOSSY_DIRECT', "Glossy Direct", ""),
+ ('GLOSSY_INDIRECT', "Glossy Indirect", ""),
+ ('GLOSSY_COLOR', "Glossy Color", ""),
+ ('TRANSMISSION_DIRECT', "Transmission Direct", ""),
+ ('TRANSMISSION_INDIRECT', "Transmission Indirect", ""),
+ ('TRANSMISSION_COLOR', "Transmission Color", ""),
+ ('SUBSURFACE_DIRECT', "Subsurface Direct", ""),
+ ('SUBSURFACE_INDIRECT', "Subsurface Indirect", ""),
+ ('SUBSURFACE_COLOR', "Subsurface Color", ""),
+ ),
+ )
+
@classmethod
def unregister(cls):
del bpy.types.Scene.cycles
diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py
index f35cb1abd2e..5c8115b6612 100644
--- a/intern/cycles/blender/addon/ui.py
+++ b/intern/cycles/blender/addon/ui.py
@@ -1227,6 +1227,54 @@ class CyclesRender_PT_CurveRendering(CyclesButtonsPanel, Panel):
row.prop(ccscene, "maximum_width", text="Max Ext.")
+class CyclesRender_PT_bake(CyclesButtonsPanel, Panel):
+ bl_label = "Bake"
+ bl_context = "render"
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'CYCLES'}
+
+ def draw(self, context):
+ layout = self.layout
+
+ scene = context.scene
+ cscene = scene.cycles
+
+ cbk = scene.render.bake
+
+ layout.operator("object.bake", icon='RENDER_STILL').type = \
+ cscene.bake_type
+
+ col = layout.column()
+ col.prop(cscene, "bake_type")
+
+ col.separator()
+ split = layout.split()
+
+ sub = split.column()
+ sub.prop(cbk, "use_clear")
+ sub.prop(cbk, "margin")
+
+ sub = split.column()
+ sub.prop(cbk, "use_selected_to_active")
+ sub = sub.column()
+
+ sub.active = cbk.use_selected_to_active
+ sub.prop(cbk, "cage_extrusion", text="Distance")
+ sub.prop_search(cbk, "cage", scene, "objects")
+
+ if cscene.bake_type == 'NORMAL':
+ col.separator()
+ box = col.box()
+ box.label(text="Normal Settings:")
+ box.prop(cbk, "normal_space", text="Space")
+
+ row = box.row(align=True)
+ row.label(text = "Swizzle:")
+ row.prop(cbk, "normal_r", text="")
+ row.prop(cbk, "normal_g", text="")
+ row.prop(cbk, "normal_b", text="")
+
+
class CyclesParticle_PT_CurveSettings(CyclesButtonsPanel, Panel):
bl_label = "Cycles Hair Settings"
bl_context = "particle"
diff --git a/intern/cycles/blender/blender_python.cpp b/intern/cycles/blender/blender_python.cpp
index 8b04a869a85..658fccaf12e 100644
--- a/intern/cycles/blender/blender_python.cpp
+++ b/intern/cycles/blender/blender_python.cpp
@@ -147,6 +147,38 @@ static PyObject *render_func(PyObject *self, PyObject *value)
Py_RETURN_NONE;
}
+/* pixel_array and result passed as pointers */
+static PyObject *bake_func(PyObject *self, PyObject *args)
+{
+ PyObject *pysession, *pyobject;
+ PyObject *pypixel_array, *pyresult;
+ const char *pass_type;
+ int num_pixels, depth;
+
+ if(!PyArg_ParseTuple(args, "OOsOiiO", &pysession, &pyobject, &pass_type, &pypixel_array, &num_pixels, &depth, &pyresult))
+ return NULL;
+
+ Py_BEGIN_ALLOW_THREADS
+
+ BlenderSession *session = (BlenderSession*)PyLong_AsVoidPtr(pysession);
+
+ PointerRNA objectptr;
+ RNA_id_pointer_create((ID*)PyLong_AsVoidPtr(pyobject), &objectptr);
+ BL::Object b_object(objectptr);
+
+ void *b_result = PyLong_AsVoidPtr(pyresult);
+
+ PointerRNA bakepixelptr;
+ RNA_id_pointer_create((ID*)PyLong_AsVoidPtr(pypixel_array), &bakepixelptr);
+ BL::BakePixel b_bake_pixel(bakepixelptr);
+
+ session->bake(b_object, pass_type, b_bake_pixel, num_pixels, depth, (float *)b_result);
+
+ Py_END_ALLOW_THREADS
+
+ Py_RETURN_NONE;
+}
+
static PyObject *draw_func(PyObject *self, PyObject *args)
{
PyObject *pysession, *pyv3d, *pyrv3d;
@@ -418,6 +450,7 @@ static PyMethodDef methods[] = {
{"create", create_func, METH_VARARGS, ""},
{"free", free_func, METH_O, ""},
{"render", render_func, METH_O, ""},
+ {"bake", bake_func, METH_VARARGS, ""},
{"draw", draw_func, METH_VARARGS, ""},
{"sync", sync_func, METH_O, ""},
{"reset", reset_func, METH_VARARGS, ""},
diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp
index f5e696bc582..6f959d42680 100644
--- a/intern/cycles/blender/blender_session.cpp
+++ b/intern/cycles/blender/blender_session.cpp
@@ -14,6 +14,8 @@
* limitations under the License
*/
+#include <stdlib.h>
+
#include "background.h"
#include "buffers.h"
#include "camera.h"
@@ -21,6 +23,8 @@
#include "integrator.h"
#include "film.h"
#include "light.h"
+#include "mesh.h"
+#include "object.h"
#include "scene.h"
#include "session.h"
#include "shader.h"
@@ -259,6 +263,58 @@ static PassType get_pass_type(BL::RenderPass b_pass)
return PASS_NONE;
}
+static ShaderEvalType get_shader_type(const string& pass_type)
+{
+ const char *shader_type = pass_type.c_str();
+
+ /* data passes */
+ if(strcmp(shader_type, "NORMAL")==0)
+ return SHADER_EVAL_NORMAL;
+ else if(strcmp(shader_type, "UV")==0)
+ return SHADER_EVAL_UV;
+ else if(strcmp(shader_type, "DIFFUSE_COLOR")==0)
+ return SHADER_EVAL_DIFFUSE_COLOR;
+ else if(strcmp(shader_type, "GLOSSY_COLOR")==0)
+ return SHADER_EVAL_GLOSSY_COLOR;
+ else if(strcmp(shader_type, "TRANSMISSION_COLOR")==0)
+ return SHADER_EVAL_TRANSMISSION_COLOR;
+ else if(strcmp(shader_type, "SUBSURFACE_COLOR")==0)
+ return SHADER_EVAL_SUBSURFACE_COLOR;
+ else if(strcmp(shader_type, "EMIT")==0)
+ return SHADER_EVAL_EMISSION;
+
+ /* light passes */
+ else if(strcmp(shader_type, "AO")==0)
+ return SHADER_EVAL_AO;
+ else if(strcmp(shader_type, "COMBINED")==0)
+ return SHADER_EVAL_COMBINED;
+ else if(strcmp(shader_type, "SHADOW")==0)
+ return SHADER_EVAL_SHADOW;
+ else if(strcmp(shader_type, "DIFFUSE_DIRECT")==0)
+ return SHADER_EVAL_DIFFUSE_DIRECT;
+ else if(strcmp(shader_type, "GLOSSY_DIRECT")==0)
+ return SHADER_EVAL_GLOSSY_DIRECT;
+ else if(strcmp(shader_type, "TRANSMISSION_DIRECT")==0)
+ return SHADER_EVAL_TRANSMISSION_DIRECT;
+ else if(strcmp(shader_type, "SUBSURFACE_DIRECT")==0)
+ return SHADER_EVAL_SUBSURFACE_DIRECT;
+ else if(strcmp(shader_type, "DIFFUSE_INDIRECT")==0)
+ return SHADER_EVAL_DIFFUSE_INDIRECT;
+ else if(strcmp(shader_type, "GLOSSY_INDIRECT")==0)
+ return SHADER_EVAL_GLOSSY_INDIRECT;
+ else if(strcmp(shader_type, "TRANSMISSION_INDIRECT")==0)
+ return SHADER_EVAL_TRANSMISSION_INDIRECT;
+ else if(strcmp(shader_type, "SUBSURFACE_INDIRECT")==0)
+ return SHADER_EVAL_SUBSURFACE_INDIRECT;
+
+ /* extra */
+ else if(strcmp(shader_type, "ENVIRONMENT")==0)
+ return SHADER_EVAL_ENVIRONMENT;
+
+ else
+ return SHADER_EVAL_BAKE;
+}
+
static BL::RenderResult begin_render_result(BL::RenderEngine b_engine, int x, int y, int w, int h, const char *layername)
{
return b_engine.begin_result(x, y, w, h, layername);
@@ -425,6 +481,105 @@ void BlenderSession::render()
sync = NULL;
}
+static void populate_bake_data(BakeData *data, BL::BakePixel pixel_array, const int num_pixels)
+{
+ BL::BakePixel bp = pixel_array;
+
+ int i;
+ for(i=0; i < num_pixels; i++) {
+ data->set(i, bp.primitive_id(), bp.uv());
+ bp = bp.next();
+ }
+}
+
+static bool is_light_pass(ShaderEvalType type)
+{
+ switch (type) {
+ case SHADER_EVAL_AO:
+ case SHADER_EVAL_COMBINED:
+ case SHADER_EVAL_SHADOW:
+ case SHADER_EVAL_DIFFUSE_DIRECT:
+ case SHADER_EVAL_GLOSSY_DIRECT:
+ case SHADER_EVAL_TRANSMISSION_DIRECT:
+ case SHADER_EVAL_SUBSURFACE_DIRECT:
+ case SHADER_EVAL_DIFFUSE_INDIRECT:
+ case SHADER_EVAL_GLOSSY_INDIRECT:
+ case SHADER_EVAL_TRANSMISSION_INDIRECT:
+ case SHADER_EVAL_SUBSURFACE_INDIRECT:
+ return true;
+ default:
+ return false;
+ }
+}
+
+void BlenderSession::bake(BL::Object b_object, const string& pass_type, BL::BakePixel pixel_array, int num_pixels, int depth, float result[])
+{
+ ShaderEvalType shader_type = get_shader_type(pass_type);
+ size_t object_index = OBJECT_NONE;
+ int tri_offset = 0;
+
+ if(shader_type == SHADER_EVAL_UV) {
+ /* force UV to be available */
+ Pass::add(PASS_UV, scene->film->passes);
+ }
+
+ if(is_light_pass(shader_type)) {
+ /* force use_light_pass to be true */
+ Pass::add(PASS_LIGHT, scene->film->passes);
+ }
+
+ /* create device and update scene */
+ scene->film->tag_update(scene);
+ scene->integrator->tag_update(scene);
+
+ /* update scene */
+ sync->sync_camera(b_render, b_engine.camera_override(), width, height);
+ sync->sync_data(b_v3d, b_engine.camera_override(), &python_thread_state);
+
+ /* get buffer parameters */
+ SessionParams session_params = BlenderSync::get_session_params(b_engine, b_userpref, b_scene, background);
+ BufferParams buffer_params = BlenderSync::get_buffer_params(b_render, b_scene, b_v3d, b_rv3d, scene->camera, width, height);
+
+ scene->bake_manager->set_baking(true);
+
+ /* set number of samples */
+ session->tile_manager.set_samples(session_params.samples);
+ session->reset(buffer_params, session_params.samples);
+ session->update_scene();
+
+ /* find object index. todo: is arbitrary - copied from mesh_displace.cpp */
+ for(size_t i = 0; i < scene->objects.size(); i++) {
+ if(strcmp(scene->objects[i]->name.c_str(), b_object.name().c_str()) == 0) {
+ object_index = i;
+ tri_offset = scene->objects[i]->mesh->tri_offset;
+ break;
+ }
+ }
+
+ /* when used, non-instanced convention: object = ~object */
+ int object = ~object_index;
+
+ BakeData *bake_data = scene->bake_manager->init(object, tri_offset, num_pixels);
+
+ populate_bake_data(bake_data, pixel_array, num_pixels);
+
+ /* set number of samples */
+ session->tile_manager.set_samples(session_params.samples);
+ session->reset(buffer_params, session_params.samples);
+ session->update_scene();
+
+ scene->bake_manager->bake(scene->device, &scene->dscene, scene, session->progress, shader_type, bake_data, result);
+
+ /* free all memory used (host and device), so we wouldn't leave render
+ * engine with extra memory allocated
+ */
+
+ session->device_free();
+
+ delete sync;
+ sync = NULL;
+}
+
void BlenderSession::do_write_update_render_result(BL::RenderResult b_rr, BL::RenderLayer b_rlay, RenderTile& rtile, bool do_update_only)
{
RenderBuffers *buffers = rtile.buffers;
diff --git a/intern/cycles/blender/blender_session.h b/intern/cycles/blender/blender_session.h
index d30e3eda870..0e44493d674 100644
--- a/intern/cycles/blender/blender_session.h
+++ b/intern/cycles/blender/blender_session.h
@@ -20,6 +20,7 @@
#include "device.h"
#include "scene.h"
#include "session.h"
+#include "bake.h"
#include "util_vector.h"
@@ -51,6 +52,8 @@ public:
/* offline render */
void render();
+ void bake(BL::Object b_object, const string& pass_type, BL::BakePixel pixel_array, int num_pixels, int depth, float pixels[]);
+
void write_render_result(BL::RenderResult b_rr, BL::RenderLayer b_rlay, RenderTile& rtile);
void write_render_tile(RenderTile& rtile);
diff --git a/intern/cycles/device/device_cpu.cpp b/intern/cycles/device/device_cpu.cpp
index e14e403d82b..c9cc7592028 100644
--- a/intern/cycles/device/device_cpu.cpp
+++ b/intern/cycles/device/device_cpu.cpp
@@ -395,7 +395,7 @@ public:
for(int x = task.shader_x; x < task.shader_x + task.shader_w; x++) {
kernel_cpu_avx_shader(&kg, (uint4*)task.shader_input, (float4*)task.shader_output, task.shader_eval_type, x);
- if(task_pool.canceled())
+ if(task.get_cancel() || task_pool.canceled())
break;
}
}
@@ -406,7 +406,7 @@ public:
for(int x = task.shader_x; x < task.shader_x + task.shader_w; x++) {
kernel_cpu_sse41_shader(&kg, (uint4*)task.shader_input, (float4*)task.shader_output, task.shader_eval_type, x);
- if(task_pool.canceled())
+ if(task.get_cancel() || task_pool.canceled())
break;
}
}
@@ -417,7 +417,7 @@ public:
for(int x = task.shader_x; x < task.shader_x + task.shader_w; x++) {
kernel_cpu_sse3_shader(&kg, (uint4*)task.shader_input, (float4*)task.shader_output, task.shader_eval_type, x);
- if(task_pool.canceled())
+ if(task.get_cancel() || task_pool.canceled())
break;
}
}
@@ -428,7 +428,7 @@ public:
for(int x = task.shader_x; x < task.shader_x + task.shader_w; x++) {
kernel_cpu_sse2_shader(&kg, (uint4*)task.shader_input, (float4*)task.shader_output, task.shader_eval_type, x);
- if(task_pool.canceled())
+ if(task.get_cancel() || task_pool.canceled())
break;
}
}
@@ -438,7 +438,7 @@ public:
for(int x = task.shader_x; x < task.shader_x + task.shader_w; x++) {
kernel_cpu_shader(&kg, (uint4*)task.shader_input, (float4*)task.shader_output, task.shader_eval_type, x);
- if(task_pool.canceled())
+ if(task.get_cancel() || task_pool.canceled())
break;
}
}
diff --git a/intern/cycles/kernel/kernel_accumulate.h b/intern/cycles/kernel/kernel_accumulate.h
index 582a220ab3c..82450b73097 100644
--- a/intern/cycles/kernel/kernel_accumulate.h
+++ b/intern/cycles/kernel/kernel_accumulate.h
@@ -407,5 +407,26 @@ ccl_device_inline float3 path_radiance_clamp_and_sum(KernelGlobals *kg, PathRadi
return L_sum;
}
+ccl_device_inline void path_radiance_accum_sample(PathRadiance *L, PathRadiance *L_sample, int num_samples)
+{
+ float fac = 1.0f/num_samples;
+
+ L->direct_diffuse += L_sample->direct_diffuse*fac;
+ L->direct_glossy += L_sample->direct_glossy*fac;
+ L->direct_transmission += L_sample->direct_transmission*fac;
+ L->direct_subsurface += L_sample->direct_subsurface*fac;
+
+ L->indirect_diffuse += L_sample->indirect_diffuse*fac;
+ L->indirect_glossy += L_sample->indirect_glossy*fac;
+ L->indirect_transmission += L_sample->indirect_transmission*fac;
+ L->indirect_subsurface += L_sample->indirect_subsurface*fac;
+
+ L->emission += L_sample->emission*fac;
+ L->background += L_sample->background*fac;
+ L->ao += L_sample->ao*fac;
+ L->shadow += L_sample->shadow*fac;
+ L->mist += L_sample->mist*fac;
+}
+
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/kernel_displace.h b/intern/cycles/kernel/kernel_displace.h
index 1935f72ce95..a2709e711d2 100644
--- a/intern/cycles/kernel/kernel_displace.h
+++ b/intern/cycles/kernel/kernel_displace.h
@@ -16,8 +16,275 @@
CCL_NAMESPACE_BEGIN
+ccl_device void compute_light_pass(KernelGlobals *kg, ShaderData *sd, PathRadiance *L, RNG rng, bool is_ao)
+{
+ int samples = kernel_data.integrator.aa_samples;
+
+ /* initialize master radiance accumulator */
+ kernel_assert(kernel_data.film.use_light_pass);
+ path_radiance_init(L, kernel_data.film.use_light_pass);
+
+ /* take multiple samples */
+ for(int sample = 0; sample < samples; sample++) {
+ PathRadiance L_sample;
+ PathState state;
+ Ray ray;
+ float3 throughput = make_float3(1.0f, 1.0f, 1.0f);
+
+ /* init radiance */
+ path_radiance_init(&L_sample, kernel_data.film.use_light_pass);
+
+ /* init path state */
+ path_state_init(kg, &state, &rng, sample);
+ state.num_samples = samples;
+
+ /* evaluate surface shader */
+ float rbsdf = path_state_rng_1D(kg, &rng, &state, PRNG_BSDF);
+ shader_eval_surface(kg, sd, rbsdf, state.flag, SHADER_CONTEXT_MAIN);
+
+ /* sample ambient occlusion */
+ if(is_ao) {
+ kernel_path_ao(kg, sd, &L_sample, &state, &rng, throughput);
+ }
+
+ /* sample light and BSDF */
+ else if(kernel_path_integrate_lighting(kg, &rng, sd, &throughput, &state, &L_sample, &ray)) {
+#ifdef __LAMP_MIS__
+ state.ray_t = 0.0f;
+#endif
+
+ /* compute indirect light */
+ kernel_path_indirect(kg, &rng, ray, throughput, state.num_samples, state, &L_sample);
+
+ /* sum and reset indirect light pass variables for the next samples */
+ path_radiance_sum_indirect(&L_sample);
+ path_radiance_reset_indirect(&L_sample);
+ }
+
+ /* accumulate into master L */
+ path_radiance_accum_sample(L, &L_sample, samples);
+ }
+}
+
+ccl_device bool is_light_pass(ShaderEvalType type)
+{
+ switch (type) {
+ case SHADER_EVAL_AO:
+ case SHADER_EVAL_COMBINED:
+ case SHADER_EVAL_SHADOW:
+ case SHADER_EVAL_DIFFUSE_DIRECT:
+ case SHADER_EVAL_GLOSSY_DIRECT:
+ case SHADER_EVAL_TRANSMISSION_DIRECT:
+ case SHADER_EVAL_SUBSURFACE_DIRECT:
+ case SHADER_EVAL_DIFFUSE_INDIRECT:
+ case SHADER_EVAL_GLOSSY_INDIRECT:
+ case SHADER_EVAL_TRANSMISSION_INDIRECT:
+ case SHADER_EVAL_SUBSURFACE_INDIRECT:
+ return true;
+ default:
+ return false;
+ }
+}
+
+ccl_device void kernel_bake_evaluate(KernelGlobals *kg, ccl_global uint4 *input, ccl_global float4 *output, ShaderEvalType type, int i)
+{
+ ShaderData sd;
+ uint4 in = input[i];
+ float3 out;
+
+ int object = in.x;
+ int prim = in.y;
+
+ if(prim == -1)
+ return;
+
+ float u = __uint_as_float(in.z);
+ float v = __uint_as_float(in.w);
+
+ int shader;
+ float3 P, Ng;
+
+ triangle_point_normal(kg, prim, u, v, &P, &Ng, &shader);
+
+ /* dummy initilizations copied from SHADER_EVAL_DISPLACE */
+ float3 I = Ng;
+ float t = 0.0f;
+ float time = TIME_INVALID;
+ int bounce = 0;
+ int transparent_bounce = 0;
+
+ /* light passes */
+ PathRadiance L;
+
+ /* TODO, disable the closures we won't need */
+ shader_setup_from_sample(kg, &sd, P, Ng, I, shader, object, prim, u, v, t, time, bounce, transparent_bounce);
+
+ if(is_light_pass(type)){
+ RNG rng = cmj_hash(i, 0);
+ compute_light_pass(kg, &sd, &L, rng, (type == SHADER_EVAL_AO));
+ }
+
+ switch (type) {
+ /* data passes */
+ case SHADER_EVAL_NORMAL:
+ {
+ /* compression: normal = (2 * color) - 1 */
+ out = sd.N * 0.5f + make_float3(0.5f, 0.5f, 0.5f);
+ break;
+ }
+ case SHADER_EVAL_UV:
+ {
+ out = primitive_uv(kg, &sd);
+ break;
+ }
+ case SHADER_EVAL_DIFFUSE_COLOR:
+ {
+ shader_eval_surface(kg, &sd, 0.f, 0, SHADER_CONTEXT_MAIN);
+ out = shader_bsdf_diffuse(kg, &sd);
+ break;
+ }
+ case SHADER_EVAL_GLOSSY_COLOR:
+ {
+ shader_eval_surface(kg, &sd, 0.f, 0, SHADER_CONTEXT_MAIN);
+ out = shader_bsdf_glossy(kg, &sd);
+ break;
+ }
+ case SHADER_EVAL_TRANSMISSION_COLOR:
+ {
+ shader_eval_surface(kg, &sd, 0.f, 0, SHADER_CONTEXT_MAIN);
+ out = shader_bsdf_transmission(kg, &sd);
+ break;
+ }
+ case SHADER_EVAL_SUBSURFACE_COLOR:
+ {
+#ifdef __SUBSURFACE__
+ shader_eval_surface(kg, &sd, 0.f, 0, SHADER_CONTEXT_MAIN);
+ out = shader_bsdf_subsurface(kg, &sd);
+#endif
+ break;
+ }
+ case SHADER_EVAL_EMISSION:
+ {
+ shader_eval_surface(kg, &sd, 0.f, 0, SHADER_CONTEXT_EMISSION);
+ out = shader_emissive_eval(kg, &sd);
+ break;
+ }
+
+ /* light passes */
+ case SHADER_EVAL_AO:
+ {
+ out = L.ao;
+ break;
+ }
+ case SHADER_EVAL_COMBINED:
+ {
+ out = path_radiance_clamp_and_sum(kg, &L);
+ break;
+ }
+ case SHADER_EVAL_SHADOW:
+ {
+ out = make_float3(L.shadow.x, L.shadow.y, L.shadow.z);
+ break;
+ }
+ case SHADER_EVAL_DIFFUSE_DIRECT:
+ {
+ shader_eval_surface(kg, &sd, 0.f, 0, SHADER_CONTEXT_MAIN);
+ out = safe_divide_color(L.direct_diffuse, shader_bsdf_diffuse(kg, &sd));
+ break;
+ }
+ case SHADER_EVAL_GLOSSY_DIRECT:
+ {
+ shader_eval_surface(kg, &sd, 0.f, 0, SHADER_CONTEXT_MAIN);
+ out = safe_divide_color(L.direct_glossy, shader_bsdf_glossy(kg, &sd));
+ break;
+ }
+ case SHADER_EVAL_TRANSMISSION_DIRECT:
+ {
+ shader_eval_surface(kg, &sd, 0.f, 0, SHADER_CONTEXT_MAIN);
+ out = safe_divide_color(L.direct_transmission, shader_bsdf_transmission(kg, &sd));
+ break;
+ }
+ case SHADER_EVAL_SUBSURFACE_DIRECT:
+ {
+#ifdef __SUBSURFACE__
+ shader_eval_surface(kg, &sd, 0.f, 0, SHADER_CONTEXT_MAIN);
+ out = safe_divide_color(L.direct_subsurface, shader_bsdf_subsurface(kg, &sd));
+#endif
+ break;
+ }
+ case SHADER_EVAL_DIFFUSE_INDIRECT:
+ {
+ shader_eval_surface(kg, &sd, 0.f, 0, SHADER_CONTEXT_MAIN);
+ out = safe_divide_color(L.indirect_diffuse, shader_bsdf_diffuse(kg, &sd));
+ break;
+ }
+ case SHADER_EVAL_GLOSSY_INDIRECT:
+ {
+ shader_eval_surface(kg, &sd, 0.f, 0, SHADER_CONTEXT_MAIN);
+ out = safe_divide_color(L.indirect_glossy, shader_bsdf_glossy(kg, &sd));
+ break;
+ }
+ case SHADER_EVAL_TRANSMISSION_INDIRECT:
+ {
+ shader_eval_surface(kg, &sd, 0.f, 0, SHADER_CONTEXT_MAIN);
+ out = safe_divide_color(L.indirect_transmission, shader_bsdf_transmission(kg, &sd));
+ break;
+ }
+ case SHADER_EVAL_SUBSURFACE_INDIRECT:
+ {
+#ifdef __SUBSURFACE__
+ shader_eval_surface(kg, &sd, 0.f, 0, SHADER_CONTEXT_MAIN);
+ out = safe_divide_color(L.indirect_subsurface, shader_bsdf_subsurface(kg, &sd));
+#endif
+ break;
+ }
+
+ /* extra */
+ case SHADER_EVAL_ENVIRONMENT:
+ {
+ /* setup ray */
+ Ray ray;
+
+ ray.P = make_float3(0.0f, 0.0f, 0.0f);
+ ray.D = normalize(P);
+ ray.t = 0.0f;
+#ifdef __CAMERA_MOTION__
+ ray.time = 0.5f;
+#endif
+
+#ifdef __RAY_DIFFERENTIALS__
+ ray.dD = differential3_zero();
+ ray.dP = differential3_zero();
+#endif
+
+ /* setup shader data */
+ shader_setup_from_background(kg, &sd, &ray, 0, 0);
+
+ /* evaluate */
+ int flag = 0; /* we can't know which type of BSDF this is for */
+ out = shader_eval_background(kg, &sd, flag, SHADER_CONTEXT_MAIN);
+ break;
+ }
+ default:
+ {
+ /* no real shader, returning the position of the verts for debugging */
+ out = normalize(P);
+ break;
+ }
+ }
+
+ /* write output */
+ output[i] = make_float4(out.x, out.y, out.z, 1.0f);
+ return;
+}
+
ccl_device void kernel_shader_evaluate(KernelGlobals *kg, ccl_global uint4 *input, ccl_global float4 *output, ShaderEvalType type, int i)
{
+ if(type >= SHADER_EVAL_BAKE) {
+ kernel_bake_evaluate(kg, input, output, type, i);
+ return;
+ }
+
ShaderData sd;
uint4 in = input[i];
float3 out;
diff --git a/intern/cycles/kernel/kernel_path.h b/intern/cycles/kernel/kernel_path.h
index 1ca6bd38ba9..e71b58aa709 100644
--- a/intern/cycles/kernel/kernel_path.h
+++ b/intern/cycles/kernel/kernel_path.h
@@ -212,7 +212,9 @@ ccl_device void kernel_branched_path_integrate_direct_lighting(KernelGlobals *kg
}
}
-ccl_device void kernel_path_indirect(KernelGlobals *kg, RNG *rng, Ray ray, ccl_global float *buffer,
+#endif
+
+ccl_device void kernel_path_indirect(KernelGlobals *kg, RNG *rng, Ray ray,
float3 throughput, int num_samples, PathState state, PathRadiance *L)
{
/* path iteration */
@@ -378,7 +380,7 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg, RNG *rng, Ray ray, ccl_g
}
#endif
-#ifdef __EMISSION__
+#if defined(__EMISSION__) && defined(__BRANCHED_PATH__)
if(kernel_data.integrator.use_direct_light) {
bool all = kernel_data.integrator.sample_all_lights_indirect;
kernel_branched_path_integrate_direct_lighting(kg, rng, &sd, &state, throughput, 1.0f, L, all);
@@ -456,10 +458,6 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg, RNG *rng, Ray ray, ccl_g
}
}
-#endif
-
-#ifdef __SUBSURFACE__
-
ccl_device_inline bool kernel_path_integrate_lighting(KernelGlobals *kg, RNG *rng,
ShaderData *sd, float3 *throughput, PathState *state, PathRadiance *L, Ray *ray)
{
@@ -569,7 +567,39 @@ ccl_device_inline bool kernel_path_integrate_lighting(KernelGlobals *kg, RNG *rn
}
}
+ccl_device void kernel_path_ao(KernelGlobals *kg, ShaderData *sd, PathRadiance *L, PathState *state, RNG *rng, float3 throughput)
+{
+ /* todo: solve correlation */
+ float bsdf_u, bsdf_v;
+
+ path_state_rng_2D(kg, rng, state, PRNG_BSDF_U, &bsdf_u, &bsdf_v);
+
+ float ao_factor = kernel_data.background.ao_factor;
+ float3 ao_N;
+ float3 ao_bsdf = shader_bsdf_ao(kg, sd, ao_factor, &ao_N);
+ float3 ao_D;
+ float ao_pdf;
+ float3 ao_alpha = shader_bsdf_alpha(kg, sd);
+
+ sample_cos_hemisphere(ao_N, bsdf_u, bsdf_v, &ao_D, &ao_pdf);
+
+ if(dot(sd->Ng, ao_D) > 0.0f && ao_pdf != 0.0f) {
+ Ray light_ray;
+ float3 ao_shadow;
+
+ light_ray.P = ray_offset(sd->P, sd->Ng);
+ light_ray.D = ao_D;
+ light_ray.t = kernel_data.background.ao_distance;
+#ifdef __OBJECT_MOTION__
+ light_ray.time = sd->time;
#endif
+ light_ray.dP = sd->dP;
+ light_ray.dD = differential3_zero();
+
+ if(!shadow_blocked(kg, state, &light_ray, &ao_shadow))
+ path_radiance_accum_ao(L, throughput, ao_alpha, ao_bsdf, ao_shadow, state->bounce);
+ }
+}
ccl_device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample, Ray ray, ccl_global float *buffer)
{
@@ -738,35 +768,7 @@ ccl_device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample,
#ifdef __AO__
/* ambient occlusion */
if(kernel_data.integrator.use_ambient_occlusion || (sd.flag & SD_AO)) {
- /* todo: solve correlation */
- float bsdf_u, bsdf_v;
- path_state_rng_2D(kg, rng, &state, PRNG_BSDF_U, &bsdf_u, &bsdf_v);
-
- float ao_factor = kernel_data.background.ao_factor;
- float3 ao_N;
- float3 ao_bsdf = shader_bsdf_ao(kg, &sd, ao_factor, &ao_N);
- float3 ao_D;
- float ao_pdf;
- float3 ao_alpha = shader_bsdf_alpha(kg, &sd);
-
- sample_cos_hemisphere(ao_N, bsdf_u, bsdf_v, &ao_D, &ao_pdf);
-
- if(dot(sd.Ng, ao_D) > 0.0f && ao_pdf != 0.0f) {
- Ray light_ray;
- float3 ao_shadow;
-
- light_ray.P = ray_offset(sd.P, sd.Ng);
- light_ray.D = ao_D;
- light_ray.t = kernel_data.background.ao_distance;
-#ifdef __OBJECT_MOTION__
- light_ray.time = sd.time;
-#endif
- light_ray.dP = sd.dP;
- light_ray.dD = differential3_zero();
-
- if(!shadow_blocked(kg, &state, &light_ray, &ao_shadow))
- path_radiance_accum_ao(&L, throughput, ao_alpha, ao_bsdf, ao_shadow, state.bounce);
- }
+ kernel_path_ao(kg, &sd, &L, &state, rng, throughput);
}
#endif
@@ -803,7 +805,7 @@ ccl_device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample,
hit_state.ray_t = 0.0f;
#endif
- kernel_path_indirect(kg, rng, hit_ray, buffer, tp, state.num_samples, hit_state, &L);
+ kernel_path_indirect(kg, rng, hit_ray, tp, state.num_samples, hit_state, &L);
/* for render passes, sum and reset indirect light pass variables
* for the next samples */
@@ -1022,7 +1024,7 @@ ccl_device_noinline void kernel_branched_path_integrate_lighting(KernelGlobals *
ps.ray_t = 0.0f;
#endif
- kernel_path_indirect(kg, rng, bsdf_ray, buffer, tp*num_samples_inv, num_samples, ps, L);
+ kernel_path_indirect(kg, rng, bsdf_ray, tp*num_samples_inv, num_samples, ps, L);
/* for render passes, sum and reset indirect light pass variables
* for the next samples */
@@ -1110,7 +1112,7 @@ ccl_device float4 kernel_branched_path_integrate(KernelGlobals *kg, RNG *rng, in
if(result == VOLUME_PATH_SCATTERED) {
/* todo: use all-light sampling */
if(kernel_path_integrate_scatter_lighting(kg, rng, &volume_sd, &tp, &ps, &L, &pray, num_samples_inv)) {
- kernel_path_indirect(kg, rng, pray, buffer, tp*num_samples_inv, num_samples, ps, &L);
+ kernel_path_indirect(kg, rng, pray, tp*num_samples_inv, num_samples, ps, &L);
/* for render passes, sum and reset indirect light pass variables
* for the next samples */
@@ -1150,7 +1152,7 @@ ccl_device float4 kernel_branched_path_integrate(KernelGlobals *kg, RNG *rng, in
if(result == VOLUME_PATH_SCATTERED) {
/* todo: use all-light sampling */
if(kernel_path_integrate_scatter_lighting(kg, rng, &volume_sd, &tp, &ps, &L, &pray, num_samples_inv)) {
- kernel_path_indirect(kg, rng, pray, buffer, tp*num_samples_inv, num_samples, ps, &L);
+ kernel_path_indirect(kg, rng, pray, tp*num_samples_inv, num_samples, ps, &L);
/* for render passes, sum and reset indirect light pass variables
* for the next samples */
diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h
index f83345925ea..b3656c38cae 100644
--- a/intern/cycles/kernel/kernel_types.h
+++ b/intern/cycles/kernel/kernel_types.h
@@ -160,7 +160,35 @@ typedef uint RNG;
typedef enum ShaderEvalType {
SHADER_EVAL_DISPLACE,
- SHADER_EVAL_BACKGROUND
+ SHADER_EVAL_BACKGROUND,
+ /* bake types */
+ SHADER_EVAL_BAKE, /* no real shade, it's used in the code to
+ * differentiate the type of shader eval from the above
+ */
+ /* data passes */
+ SHADER_EVAL_NORMAL,
+ SHADER_EVAL_UV,
+ SHADER_EVAL_DIFFUSE_COLOR,
+ SHADER_EVAL_GLOSSY_COLOR,
+ SHADER_EVAL_TRANSMISSION_COLOR,
+ SHADER_EVAL_SUBSURFACE_COLOR,
+ SHADER_EVAL_EMISSION,
+
+ /* light passes */
+ SHADER_EVAL_AO,
+ SHADER_EVAL_COMBINED,
+ SHADER_EVAL_SHADOW,
+ SHADER_EVAL_DIFFUSE_DIRECT,
+ SHADER_EVAL_GLOSSY_DIRECT,
+ SHADER_EVAL_TRANSMISSION_DIRECT,
+ SHADER_EVAL_SUBSURFACE_DIRECT,
+ SHADER_EVAL_DIFFUSE_INDIRECT,
+ SHADER_EVAL_GLOSSY_INDIRECT,
+ SHADER_EVAL_TRANSMISSION_INDIRECT,
+ SHADER_EVAL_SUBSURFACE_INDIRECT,
+
+ /* extra */
+ SHADER_EVAL_ENVIRONMENT,
} ShaderEvalType;
/* Path Tracing
@@ -281,7 +309,8 @@ typedef enum PassType {
PASS_MIST = 2097152,
PASS_SUBSURFACE_DIRECT = 4194304,
PASS_SUBSURFACE_INDIRECT = 8388608,
- PASS_SUBSURFACE_COLOR = 16777216
+ PASS_SUBSURFACE_COLOR = 16777216,
+ PASS_LIGHT = 33554432, /* no real pass, used to force use_light_pass */
} PassType;
#define PASS_ALL (~0)
diff --git a/intern/cycles/render/CMakeLists.txt b/intern/cycles/render/CMakeLists.txt
index 7d00ed92164..449c1391980 100644
--- a/intern/cycles/render/CMakeLists.txt
+++ b/intern/cycles/render/CMakeLists.txt
@@ -16,6 +16,7 @@ set(INC_SYS
set(SRC
attribute.cpp
background.cpp
+ bake.cpp
blackbody.cpp
buffers.cpp
camera.cpp
@@ -43,6 +44,7 @@ set(SRC
set(SRC_HEADERS
attribute.h
+ bake.h
background.h
blackbody.h
buffers.h
diff --git a/intern/cycles/render/bake.cpp b/intern/cycles/render/bake.cpp
new file mode 100644
index 00000000000..2e3022e2c02
--- /dev/null
+++ b/intern/cycles/render/bake.cpp
@@ -0,0 +1,183 @@
+/*
+ * 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 "bake.h"
+
+CCL_NAMESPACE_BEGIN
+
+BakeData::BakeData(const int object, const int tri_offset, const int num_pixels):
+m_object(object),
+m_tri_offset(tri_offset),
+m_num_pixels(num_pixels)
+{
+ m_primitive.resize(num_pixels);
+ m_u.resize(num_pixels);
+ m_v.resize(num_pixels);
+}
+
+BakeData::~BakeData()
+{
+ m_primitive.clear();
+ m_u.clear();
+ m_v.clear();
+}
+
+void BakeData::set(int i, int prim, float uv[2])
+{
+ m_primitive[i] = (prim == -1 ? -1 : m_tri_offset + prim);
+ m_u[i] = uv[0];
+ m_v[i] = uv[1];
+}
+
+int BakeData::object()
+{
+ return m_object;
+}
+
+int BakeData::size()
+{
+ return m_num_pixels;
+}
+
+bool BakeData::is_valid(int i)
+{
+ return m_primitive[i] != -1;
+}
+
+uint4 BakeData::data(int i)
+{
+ return make_uint4(
+ m_object,
+ m_primitive[i],
+ __float_as_int(m_u[i]),
+ __float_as_int(m_v[i])
+ );
+}
+
+BakeManager::BakeManager()
+{
+ m_bake_data = NULL;
+ m_is_baking = false;
+ need_update = true;
+}
+
+BakeManager::~BakeManager()
+{
+ if(m_bake_data)
+ delete m_bake_data;
+}
+
+bool BakeManager::get_baking()
+{
+ return m_is_baking;
+}
+
+void BakeManager::set_baking(const bool value)
+{
+ m_is_baking = value;
+}
+
+BakeData *BakeManager::init(const int object, const int tri_offset, const int num_pixels)
+{
+ m_bake_data = new BakeData(object, tri_offset, num_pixels);
+ return m_bake_data;
+}
+
+bool BakeManager::bake(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress, ShaderEvalType shader_type, BakeData *bake_data, float result[])
+{
+ size_t limit = bake_data->size();
+
+ /* setup input for device task */
+ device_vector<uint4> d_input;
+ uint4 *d_input_data = d_input.resize(limit);
+ size_t d_input_size = 0;
+
+ for(size_t i = 0; i < limit; i++) {
+ d_input_data[d_input_size++] = bake_data->data(i);
+ }
+
+ if(d_input_size == 0)
+ return false;
+
+ /* run device task */
+ device_vector<float4> d_output;
+ d_output.resize(d_input_size);
+
+ /* needs to be up to data for attribute access */
+ device->const_copy_to("__data", &dscene->data, sizeof(dscene->data));
+
+ device->mem_alloc(d_input, MEM_READ_ONLY);
+ device->mem_copy_to(d_input);
+ device->mem_alloc(d_output, MEM_WRITE_ONLY);
+
+ DeviceTask task(DeviceTask::SHADER);
+ task.shader_input = d_input.device_pointer;
+ task.shader_output = d_output.device_pointer;
+ task.shader_eval_type = shader_type;
+ task.shader_x = 0;
+ task.shader_w = d_output.size();
+ task.get_cancel = function_bind(&Progress::get_cancel, &progress);
+
+ device->task_add(task);
+ device->task_wait();
+
+ if(progress.get_cancel()) {
+ device->mem_free(d_input);
+ device->mem_free(d_output);
+ m_is_baking = false;
+ return false;
+ }
+
+ device->mem_copy_from(d_output, 0, 1, d_output.size(), sizeof(float4));
+ device->mem_free(d_input);
+ device->mem_free(d_output);
+
+ /* read result */
+ int k = 0;
+
+ float4 *offset = (float4*)d_output.data_pointer;
+
+ size_t depth = 4;
+ for(size_t i = 0; i < limit; i++) {
+ size_t index = i * depth;
+ float4 out = offset[k++];
+
+ if(bake_data->is_valid(i)) {
+ for(size_t j=0; j < 4; j++) {
+ result[index + j] = out[j];
+ }
+ }
+ }
+
+ m_is_baking = false;
+ return true;
+}
+
+void BakeManager::device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
+{
+ if(!need_update)
+ return;
+
+ if(progress.get_cancel()) return;
+
+ need_update = false;
+}
+
+void BakeManager::device_free(Device *device, DeviceScene *dscene)
+{
+}
+
+CCL_NAMESPACE_END
diff --git a/intern/cycles/render/bake.h b/intern/cycles/render/bake.h
new file mode 100644
index 00000000000..830a9513065
--- /dev/null
+++ b/intern/cycles/render/bake.h
@@ -0,0 +1,72 @@
+/*
+ * 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 __BAKE_H__
+#define __BAKE_H__
+
+#include "util_vector.h"
+#include "device.h"
+#include "scene.h"
+#include "session.h"
+
+CCL_NAMESPACE_BEGIN
+
+class BakeData {
+public:
+ BakeData(const int object, const int tri_offset, const int num_pixels);
+ ~BakeData();
+
+ void set(int i, int prim, float uv[2]);
+ int object();
+ int size();
+ uint4 data(int i);
+ bool is_valid(int i);
+
+private:
+ int m_object;
+ int m_tri_offset;
+ int m_num_pixels;
+ vector<int>m_primitive;
+ vector<float>m_u;
+ vector<float>m_v;
+};
+
+class BakeManager {
+public:
+ BakeManager();
+ ~BakeManager();
+
+ bool get_baking();
+ void set_baking(const bool value);
+
+ BakeData *init(const int object, const int tri_offset, const int num_pixels);
+
+ bool bake(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress, ShaderEvalType shader_type, BakeData *bake_data, float result[]);
+
+ void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress);
+ void device_free(Device *device, DeviceScene *dscene);
+
+ bool need_update;
+
+private:
+ BakeData *m_bake_data;
+ bool m_is_baking;
+};
+
+CCL_NAMESPACE_END
+
+#endif /* __BAKE_H__ */
+
diff --git a/intern/cycles/render/film.cpp b/intern/cycles/render/film.cpp
index 30ad86a8d4c..c1aefbcfbbc 100644
--- a/intern/cycles/render/film.cpp
+++ b/intern/cycles/render/film.cpp
@@ -155,6 +155,9 @@ void Pass::add(PassType type, vector<Pass>& passes)
pass.components = 4;
pass.exposure = false;
break;
+ case PASS_LIGHT:
+ /* ignores */
+ break;
}
passes.push_back(pass);
@@ -393,6 +396,10 @@ void Film::device_update(Device *device, DeviceScene *dscene, Scene *scene)
kfilm->pass_shadow = kfilm->pass_stride;
kfilm->use_light_pass = 1;
break;
+
+ case PASS_LIGHT:
+ kfilm->use_light_pass = 1;
+ break;
case PASS_NONE:
break;
}
diff --git a/intern/cycles/render/light.cpp b/intern/cycles/render/light.cpp
index dd5694582e6..a5e3fabb19d 100644
--- a/intern/cycles/render/light.cpp
+++ b/intern/cycles/render/light.cpp
@@ -29,7 +29,7 @@
CCL_NAMESPACE_BEGIN
-static void shade_background_pixels(Device *device, DeviceScene *dscene, int res, vector<float3>& pixels)
+static void shade_background_pixels(Device *device, DeviceScene *dscene, int res, vector<float3>& pixels, Progress& progress)
{
/* create input */
int width = res;
@@ -66,6 +66,7 @@ static void shade_background_pixels(Device *device, DeviceScene *dscene, int res
main_task.shader_eval_type = SHADER_EVAL_BACKGROUND;
main_task.shader_x = 0;
main_task.shader_w = width*height;
+ main_task.get_cancel = function_bind(&Progress::get_cancel, &progress);
/* disabled splitting for now, there's an issue with multi-GPU mem_copy_from */
list<DeviceTask> split_tasks;
@@ -396,7 +397,7 @@ void LightManager::device_update_background(Device *device, DeviceScene *dscene,
assert(res > 0);
vector<float3> pixels;
- shade_background_pixels(device, dscene, res, pixels);
+ shade_background_pixels(device, dscene, res, pixels, progress);
if(progress.get_cancel())
return;
diff --git a/intern/cycles/render/mesh_displace.cpp b/intern/cycles/render/mesh_displace.cpp
index 09d3ce6a588..661fd9c66c1 100644
--- a/intern/cycles/render/mesh_displace.cpp
+++ b/intern/cycles/render/mesh_displace.cpp
@@ -119,17 +119,21 @@ bool MeshManager::displace(Device *device, DeviceScene *dscene, Scene *scene, Me
task.shader_eval_type = SHADER_EVAL_DISPLACE;
task.shader_x = 0;
task.shader_w = d_output.size();
+ task.get_cancel = function_bind(&Progress::get_cancel, &progress);
device->task_add(task);
device->task_wait();
+ if(progress.get_cancel()) {
+ device->mem_free(d_input);
+ device->mem_free(d_output);
+ return false;
+ }
+
device->mem_copy_from(d_output, 0, 1, d_output.size(), sizeof(float4));
device->mem_free(d_input);
device->mem_free(d_output);
- if(progress.get_cancel())
- return false;
-
/* read result */
done.clear();
done.resize(mesh->verts.size(), false);
diff --git a/intern/cycles/render/scene.cpp b/intern/cycles/render/scene.cpp
index 2ed4efe7f2b..4a42b2c9e35 100644
--- a/intern/cycles/render/scene.cpp
+++ b/intern/cycles/render/scene.cpp
@@ -17,6 +17,7 @@
#include <stdlib.h>
#include "background.h"
+#include "bake.h"
#include "camera.h"
#include "curves.h"
#include "device.h"
@@ -54,6 +55,7 @@ Scene::Scene(const SceneParams& params_, const DeviceInfo& device_info_)
image_manager = new ImageManager();
particle_system_manager = new ParticleSystemManager();
curve_system_manager = new CurveSystemManager();
+ bake_manager = new BakeManager();
/* OSL only works on the CPU */
if(device_info_.type == DEVICE_CPU)
@@ -103,6 +105,8 @@ void Scene::free_memory(bool final)
particle_system_manager->device_free(device, &dscene);
curve_system_manager->device_free(device, &dscene);
+ bake_manager->device_free(device, &dscene);
+
if(!params.persistent_data || final)
image_manager->device_free(device, &dscene);
@@ -122,6 +126,7 @@ void Scene::free_memory(bool final)
delete particle_system_manager;
delete curve_system_manager;
delete image_manager;
+ delete bake_manager;
}
}
@@ -208,6 +213,11 @@ void Scene::device_update(Device *device_, Progress& progress)
if(progress.get_cancel()) return;
+ progress.set_status("Updating Baking");
+ bake_manager->device_update(device, &dscene, this, progress);
+
+ if(progress.get_cancel()) return;
+
progress.set_status("Updating Device", "Writing constant memory");
device->const_copy_to("__data", &dscene.data, sizeof(dscene.data));
}
@@ -258,7 +268,8 @@ bool Scene::need_reset()
|| integrator->need_update
|| shader_manager->need_update
|| particle_system_manager->need_update
- || curve_system_manager->need_update);
+ || curve_system_manager->need_update
+ || bake_manager->need_update);
}
void Scene::reset()
diff --git a/intern/cycles/render/scene.h b/intern/cycles/render/scene.h
index b6a4d6c0436..c913b4c59da 100644
--- a/intern/cycles/render/scene.h
+++ b/intern/cycles/render/scene.h
@@ -51,6 +51,8 @@ class CurveSystemManager;
class Shader;
class ShaderManager;
class Progress;
+class BakeManager;
+class BakeData;
/* Scene Device Data */
@@ -174,6 +176,7 @@ public:
ObjectManager *object_manager;
ParticleSystemManager *particle_system_manager;
CurveSystemManager *curve_system_manager;
+ BakeManager *bake_manager;
/* default shaders */
int default_surface;
diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp
index 9cf7f49754c..28b44df6b36 100644
--- a/intern/cycles/render/session.cpp
+++ b/intern/cycles/render/session.cpp
@@ -23,6 +23,7 @@
#include "integrator.h"
#include "scene.h"
#include "session.h"
+#include "bake.h"
#include "util_foreach.h"
#include "util_function.h"
@@ -733,10 +734,14 @@ void Session::update_scene()
cam->tag_update();
}
- /* number of samples is needed by multi jittered sampling pattern */
+ /* number of samples is needed by multi jittered
+ * sampling pattern and by baking */
Integrator *integrator = scene->integrator;
+ BakeManager *bake_manager = scene->bake_manager;
- if(integrator->sampling_pattern == SAMPLING_PATTERN_CMJ) {
+ if(integrator->sampling_pattern == SAMPLING_PATTERN_CMJ ||
+ bake_manager->get_baking())
+ {
int aa_samples = tile_manager.num_samples;
if(aa_samples != integrator->aa_samples) {
diff --git a/intern/cycles/render/session.h b/intern/cycles/render/session.h
index 8c597c431bb..1e625158652 100644
--- a/intern/cycles/render/session.h
+++ b/intern/cycles/render/session.h
@@ -136,6 +136,7 @@ public:
void set_samples(int samples);
void set_pause(bool pause);
+ void update_scene();
void device_free();
protected:
struct DelayedReset {
@@ -147,7 +148,6 @@ protected:
void run();
- void update_scene();
void update_status_time(bool show_pause = false, bool show_done = false);
void tonemap(int sample);