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; /* copy data from device */ if(!buffers->copy_from_device()) return; BufferParams& params = buffers->params; float exposure = scene->film->exposure; vector<float> pixels(params.width*params.height*4); if(!do_update_only) { /* copy each pass */ BL::RenderLayer::passes_iterator b_iter; for(b_rlay.passes.begin(b_iter); b_iter != b_rlay.passes.end(); ++b_iter) { BL::RenderPass b_pass(*b_iter); /* find matching pass type */ PassType pass_type = get_pass_type(b_pass); int components = b_pass.channels(); /* copy pixels */ if(!buffers->get_pass_rect(pass_type, exposure, rtile.sample, components, &pixels[0])) memset(&pixels[0], 0, pixels.size()*sizeof(float)); b_pass.rect(&pixels[0]); } } else { /* copy combined pass */ BL::RenderPass b_combined_pass(b_rlay.passes.find_by_type(BL::RenderPass::type_COMBINED, b_rview_name.c_str())); if(buffers->get_pass_rect(PASS_COMBINED, exposure, rtile.sample, 4, &pixels[0])) b_combined_pass.rect(&pixels[0]); } /* tag result as updated */ b_engine.update_result(b_rr); }
void BlenderSession::write_render_result() { /* get state */ RenderBuffers *buffers = session->buffers; /* copy data from device */ if(!buffers->copy_from_device()) return; BufferParams& params = buffers->params; float exposure = scene->film->exposure; double total_time, sample_time; int sample; session->progress.get_sample(sample, total_time, sample_time); vector<float> pixels(params.width*params.height*4); /* copy each pass */ BL::RenderLayer::passes_iterator b_iter; for(b_rlay.passes.begin(b_iter); b_iter != b_rlay.passes.end(); ++b_iter) { BL::RenderPass b_pass(*b_iter); /* find matching pass type */ PassType pass_type = get_pass_type(b_pass); int components = b_pass.channels(); /* copy pixels */ if(buffers->get_pass(pass_type, exposure, sample, components, &pixels[0])) rna_RenderPass_rect_set(&b_pass.ptr, &pixels[0]); } /* copy combined pass */ if(buffers->get_pass(PASS_COMBINED, exposure, sample, 4, &pixels[0])) rna_RenderLayer_rect_set(&b_rlay.ptr, &pixels[0]); /* tag result as updated */ RE_engine_update_result((RenderEngine*)b_engine.ptr.data, (RenderResult*)b_rr.ptr.data); }
void BlenderSession::render() { /* set callback to write out render results */ session->write_render_tile_cb = function_bind(&BlenderSession::write_render_tile, this, _1); session->update_render_tile_cb = function_bind(&BlenderSession::update_render_tile, this, _1); /* 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_v3d, b_rv3d, scene->camera, width, height); /* render each layer */ BL::RenderSettings r = b_scene.render(); BL::RenderSettings::layers_iterator b_layer_iter; BL::RenderResult::views_iterator b_view_iter; for(r.layers.begin(b_layer_iter); b_layer_iter != r.layers.end(); ++b_layer_iter) { b_rlay_name = b_layer_iter->name(); /* temporary render result to find needed passes and views */ BL::RenderResult b_rr = begin_render_result(b_engine, 0, 0, 1, 1, b_rlay_name.c_str(), NULL); BL::RenderResult::layers_iterator b_single_rlay; b_rr.layers.begin(b_single_rlay); /* layer will be missing if it was disabled in the UI */ if(b_single_rlay == b_rr.layers.end()) { end_render_result(b_engine, b_rr, true, false); continue; } BL::RenderLayer b_rlay = *b_single_rlay; /* add passes */ vector<Pass> passes; Pass::add(PASS_COMBINED, passes); #ifdef WITH_CYCLES_DEBUG Pass::add(PASS_BVH_TRAVERSAL_STEPS, passes); #endif if(session_params.device.advanced_shading) { /* loop over passes */ BL::RenderLayer::passes_iterator b_pass_iter; for(b_rlay.passes.begin(b_pass_iter); b_pass_iter != b_rlay.passes.end(); ++b_pass_iter) { BL::RenderPass b_pass(*b_pass_iter); PassType pass_type = get_pass_type(b_pass); if(pass_type == PASS_MOTION && scene->integrator->motion_blur) continue; if(pass_type != PASS_NONE) Pass::add(pass_type, passes); } } buffer_params.passes = passes; scene->film->pass_alpha_threshold = b_layer_iter->pass_alpha_threshold(); scene->film->tag_passes_update(scene, passes); scene->film->tag_update(scene); scene->integrator->tag_update(scene); for(b_rr.views.begin(b_view_iter); b_view_iter != b_rr.views.end(); ++b_view_iter) { b_rview_name = b_view_iter->name(); /* set the current view */ b_engine.active_view_set(b_rview_name.c_str()); /* 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, b_rlay_name.c_str()); /* update number of samples per layer */ int samples = sync->get_layer_samples(); bool bound_samples = sync->get_layer_bound_samples(); if(samples != 0 && (!bound_samples || (samples < session_params.samples))) session->reset(buffer_params, samples); else session->reset(buffer_params, session_params.samples); /* render */ session->start(); session->wait(); if(session->progress.get_cancel()) break; } /* free result without merging */ end_render_result(b_engine, b_rr, true, false); if(session->progress.get_cancel()) break; } /* clear callback */ session->write_render_tile_cb = function_null; session->update_render_tile_cb = function_null; /* 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::render() { /* get buffer parameters */ SessionParams session_params = BlenderSync::get_session_params(b_userpref, b_scene, background); BufferParams buffer_params = BlenderSync::get_buffer_params(b_scene, b_rv3d, width, height); int w = buffer_params.width, h = buffer_params.height; /* create render result */ RenderResult *rrp = RE_engine_begin_result((RenderEngine*)b_engine.ptr.data, 0, 0, w, h); PointerRNA rrptr; RNA_pointer_create(NULL, &RNA_RenderResult, rrp, &rrptr); b_rr = BL::RenderResult(rrptr); BL::RenderSettings r = b_scene.render(); BL::RenderResult::layers_iterator b_iter; BL::RenderLayers b_rr_layers(r.ptr); /* render each layer */ for(b_rr.layers.begin(b_iter); b_iter != b_rr.layers.end(); ++b_iter) { /* set layer */ b_rlay = *b_iter; /* add passes */ vector<Pass> passes; Pass::add(PASS_COMBINED, passes); if(session_params.device.advanced_shading) { BL::RenderLayer::passes_iterator b_pass_iter; for(b_rlay.passes.begin(b_pass_iter); b_pass_iter != b_rlay.passes.end(); ++b_pass_iter) { BL::RenderPass b_pass(*b_pass_iter); PassType pass_type = get_pass_type(b_pass); if(pass_type != PASS_NONE) Pass::add(pass_type, passes); } } buffer_params.passes = passes; scene->film->passes = passes; scene->film->tag_update(scene); /* update session */ session->reset(buffer_params, session_params.samples); /* update scene */ sync->sync_data(b_v3d, b_iter->name().c_str()); /* render */ session->start(); session->wait(); if(session->progress.get_cancel()) break; /* write result */ write_render_result(); } /* delete render result */ RE_engine_end_result((RenderEngine*)b_engine.ptr.data, (RenderResult*)b_rr.ptr.data); }
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Update render image, with passes if needed ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void BlenderSession::do_write_update_render_result(BL::RenderResult b_rr, BL::RenderLayer b_rlay, bool do_update_only) { int buf_size = width * height * 4; float* pixels = pass_buffers[0]; if(!pixels) { pixels = new float[buf_size]; pass_buffers[0] = pixels; } float* mb_pixels = mb_pass_buffers[0]; if(motion_blur && !mb_pixels) { mb_pixels = new float[buf_size]; mb_pass_buffers[0] = mb_pixels; } Passes::PassTypes cur_pass_type; if(scene->passes->use_passes) cur_pass_type = scene->passes->cur_pass_type; else cur_pass_type = Passes::COMBINED; if(scene->passes->use_passes && session->server->cur_pass_type != cur_pass_type) session->server->get_image_buffer(session->params.image_stat, session->params.interactive ? 0 : (session->params.hdr_tonemapped ? 2 : 1), cur_pass_type, session->progress); if(motion_blur && mb_type == SUBFRAME && mb_cur_sample > 1) { if(!do_update_only) { for(unsigned int k = 0; k < buf_size; ++k) pixels[k] = (pixels[k] * (mb_cur_sample - 1) + mb_pixels[k]) / (float)mb_cur_sample; } else { if(mb_cur_sample > 2 && mb_cur_sample > mb_sample_in_work) { mb_sample_in_work = mb_cur_sample; for(unsigned int k = 0; k < buf_size; ++k) pixels[k] = (pixels[k] * (mb_cur_sample - 2) + mb_pixels[k]) / (float)(mb_cur_sample - 1); } session->server->get_pass_rect(cur_pass_type, 4, mb_pixels, width, height, (scene->camera->use_border ? scene->camera->border.z - scene->camera->border.x : width), (scene->camera->use_border ? scene->camera->border.w - scene->camera->border.y : height)); } b_rlay.rect(pixels); } else if(session->server->get_pass_rect(cur_pass_type, 4, pixels, width, height, (scene->camera->use_border ? scene->camera->border.z - scene->camera->border.x : width), (scene->camera->use_border ? scene->camera->border.w - scene->camera->border.y : height))) b_rlay.rect(pixels); if(scene->passes->use_passes && (!do_update_only || (motion_blur && mb_type == SUBFRAME && session->params.image_stat.cur_samples >= session->params.samples))) { // Copy each pass BL::RenderLayer::passes_iterator b_iter; for(b_rlay.passes.begin(b_iter); b_iter != b_rlay.passes.end(); ++b_iter) { BL::RenderPass b_pass(*b_iter); int components = b_pass.channels(); buf_size = width * height * components; // Find matching pass type Passes::PassTypes pass_type = get_octane_pass_type(b_pass); if(pass_type == Passes::COMBINED) continue; else if(pass_type == Passes::PASS_NONE || !session->server->get_image_buffer(session->params.image_stat, session->params.interactive ? 0 : (session->params.hdr_tonemapped ? 2 : 1), pass_type, session->progress)) { if(!do_update_only) { float* pixels = new float[buf_size]; memset(pixels, 0, sizeof(float) * buf_size); b_pass.rect(pixels); delete[] pixels; } continue; } int pass_idx = get_pass_index(pass_type); pixels = pass_buffers[pass_idx]; if(!pixels) { pixels = new float[buf_size]; pass_buffers[pass_idx] = pixels; } mb_pixels = mb_pass_buffers[pass_idx]; if(motion_blur && !mb_pixels) { mb_pixels = new float[buf_size]; mb_pass_buffers[pass_idx] = mb_pixels; } if(motion_blur && mb_type == SUBFRAME && mb_cur_sample > 1) { if(!do_update_only) { for(unsigned int k = 0; k < buf_size; ++k) pixels[k] = (pixels[k] * (mb_cur_sample - 1) + mb_pixels[k]) / (float)mb_cur_sample; } else { if(mb_cur_sample > 2 && mb_cur_sample > mb_sample_in_work) { mb_sample_in_work = mb_cur_sample; for(unsigned int k = 0; k < buf_size; ++k) pixels[k] = (pixels[k] * (mb_cur_sample - 2) + mb_pixels[k]) / (float)(mb_cur_sample - 1); } session->server->get_pass_rect(pass_type, components, mb_pixels, width, height, (scene->camera->use_border ? scene->camera->border.z - scene->camera->border.x : width), (scene->camera->use_border ? scene->camera->border.w - scene->camera->border.y : height)); } b_pass.rect(pixels); } else { if(session->server->get_pass_rect(pass_type, components, pixels, width, height, (scene->camera->use_border ? scene->camera->border.z - scene->camera->border.x : width), (scene->camera->use_border ? scene->camera->border.w - scene->camera->border.y : height))) b_pass.rect(pixels); } } //for(b_rlay.passes.begin(b_iter); b_iter != b_rlay.passes.end(); ++b_iter) } //if(scene->passes->use_passes && (!do_update_only || motion_blur && mb_type == SUBFRAME)) // Tag result as updated b_engine.update_result(b_rr); } //do_write_update_render_result()
void BlenderSession::render() { /* set callback to write out render results */ session->write_render_tile_cb = function_bind(&BlenderSession::write_render_tile, this, _1); session->update_render_tile_cb = function_bind(&BlenderSession::update_render_tile, this, _1); /* 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_scene, b_v3d, b_rv3d, scene->camera, width, height); /* render each layer */ BL::RenderSettings r = b_scene.render(); BL::RenderSettings::layers_iterator b_iter; for(r.layers.begin(b_iter); b_iter != r.layers.end(); ++b_iter) { b_rlay_name = b_iter->name(); /* temporary render result to find needed passes */ BL::RenderResult b_rr = begin_render_result(b_engine, 0, 0, 1, 1, b_rlay_name.c_str()); BL::RenderResult::layers_iterator b_single_rlay; b_rr.layers.begin(b_single_rlay); /* layer will be missing if it was disabled in the UI */ if(b_single_rlay == b_rr.layers.end()) { end_render_result(b_engine, b_rr, true); continue; } BL::RenderLayer b_rlay = *b_single_rlay; /* add passes */ vector<Pass> passes; Pass::add(PASS_COMBINED, passes); if(session_params.device.advanced_shading) { /* loop over passes */ BL::RenderLayer::passes_iterator b_pass_iter; for(b_rlay.passes.begin(b_pass_iter); b_pass_iter != b_rlay.passes.end(); ++b_pass_iter) { BL::RenderPass b_pass(*b_pass_iter); PassType pass_type = get_pass_type(b_pass); if(pass_type == PASS_MOTION && scene->integrator->motion_blur) continue; if(pass_type != PASS_NONE) Pass::add(pass_type, passes); } } /* free result without merging */ end_render_result(b_engine, b_rr, true); buffer_params.passes = passes; scene->film->tag_passes_update(scene, passes); scene->film->tag_update(scene); scene->integrator->tag_update(scene); /* update scene */ sync->sync_data(b_v3d, b_engine.camera_override(), b_rlay_name.c_str()); /* update session */ int samples = sync->get_layer_samples(); session->reset(buffer_params, (samples == 0)? session_params.samples: samples); /* render */ session->start(); session->wait(); if(session->progress.get_cancel()) break; } /* clear callback */ session->write_render_tile_cb = NULL; session->update_render_tile_cb = NULL; /* 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; }