Overlay-Next: Initial implementation #107045
@ -77,7 +77,7 @@ template<typename SelectEngineT> class Background {
|
||||
|
||||
bg_ps_.init();
|
||||
bg_ps_.state_set(pass_state);
|
||||
bg_ps_.shader_set(OVERLAY_shader_background());
|
||||
bg_ps_.shader_set(res.shaders.background_fill);
|
||||
bg_ps_.bind_ubo("globalsBlock", &res.globals_buf);
|
||||
bg_ps_.bind_texture("colorBuffer", &res.color_render_tx);
|
||||
bg_ps_.bind_texture("depthBuffer", &res.depth_tx);
|
||||
@ -87,7 +87,7 @@ template<typename SelectEngineT> class Background {
|
||||
|
||||
if (state.clipping_state != 0 && state.rv3d != nullptr && state.rv3d->clipbb != nullptr) {
|
||||
bg_ps_.state_set(DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_ALPHA | DRW_STATE_CULL_BACK);
|
||||
bg_ps_.shader_set(OVERLAY_shader_clipbound());
|
||||
bg_ps_.shader_set(res.shaders.background_clip_bound);
|
||||
bg_ps_.push_constant("ucolor", res.theme_settings.color_clipping_border);
|
||||
bg_ps_.push_constant("boundbox", &state.rv3d->clipbb->vec[0][0], 8);
|
||||
bg_ps_.draw(DRW_cache_cube_get());
|
||||
|
@ -95,7 +95,7 @@ template<typename SelectEngineT> class Empties {
|
||||
pass.init();
|
||||
pass.state_set(DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL |
|
||||
state.clipping_state);
|
||||
pass.shader_set(OVERLAY_shader_extra(false));
|
||||
pass.shader_set(res.shaders.extra_shape);
|
||||
pass.bind_ubo("globalsBlock", &res.globals_buf);
|
||||
|
||||
call_bufs.plain_axes_buf.end_sync(pass, shapes.plain_axes);
|
||||
|
@ -737,6 +737,7 @@ static void OVERLAY_draw_scene(void *vedata)
|
||||
static void OVERLAY_engine_free()
|
||||
{
|
||||
OVERLAY_shader_free();
|
||||
overlay::shader_module_free();
|
||||
}
|
||||
|
||||
static void OVERLAY_instance_free(void *instance_)
|
||||
|
@ -176,7 +176,7 @@ template<typename SelectEngineT> class Grid {
|
||||
|
||||
grid_ps_.init();
|
||||
grid_ps_.state_set(DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_ALPHA);
|
||||
grid_ps_.shader_set(OVERLAY_shader_grid());
|
||||
grid_ps_.shader_set(res.shaders.grid);
|
||||
grid_ps_.bind_ubo("grid_buf", &data_);
|
||||
grid_ps_.bind_ubo("globalsBlock", &res.globals_buf);
|
||||
grid_ps_.bind_texture("depth_tx", &res.depth_tx);
|
||||
|
@ -71,7 +71,7 @@ template<typename T> void Instance<T>::begin_sync()
|
||||
View view("OverlayView", view_legacy);
|
||||
|
||||
background.begin_sync(resources, state);
|
||||
prepass.begin_sync(state);
|
||||
prepass.begin_sync(resources, state);
|
||||
empties.begin_sync();
|
||||
metaballs.begin_sync();
|
||||
grid.begin_sync(resources, state, view);
|
||||
|
@ -20,12 +20,6 @@
|
||||
|
||||
namespace blender::draw::overlay {
|
||||
|
||||
class ShaderCache {
|
||||
Map<StringRefNull, std::array<GPUShader *, 2>> cache;
|
||||
|
||||
int clipping_enabled = 0;
|
||||
};
|
||||
|
||||
template<
|
||||
/* Selection engine reuse most of the Overlay engine by creating selection IDs for each
|
||||
* selectable component and using a special shaders for drawing.
|
||||
@ -34,14 +28,13 @@ template<
|
||||
typename SelectEngineT = select::EngineEmpty>
|
||||
class Instance {
|
||||
public:
|
||||
ShaderCache shaders;
|
||||
ShapeCache shapes;
|
||||
|
||||
/* WORKAROUND: Legacy. Move to grid pass. */
|
||||
GPUUniformBuf *grid_ubo = nullptr;
|
||||
|
||||
ShapeCache shapes;
|
||||
|
||||
/** Global types. */
|
||||
Resources<SelectEngineT> resources;
|
||||
Resources<SelectEngineT> resources = {overlay::ShaderModule<SelectEngineT>::module_get()};
|
||||
State state;
|
||||
|
||||
/** Overlay types. */
|
||||
|
@ -88,7 +88,7 @@ template<typename SelectEngineT> class Metaballs {
|
||||
pass.init();
|
||||
pass.state_set(DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL |
|
||||
state.clipping_state);
|
||||
pass.shader_set(OVERLAY_shader_armature_sphere(true));
|
||||
pass.shader_set(res.shaders.armature_sphere_outline);
|
||||
pass.bind_ubo("globalsBlock", &res.globals_buf);
|
||||
|
||||
call_buf.end_sync(pass, shapes.metaball_wire_circle);
|
||||
|
@ -24,12 +24,12 @@ template<typename SelectEngineT> class Prepass {
|
||||
PassMain prepass_in_front_ps_ = {"prepass_in_front"};
|
||||
|
||||
public:
|
||||
void begin_sync(const State &state)
|
||||
void begin_sync(ResourcesT &res, const State &state)
|
||||
{
|
||||
auto init_pass = [&](PassMain &pass) {
|
||||
pass.init();
|
||||
pass.state_set(DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | state.clipping_state);
|
||||
pass.shader_set(OVERLAY_shader_depth_only());
|
||||
pass.shader_set(res.shaders.depth_mesh);
|
||||
};
|
||||
init_pass(prepass_ps_);
|
||||
init_pass(prepass_in_front_ps_);
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
#include "draw_handle.hh"
|
||||
|
||||
#include "overlay_shader.hh"
|
||||
#include "overlay_shader_shared.h"
|
||||
|
||||
#ifdef __APPLE__
|
||||
@ -64,6 +65,8 @@ using blender::draw::TextureFromPool;
|
||||
using blender::draw::TextureRef;
|
||||
|
||||
template<typename SelectEngineT> struct Resources : public SelectEngineT::SelectMap {
|
||||
ShaderModule<SelectEngineT> &shaders;
|
||||
|
||||
Framebuffer overlay_fb = {"overlay_fb"};
|
||||
Framebuffer overlay_in_front_fb = {"overlay_in_front_fb"};
|
||||
Framebuffer overlay_color_only_fb = {"overlay_color_only_fb"};
|
||||
@ -83,6 +86,8 @@ template<typename SelectEngineT> struct Resources : public SelectEngineT::Select
|
||||
TextureRef color_overlay_tx;
|
||||
TextureRef color_render_tx;
|
||||
|
||||
Resources(ShaderModule<SelectEngineT> &shader_module) : shaders(shader_module){};
|
||||
|
||||
[[nodiscard]] ThemeColorID object_wire_theme_id(const ObjectRef &ob_ref,
|
||||
const State &state) const
|
||||
{
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "gpu_shader_create_info.hh"
|
||||
|
||||
#include "overlay_private.hh"
|
||||
#include "overlay_shader.hh"
|
||||
|
||||
struct OVERLAY_Shaders {
|
||||
GPUShader *antialiasing;
|
||||
@ -1231,3 +1232,19 @@ void OVERLAY_shader_free(void)
|
||||
MEM_SAFE_FREE(*format);
|
||||
}
|
||||
}
|
||||
|
||||
namespace blender::draw::overlay {
|
||||
|
||||
template<>
|
||||
ShaderModule<select::EngineEmpty> *ShaderModule<select::EngineEmpty>::g_shader_module = nullptr;
|
||||
|
||||
template<>
|
||||
ShaderModule<select::EngineObject> *ShaderModule<select::EngineObject>::g_shader_module = nullptr;
|
||||
|
||||
void shader_module_free()
|
||||
{
|
||||
ShaderModule<select::EngineEmpty>::module_free();
|
||||
ShaderModule<select::EngineObject>::module_free();
|
||||
}
|
||||
|
||||
} // namespace blender::draw::overlay
|
||||
|
150
source/blender/draw/engines/overlay/overlay_shader.hh
Normal file
150
source/blender/draw/engines/overlay/overlay_shader.hh
Normal file
@ -0,0 +1,150 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup overlay
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
|
||||
#include "GPU_shader.h"
|
||||
|
||||
#include "gpu_shader_create_info.hh"
|
||||
|
||||
#include "../select/select_empty.hh"
|
||||
#include "../select/select_object.hh"
|
||||
|
||||
namespace blender::draw::overlay {
|
||||
|
||||
/**
|
||||
* Shader module. Shared between instances.
|
||||
*/
|
||||
template<typename SelectEngineT, bool ClippingEnabled = false> class ShaderModule {
|
||||
private:
|
||||
/** Shared shader module across all engine instances. */
|
||||
static ShaderModule *g_shader_module;
|
||||
|
||||
/** TODO: Support clipping. This global state should be set by the overlay::Instance and switch
|
||||
* to the shader variations that use clipping. */
|
||||
// bool clipping_enabled = false;
|
||||
|
||||
class Shader {
|
||||
protected:
|
||||
GPUShader *shader_ = nullptr;
|
||||
|
||||
public:
|
||||
Shader() = default;
|
||||
|
||||
Shader(const char *create_info_name)
|
||||
: shader_(GPU_shader_create_from_info_name(create_info_name)){};
|
||||
|
||||
~Shader()
|
||||
{
|
||||
DRW_SHADER_FREE_SAFE(shader_);
|
||||
}
|
||||
|
||||
operator GPUShader *()
|
||||
{
|
||||
return shader_;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Special class for every shader that needs to have clipped and selection variations.
|
||||
*/
|
||||
class ShaderGeometry : public Shader {
|
||||
public:
|
||||
ShaderGeometry(const char *create_info_name)
|
||||
{
|
||||
/* TODO: This is what it should be like with all variations defined with create infos. */
|
||||
// std::string create_info_name = base_create_info;
|
||||
// create_info_name += SelectEngineT::shader_suffix;
|
||||
// create_info_name += ClippingEnabled ? "_clipped" : "";
|
||||
// this->shader_ = GPU_shader_create_from_info_name(create_info_name.c_str());
|
||||
|
||||
/* WORKAROUND: ... but for now, we have to patch the create info used by the old engine. */
|
||||
gpu::shader::ShaderCreateInfo info =
|
||||
*reinterpret_cast<const gpu::shader::ShaderCreateInfo *>(
|
||||
GPU_shader_create_info_get(create_info_name));
|
||||
|
||||
info.define(SelectEngineT::shader_define);
|
||||
|
||||
this->shader_ = GPU_shader_create_from_info(
|
||||
reinterpret_cast<const GPUShaderCreateInfo *>(&info));
|
||||
}
|
||||
|
||||
/* WORKAROUND: Create a shader using a patch function to patch the create info. */
|
||||
ShaderGeometry(const char *create_info_name,
|
||||
std::function<void(gpu::shader::ShaderCreateInfo &info)> patch)
|
||||
{
|
||||
gpu::shader::ShaderCreateInfo info =
|
||||
*reinterpret_cast<const gpu::shader::ShaderCreateInfo *>(
|
||||
GPU_shader_create_info_get(create_info_name));
|
||||
|
||||
patch(info);
|
||||
info.define(SelectEngineT::shader_define);
|
||||
|
||||
this->shader_ = GPU_shader_create_from_info(
|
||||
reinterpret_cast<const GPUShaderCreateInfo *>(&info));
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
/** ShaderGeometry */
|
||||
|
||||
ShaderGeometry armature_sphere_outline = {
|
||||
"overlay_armature_sphere_outline", [](gpu::shader::ShaderCreateInfo &info) {
|
||||
using namespace blender::gpu::shader;
|
||||
info.storage_buf(0, Qualifier::READ, "mat4", "data_buf[]");
|
||||
info.define("inst_obmat", "data_buf[gl_InstanceID]");
|
||||
info.vertex_inputs_.pop_last();
|
||||
}};
|
||||
|
||||
ShaderGeometry depth_mesh = {"overlay_depth_only", [](gpu::shader::ShaderCreateInfo &info) {
|
||||
using namespace blender::gpu::shader;
|
||||
info.additional_infos_.clear();
|
||||
info.additional_info(
|
||||
"draw_view", "draw_modelmat_new", "draw_resource_handle_new");
|
||||
}};
|
||||
|
||||
ShaderGeometry extra_shape = {
|
||||
"overlay_extra", [](gpu::shader::ShaderCreateInfo &info) {
|
||||
using namespace blender::gpu::shader;
|
||||
info.storage_buf(0, Qualifier::READ, "ExtraInstanceData", "data_buf[]");
|
||||
info.define("color", "data_buf[gl_InstanceID].color_");
|
||||
info.define("inst_obmat", "data_buf[gl_InstanceID].object_to_world_");
|
||||
info.vertex_inputs_.pop_last();
|
||||
info.vertex_inputs_.pop_last();
|
||||
}};
|
||||
|
||||
/** Shader */
|
||||
|
||||
Shader grid = {"overlay_grid"};
|
||||
|
||||
Shader background_fill = {"overlay_background"};
|
||||
Shader background_clip_bound = {"overlay_clipbound"};
|
||||
|
||||
/** Only to be used by Instance constructor. */
|
||||
static ShaderModule &module_get()
|
||||
{
|
||||
if (g_shader_module == nullptr) {
|
||||
/* TODO(@fclem) thread-safety. */
|
||||
g_shader_module = new ShaderModule();
|
||||
}
|
||||
return *g_shader_module;
|
||||
}
|
||||
|
||||
static void module_free()
|
||||
{
|
||||
if (g_shader_module != nullptr) {
|
||||
/* TODO(@fclem) thread-safety. */
|
||||
delete g_shader_module;
|
||||
g_shader_module = nullptr;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void shader_module_free();
|
||||
|
||||
} // namespace blender::draw::overlay
|
@ -17,6 +17,8 @@ struct EngineEmpty {
|
||||
/* Add type safety to selection ID. Only the select engine should provide them. */
|
||||
struct ID {};
|
||||
|
||||
static constexpr const char *shader_define = "NO_SELECT";
|
||||
|
||||
struct SelectBuf {
|
||||
void select_clear(){};
|
||||
void select_append(ID){};
|
||||
|
@ -12,6 +12,7 @@
|
||||
|
||||
#include "DRW_gpu_wrapper.hh"
|
||||
#include "draw_manager.hh"
|
||||
#include "draw_pass.hh"
|
||||
|
||||
namespace blender::draw::select {
|
||||
|
||||
@ -21,6 +22,8 @@ struct EngineObject {
|
||||
uint32_t value;
|
||||
};
|
||||
|
||||
static constexpr const char *shader_define = "SELECT_OBJECT";
|
||||
|
||||
/**
|
||||
* Add a dedicated selection id buffer to a pass.
|
||||
* Use this when not using a #PassMain which can pass the select ID via CustomID.
|
||||
|
Loading…
Reference in New Issue
Block a user