123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298 |
- /*
- * 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 "render/bake.h"
- #include "render/mesh.h"
- #include "render/object.h"
- #include "render/shader.h"
- #include "render/integrator.h"
- #include "util/util_foreach.h"
- CCL_NAMESPACE_BEGIN
- BakeData::BakeData(const int object, const size_t tri_offset, const size_t 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);
- m_dudx.resize(num_pixels);
- m_dudy.resize(num_pixels);
- m_dvdx.resize(num_pixels);
- m_dvdy.resize(num_pixels);
- }
- BakeData::~BakeData()
- {
- m_primitive.clear();
- m_u.clear();
- m_v.clear();
- m_dudx.clear();
- m_dudy.clear();
- m_dvdx.clear();
- m_dvdy.clear();
- }
- void BakeData::set(int i, int prim, float uv[2], float dudx, float dudy, float dvdx, float dvdy)
- {
- m_primitive[i] = (prim == -1 ? -1 : m_tri_offset + prim);
- m_u[i] = uv[0];
- m_v[i] = uv[1];
- m_dudx[i] = dudx;
- m_dudy[i] = dudy;
- m_dvdx[i] = dvdx;
- m_dvdy[i] = dvdy;
- }
- void BakeData::set_null(int i)
- {
- m_primitive[i] = -1;
- }
- int BakeData::object()
- {
- return m_object;
- }
- size_t 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]));
- }
- uint4 BakeData::differentials(int i)
- {
- return make_uint4(__float_as_int(m_dudx[i]),
- __float_as_int(m_dudy[i]),
- __float_as_int(m_dvdx[i]),
- __float_as_int(m_dvdy[i]));
- }
- BakeManager::BakeManager()
- {
- m_bake_data = NULL;
- m_is_baking = false;
- need_update = true;
- m_shader_limit = 512 * 512;
- }
- 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 size_t tri_offset, const size_t num_pixels)
- {
- m_bake_data = new BakeData(object, tri_offset, num_pixels);
- return m_bake_data;
- }
- void BakeManager::set_shader_limit(const size_t x, const size_t y)
- {
- m_shader_limit = x * y;
- m_shader_limit = (size_t)pow(2, ceil(log(m_shader_limit) / log(2)));
- }
- bool BakeManager::bake(Device *device,
- DeviceScene *dscene,
- Scene *scene,
- Progress &progress,
- ShaderEvalType shader_type,
- const int pass_filter,
- BakeData *bake_data,
- float result[])
- {
- size_t num_pixels = bake_data->size();
- int num_samples = aa_samples(scene, bake_data, shader_type);
- /* calculate the total pixel samples for the progress bar */
- total_pixel_samples = 0;
- for (size_t shader_offset = 0; shader_offset < num_pixels; shader_offset += m_shader_limit) {
- size_t shader_size = (size_t)fminf(num_pixels - shader_offset, m_shader_limit);
- total_pixel_samples += shader_size * num_samples;
- }
- progress.reset_sample();
- progress.set_total_pixel_samples(total_pixel_samples);
- /* needs to be up to date for baking specific AA samples */
- dscene->data.integrator.aa_samples = num_samples;
- device->const_copy_to("__data", &dscene->data, sizeof(dscene->data));
- for (size_t shader_offset = 0; shader_offset < num_pixels; shader_offset += m_shader_limit) {
- size_t shader_size = (size_t)fminf(num_pixels - shader_offset, m_shader_limit);
- /* setup input for device task */
- device_vector<uint4> d_input(device, "bake_input", MEM_READ_ONLY);
- uint4 *d_input_data = d_input.alloc(shader_size * 2);
- size_t d_input_size = 0;
- for (size_t i = shader_offset; i < (shader_offset + shader_size); i++) {
- d_input_data[d_input_size++] = bake_data->data(i);
- d_input_data[d_input_size++] = bake_data->differentials(i);
- }
- if (d_input_size == 0) {
- m_is_baking = false;
- return false;
- }
- /* run device task */
- device_vector<float4> d_output(device, "bake_output", MEM_READ_WRITE);
- d_output.alloc(shader_size);
- d_output.zero_to_device();
- d_input.copy_to_device();
- 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_filter = pass_filter;
- task.shader_x = 0;
- task.offset = shader_offset;
- task.shader_w = d_output.size();
- task.num_samples = num_samples;
- task.get_cancel = function_bind(&Progress::get_cancel, &progress);
- task.update_progress_sample = function_bind(&Progress::add_samples_update, &progress, _1, _2);
- device->task_add(task);
- device->task_wait();
- if (progress.get_cancel()) {
- d_input.free();
- d_output.free();
- m_is_baking = false;
- return false;
- }
- d_output.copy_from_device(0, 1, d_output.size());
- d_input.free();
- /* read result */
- int k = 0;
- float4 *offset = d_output.data();
- size_t depth = 4;
- for (size_t i = shader_offset; i < (shader_offset + shader_size); 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];
- }
- }
- }
- d_output.free();
- }
- 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*/)
- {
- }
- int BakeManager::aa_samples(Scene *scene, BakeData *bake_data, ShaderEvalType type)
- {
- if (type == SHADER_EVAL_UV || type == SHADER_EVAL_ROUGHNESS) {
- return 1;
- }
- else if (type == SHADER_EVAL_NORMAL) {
- /* Only antialias normal if mesh has bump mapping. */
- Object *object = scene->objects[bake_data->object()];
- if (object->mesh) {
- foreach (Shader *shader, object->mesh->used_shaders) {
- if (shader->has_bump) {
- return scene->integrator->aa_samples;
- }
- }
- }
- return 1;
- }
- else {
- return scene->integrator->aa_samples;
- }
- }
- /* Keep it synced with kernel_bake.h logic */
- int BakeManager::shader_type_to_pass_filter(ShaderEvalType type, const int pass_filter)
- {
- const int component_flags = pass_filter &
- (BAKE_FILTER_DIRECT | BAKE_FILTER_INDIRECT | BAKE_FILTER_COLOR);
- switch (type) {
- case SHADER_EVAL_AO:
- return BAKE_FILTER_AO;
- case SHADER_EVAL_SHADOW:
- return BAKE_FILTER_DIRECT;
- case SHADER_EVAL_DIFFUSE:
- return BAKE_FILTER_DIFFUSE | component_flags;
- case SHADER_EVAL_GLOSSY:
- return BAKE_FILTER_GLOSSY | component_flags;
- case SHADER_EVAL_TRANSMISSION:
- return BAKE_FILTER_TRANSMISSION | component_flags;
- case SHADER_EVAL_SUBSURFACE:
- return BAKE_FILTER_SUBSURFACE | component_flags;
- case SHADER_EVAL_COMBINED:
- return pass_filter;
- default:
- return 0;
- }
- }
- CCL_NAMESPACE_END
|