From a083b23cebee4a35c7b658ce6f5c15bd7db9db58 Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Wed, 2 Nov 2022 13:17:35 +0100 Subject: First iteration of a virtual camera node. --- source/blender/blenkernel/BKE_node.h | 1 + source/blender/blenkernel/intern/camera.c | 2 + source/blender/blenkernel/intern/node.cc | 2 + source/blender/draw/intern/draw_manager_data.cc | 5 ++ source/blender/editors/space_node/drawnode.cc | 17 +++++++ source/blender/gpu/CMakeLists.txt | 1 + source/blender/gpu/GPU_material.h | 5 ++ source/blender/gpu/intern/gpu_codegen.cc | 4 ++ source/blender/gpu/intern/gpu_node_graph.c | 30 ++++++++--- .../gpu_shader_material_virtual_camera.glsl | 11 ++++ source/blender/makesdna/DNA_camera_types.h | 6 +++ source/blender/makesrna/intern/rna_nodetree.c | 15 ++++++ source/blender/nodes/NOD_shader.h | 2 + source/blender/nodes/NOD_static_types.h | 1 + source/blender/nodes/shader/CMakeLists.txt | 1 + .../shader/nodes/node_shader_virtual_camera.cc | 58 ++++++++++++++++++++++ 16 files changed, 155 insertions(+), 6 deletions(-) create mode 100644 source/blender/gpu/shaders/material/gpu_shader_material_virtual_camera.glsl create mode 100644 source/blender/nodes/shader/nodes/node_shader_virtual_camera.cc diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index ecf7a556459..cf78c954e44 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -1222,6 +1222,7 @@ void BKE_nodetree_remove_layer_n(struct bNodeTree *ntree, struct Scene *scene, i #define SH_NODE_COMBINE_COLOR 711 #define SH_NODE_SEPARATE_COLOR 712 #define SH_NODE_MIX 713 +#define SH_NODE_VIRTUAL_CAMERA 714 /** \} */ diff --git a/source/blender/blenkernel/intern/camera.c b/source/blender/blenkernel/intern/camera.c index 7c1193d80ab..71ef05e9a4f 100644 --- a/source/blender/blenkernel/intern/camera.c +++ b/source/blender/blenkernel/intern/camera.c @@ -137,6 +137,8 @@ static void camera_blend_read_data(BlendDataReader *reader, ID *id) bgpic->flag &= ~CAM_BGIMG_FLAG_OVERRIDE_LIBRARY_LOCAL; } } + ca->runtime.virtual_camera_stage = false; + ca->runtime.virtual_display_texture = NULL; } static void camera_blend_read_lib(BlendLibReader *reader, ID *id) diff --git a/source/blender/blenkernel/intern/node.cc b/source/blender/blenkernel/intern/node.cc index 8f8cd02e119..d6beb423b5a 100644 --- a/source/blender/blenkernel/intern/node.cc +++ b/source/blender/blenkernel/intern/node.cc @@ -4667,6 +4667,8 @@ static void registerShaderNodes() register_node_type_sh_tex_pointdensity(); register_node_type_sh_tex_ies(); register_node_type_sh_tex_white_noise(); + + register_node_type_sh_virtual_camera(); } static void registerTextureNodes() diff --git a/source/blender/draw/intern/draw_manager_data.cc b/source/blender/draw/intern/draw_manager_data.cc index 4aa27e2288c..bae99a945d2 100644 --- a/source/blender/draw/intern/draw_manager_data.cc +++ b/source/blender/draw/intern/draw_manager_data.cc @@ -1835,6 +1835,11 @@ void DRW_shgroup_add_material_resources(DRWShadingGroup *grp, GPUMaterial *mater DRW_shgroup_uniform_texture_ex( grp, tex->sampler_name, *tex->sky, eGPUSamplerState(tex->sampler_state)); } + else if (tex->camera) { + /* Sky */ + DRW_shgroup_uniform_texture_ex( + grp, tex->sampler_name, *tex->camera, eGPUSamplerState(tex->sampler_state)); + } } GPUUniformBuf *ubo = GPU_material_uniform_buffer_get(material); diff --git a/source/blender/editors/space_node/drawnode.cc b/source/blender/editors/space_node/drawnode.cc index df31a0342cb..b713b225638 100644 --- a/source/blender/editors/space_node/drawnode.cc +++ b/source/blender/editors/space_node/drawnode.cc @@ -432,6 +432,20 @@ static void node_shader_buts_tex_environment(uiLayout *layout, bContext *C, Poin node_buts_image_user(layout, C, &iuserptr, &imaptr, &iuserptr, false, true); } +static void node_shader_buts_virtual_camera(uiLayout *layout, bContext *C, PointerRNA *ptr) +{ + uiTemplateID(layout, + C, + ptr, + "camera", + nullptr, + nullptr, + nullptr, + UI_TEMPLATE_ID_FILTER_ALL, + false, + nullptr); +} + static void node_shader_buts_tex_environment_ex(uiLayout *layout, bContext *C, PointerRNA *ptr) { PointerRNA iuserptr = RNA_pointer_get(ptr, "image_user"); @@ -499,6 +513,9 @@ static void node_shader_set_butfunc(bNodeType *ntype) ntype->draw_buttons = node_shader_buts_tex_environment; ntype->draw_buttons_ex = node_shader_buts_tex_environment_ex; break; + case SH_NODE_VIRTUAL_CAMERA: + ntype->draw_buttons = node_shader_buts_virtual_camera; + break; case SH_NODE_DISPLACEMENT: case SH_NODE_VECTOR_DISPLACEMENT: ntype->draw_buttons = node_shader_buts_displacement; diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt index bfbbf1be225..a636fcb86f0 100644 --- a/source/blender/gpu/CMakeLists.txt +++ b/source/blender/gpu/CMakeLists.txt @@ -506,6 +506,7 @@ set(GLSL_SRC shaders/material/gpu_shader_material_vector_rotate.glsl shaders/material/gpu_shader_material_velvet.glsl shaders/material/gpu_shader_material_vertex_color.glsl + shaders/material/gpu_shader_material_virtual_camera.glsl shaders/material/gpu_shader_material_volume_absorption.glsl shaders/material/gpu_shader_material_volume_principled.glsl shaders/material/gpu_shader_material_volume_scatter.glsl diff --git a/source/blender/gpu/GPU_material.h b/source/blender/gpu/GPU_material.h index 3dad2a1a19a..48eb53d662f 100644 --- a/source/blender/gpu/GPU_material.h +++ b/source/blender/gpu/GPU_material.h @@ -35,6 +35,7 @@ struct Material; struct Scene; struct bNode; struct bNodeTree; +struct Camera; typedef struct GPUMaterial GPUMaterial; typedef struct GPUNode GPUNode; @@ -178,6 +179,9 @@ GPUNodeLink *GPU_image_sky(GPUMaterial *mat, const float *pixels, float *layer, eGPUSamplerState sampler_state); +GPUNodeLink *GPU_image_camera(GPUMaterial *mat, + struct Camera *camera, + eGPUSamplerState sampler_state); GPUNodeLink *GPU_color_band(GPUMaterial *mat, int size, float *pixels, float *row); /** @@ -322,6 +326,7 @@ typedef struct GPUMaterialTexture { bool iuser_available; struct GPUTexture **colorband; struct GPUTexture **sky; + struct GPUTexture **camera; char sampler_name[32]; /* Name of sampler in GLSL. */ char tiled_mapping_name[32]; /* Name of tile mapping sampler in GLSL. */ int users; diff --git a/source/blender/gpu/intern/gpu_codegen.cc b/source/blender/gpu/intern/gpu_codegen.cc index 4adeac1b49a..2ce03f88693 100644 --- a/source/blender/gpu/intern/gpu_codegen.cc +++ b/source/blender/gpu/intern/gpu_codegen.cc @@ -392,6 +392,10 @@ void GPUCodegen::generate_resources() const char *name = info.name_buffer.append_sampler_name(tex->sampler_name); info.sampler(0, ImageType::FLOAT_2D_ARRAY, name, Frequency::BATCH); } + else if (tex->camera) { + const char *name = info.name_buffer.append_sampler_name(tex->sampler_name); + info.sampler(0, ImageType::FLOAT_2D, name, Frequency::PASS); + } else if (tex->tiled_mapping_name[0] != '\0') { const char *name = info.name_buffer.append_sampler_name(tex->sampler_name); info.sampler(slot++, ImageType::FLOAT_2D_ARRAY, name, Frequency::BATCH); diff --git a/source/blender/gpu/intern/gpu_node_graph.c b/source/blender/gpu/intern/gpu_node_graph.c index c72e7097b33..17136308cdd 100644 --- a/source/blender/gpu/intern/gpu_node_graph.c +++ b/source/blender/gpu/intern/gpu_node_graph.c @@ -12,6 +12,7 @@ #include "MEM_guardedalloc.h" +#include "DNA_camera_types.h" #include "DNA_node_types.h" #include "BLI_ghash.h" @@ -470,6 +471,7 @@ static GPUMaterialTexture *gpu_node_graph_add_texture(GPUNodeGraph *graph, ImageUser *iuser, struct GPUTexture **colorband, struct GPUTexture **sky, + struct GPUTexture **camera, GPUNodeLinkType link_type, eGPUSamplerState sampler_state) { @@ -478,7 +480,7 @@ static GPUMaterialTexture *gpu_node_graph_add_texture(GPUNodeGraph *graph, GPUMaterialTexture *tex = graph->textures.first; for (; tex; tex = tex->next) { if (tex->ima == ima && tex->colorband == colorband && tex->sky == sky && - tex->sampler_state == sampler_state) { + tex->camera == camera && tex->sampler_state == sampler_state) { break; } num_textures++; @@ -625,7 +627,23 @@ GPUNodeLink *GPU_image(GPUMaterial *mat, GPUNodeLink *link = gpu_node_link_create(); link->link_type = GPU_NODE_LINK_IMAGE; link->texture = gpu_node_graph_add_texture( - graph, ima, iuser, NULL, NULL, link->link_type, sampler_state); + graph, ima, iuser, NULL, NULL, NULL, link->link_type, sampler_state); + return link; +} + +GPUNodeLink *GPU_image_camera(GPUMaterial *mat, Camera *camera, eGPUSamplerState sampler_state) +{ + 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); return link; } @@ -642,7 +660,7 @@ GPUNodeLink *GPU_image_sky(GPUMaterial *mat, GPUNodeLink *link = gpu_node_link_create(); link->link_type = GPU_NODE_LINK_IMAGE_SKY; link->texture = gpu_node_graph_add_texture( - graph, NULL, NULL, NULL, sky, link->link_type, sampler_state); + graph, NULL, NULL, NULL, sky, NULL, link->link_type, sampler_state); return link; } @@ -655,7 +673,7 @@ GPUNodeLink *GPU_image_tiled(GPUMaterial *mat, GPUNodeLink *link = gpu_node_link_create(); link->link_type = GPU_NODE_LINK_IMAGE_TILED; link->texture = gpu_node_graph_add_texture( - graph, ima, iuser, NULL, NULL, link->link_type, sampler_state); + graph, ima, iuser, NULL, NULL, NULL, link->link_type, sampler_state); return link; } @@ -665,7 +683,7 @@ GPUNodeLink *GPU_image_tiled_mapping(GPUMaterial *mat, Image *ima, ImageUser *iu GPUNodeLink *link = gpu_node_link_create(); link->link_type = GPU_NODE_LINK_IMAGE_TILED_MAPPING; link->texture = gpu_node_graph_add_texture( - graph, ima, iuser, NULL, NULL, link->link_type, GPU_SAMPLER_MAX); + graph, ima, iuser, NULL, NULL, NULL, link->link_type, GPU_SAMPLER_MAX); return link; } @@ -678,7 +696,7 @@ GPUNodeLink *GPU_color_band(GPUMaterial *mat, int size, float *pixels, float *ro GPUNodeLink *link = gpu_node_link_create(); link->link_type = GPU_NODE_LINK_COLORBAND; link->texture = gpu_node_graph_add_texture( - graph, NULL, NULL, colorband, NULL, link->link_type, GPU_SAMPLER_MAX); + graph, NULL, NULL, colorband, NULL, NULL, link->link_type, GPU_SAMPLER_MAX); return link; } 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 new file mode 100644 index 00000000000..05bc6f90686 --- /dev/null +++ b/source/blender/gpu/shaders/material/gpu_shader_material_virtual_camera.glsl @@ -0,0 +1,11 @@ +void node_virtual_camera_empty(vec3 co, out vec4 color, out float alpha) +{ + color = vec4(0.0); + alpha = 0.0; +} + +void node_virtual_camera(vec3 co, sampler2D ima, out vec4 color, out float alpha) +{ + 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 10a6c936be1..b6a5b95e404 100644 --- a/source/blender/makesdna/DNA_camera_types.h +++ b/source/blender/makesdna/DNA_camera_types.h @@ -71,6 +71,12 @@ typedef struct Camera_Runtime { float drw_depth[2]; float drw_focusmat[4][4]; float drw_normalmat[4][4]; + + /* XXX(jbakker): Yuck but we are experimenting... true when virtual camera is evaluated, false + * when scene camera/main camera is evaluated. */ + int virtual_camera_stage; + int _pad[1]; + struct GPUTexture *virtual_display_texture; } Camera_Runtime; typedef struct Camera { diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index 865399df9ef..1c903ce1dcd 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -5885,6 +5885,21 @@ static void def_sh_tex_coord(StructRNA *srna) RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); } +static void def_sh_virtual_camera(StructRNA *srna) +{ + PropertyRNA *prop; + + prop = RNA_def_property(srna, "camera", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_EDITABLE); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); + RNA_def_property_pointer_sdna(prop, NULL, "id"); + RNA_def_property_pointer_funcs(prop, NULL, NULL, NULL, "rna_Camera_object_poll"); + RNA_def_property_struct_type(prop, "Object"); + RNA_def_property_ui_text(prop, "Camera", ""); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); + // TODO: add poll function show all cameras in active scene, excluding scene camera. +} + static void def_sh_vect_transform(StructRNA *srna) { static const EnumPropertyItem prop_vect_type_items[] = { diff --git a/source/blender/nodes/NOD_shader.h b/source/blender/nodes/NOD_shader.h index 8fe77bffaad..681851eab85 100644 --- a/source/blender/nodes/NOD_shader.h +++ b/source/blender/nodes/NOD_shader.h @@ -129,6 +129,8 @@ void register_node_type_sh_bump(void); void register_node_type_sh_tex_ies(void); void register_node_type_sh_tex_white_noise(void); +void register_node_type_sh_virtual_camera(void); + void register_node_type_sh_custom_group(bNodeType *ntype); struct bNodeTreeExec *ntreeShaderBeginExecTree(struct bNodeTree *ntree); diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h index 9671f8148ec..1a3311c6fe6 100644 --- a/source/blender/nodes/NOD_static_types.h +++ b/source/blender/nodes/NOD_static_types.h @@ -123,6 +123,7 @@ DefNode(ShaderNode, SH_NODE_CURVE_FLOAT, def_float_curve, "CUR DefNode(ShaderNode, SH_NODE_COMBINE_COLOR, def_sh_combsep_color, "COMBINE_COLOR", CombineColor, "Combine Color", "Create a color from individual components using multiple models") DefNode(ShaderNode, SH_NODE_SEPARATE_COLOR, def_sh_combsep_color, "SEPARATE_COLOR", SeparateColor, "Separate Color", "Split a color into its individual components using multiple models") DefNode(ShaderNode, SH_NODE_MIX, def_sh_mix, "MIX", Mix, "Mix", "Mix values by a factor") +DefNode(ShaderNode, SH_NODE_VIRTUAL_CAMERA, def_sh_virtual_camera, "VIRTUAL_CAMERA", VirtualCamera, "Virtual Camera", "Virtual Camera") DefNode(CompositorNode, CMP_NODE_VIEWER, def_cmp_viewer, "VIEWER", Viewer, "Viewer", "" ) DefNode(CompositorNode, CMP_NODE_RGB, 0, "RGB", RGB, "RGB", "" ) diff --git a/source/blender/nodes/shader/CMakeLists.txt b/source/blender/nodes/shader/CMakeLists.txt index e6f90449843..9a429307542 100644 --- a/source/blender/nodes/shader/CMakeLists.txt +++ b/source/blender/nodes/shader/CMakeLists.txt @@ -113,6 +113,7 @@ set(SRC nodes/node_shader_vector_rotate.cc nodes/node_shader_vector_transform.cc nodes/node_shader_vertex_color.cc + nodes/node_shader_virtual_camera.cc nodes/node_shader_volume_absorption.cc nodes/node_shader_volume_info.cc nodes/node_shader_volume_principled.cc diff --git a/source/blender/nodes/shader/nodes/node_shader_virtual_camera.cc b/source/blender/nodes/shader/nodes/node_shader_virtual_camera.cc new file mode 100644 index 00000000000..1e26ee2fe63 --- /dev/null +++ b/source/blender/nodes/shader/nodes/node_shader_virtual_camera.cc @@ -0,0 +1,58 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later + * Copyright 2005 Blender Foundation. All rights reserved. */ + +#include "node_shader_util.hh" + +#include "DNA_camera_types.h" + +namespace blender::nodes::node_shader_virtual_camera_cc { + +static void sh_node_virtual_camera_declare(NodeDeclarationBuilder &b) +{ + b.add_input(N_("Vector")).implicit_field(implicit_field_inputs::position); + b.add_output(N_("Color")).no_muted_links(); + b.add_output(N_("Alpha")).no_muted_links(); +} + +static int node_shader_gpu_virtual_camera(GPUMaterial *mat, + bNode *node, + bNodeExecData * /*execdata*/, + GPUNodeStack *in, + GPUNodeStack *out) +{ + Object *object = (Object *)node->id; + if (object == nullptr || object->type != OB_CAMERA) { + return GPU_stack_link(mat, node, "node_virtual_camera_empty", in, out); + } + + Camera *cam = static_cast(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); + } + + 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); + + return GPU_stack_link( + mat, node, "node_virtual_camera", in, out, GPU_image_camera(mat, cam, GPU_SAMPLER_DEFAULT)); +} + +} // namespace blender::nodes::node_shader_virtual_camera_cc + +void register_node_type_sh_virtual_camera() +{ + namespace file_ns = blender::nodes::node_shader_virtual_camera_cc; + + static bNodeType ntype; + + sh_node_type_base(&ntype, SH_NODE_VIRTUAL_CAMERA, "Virtual Camera", NODE_CLASS_TEXTURE); + ntype.declare = file_ns::sh_node_virtual_camera_declare; + node_type_gpu(&ntype, file_ns::node_shader_gpu_virtual_camera); + + nodeRegisterType(&ntype); +} -- cgit v1.2.3