Initial implementation of 2 stage drawing.

This commit is contained in:
Jeroen Bakker 2022-11-02 15:47:53 +01:00
parent a083b23ceb
commit 935cabdb6a
6 changed files with 107 additions and 23 deletions

View File

@ -7,6 +7,7 @@
#include <cmath>
#include "BLI_float4x4.hh"
#include "BLI_jitter_2d.h"
#include "BLI_listbase.h"
#include "BLI_math.h"
@ -15,6 +16,7 @@
#include "BLI_string.h"
#include "BLI_string_utils.h"
#include "BLI_threads.h"
#include "BLI_vector.hh"
#include "BKE_armature.h"
#include "BKE_camera.h"
@ -26,6 +28,7 @@
#include "BKE_key.h"
#include "BKE_layer.h"
#include "BKE_main.h"
#include "BKE_node.h"
#include "BKE_object.h"
#include "BKE_paint.h"
#include "BKE_scene.h"
@ -40,6 +43,7 @@
#include "DNA_brush_types.h"
#include "DNA_camera_types.h"
#include "DNA_key_types.h"
#include "DNA_material_types.h"
#include "DNA_mesh_types.h"
#include "DNA_object_types.h"
#include "DNA_view3d_types.h"
@ -87,6 +91,9 @@
#include "view3d_intern.h" /* own include */
using blender::float4;
using blender::float4x4;
using blender::int2;
using blender::Vector;
#define M_GOLDEN_RATIO_CONJUGATE 0.618033988749895f
@ -1535,8 +1542,78 @@ void view3d_draw_region_info(const bContext *C, ARegion *region)
/** \name Draw Viewport Contents
* \{ */
static void view3d_virtual_camera_stage_set(Main *bmain, const bool virtual_stage)
{
LISTBASE_FOREACH (Camera *, camera, &bmain->cameras) {
camera->runtime.virtual_camera_stage = virtual_stage;
}
}
static void view3d_virtual_camera_update(const bContext *C, ARegion *region, Object *object)
{
BLI_assert(object->type == OB_CAMERA);
Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
Scene *scene = CTX_data_scene(C);
View3D *v3d = CTX_wm_view3d(C);
int2 resolution(1920 / 2, 1080 / 2);
Camera *camera = static_cast<Camera *>(object->data);
RenderEngineType *engine_type = ED_view3d_engine_type(scene, OB_RENDER);
if (camera->runtime.virtual_display_texture == nullptr) {
camera->runtime.virtual_display_texture = GPU_offscreen_create(
UNPACK2(resolution), true, GPU_RGBA16F, nullptr);
}
GPUOffScreen *offscreen = camera->runtime.virtual_display_texture;
GPU_offscreen_bind(offscreen, true);
DRW_draw_render_loop_offscreen(
depsgraph, engine_type, region, v3d, true, false, false, offscreen, nullptr);
GPU_offscreen_unbind(offscreen, true);
}
static void view3d_draw_virtual_camera(const bContext *C, ARegion *region)
{
Main *bmain = CTX_data_main(C);
// create a custom view3d offscreen rendering.
Vector<Object *> virtual_cameras;
LISTBASE_FOREACH (Material *, material, &bmain->materials) {
if (!material->nodetree) {
continue;
}
LISTBASE_FOREACH (bNode *, node, &material->nodetree->nodes) {
if (node->type != SH_NODE_VIRTUAL_CAMERA) {
continue;
}
Object *ob = static_cast<Object *>(static_cast<void *>(node->id));
if (ob == nullptr || ob->type != OB_CAMERA) {
continue;
}
virtual_cameras.append(ob);
}
}
if (virtual_cameras.is_empty()) {
/* No virtual cameras, so skip updating. */
return;
}
// go over each camera and set the flag to virtual camera.
view3d_virtual_camera_stage_set(bmain, true);
for (Object *object : virtual_cameras) {
view3d_virtual_camera_update(C, region, object);
}
// get reference of the gpu texture and change its ownership
// go over eah camera and set the flag back to main camera.
view3d_virtual_camera_stage_set(bmain, false);
}
static void view3d_draw_view(const bContext *C, ARegion *region)
{
view3d_draw_virtual_camera(C, region);
ED_view3d_draw_setup_view(CTX_wm_manager(C),
CTX_wm_window(C),
CTX_data_expect_evaluated_depsgraph(C),

View File

@ -20,6 +20,7 @@
#include "BLI_string.h"
#include "BLI_utildefines.h"
#include "GPU_framebuffer.h"
#include "GPU_texture.h"
#include "GPU_vertex_format.h"
@ -115,6 +116,7 @@ static void gpu_node_input_link(GPUNode *node, GPUNodeLink *link, const eGPUType
link->users++;
break;
case GPU_NODE_LINK_IMAGE:
case GPU_NODE_LINK_IMAGE_CAMERA:
case GPU_NODE_LINK_IMAGE_TILED:
case GPU_NODE_LINK_IMAGE_SKY:
case GPU_NODE_LINK_COLORBAND:
@ -635,15 +637,12 @@ GPUNodeLink *GPU_image_camera(GPUMaterial *mat, Camera *camera, eGPUSamplerState
{
GPUNodeGraph *graph = gpu_material_node_graph(mat);
GPUNodeLink *link = gpu_node_link_create();
link->link_type = GPU_NODE_LINK_IMAGE;
link->texture = gpu_node_graph_add_texture(graph,
NULL,
NULL,
NULL,
NULL,
&camera->runtime.virtual_display_texture,
link->link_type,
sampler_state);
GPUTexture *texture = camera->runtime.virtual_camera_stage ?
NULL :
GPU_offscreen_color_texture(camera->runtime.virtual_display_texture);
link->link_type = GPU_NODE_LINK_IMAGE_CAMERA;
link->texture = gpu_node_graph_add_texture(
graph, NULL, NULL, NULL, NULL, &texture, link->link_type, sampler_state);
return link;
}

View File

@ -50,6 +50,7 @@ typedef enum {
GPU_NODE_LINK_IMAGE_TILED,
GPU_NODE_LINK_IMAGE_TILED_MAPPING,
GPU_NODE_LINK_IMAGE_SKY,
GPU_NODE_LINK_IMAGE_CAMERA,
GPU_NODE_LINK_OUTPUT,
GPU_NODE_LINK_UNIFORM,
GPU_NODE_LINK_DIFFERENTIATE_FLOAT_FN,

View File

@ -4,8 +4,13 @@ void node_virtual_camera_empty(vec3 co, out vec4 color, out float alpha)
alpha = 0.0;
}
void node_virtual_camera(vec3 co, sampler2D ima, out vec4 color, out float alpha)
void node_virtual_camera(vec3 co, sampler2D ima, float mix, out vec4 color, out float alpha)
{
if (mix == 1.0) {
node_virtual_camera_empty(co, color, alpha);
return;
}
color = texture(ima, co.xy);
alpha = color.a;
}

View File

@ -76,7 +76,7 @@ typedef struct Camera_Runtime {
* when scene camera/main camera is evaluated. */
int virtual_camera_stage;
int _pad[1];
struct GPUTexture *virtual_display_texture;
struct GPUOffScreen *virtual_display_texture;
} Camera_Runtime;
typedef struct Camera {

View File

@ -5,6 +5,8 @@
#include "DNA_camera_types.h"
#include "DEG_depsgraph_query.h"
namespace blender::nodes::node_shader_virtual_camera_cc {
static void sh_node_virtual_camera_declare(NodeDeclarationBuilder &b)
@ -25,21 +27,21 @@ static int node_shader_gpu_virtual_camera(GPUMaterial *mat,
return GPU_stack_link(mat, node, "node_virtual_camera_empty", in, out);
}
Camera *cam = static_cast<Camera *>(object->data);
Object *orig_object = DEG_get_original_object(object);
Camera *cam = static_cast<Camera *>(orig_object->data);
const bool virtual_camera_stage = cam->runtime.virtual_camera_stage;
if (virtual_camera_stage || cam->runtime.virtual_display_texture == nullptr) {
return GPU_stack_link(mat, node, "node_virtual_camera_empty", in, out);
}
const float stage_mix = virtual_camera_stage ? 1.0f : 0.0f;
GPUNodeLink **texco = &in[0].link;
if (!*texco) {
*texco = GPU_attribute(mat, CD_AUTO_FROM_NAME, "");
node_shader_gpu_bump_tex_coord(mat, node, texco);
}
node_shader_gpu_tex_mapping(mat, node, in, out);
node_shader_gpu_default_tex_coord(mat, node, &in[0].link);
return GPU_stack_link(
mat, node, "node_virtual_camera", in, out, GPU_image_camera(mat, cam, GPU_SAMPLER_DEFAULT));
return GPU_stack_link(mat,
node,
"node_virtual_camera",
in,
out,
GPU_image_camera(mat, cam, GPU_SAMPLER_DEFAULT),
GPU_uniform(&stage_mix));
}
} // namespace blender::nodes::node_shader_virtual_camera_cc