This repository has been archived on 2023-10-09. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
blender-archive/source/blender/draw/engines/workbench/workbench_render.c
Philipp Oeser ff62481f65 Fix T69060: File Output Node does not work with Time Remapping
Problem is that the RenderEngines will change the RenderData cfra when
rendering (when time remapping is used -- at least workbench/eevee/
gpencil do a combination of BKE_scene_frame_get() plus
RE_GetCameraWindow() which alters the RenderData cfra).

Later on in the pipeline, the Compositor will use this RenderData cfra
to determine the output file name for the FileOutput node. (In contrast
to this, the 'regular' Output will use the Scene's RenderData -- not the
Render's -- cfra [which hasnt been altered])

It is not entirely clear why RE_GetCameraWindow was setting the cfra on
the Render, but it appears to be legacy OGL rendering related and is not
needed anymore.
Removing this will keep the cfra as needed for the Compositor FileOutput
node.
2020-03-27 10:10:54 +01:00

224 lines
7.2 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_cache(void *vedata,
struct Object *ob,
struct RenderEngine *UNUSED(engine),
struct Depsgraph *UNUSED(depsgraph))
{
workbench_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? */
struct Object *ob_camera_eval = DEG_get_evaluated_object(depsgraph, RE_GetCamera(engine->re));
/* Set the persective, view and window matrix. */
float winmat[4][4], viewmat[4][4], viewinv[4][4];
RE_GetCameraWindow(engine->re, ob_camera_eval, 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_result_z(struct RenderLayer *rl,
const char *viewname,
const rcti *rect)
{
DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
const DRWContextState *draw_ctx = DRW_context_state_get();
ViewLayer *view_layer = draw_ctx->view_layer;
if ((view_layer->passflag & SCE_PASS_Z) != 0) {
RenderPass *rp = RE_pass_find_by_name(rl, RE_PASSNAME_Z, viewname);
GPU_framebuffer_bind(dfbl->default_fb);
GPU_framebuffer_read_depth(dfbl->default_fb,
rect->xmin,
rect->ymin,
BLI_rcti_size_x(rect),
BLI_rcti_size_y(rect),
rp->rect);
float winmat[4][4];
DRW_view_winmat_get(NULL, winmat, false);
int pix_ct = BLI_rcti_size_x(rect) * BLI_rcti_size_y(rect);
/* Convert ogl depth [0..1] to view Z [near..far] */
if (DRW_view_is_persp_get(NULL)) {
for (int i = 0; i < pix_ct; i++) {
if (rp->rect[i] == 1.0f) {
rp->rect[i] = 1e10f; /* Background */
}
else {
rp->rect[i] = rp->rect[i] * 2.0f - 1.0f;
rp->rect[i] = winmat[3][2] / (rp->rect[i] + winmat[2][2]);
}
}
}
else {
/* Keep in mind, near and far distance are negatives. */
float near = DRW_view_near_distance_get(NULL);
float far = DRW_view_far_distance_get(NULL);
float range = fabsf(far - near);
for (int i = 0; i < pix_ct; i++) {
if (rp->rect[i] == 1.0f) {
rp->rect[i] = 1e10f; /* Background */
}
else {
rp->rect[i] = -rp->rect[i] * range + near;
}
}
}
}
}
void workbench_render(void *ved, RenderEngine *engine, RenderLayer *render_layer, const rcti *rect)
{
WORKBENCH_Data *data = ved;
DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
const DRWContextState *draw_ctx = DRW_context_state_get();
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;
}
workbench_engine_init(data);
workbench_cache_init(data);
DRW_render_object_iter(data, engine, depsgraph, workbench_render_cache);
workbench_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->default_fb);
DRW_hair_update();
GPU_framebuffer_bind(dfbl->default_fb);
GPU_framebuffer_clear_depth(dfbl->default_fb, 1.0f);
WORKBENCH_PrivateData *wpd = data->stl->wpd;
while (wpd->taa_sample < max_ii(1, wpd->taa_sample_len)) {
if (RE_engine_test_break(engine)) {
break;
}
workbench_update_world_ubo(wpd);
workbench_draw_sample(data);
}
workbench_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->default_fb);
GPU_framebuffer_read_color(dfbl->default_fb,
rect->xmin,
rect->ymin,
BLI_rcti_size_x(rect),
BLI_rcti_size_y(rect),
4,
0,
rp->rect);
workbench_render_result_z(render_layer, viewname, rect);
}
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);
}