diff options
author | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2011-08-28 17:55:59 +0400 |
---|---|---|
committer | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2011-08-28 17:55:59 +0400 |
commit | bae896691aa3d7bb2a75292da3cc490894996b01 (patch) | |
tree | 9c3703f11ccdf76c575c2ea18b70dee1ff665913 /intern/cycles/render | |
parent | d48e4fc92be346810baa8cac595ab0a735882a87 (diff) |
Cycles:
* Add alpha pass output, to use set Transparent option in Film panel.
* Add Holdout closure (OSL terminology), this is like the Sky option in the
internal renderer, objects with this closure show the background / zero
alpha.
* Add option to use Gaussian instead of Box pixel filter in the UI.
* Remove camera response curves for now, they don't really belong here in
the pipeline, should be moved to compositor.
* Output full float values for rendering now, previously was only byte precision.
* Add a patch from Thomas to get a preview passes option, but still disabled
because it isn't quite working right yet.
* CUDA: don't compile shader graph evaluation inline.
* Convert tabs to spaces in python files.
Diffstat (limited to 'intern/cycles/render')
-rw-r--r-- | intern/cycles/render/CMakeLists.txt | 2 | ||||
-rw-r--r-- | intern/cycles/render/background.cpp | 6 | ||||
-rw-r--r-- | intern/cycles/render/background.h | 1 | ||||
-rw-r--r-- | intern/cycles/render/buffers.cpp | 59 | ||||
-rw-r--r-- | intern/cycles/render/buffers.h | 4 | ||||
-rw-r--r-- | intern/cycles/render/camera.h | 2 | ||||
-rw-r--r-- | intern/cycles/render/film.cpp | 72 | ||||
-rw-r--r-- | intern/cycles/render/film.h | 2 | ||||
-rw-r--r-- | intern/cycles/render/filter.cpp | 11 | ||||
-rw-r--r-- | intern/cycles/render/filter.h | 7 | ||||
-rw-r--r-- | intern/cycles/render/mesh.cpp | 2 | ||||
-rw-r--r-- | intern/cycles/render/nodes.cpp | 18 | ||||
-rw-r--r-- | intern/cycles/render/nodes.h | 5 | ||||
-rw-r--r-- | intern/cycles/render/scene.h | 5 | ||||
-rw-r--r-- | intern/cycles/render/session.cpp | 49 | ||||
-rw-r--r-- | intern/cycles/render/session.h | 10 | ||||
-rw-r--r-- | intern/cycles/render/tile.cpp | 12 | ||||
-rw-r--r-- | intern/cycles/render/tile.h | 3 |
18 files changed, 163 insertions, 107 deletions
diff --git a/intern/cycles/render/CMakeLists.txt b/intern/cycles/render/CMakeLists.txt index c3d5ae1ea05..14859aa4414 100644 --- a/intern/cycles/render/CMakeLists.txt +++ b/intern/cycles/render/CMakeLists.txt @@ -15,7 +15,6 @@ set(sources buffers.cpp camera.cpp film.cpp - film_response.cpp filter.cpp graph.cpp image.cpp @@ -39,7 +38,6 @@ set(headers buffers.h camera.h film.h - film_response.h filter.h graph.h image.h diff --git a/intern/cycles/render/background.cpp b/intern/cycles/render/background.cpp index 871fe128514..bf4131b6d38 100644 --- a/intern/cycles/render/background.cpp +++ b/intern/cycles/render/background.cpp @@ -31,6 +31,7 @@ CCL_NAMESPACE_BEGIN Background::Background() { + transparent = false; need_update = true; } @@ -45,8 +46,9 @@ void Background::device_update(Device *device, DeviceScene *dscene, Scene *scene device_free(device, dscene); - /* set shader index */ + /* set shader index and transparent option */ KernelBackground *kbackground = &dscene->data.background; + kbackground->transparent = transparent; kbackground->shader = scene->shader_manager->get_shader_id(scene->default_background); need_update = false; @@ -58,7 +60,7 @@ void Background::device_free(Device *device, DeviceScene *dscene) bool Background::modified(const Background& background) { - return false; + return !(transparent == background.transparent); } void Background::tag_update(Scene *scene) diff --git a/intern/cycles/render/background.h b/intern/cycles/render/background.h index a048cbc535c..16d2ccb6caa 100644 --- a/intern/cycles/render/background.h +++ b/intern/cycles/render/background.h @@ -29,6 +29,7 @@ class Scene; class Background { public: + bool transparent; bool need_update; Background(); diff --git a/intern/cycles/render/buffers.cpp b/intern/cycles/render/buffers.cpp index c1d9158c85e..62dc17960ae 100644 --- a/intern/cycles/render/buffers.cpp +++ b/intern/cycles/render/buffers.cpp @@ -24,6 +24,7 @@ #include "util_debug.h" #include "util_hash.h" #include "util_image.h" +#include "util_math.h" #include "util_opengl.h" #include "util_time.h" #include "util_types.h" @@ -84,6 +85,33 @@ void RenderBuffers::reset(Device *device, int width_, int height_) device->mem_copy_to(rng_state); } +float4 *RenderBuffers::copy_from_device(float exposure, int pass) +{ + if(!buffer.device_pointer) + return NULL; + + device->mem_copy_from(buffer, 0, buffer.memory_size()); + + float4 *out = new float4[width*height]; + float4 *in = (float4*)buffer.data_pointer; + float scale = 1.0f/(float)pass; + + for(int i = width*height - 1; i >= 0; i--) { + float4 rgba = in[i]*scale; + + rgba.x = rgba.x*exposure; + rgba.y = rgba.y*exposure; + rgba.z = rgba.z*exposure; + + /* clamp since alpha might be > 1.0 due to russian roulette */ + rgba.w = clamp(rgba.w, 0.0f, 1.0f); + + out[i] = rgba; + } + + return out; +} + /* Display Buffer */ DisplayBuffer::DisplayBuffer(Device *device_) @@ -93,6 +121,7 @@ DisplayBuffer::DisplayBuffer(Device *device_) height = 0; draw_width = 0; draw_height = 0; + transparent = true; /* todo: determine from background */ } DisplayBuffer::~DisplayBuffer() @@ -132,10 +161,36 @@ void DisplayBuffer::draw_set(int width_, int height_) draw_height = height_; } +void DisplayBuffer::draw_transparency_grid() +{ + GLubyte checker_stipple_sml[32*32/8] = { + 255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0, \ + 255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0, \ + 0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255, \ + 0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255, \ + 255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0, \ + 255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0, \ + 0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255, \ + 0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255, \ + }; + + glColor4ub(50, 50, 50, 255); + glRectf(0, 0, width, height); + glEnable(GL_POLYGON_STIPPLE); + glColor4ub(55, 55, 55, 255); + glPolygonStipple(checker_stipple_sml); + glRectf(0, 0, width, height); + glDisable(GL_POLYGON_STIPPLE); +} + void DisplayBuffer::draw(Device *device) { - if(draw_width != 0 && draw_height != 0) - device->draw_pixels(rgba, 0, draw_width, draw_height, width, height); + if(draw_width != 0 && draw_height != 0) { + if(transparent) + draw_transparency_grid(); + + device->draw_pixels(rgba, 0, draw_width, draw_height, width, height, transparent); + } } bool DisplayBuffer::draw_ready() diff --git a/intern/cycles/render/buffers.h b/intern/cycles/render/buffers.h index 1922f875d86..e99fedb0dff 100644 --- a/intern/cycles/render/buffers.h +++ b/intern/cycles/render/buffers.h @@ -47,6 +47,7 @@ public: ~RenderBuffers(); void reset(Device *device, int width, int height); + float4 *copy_from_device(float exposure, int pass); protected: void device_free(); @@ -67,6 +68,8 @@ public: with progressive render we can be using only a subset of the buffer. if these are zero, it means nothing can be drawn yet */ int draw_width, draw_height; + /* draw alpha channel? */ + bool transparent; /* byte buffer for tonemapped result */ device_vector<uchar4> rgba; /* mutex, must be locked manually by callers */ @@ -83,6 +86,7 @@ public: bool draw_ready(); protected: + void draw_transparency_grid(); void device_free(); Device *device; diff --git a/intern/cycles/render/camera.h b/intern/cycles/render/camera.h index 6ae8c8fa4ae..d385aa274f4 100644 --- a/intern/cycles/render/camera.h +++ b/intern/cycles/render/camera.h @@ -19,8 +19,6 @@ #ifndef __CAMERA_H__ #define __CAMERA_H__ -#include "film_response.h" - #include "util_transform.h" #include "util_types.h" diff --git a/intern/cycles/render/film.cpp b/intern/cycles/render/film.cpp index 05874244605..657abd97f70 100644 --- a/intern/cycles/render/film.cpp +++ b/intern/cycles/render/film.cpp @@ -19,30 +19,13 @@ #include "camera.h" #include "device.h" #include "film.h" -#include "film_response.h" #include "scene.h" CCL_NAMESPACE_BEGIN -static FilmResponseType find_response_type(const string& name) -{ - if(name == "" || name == "None") - return FILM_RESPONSE_NONE; - - for(size_t i = 0; i < FILM_RESPONSE_NUM; i++) { - FilmResponse *curve = &FILM_RESPONSE[i]; - if(curve->name == name) - return (FilmResponseType)i; - } - - return FILM_RESPONSE_NONE; -} - Film::Film() { exposure = 0.8f; - response = "Advantix 400"; - last_response = ""; need_update = true; } @@ -50,18 +33,6 @@ Film::~Film() { } -#if 0 -static void generate_python_enum() -{ - for(size_t i = 0; i < FILM_RESPONSE_NUM; i++) { - FilmResponse *curve = &FILM_RESPONSE[i]; - /*if(i == 0 || strcmp(curve->brand, FILM_RESPONSE[i-1].brand)) - printf("(\"\", \"%s\", \"\"),\n", curve->brand);*/ - printf("(\"%s\", \"%s %s\", \"\"),\n", curve->name, curve->brand, curve->name); - } -} -#endif - void Film::device_update(Device *device, DeviceScene *dscene) { if(!need_update) @@ -72,57 +43,16 @@ void Film::device_update(Device *device, DeviceScene *dscene) /* update __data */ kfilm->exposure = exposure; - FilmResponseType response_type = find_response_type(response); - - /* update __response_curves */ - if(response != last_response) { - device_free(device, dscene); - - if(response_type != FILM_RESPONSE_NONE) { - FilmResponse *curve = &FILM_RESPONSE[response_type]; - size_t response_curve_size = FILM_RESPONSE_SIZE; - - dscene->response_curve_R.copy(curve->B_R, response_curve_size); - - if(curve->rgb) { - dscene->response_curve_G.copy(curve->B_G, response_curve_size); - dscene->response_curve_B.copy(curve->B_B, response_curve_size); - } - else { - dscene->response_curve_G.copy(curve->B_R, response_curve_size); - dscene->response_curve_B.copy(curve->B_R, response_curve_size); - } - - device->tex_alloc("__response_curve_R", dscene->response_curve_R, true); - device->tex_alloc("__response_curve_G", dscene->response_curve_G, true); - device->tex_alloc("__response_curve_B", dscene->response_curve_B, true); - } - - last_response = response; - } - - kfilm->use_response_curve = (response_type != FILM_RESPONSE_NONE); - need_update = false; } void Film::device_free(Device *device, DeviceScene *dscene) { - device->tex_free(dscene->response_curve_R); - device->tex_free(dscene->response_curve_G); - device->tex_free(dscene->response_curve_B); - - dscene->response_curve_R.clear(); - dscene->response_curve_G.clear(); - dscene->response_curve_B.clear(); - - last_response = ""; } bool Film::modified(const Film& film) { - return !(response == film.response && - exposure == film.exposure && + return !(exposure == film.exposure && pass == film.pass); } diff --git a/intern/cycles/render/film.h b/intern/cycles/render/film.h index 9d6c58b30d1..201fc174f4f 100644 --- a/intern/cycles/render/film.h +++ b/intern/cycles/render/film.h @@ -29,8 +29,6 @@ class Scene; class Film { public: - string response; - string last_response; float exposure; int pass; bool need_update; diff --git a/intern/cycles/render/filter.cpp b/intern/cycles/render/filter.cpp index d7682bedc12..4925521e4a5 100644 --- a/intern/cycles/render/filter.cpp +++ b/intern/cycles/render/filter.cpp @@ -125,5 +125,16 @@ void Filter::device_free(Device *device, DeviceScene *dscene) dscene->filter_table.clear(); } +bool Filter::modified(const Filter& filter) +{ + return !(filter_type == filter.filter_type && + filter_width == filter.filter_width); +} + +void Filter::tag_update(Scene *scene) +{ + need_update = true; +} + CCL_NAMESPACE_END diff --git a/intern/cycles/render/filter.h b/intern/cycles/render/filter.h index 620e6ebe083..5df7bb8fd14 100644 --- a/intern/cycles/render/filter.h +++ b/intern/cycles/render/filter.h @@ -21,6 +21,10 @@ CCL_NAMESPACE_BEGIN +class Device; +class DeviceScene; +class Scene; + typedef enum FilterType { FILTER_BOX, FILTER_GAUSSIAN @@ -38,6 +42,9 @@ public: void device_update(Device *device, DeviceScene *dscene); void device_free(Device *device, DeviceScene *dscene); + + bool modified(const Filter& filter); + void tag_update(Scene *scene); }; CCL_NAMESPACE_END diff --git a/intern/cycles/render/mesh.cpp b/intern/cycles/render/mesh.cpp index aae32851131..b9163309652 100644 --- a/intern/cycles/render/mesh.cpp +++ b/intern/cycles/render/mesh.cpp @@ -392,7 +392,7 @@ void MeshManager::device_update_attributes(Device *device, DeviceScene *dscene, progress.set_status("Updating Mesh", "Computing attributes"); /* gather per mesh requested attributes. as meshes may have multiple - * shaders assigned, this merged the requested attributes that have + * shaders assigned, this merges the requested attributes that have * been set per shader by the shader manager */ vector<AttributeRequestSet> mesh_attributes(scene->meshes.size()); diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp index 546d74c5c22..5ffc3fbbabb 100644 --- a/intern/cycles/render/nodes.cpp +++ b/intern/cycles/render/nodes.cpp @@ -1275,6 +1275,24 @@ void BackgroundNode::compile(OSLCompiler& compiler) compiler.add(this, "node_background"); } +/* Holdout Closure */ + +HoldoutNode::HoldoutNode() +: ShaderNode("holdout") +{ + add_output("Holdout", SHADER_SOCKET_CLOSURE); +} + +void HoldoutNode::compile(SVMCompiler& compiler) +{ + compiler.add_node(NODE_CLOSURE_HOLDOUT, CLOSURE_HOLDOUT_ID); +} + +void HoldoutNode::compile(OSLCompiler& compiler) +{ + compiler.add(this, "node_holdout"); +} + /* Geometry */ GeometryNode::GeometryNode() diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h index da3b743e79b..2afe585c3ac 100644 --- a/intern/cycles/render/nodes.h +++ b/intern/cycles/render/nodes.h @@ -257,6 +257,11 @@ public: SHADER_NODE_CLASS(BackgroundNode) }; +class HoldoutNode : public ShaderNode { +public: + SHADER_NODE_CLASS(HoldoutNode) +}; + class GeometryNode : public ShaderNode { public: SHADER_NODE_CLASS(GeometryNode) diff --git a/intern/cycles/render/scene.h b/intern/cycles/render/scene.h index 965a0054846..9d475cd9fa5 100644 --- a/intern/cycles/render/scene.h +++ b/intern/cycles/render/scene.h @@ -84,11 +84,6 @@ public: /* filter */ device_vector<float> filter_table; - /* film */ - device_vector<float> response_curve_R; - device_vector<float> response_curve_G; - device_vector<float> response_curve_B; - /* integrator */ device_vector<uint> sobol_directions; diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp index 56fbadcee08..5890714d740 100644 --- a/intern/cycles/render/session.cpp +++ b/intern/cycles/render/session.cpp @@ -52,6 +52,7 @@ Session::Session(const SessionParams& params_) delayed_reset.do_reset = false; delayed_reset.w = 0; delayed_reset.h = 0; + delayed_reset.passes = 0; display_outdated = false; gpu_draw_ready = false; @@ -95,7 +96,7 @@ bool Session::ready_to_reset() /* GPU Session */ -void Session::reset_gpu(int w, int h) +void Session::reset_gpu(int w, int h, int passes) { /* block for buffer acces and reset immediately. we can't do this in the thread, because we need to allocate an OpenGL buffer, and @@ -106,7 +107,7 @@ void Session::reset_gpu(int w, int h) display_outdated = true; reset_time = time_dt(); - reset_(w, h); + reset_(w, h, passes); gpu_need_tonemap = false; gpu_need_tonemap_cond.notify_all(); @@ -148,7 +149,14 @@ void Session::run_gpu() start_time = time_dt(); reset_time = time_dt(); - while(!progress.get_cancel() && tile_manager.next()) { + while(!progress.get_cancel()) { + bool done = !tile_manager.next(); + + if(done && params.background) + break; + + /* todo: wait when done in interactive mode */ + /* buffers mutex is locked entirely while rendering each pass, and released/reacquired on each iteration to allow reset and draw in between */ @@ -193,7 +201,7 @@ void Session::run_gpu() /* CPU Session */ -void Session::reset_cpu(int w, int h) +void Session::reset_cpu(int w, int h, int passes) { thread_scoped_lock reset_lock(delayed_reset.mutex); @@ -202,6 +210,7 @@ void Session::reset_cpu(int w, int h) delayed_reset.w = w; delayed_reset.h = h; + delayed_reset.passes = passes; delayed_reset.do_reset = true; device->task_cancel(); } @@ -235,11 +244,18 @@ void Session::run_cpu() thread_scoped_lock buffers_lock(buffers->mutex); thread_scoped_lock display_lock(display->mutex); - reset_(delayed_reset.w, delayed_reset.h); + reset_(delayed_reset.w, delayed_reset.h, delayed_reset.passes); delayed_reset.do_reset = false; } - while(!progress.get_cancel() && tile_manager.next()) { + while(!progress.get_cancel()) { + bool done = !tile_manager.next(); + + if(done && params.background) + break; + + /* todo: wait when done in interactive mode */ + { thread_scoped_lock buffers_lock(buffers->mutex); @@ -266,7 +282,7 @@ void Session::run_cpu() if(delayed_reset.do_reset) { /* reset rendering if request from main thread */ delayed_reset.do_reset = false; - reset_(delayed_reset.w, delayed_reset.h); + reset_(delayed_reset.w, delayed_reset.h, delayed_reset.passes); } else { /* tonemap only if we do not reset, we don't we don't @@ -313,7 +329,7 @@ bool Session::draw(int w, int h) return draw_cpu(w, h); } -void Session::reset_(int w, int h) +void Session::reset_(int w, int h, int passes) { if(w != buffers->width || h != buffers->height) { gpu_draw_ready = false; @@ -321,19 +337,28 @@ void Session::reset_(int w, int h) display->reset(device, w, h); } - tile_manager.reset(w, h); + tile_manager.reset(w, h, passes); start_time = time_dt(); preview_time = 0.0; pass = 0; } -void Session::reset(int w, int h) +void Session::reset(int w, int h, int passes) { if(device_use_gl) - reset_gpu(w, h); + reset_gpu(w, h, passes); else - reset_cpu(w, h); + reset_cpu(w, h, passes); +} + +void Session::set_passes(int passes) +{ + if(passes != params.passes) { + params.passes = passes; + tile_manager.set_passes(passes); + /* todo: awake in paused loop */ + } } void Session::wait() diff --git a/intern/cycles/render/session.h b/intern/cycles/render/session.h index 3411dcd23c6..18983f55353 100644 --- a/intern/cycles/render/session.h +++ b/intern/cycles/render/session.h @@ -107,13 +107,15 @@ public: void wait(); bool ready_to_reset(); - void reset(int w, int h); + void reset(int w, int h, int passes); + void set_passes(int passes); protected: struct DelayedReset { thread_mutex mutex; bool do_reset; int w, h; + int passes; } delayed_reset; void run(); @@ -123,15 +125,15 @@ protected: void tonemap(); void path_trace(Tile& tile); - void reset_(int w, int h); + void reset_(int w, int h, int passes); void run_cpu(); bool draw_cpu(int w, int h); - void reset_cpu(int w, int h); + void reset_cpu(int w, int h, int passes); void run_gpu(); bool draw_gpu(int w, int h); - void reset_gpu(int w, int h); + void reset_gpu(int w, int h, int passes); TileManager tile_manager; bool device_use_gl; diff --git a/intern/cycles/render/tile.cpp b/intern/cycles/render/tile.cpp index 28ea39e70ed..450090c42f8 100644 --- a/intern/cycles/render/tile.cpp +++ b/intern/cycles/render/tile.cpp @@ -25,18 +25,17 @@ CCL_NAMESPACE_BEGIN TileManager::TileManager(bool progressive_, int passes_, int tile_size_, int min_size_) { progressive = progressive_; - passes = passes_; tile_size = tile_size_; min_size = min_size_; - reset(0, 0); + reset(0, 0, 0); } TileManager::~TileManager() { } -void TileManager::reset(int width_, int height_) +void TileManager::reset(int width_, int height_, int passes_) { full_width = width_; full_height = height_; @@ -54,6 +53,8 @@ void TileManager::reset(int width_, int height_) } } + passes = passes_; + state.width = 0; state.height = 0; state.pass = -1; @@ -61,6 +62,11 @@ void TileManager::reset(int width_, int height_) state.tiles.clear(); } +void TileManager::set_passes(int passes_) +{ + passes = passes_; +} + void TileManager::set_tiles() { int resolution = state.resolution; diff --git a/intern/cycles/render/tile.h b/intern/cycles/render/tile.h index c3517b1e24d..56c69cdce88 100644 --- a/intern/cycles/render/tile.h +++ b/intern/cycles/render/tile.h @@ -50,7 +50,8 @@ public: TileManager(bool progressive, int passes, int tile_size, int min_size); ~TileManager(); - void reset(int width, int height); + void reset(int width, int height, int passes); + void set_passes(int passes); bool next(); bool done(); |