From 935cabdb6af74a0d31799d4b1f8111a17bcc2772 Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Wed, 2 Nov 2022 15:47:53 +0100 Subject: Initial implementation of 2 stage drawing. --- source/blender/editors/space_view3d/view3d_draw.cc | 77 ++++++++++++++++++++++ source/blender/gpu/intern/gpu_node_graph.c | 17 +++-- source/blender/gpu/intern/gpu_node_graph.h | 1 + .../gpu_shader_material_virtual_camera.glsl | 7 +- source/blender/makesdna/DNA_camera_types.h | 2 +- .../shader/nodes/node_shader_virtual_camera.cc | 26 ++++---- 6 files changed, 107 insertions(+), 23 deletions(-) diff --git a/source/blender/editors/space_view3d/view3d_draw.cc b/source/blender/editors/space_view3d/view3d_draw.cc index 31b26ba4cda..15356adab58 100644 --- a/source/blender/editors/space_view3d/view3d_draw.cc +++ b/source/blender/editors/space_view3d/view3d_draw.cc @@ -7,6 +7,7 @@ #include +#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(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 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(static_cast(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), diff --git a/source/blender/gpu/intern/gpu_node_graph.c b/source/blender/gpu/intern/gpu_node_graph.c index 17136308cdd..553ca219617 100644 --- a/source/blender/gpu/intern/gpu_node_graph.c +++ b/source/blender/gpu/intern/gpu_node_graph.c @@ -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; } diff --git a/source/blender/gpu/intern/gpu_node_graph.h b/source/blender/gpu/intern/gpu_node_graph.h index de0a0687b13..6417f7d0a47 100644 --- a/source/blender/gpu/intern/gpu_node_graph.h +++ b/source/blender/gpu/intern/gpu_node_graph.h @@ -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, diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_virtual_camera.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_virtual_camera.glsl index 05bc6f90686..26d15292e6a 100644 --- a/source/blender/gpu/shaders/material/gpu_shader_material_virtual_camera.glsl +++ b/source/blender/gpu/shaders/material/gpu_shader_material_virtual_camera.glsl @@ -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; } diff --git a/source/blender/makesdna/DNA_camera_types.h b/source/blender/makesdna/DNA_camera_types.h index b6a5b95e404..a257f3b876b 100644 --- a/source/blender/makesdna/DNA_camera_types.h +++ b/source/blender/makesdna/DNA_camera_types.h @@ -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 { diff --git a/source/blender/nodes/shader/nodes/node_shader_virtual_camera.cc b/source/blender/nodes/shader/nodes/node_shader_virtual_camera.cc index 1e26ee2fe63..f9af9356242 100644 --- a/source/blender/nodes/shader/nodes/node_shader_virtual_camera.cc +++ b/source/blender/nodes/shader/nodes/node_shader_virtual_camera.cc @@ -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(object->data); + Object *orig_object = DEG_get_original_object(object); + + Camera *cam = static_cast(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 -- cgit v1.2.3