This repository has been archived on 2023-10-09. You can view files and clone it, but cannot push or open issues or pull requests.
Files
blender-archive/source/blender/draw/engines/workbench/workbench_render.c
Campbell Barton fa7ee622f0 Cleanup: includes in headers
Forward declare structs where possible.
2019-09-07 23:17:40 +10:00

217 lines
7.0 KiB
C

/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Copyright 2016, Blender Foundation.
*/
/** \file
* \ingroup draw_engine
*
* Render functions for final render output.
*/
#include "BLI_rect.h"
#include "DNA_node_types.h"
#include "BKE_report.h"
#include "DRW_render.h"
#include "ED_view3d.h"
#include "GPU_shader.h"
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_query.h"
#include "RE_pipeline.h"
#include "workbench_private.h"
static void workbench_render_deferred_cache(void *vedata,
struct Object *ob,
struct RenderEngine *UNUSED(engine),
struct Depsgraph *UNUSED(depsgraph))
{
workbench_deferred_solid_cache_populate(vedata, ob);
}
static void workbench_render_forward_cache(void *vedata,
struct Object *ob,
struct RenderEngine *UNUSED(engine),
struct Depsgraph *UNUSED(depsgraph))
{
workbench_forward_cache_populate(vedata, ob);
}
static void workbench_render_matrices_init(RenderEngine *engine, Depsgraph *depsgraph)
{
/* TODO(sergey): Shall render hold pointer to an evaluated camera instead? */
Scene *scene = DEG_get_evaluated_scene(depsgraph);
struct Object *ob_camera_eval = DEG_get_evaluated_object(depsgraph, RE_GetCamera(engine->re));
float frame = BKE_scene_frame_get(scene);
/* Set the persective, view and window matrix. */
float winmat[4][4], viewmat[4][4], viewinv[4][4];
RE_GetCameraWindow(engine->re, ob_camera_eval, frame, winmat);
RE_GetCameraModelMatrix(engine->re, ob_camera_eval, viewinv);
invert_m4_m4(viewmat, viewinv);
DRWView *view = DRW_view_create(viewmat, winmat, NULL, NULL, NULL);
DRW_view_default_set(view);
DRW_view_set_active(view);
}
static bool workbench_render_framebuffers_init(void)
{
/* For image render, allocate own buffers because we don't have a viewport. */
const float *viewport_size = DRW_viewport_size_get();
const int size[2] = {(int)viewport_size[0], (int)viewport_size[1]};
DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
/* When doing a multi view rendering the first view will allocate the buffers
* the other views will reuse these buffers */
if (dtxl->color == NULL) {
BLI_assert(dtxl->depth == NULL);
dtxl->color = GPU_texture_create_2d(size[0], size[1], GPU_RGBA16F, NULL, NULL);
dtxl->depth = GPU_texture_create_2d(size[0], size[1], GPU_DEPTH24_STENCIL8, NULL, NULL);
}
if (!(dtxl->depth && dtxl->color)) {
return false;
}
DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
GPU_framebuffer_ensure_config(
&dfbl->default_fb,
{GPU_ATTACHMENT_TEXTURE(dtxl->depth), GPU_ATTACHMENT_TEXTURE(dtxl->color)});
GPU_framebuffer_ensure_config(&dfbl->depth_only_fb,
{GPU_ATTACHMENT_TEXTURE(dtxl->depth), GPU_ATTACHMENT_NONE});
GPU_framebuffer_ensure_config(&dfbl->color_only_fb,
{GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(dtxl->color)});
bool ok = true;
ok = ok && GPU_framebuffer_check_valid(dfbl->default_fb, NULL);
ok = ok && GPU_framebuffer_check_valid(dfbl->color_only_fb, NULL);
ok = ok && GPU_framebuffer_check_valid(dfbl->depth_only_fb, NULL);
return ok;
}
static void workbench_render_framebuffers_finish(void)
{
}
void workbench_render(WORKBENCH_Data *data,
RenderEngine *engine,
RenderLayer *render_layer,
const rcti *rect)
{
DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
const DRWContextState *draw_ctx = DRW_context_state_get();
const Scene *scene = draw_ctx->scene;
Depsgraph *depsgraph = draw_ctx->depsgraph;
workbench_render_matrices_init(engine, depsgraph);
if (!workbench_render_framebuffers_init()) {
RE_engine_report(engine, RPT_ERROR, "Failed to allocate OpenGL buffers");
return;
}
const bool deferred = !XRAY_FLAG_ENABLED(&scene->display);
if (deferred) {
/* Init engine. */
workbench_deferred_engine_init(data);
/* Init objects. */
workbench_deferred_cache_init(data);
DRW_render_object_iter(data, engine, depsgraph, workbench_render_deferred_cache);
workbench_deferred_cache_finish(data);
DRW_render_instance_buffer_finish();
/* Also we weed to have a correct fbo bound for DRW_hair_update */
GPU_framebuffer_bind(dfbl->color_only_fb);
DRW_hair_update();
/* Draw. */
int num_samples = workbench_taa_calculate_num_iterations(data);
for (int sample = 0; sample < num_samples; sample++) {
if (RE_engine_test_break(engine)) {
break;
}
workbench_deferred_draw_background(data);
workbench_deferred_draw_scene(data);
}
workbench_deferred_draw_finish(data);
}
else {
/* Init engine. */
workbench_forward_engine_init(data);
/* Init objects. */
workbench_forward_cache_init(data);
DRW_render_object_iter(data, engine, depsgraph, workbench_render_forward_cache);
workbench_forward_cache_finish(data);
DRW_render_instance_buffer_finish();
/* Also we weed to have a correct fbo bound for DRW_hair_update */
GPU_framebuffer_bind(dfbl->color_only_fb);
DRW_hair_update();
/* Draw. */
int num_samples = workbench_taa_calculate_num_iterations(data);
for (int sample = 0; sample < num_samples; sample++) {
if (RE_engine_test_break(engine)) {
break;
}
workbench_forward_draw_background(data);
workbench_forward_draw_scene(data);
}
workbench_forward_draw_finish(data);
}
/* Write render output. */
const char *viewname = RE_GetActiveRenderView(engine->re);
RenderPass *rp = RE_pass_find_by_name(render_layer, RE_PASSNAME_COMBINED, viewname);
GPU_framebuffer_bind(dfbl->color_only_fb);
GPU_framebuffer_read_color(dfbl->color_only_fb,
rect->xmin,
rect->ymin,
BLI_rcti_size_x(rect),
BLI_rcti_size_y(rect),
4,
0,
rp->rect);
workbench_render_framebuffers_finish();
}
void workbench_render_update_passes(RenderEngine *engine, Scene *scene, ViewLayer *view_layer)
{
RE_engine_register_pass(engine, scene, view_layer, RE_PASSNAME_COMBINED, 4, "RGBA", SOCK_RGBA);
}