2022-02-11 09:07:11 +11:00
|
|
|
/* SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
|
* Copyright 2016 Blender Foundation. */
|
2018-07-11 11:43:56 +02:00
|
|
|
|
2019-02-18 08:08:12 +11:00
|
|
|
/** \file
|
|
|
|
|
* \ingroup draw_engine
|
2018-07-11 11:43:56 +02:00
|
|
|
*
|
|
|
|
|
* Render functions for final render output.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include "BLI_rect.h"
|
|
|
|
|
|
2019-09-07 23:17:40 +10:00
|
|
|
#include "DNA_node_types.h"
|
|
|
|
|
|
2018-07-11 11:43:56 +02:00
|
|
|
#include "BKE_report.h"
|
|
|
|
|
|
|
|
|
|
#include "DRW_render.h"
|
|
|
|
|
|
2019-04-09 12:29:02 +02:00
|
|
|
#include "ED_view3d.h"
|
|
|
|
|
|
2022-07-01 10:30:16 +02:00
|
|
|
#include "GPU_context.h"
|
2018-07-11 11:43:56 +02:00
|
|
|
#include "GPU_shader.h"
|
|
|
|
|
|
|
|
|
|
#include "DEG_depsgraph.h"
|
|
|
|
|
#include "DEG_depsgraph_query.h"
|
|
|
|
|
|
|
|
|
|
#include "RE_pipeline.h"
|
|
|
|
|
|
|
|
|
|
#include "workbench_private.h"
|
|
|
|
|
|
2020-03-11 17:07:43 +01:00
|
|
|
static void workbench_render_cache(void *vedata,
|
|
|
|
|
struct Object *ob,
|
|
|
|
|
struct RenderEngine *UNUSED(engine),
|
|
|
|
|
struct Depsgraph *UNUSED(depsgraph))
|
2018-07-11 11:43:56 +02:00
|
|
|
{
|
2020-03-11 17:07:43 +01:00
|
|
|
workbench_cache_populate(vedata, ob);
|
2018-08-21 10:59:01 +02:00
|
|
|
}
|
|
|
|
|
|
2018-07-11 11:43:56 +02:00
|
|
|
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));
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-02-13 17:44:51 +11:00
|
|
|
/* Set the perspective, view and window matrix. */
|
2019-05-20 20:33:56 +02:00
|
|
|
float winmat[4][4], viewmat[4][4], viewinv[4][4];
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-03-27 10:05:08 +01:00
|
|
|
RE_GetCameraWindow(engine->re, ob_camera_eval, winmat);
|
2018-07-11 11:43:56 +02:00
|
|
|
RE_GetCameraModelMatrix(engine->re, ob_camera_eval, viewinv);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-11 11:43:56 +02:00
|
|
|
invert_m4_m4(viewmat, viewinv);
|
2019-05-20 20:33:56 +02:00
|
|
|
|
|
|
|
|
DRWView *view = DRW_view_create(viewmat, winmat, NULL, NULL, NULL);
|
|
|
|
|
DRW_view_default_set(view);
|
|
|
|
|
DRW_view_set_active(view);
|
2018-07-11 11:43:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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();
|
2019-06-26 15:15:39 +02:00
|
|
|
|
|
|
|
|
/* When doing a multi view rendering the first view will allocate the buffers
|
|
|
|
|
* the other views will reuse these buffers */
|
|
|
|
|
if (dtxl->color == NULL) {
|
2022-12-08 23:30:57 +01:00
|
|
|
eGPUTextureUsage usage = GPU_TEXTURE_USAGE_SHADER_READ | GPU_TEXTURE_USAGE_ATTACHMENT;
|
2019-06-26 15:15:39 +02:00
|
|
|
BLI_assert(dtxl->depth == NULL);
|
2022-12-08 23:30:57 +01:00
|
|
|
dtxl->color = GPU_texture_create_2d_ex(
|
|
|
|
|
"txl.color", UNPACK2(size), 1, GPU_RGBA16F, usage, NULL);
|
|
|
|
|
dtxl->depth = GPU_texture_create_2d_ex(
|
|
|
|
|
"txl.depth", UNPACK2(size), 1, GPU_DEPTH24_STENCIL8, usage, NULL);
|
2019-06-26 15:15:39 +02:00
|
|
|
}
|
2018-07-11 11:43:56 +02:00
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-09 16:27:24 +01:00
|
|
|
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),
|
2020-09-07 21:08:31 +02:00
|
|
|
GPU_DATA_FLOAT,
|
2020-03-09 16:27:24 +01:00
|
|
|
rp->rect);
|
|
|
|
|
|
|
|
|
|
float winmat[4][4];
|
|
|
|
|
DRW_view_winmat_get(NULL, winmat, false);
|
|
|
|
|
|
2022-05-11 13:19:56 +10:00
|
|
|
int pix_num = BLI_rcti_size_x(rect) * BLI_rcti_size_y(rect);
|
2020-03-09 16:27:24 +01:00
|
|
|
|
|
|
|
|
/* Convert ogl depth [0..1] to view Z [near..far] */
|
|
|
|
|
if (DRW_view_is_persp_get(NULL)) {
|
2022-05-11 13:19:56 +10:00
|
|
|
for (int i = 0; i < pix_num; i++) {
|
2020-03-09 16:27:24 +01:00
|
|
|
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);
|
|
|
|
|
|
2022-05-11 13:19:56 +10:00
|
|
|
for (int i = 0; i < pix_num; i++) {
|
2020-03-09 16:27:24 +01:00
|
|
|
if (rp->rect[i] == 1.0f) {
|
|
|
|
|
rp->rect[i] = 1e10f; /* Background */
|
|
|
|
|
}
|
|
|
|
|
else {
|
2021-02-01 13:49:07 +01:00
|
|
|
rp->rect[i] = rp->rect[i] * range - near;
|
2020-03-09 16:27:24 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-11 17:07:43 +01:00
|
|
|
void workbench_render(void *ved, RenderEngine *engine, RenderLayer *render_layer, const rcti *rect)
|
2018-07-11 11:43:56 +02:00
|
|
|
{
|
2020-03-11 17:07:43 +01:00
|
|
|
WORKBENCH_Data *data = ved;
|
2019-03-16 02:47:03 +01:00
|
|
|
DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
|
2018-07-11 11:43:56 +02:00
|
|
|
const DRWContextState *draw_ctx = DRW_context_state_get();
|
|
|
|
|
Depsgraph *depsgraph = draw_ctx->depsgraph;
|
|
|
|
|
workbench_render_matrices_init(engine, depsgraph);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-07-11 11:43:56 +02:00
|
|
|
if (!workbench_render_framebuffers_init()) {
|
|
|
|
|
RE_engine_report(engine, RPT_ERROR, "Failed to allocate OpenGL buffers");
|
|
|
|
|
return;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-01-26 17:40:35 +01:00
|
|
|
workbench_private_data_alloc(data->stl);
|
|
|
|
|
data->stl->wpd->cam_original_ob = DEG_get_evaluated_object(depsgraph, RE_GetCamera(engine->re));
|
2020-03-11 17:07:43 +01:00
|
|
|
workbench_engine_init(data);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-03-11 17:07:43 +01:00
|
|
|
workbench_cache_init(data);
|
|
|
|
|
DRW_render_object_iter(data, engine, depsgraph, workbench_render_cache);
|
|
|
|
|
workbench_cache_finish(data);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-03-11 17:07:43 +01:00
|
|
|
DRW_render_instance_buffer_finish();
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-04-22 10:43:48 -05:00
|
|
|
/* Also we weed to have a correct FBO bound for #DRW_curves_update */
|
2020-03-11 17:07:43 +01:00
|
|
|
GPU_framebuffer_bind(dfbl->default_fb);
|
2022-04-22 10:43:48 -05:00
|
|
|
DRW_curves_update();
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-03-11 17:07:43 +01:00
|
|
|
GPU_framebuffer_bind(dfbl->default_fb);
|
|
|
|
|
GPU_framebuffer_clear_depth(dfbl->default_fb, 1.0f);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-03-11 17:07:43 +01:00
|
|
|
WORKBENCH_PrivateData *wpd = data->stl->wpd;
|
|
|
|
|
while (wpd->taa_sample < max_ii(1, wpd->taa_sample_len)) {
|
|
|
|
|
if (RE_engine_test_break(engine)) {
|
|
|
|
|
break;
|
2018-08-21 10:59:01 +02:00
|
|
|
}
|
2020-03-11 17:07:43 +01:00
|
|
|
workbench_update_world_ubo(wpd);
|
|
|
|
|
workbench_draw_sample(data);
|
2018-08-21 10:59:01 +02:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-03-11 17:07:43 +01:00
|
|
|
workbench_draw_finish(data);
|
|
|
|
|
|
2022-07-01 10:30:16 +02:00
|
|
|
/* Perform render step between samples to allow
|
|
|
|
|
* flushing of freed GPUBackend resources. */
|
|
|
|
|
GPU_render_step();
|
|
|
|
|
|
2018-07-11 11:43:56 +02:00
|
|
|
/* Write render output. */
|
|
|
|
|
const char *viewname = RE_GetActiveRenderView(engine->re);
|
|
|
|
|
RenderPass *rp = RE_pass_find_by_name(render_layer, RE_PASSNAME_COMBINED, viewname);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-03-09 16:27:24 +01:00
|
|
|
GPU_framebuffer_bind(dfbl->default_fb);
|
|
|
|
|
GPU_framebuffer_read_color(dfbl->default_fb,
|
2018-07-11 11:43:56 +02:00
|
|
|
rect->xmin,
|
|
|
|
|
rect->ymin,
|
|
|
|
|
BLI_rcti_size_x(rect),
|
|
|
|
|
BLI_rcti_size_y(rect),
|
|
|
|
|
4,
|
|
|
|
|
0,
|
2020-07-16 02:50:55 +02:00
|
|
|
GPU_DATA_FLOAT,
|
2018-07-11 11:43:56 +02:00
|
|
|
rp->rect);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-03-09 16:27:24 +01:00
|
|
|
workbench_render_result_z(render_layer, viewname, rect);
|
2018-07-11 11:43:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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);
|
2022-12-13 01:45:52 +01:00
|
|
|
if ((view_layer->passflag & SCE_PASS_Z) != 0) {
|
|
|
|
|
RE_engine_register_pass(engine, scene, view_layer, RE_PASSNAME_Z, 1, "Z", SOCK_FLOAT);
|
|
|
|
|
}
|
2018-07-11 11:43:56 +02:00
|
|
|
}
|