修改pixel_shader绘制,抽象出pixel_shader_drawer
This commit is contained in:
parent
c75cdff50f
commit
423c09e628
@ -172,7 +172,7 @@ void application::init(window_params in_window_params, int argc, char** argv)
|
||||
SDL_ShowWindow(window_);
|
||||
|
||||
renderer_->init(window_);
|
||||
renderer_->init_slang(R"(E:\Projects\AronaStudio\Arona\shaders\)");
|
||||
renderer_->init_slang(get_shader_path());
|
||||
renderer_->resize(in_window_params.width, in_window_params.height);
|
||||
g_is_running = true;
|
||||
}
|
||||
@ -251,3 +251,8 @@ std::shared_ptr<render_target> application::create_render_target(const int width
|
||||
{
|
||||
return renderer_->create_render_target(width, height, format);
|
||||
}
|
||||
|
||||
std::shared_ptr<pixel_shader_drawer> application::create_pixel_shader_drawer() const
|
||||
{
|
||||
return renderer_->create_pixel_shader_drawer();
|
||||
}
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include "slang-com-ptr.h"
|
||||
#include "slang.h"
|
||||
|
||||
class pixel_shader_drawer;
|
||||
class render_target;
|
||||
class renderer;
|
||||
class texture;
|
||||
@ -48,10 +49,12 @@ public:
|
||||
virtual int run();
|
||||
virtual void shutdown();
|
||||
virtual void draw_gui() = 0;
|
||||
virtual const char* get_shader_path() = 0;
|
||||
virtual void init_imgui(ImGuiContext* in_context) = 0;
|
||||
std::shared_ptr<texture> load_texture(const std::string& path) const;
|
||||
std::shared_ptr<texture> create_texture(const unsigned char* data, const int width, const int height) const;
|
||||
std::shared_ptr<render_target> create_render_target(const int width, const int height, texture_format format) const;
|
||||
std::shared_ptr<pixel_shader_drawer> create_pixel_shader_drawer() const;
|
||||
|
||||
virtual const char* get_entry_model() const = 0;
|
||||
virtual const char* get_draw_ps_vertex_shader_entry() const = 0; // Vertex Shader used for drawing ps
|
||||
|
140
core/rhi/opengl/pixel_shader_drawer_opengl.cpp
Normal file
140
core/rhi/opengl/pixel_shader_drawer_opengl.cpp
Normal file
@ -0,0 +1,140 @@
|
||||
#include "pixel_shader_drawer_opengl.h"
|
||||
|
||||
#include "application/application.h"
|
||||
#include "rhi/renderer.h"
|
||||
#include "shader/shader_ps_opengl.h"
|
||||
#include "shader/shader_vs_opengl.h"
|
||||
|
||||
void ps_opengl_compute_callback(const ImDrawList* parent_list, const ImDrawCmd* cmd)
|
||||
{
|
||||
const auto data = static_cast<pixel_shader_drawer_opengl*>(cmd->UserCallbackData);
|
||||
const std::shared_ptr<render_target_opengl>& rt = data->rt;
|
||||
const auto program = data->program;
|
||||
program->use_program();
|
||||
|
||||
// do on callback
|
||||
float x = 0;
|
||||
float width = rt->get_width();
|
||||
float y = 0;
|
||||
float height = rt->get_height();
|
||||
|
||||
const float ortho_projection[4][4] =
|
||||
{
|
||||
{ 2.0f/(width-x), 0.0f, 0.0f, 0.0f },
|
||||
{ 0.0f, 2.0f/(y-height), 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f, -1.0f, 0.0f },
|
||||
{ (width+x)/(x-width), (y+height)/(height-y), 0.0f, 1.0f },
|
||||
};
|
||||
// glUseProgram(bd->ShaderHandle);
|
||||
// glUniform1i(bd->AttribLocationTex, 0);
|
||||
// glUniformMatrix4fv(bd->AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]);
|
||||
program->set_uniform("viewMatrix", ortho_projection);
|
||||
|
||||
// ImVec2 clip_min(x, y);
|
||||
// ImVec2 clip_max(width, height);
|
||||
glViewport(0, 0, width, height);
|
||||
|
||||
// Apply scissor/clipping rectangle (Y is inverted in OpenGL)
|
||||
glScissor(0, 0, width, height);
|
||||
// glScissor((int)clip_min.x, (int)(0 - clip_max.y), (int)(clip_max.x - clip_min.x), (int)(clip_max.y - clip_min.y));
|
||||
|
||||
ImDrawVert& vert1 = data->vtx_buffer[0];
|
||||
ImDrawVert& vert2 = data->vtx_buffer[1];
|
||||
ImDrawVert& vert3 = data->vtx_buffer[2];
|
||||
ImDrawVert& vert4 = data->vtx_buffer[3];
|
||||
vert1.pos = ImVec2(0, 0);
|
||||
vert2.pos = ImVec2(width, 0);
|
||||
vert3.pos = ImVec2(width, height);
|
||||
vert4.pos = ImVec2(0, height);
|
||||
vert1.uv = ImVec2(0, 0);
|
||||
vert2.uv = ImVec2(1, 0);
|
||||
vert3.uv = ImVec2(1, 1);
|
||||
vert4.uv = ImVec2(0, 1);
|
||||
vert1.col = 0xFFFFFFFF;
|
||||
vert2.col = 0xFFFFFFFF;
|
||||
vert3.col = 0xFFFFFFFF;
|
||||
vert4.col = 0xFFFFFFFF;
|
||||
|
||||
|
||||
const size_t vtx_size = data->vtx_buffer.size() * sizeof(ImDrawVert);
|
||||
const size_t idx_size = data->idx_buffer.size() * sizeof(ImDrawIdx);
|
||||
glBufferSubData(GL_ARRAY_BUFFER, 0, vtx_size, data->vtx_buffer.data());
|
||||
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, idx_size, data->idx_buffer.data());
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, data->vbo);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, data->ibo);
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, rt->get_fbo());
|
||||
|
||||
glDrawElementsBaseVertex(GL_TRIANGLES, 6, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, 0, 0);
|
||||
// glDrawElements(GL_TRIANGLES, 6, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, 0);
|
||||
|
||||
program->unuse_program();
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
}
|
||||
|
||||
|
||||
pixel_shader_drawer_opengl::~pixel_shader_drawer_opengl()
|
||||
{
|
||||
if (vbo)
|
||||
glDeleteBuffers(1, &vbo);
|
||||
if (ibo)
|
||||
glDeleteBuffers(1, &ibo);
|
||||
}
|
||||
|
||||
void pixel_shader_drawer_opengl::init(int width, int height, std::shared_ptr<shader> in_pixel_shader, std::shared_ptr<shader> in_vertex_shader)
|
||||
{
|
||||
if (!in_vertex_shader)
|
||||
{
|
||||
in_vertex_shader = application::get()->get_renderer()->get_pixel_shader_render_default_vs();
|
||||
}
|
||||
|
||||
const auto gl_ps = std::static_pointer_cast<shader_ps_opengl>(in_pixel_shader);
|
||||
const auto gl_vs = std::static_pointer_cast<shader_vs_opengl>(in_vertex_shader);
|
||||
vertex_shader = gl_vs;
|
||||
pixel_shader = gl_ps;
|
||||
rt = std::static_pointer_cast<render_target_opengl>(application::get()->create_render_target(width, height, texture_format::RGBA32_FLOAT));
|
||||
program = std::make_shared<shader_program_opengl>();
|
||||
program->create_program(gl_ps, gl_vs);
|
||||
|
||||
idx_buffer = {0, 1, 2, 0, 2, 3};
|
||||
vtx_buffer.resize(4);
|
||||
|
||||
glGenBuffers(1, &vbo);
|
||||
glGenBuffers(1, &ibo);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vbo);
|
||||
const size_t vtx_size = vtx_buffer.size() * sizeof(ImDrawVert);
|
||||
glBufferData(GL_ARRAY_BUFFER, vtx_size, vtx_buffer.data(), GL_STREAM_DRAW);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
|
||||
const size_t idx_size = idx_buffer.size() * sizeof(ImDrawIdx);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, idx_size, idx_buffer.data(), GL_STREAM_DRAW);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
}
|
||||
|
||||
void pixel_shader_drawer_opengl::resize(int width, int height)
|
||||
{
|
||||
rt->resize(width, height);
|
||||
}
|
||||
|
||||
void pixel_shader_drawer_opengl::draw()
|
||||
{
|
||||
#if _DEBUG
|
||||
assert(!(pixel_shader.expired() || vertex_shader.expired()));
|
||||
#endif
|
||||
ImGui::GetWindowDrawList()->AddCallback(ps_opengl_compute_callback, this);
|
||||
ImGui::GetWindowDrawList()->AddCallback(ImDrawCallback_ResetRenderState, nullptr);
|
||||
rt->draw();
|
||||
}
|
||||
|
||||
void pixel_shader_drawer_opengl::set_vertex_shader(std::shared_ptr<shader> in_vertex_shader)
|
||||
{
|
||||
#if _DEBUG
|
||||
assert(!(pixel_shader.expired() || vertex_shader.expired()));
|
||||
#endif
|
||||
program->create_program(pixel_shader.lock(), vertex_shader.lock());
|
||||
}
|
28
core/rhi/opengl/pixel_shader_drawer_opengl.h
Normal file
28
core/rhi/opengl/pixel_shader_drawer_opengl.h
Normal file
@ -0,0 +1,28 @@
|
||||
#pragma once
|
||||
#include "render_target_opengl.h"
|
||||
#include "rhi/pixel_shader_drawer.h"
|
||||
#include "shader/shader_program_opengl.h"
|
||||
|
||||
class shader_ps_opengl;
|
||||
class shader_vs_opengl;
|
||||
|
||||
class pixel_shader_drawer_opengl : public pixel_shader_drawer
|
||||
{
|
||||
public:
|
||||
pixel_shader_drawer_opengl() = default;
|
||||
~pixel_shader_drawer_opengl() override;
|
||||
void init(int width, int height, std::shared_ptr<shader> in_pixel_shader, std::shared_ptr<shader> in_vertex_shader) override;
|
||||
void resize(int width, int height) override;
|
||||
void draw() override;
|
||||
void set_vertex_shader(std::shared_ptr<shader> in_vertex_shader) override;
|
||||
|
||||
std::shared_ptr<render_target_opengl> rt;
|
||||
std::shared_ptr<shader_program_opengl> program;
|
||||
std::vector<ImDrawVert> vtx_buffer;
|
||||
std::vector<ImDrawIdx> idx_buffer;
|
||||
GLuint vbo = 0;
|
||||
GLuint ibo = 0;
|
||||
|
||||
std::weak_ptr<shader_vs_opengl> vertex_shader;
|
||||
std::weak_ptr<shader_ps_opengl> pixel_shader;
|
||||
};
|
@ -4,6 +4,7 @@
|
||||
|
||||
#include "imgui_impl_opengl3.h"
|
||||
#include "imgui_impl_sdl3.h"
|
||||
#include "pixel_shader_drawer_opengl.h"
|
||||
#include "render_target_opengl.h"
|
||||
#include "texture_opengl.h"
|
||||
#include "application/application.h"
|
||||
@ -129,6 +130,11 @@ std::shared_ptr<shader> renderer_opengl::load_shader(const std::string& entry_na
|
||||
return out;
|
||||
}
|
||||
|
||||
std::shared_ptr<pixel_shader_drawer> renderer_opengl::create_pixel_shader_drawer()
|
||||
{
|
||||
return std::make_shared<pixel_shader_drawer_opengl>();
|
||||
}
|
||||
|
||||
void renderer_opengl::new_frame(SDL_Window* window_handle)
|
||||
{
|
||||
ImGui_ImplOpenGL3_NewFrame();
|
||||
|
@ -12,6 +12,7 @@ public:
|
||||
|
||||
void create_slang_session(const std::string& shader_path, slang::ISession** out_session) override;
|
||||
std::shared_ptr<shader> load_shader(const std::string& entry_name) override;
|
||||
std::shared_ptr<pixel_shader_drawer> create_pixel_shader_drawer() override;
|
||||
|
||||
void new_frame(SDL_Window* window_handle) override;
|
||||
void end_frame(SDL_Window* window_handle) override;
|
||||
|
@ -1,133 +1 @@
|
||||
#include "shader_ps_opengl.h"
|
||||
|
||||
#include "shader_program_opengl.h"
|
||||
#include "shader_vs_opengl.h"
|
||||
#include "application/application.h"
|
||||
#include "misc/likely.h"
|
||||
#include "rhi/renderer.h"
|
||||
|
||||
void ps_opengl_compute_callback(const ImDrawList* parent_list, const ImDrawCmd* cmd)
|
||||
{
|
||||
const auto data = (shader_ps_opengl::ps_data*)cmd->UserCallbackData;
|
||||
std::shared_ptr<render_target_opengl>& rt = data->rt;
|
||||
const auto program = data->program;
|
||||
program->use_program();
|
||||
|
||||
// do on callback
|
||||
float x = 0;
|
||||
float width = rt->get_width();
|
||||
float y = 0;
|
||||
float height = rt->get_height();
|
||||
|
||||
const float ortho_projection[4][4] =
|
||||
{
|
||||
{ 2.0f/(width-x), 0.0f, 0.0f, 0.0f },
|
||||
{ 0.0f, 2.0f/(y-height), 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f, -1.0f, 0.0f },
|
||||
{ (width+x)/(x-width), (y+height)/(height-y), 0.0f, 1.0f },
|
||||
};
|
||||
// glUseProgram(bd->ShaderHandle);
|
||||
// glUniform1i(bd->AttribLocationTex, 0);
|
||||
// glUniformMatrix4fv(bd->AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]);
|
||||
program->set_uniform("viewMatrix", ortho_projection);
|
||||
|
||||
ImVec2 clip_min(x, y);
|
||||
ImVec2 clip_max(width, height);
|
||||
glViewport(0, 0, width, height);
|
||||
|
||||
// Apply scissor/clipping rectangle (Y is inverted in OpenGL)
|
||||
glScissor(0, 0, width, height);
|
||||
// glScissor((int)clip_min.x, (int)(0 - clip_max.y), (int)(clip_max.x - clip_min.x), (int)(clip_max.y - clip_min.y));
|
||||
|
||||
ImDrawVert& vert1 = data->vtx_buffer[0];
|
||||
ImDrawVert& vert2 = data->vtx_buffer[1];
|
||||
ImDrawVert& vert3 = data->vtx_buffer[2];
|
||||
ImDrawVert& vert4 = data->vtx_buffer[3];
|
||||
vert1.pos = ImVec2(0, 0);
|
||||
vert2.pos = ImVec2(width, 0);
|
||||
vert3.pos = ImVec2(width, height);
|
||||
vert4.pos = ImVec2(0, height);
|
||||
vert1.uv = ImVec2(0, 0);
|
||||
vert2.uv = ImVec2(1, 0);
|
||||
vert3.uv = ImVec2(1, 1);
|
||||
vert4.uv = ImVec2(0, 1);
|
||||
vert1.col = 0xFFFFFFFF;
|
||||
vert2.col = 0xFFFFFFFF;
|
||||
vert3.col = 0xFFFFFFFF;
|
||||
vert4.col = 0xFFFFFFFF;
|
||||
|
||||
|
||||
const size_t vtx_size = data->vtx_buffer.size() * sizeof(ImDrawVert);
|
||||
const size_t idx_size = data->idx_buffer.size() * sizeof(ImDrawIdx);
|
||||
glBufferSubData(GL_ARRAY_BUFFER, 0, vtx_size, data->vtx_buffer.data());
|
||||
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, idx_size, data->idx_buffer.data());
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, data->vbo);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, data->ibo);
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, rt->get_fbo());
|
||||
|
||||
glDrawElementsBaseVertex(GL_TRIANGLES, 6, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, 0, 0);
|
||||
// glDrawElements(GL_TRIANGLES, 6, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, 0);
|
||||
|
||||
program->unuse_program();
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
}
|
||||
|
||||
void shader_ps_opengl::draw(int width, int height, std::shared_ptr<shader> in_vertex_shader)
|
||||
{
|
||||
const bool is_default_vtx_shader = in_vertex_shader == nullptr;
|
||||
if (is_default_vtx_shader)
|
||||
{
|
||||
in_vertex_shader = application::get()->get_renderer()->get_pixel_shader_render_default_vs();
|
||||
}
|
||||
const std::shared_ptr<shader_vs_opengl> vs = std::static_pointer_cast<shader_vs_opengl>(in_vertex_shader);
|
||||
const std::shared_ptr<shader_ps_opengl> ps = std::static_pointer_cast<shader_ps_opengl>(shared_from_this());
|
||||
|
||||
if (draw_data.fragment_shader_id != get_shader_id() || draw_data.vertex_shader_id != vs->get_shader_id())
|
||||
{
|
||||
if (!draw_data.program)
|
||||
draw_data.program = std::make_shared<shader_program_opengl>();
|
||||
|
||||
draw_data.program->create_program(ps, vs);
|
||||
draw_data.fragment_shader_id = get_shader_id();
|
||||
draw_data.vertex_shader_id = vs->get_shader_id();
|
||||
}
|
||||
|
||||
if (UNLIKELY(!draw_data.rt))
|
||||
{
|
||||
draw_data.rt = std::static_pointer_cast<render_target_opengl>(application::get()->create_render_target(width, height, texture_format::RGBA8));
|
||||
}
|
||||
|
||||
draw_data.rt->resize(width, height);
|
||||
|
||||
if (draw_data.vbo == 0)
|
||||
{
|
||||
glGenBuffers(1, &draw_data.vbo);
|
||||
glGenBuffers(1, &draw_data.ibo);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, draw_data.vbo);
|
||||
const size_t vtx_size = draw_data.vtx_buffer.size() * sizeof(ImDrawVert);
|
||||
glBufferData(GL_ARRAY_BUFFER, vtx_size, draw_data.vtx_buffer.data(), GL_STREAM_DRAW);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, draw_data.ibo);
|
||||
const size_t idx_size = draw_data.idx_buffer.size() * sizeof(ImDrawIdx);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, idx_size, draw_data.idx_buffer.data(), GL_STREAM_DRAW);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
}
|
||||
|
||||
ImGui::GetWindowDrawList()->AddCallback(ps_opengl_compute_callback, &draw_data);
|
||||
ImGui::GetWindowDrawList()->AddCallback(ImDrawCallback_ResetRenderState, nullptr);
|
||||
draw_data.rt->draw();
|
||||
}
|
||||
|
||||
shader_ps_opengl::ps_data::~ps_data()
|
||||
{
|
||||
if (vbo)
|
||||
glDeleteBuffers(1, &vbo);
|
||||
if (ibo)
|
||||
glDeleteBuffers(1, &ibo);
|
||||
}
|
||||
|
@ -7,27 +7,10 @@ class shader_vs_opengl;
|
||||
class shader_ps_opengl : public shader_opengl
|
||||
{
|
||||
public:
|
||||
explicit shader_ps_opengl(const std::shared_ptr<slang_handle>& handle) : shader_opengl(handle), draw_data({})
|
||||
explicit shader_ps_opengl(const std::shared_ptr<slang_handle>& handle) : shader_opengl(handle)
|
||||
{
|
||||
draw_data.idx_buffer = {0, 1, 2, 0, 2, 3};
|
||||
draw_data.vtx_buffer.resize(4);
|
||||
|
||||
}
|
||||
|
||||
[[nodiscard]] GLenum get_shader_type() const override { return GL_FRAGMENT_SHADER; }
|
||||
|
||||
void draw(int width, int height, std::shared_ptr<shader> in_vertex_shader) override;
|
||||
|
||||
struct ps_data
|
||||
{
|
||||
~ps_data();
|
||||
std::shared_ptr<render_target_opengl> rt;
|
||||
std::shared_ptr<shader_program_opengl> program;
|
||||
std::vector<ImDrawVert> vtx_buffer;
|
||||
std::vector<ImDrawIdx> idx_buffer;
|
||||
GLuint vbo = 0;
|
||||
GLuint ibo = 0;
|
||||
|
||||
GLuint vertex_shader_id;
|
||||
GLuint fragment_shader_id;
|
||||
} draw_data;
|
||||
};
|
||||
|
2
core/rhi/pixel_shader_drawer.cpp
Normal file
2
core/rhi/pixel_shader_drawer.cpp
Normal file
@ -0,0 +1,2 @@
|
||||
#include "E:/Projects/Arona/build/AronaCore/core/CMakeFiles/core.dir/Debug/cmake_pch.hxx"
|
||||
#include "pixel_shader_drawer.h"
|
16
core/rhi/pixel_shader_drawer.h
Normal file
16
core/rhi/pixel_shader_drawer.h
Normal file
@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
class shader;
|
||||
class render_target;
|
||||
|
||||
class pixel_shader_drawer
|
||||
{
|
||||
public:
|
||||
virtual ~pixel_shader_drawer() = default;
|
||||
virtual void init(int width, int height, std::shared_ptr<shader> in_pixel_shader, std::shared_ptr<shader> in_vertex_shader = nullptr) = 0;
|
||||
virtual void resize(int width, int height) = 0;
|
||||
virtual void draw() = 0;
|
||||
virtual void set_vertex_shader(std::shared_ptr<shader> in_vertex_shader) {}
|
||||
protected:
|
||||
std::shared_ptr<render_target> rt_;
|
||||
};
|
@ -4,6 +4,7 @@
|
||||
#include "imgui.h"
|
||||
#include "slang_handle.h"
|
||||
|
||||
class pixel_shader_drawer;
|
||||
class shader;
|
||||
class render_target;
|
||||
class texture;
|
||||
@ -24,6 +25,7 @@ public:
|
||||
virtual Slang::ComPtr<slang::ISession> get_slang_session() { return session_; }
|
||||
virtual std::shared_ptr<shader> load_shader(const std::string& entry_name) = 0;
|
||||
virtual std::shared_ptr<shader> get_pixel_shader_render_default_vs();
|
||||
virtual std::shared_ptr<pixel_shader_drawer> create_pixel_shader_drawer() = 0;
|
||||
|
||||
virtual void new_frame(SDL_Window* window_handle) = 0;
|
||||
virtual void end_frame(SDL_Window* window_handle) = 0;
|
||||
|
@ -4,6 +4,12 @@ class render_target;
|
||||
class texture;
|
||||
class slang_handle;
|
||||
|
||||
struct shader_draw_data
|
||||
{
|
||||
int width;
|
||||
int height;
|
||||
};
|
||||
|
||||
class shader : public std::enable_shared_from_this<shader>
|
||||
{
|
||||
public:
|
||||
@ -18,7 +24,6 @@ public:
|
||||
virtual void bind() = 0;
|
||||
virtual void unbind() = 0;
|
||||
virtual void compute(int x, int y, int z) {}
|
||||
virtual void draw(int width, int height, std::shared_ptr<shader> in_vertex_shader = nullptr) {}
|
||||
|
||||
// param setters
|
||||
virtual void set_cbuffer(const char* name, void* buffer, int size) = 0;
|
||||
@ -47,6 +52,9 @@ public:
|
||||
{
|
||||
set_uav_buffer(name, (void*)buffer.data(), buffer.size(), sizeof(T));
|
||||
}
|
||||
|
||||
void begin_draw(const shader_draw_data& in_data) { if (on_begin_draw) on_begin_draw(in_data, *this); }
|
||||
std::function<void(const shader_draw_data&, shader&)> on_begin_draw;
|
||||
protected:
|
||||
std::shared_ptr<slang_handle> handle_;
|
||||
};
|
||||
|
156
core/rhi/windows/dx11/pixel_shader_drawer_dx11.cpp
Normal file
156
core/rhi/windows/dx11/pixel_shader_drawer_dx11.cpp
Normal file
@ -0,0 +1,156 @@
|
||||
#include "pixel_shader_drawer_dx11.h"
|
||||
|
||||
#include "renderer_dx11.h"
|
||||
#include "render_target_dx11.h"
|
||||
#include "application/application.h"
|
||||
#include "shader/shader_ps_dx11.h"
|
||||
|
||||
void ps_dx11_compute_callback(const ImDrawList* parent_list, const ImDrawCmd* cmd)
|
||||
{
|
||||
pixel_shader_drawer_dx11* data = static_cast<pixel_shader_drawer_dx11*>(cmd->UserCallbackData);
|
||||
auto& ps = data->pixel_shader;
|
||||
const auto& vertex_buffer = data->vertex_buffer;
|
||||
const auto& render_target = data->render_target;
|
||||
const auto& index_buffer = data->index_buffer;
|
||||
const auto vertex_shader = data->vertex_shader.lock();
|
||||
const int width = render_target->get_width();
|
||||
const int height = render_target->get_height();
|
||||
|
||||
D3D11_MAPPED_SUBRESOURCE vtx_resource;
|
||||
ID3D11Buffer* vb = vertex_buffer;
|
||||
if (g_d3d11_device_context->Map(vb, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK)
|
||||
return;
|
||||
ImDrawVert* vtx_dst = (ImDrawVert*)vtx_resource.pData;
|
||||
vtx_dst[0].pos = ImVec2(0, 0);
|
||||
vtx_dst[0].uv = ImVec2(0, 0);
|
||||
vtx_dst[0].col = 0xffffffff;
|
||||
|
||||
vtx_dst[1].pos = ImVec2(width, 0);
|
||||
vtx_dst[1].uv = ImVec2(1, 0);
|
||||
vtx_dst[1].col = 0xffffffff;
|
||||
|
||||
vtx_dst[2].pos = ImVec2(width, height);
|
||||
vtx_dst[2].uv = ImVec2(1, 1);
|
||||
vtx_dst[2].col = 0xffffffff;
|
||||
|
||||
vtx_dst[3].pos = ImVec2(0, height);
|
||||
vtx_dst[3].uv = ImVec2(0, 1);
|
||||
vtx_dst[3].col = 0xffffffff;
|
||||
g_d3d11_device_context->Unmap(vb, 0);
|
||||
|
||||
const auto target_rtv = render_target->get_render_target_view().get_reference();
|
||||
g_d3d11_device_context->OMSetRenderTargets(1, &target_rtv, nullptr);
|
||||
|
||||
g_d3d11_device_context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
|
||||
|
||||
D3D11_VIEWPORT vp = {};
|
||||
vp.Width = width;
|
||||
vp.Height = height;
|
||||
vp.MinDepth = 0.0f;
|
||||
vp.MaxDepth = 1.0f;
|
||||
vp.TopLeftX = vp.TopLeftY = 0;
|
||||
g_d3d11_device_context->RSSetViewports(1, &vp);
|
||||
|
||||
vertex_shader->bind();
|
||||
|
||||
const unsigned int stride = sizeof(ImDrawVert);
|
||||
const unsigned int offset = 0;
|
||||
g_d3d11_device_context->IASetVertexBuffers(0, 1, &vb, &stride, &offset);
|
||||
g_d3d11_device_context->IASetIndexBuffer(index_buffer, DXGI_FORMAT_R16_UINT, 0);
|
||||
|
||||
// setup new scissors
|
||||
D3D11_RECT new_scissors;
|
||||
new_scissors.left = 0;
|
||||
new_scissors.right = width;
|
||||
new_scissors.top = 0;
|
||||
new_scissors.bottom = height;
|
||||
g_d3d11_device_context->RSSetScissorRects(1, &new_scissors);
|
||||
|
||||
ps.lock()->bind();
|
||||
g_d3d11_device_context->DrawIndexed(6, 0, 0);
|
||||
vertex_shader->unbind();
|
||||
ps.lock()->unbind();
|
||||
|
||||
ID3D11RenderTargetView* main_render_target = g_main_render_target_view.get_reference();
|
||||
g_d3d11_device_context->OMSetRenderTargets(1, &main_render_target, nullptr);
|
||||
}
|
||||
|
||||
void pixel_shader_drawer_dx11::init(int width, int height, std::shared_ptr<shader> in_pixel_shader,
|
||||
std::shared_ptr<shader> in_vertex_shader)
|
||||
{
|
||||
if (!in_vertex_shader)
|
||||
{
|
||||
in_vertex_shader = application::get()->get_renderer()->get_pixel_shader_render_default_vs();
|
||||
}
|
||||
vertex_shader = in_vertex_shader;
|
||||
pixel_shader = in_pixel_shader;
|
||||
|
||||
render_target = std::static_pointer_cast<render_target_dx11>(application::get()->create_render_target(width, height, texture_format::RGBA8));
|
||||
|
||||
{
|
||||
D3D11_BUFFER_DESC desc = {};
|
||||
desc.Usage = D3D11_USAGE_DYNAMIC;
|
||||
desc.ByteWidth = sizeof(ImDrawVert) * 4;
|
||||
desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
|
||||
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
|
||||
g_d3d11_device->CreateBuffer(&desc, nullptr, vertex_buffer.get_init_reference());
|
||||
}
|
||||
{
|
||||
D3D11_BUFFER_DESC desc = {};
|
||||
desc.Usage = D3D11_USAGE_DYNAMIC;
|
||||
desc.ByteWidth = sizeof(ImDrawIdx) * 6;
|
||||
desc.BindFlags = D3D11_BIND_INDEX_BUFFER;
|
||||
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
|
||||
g_d3d11_device->CreateBuffer(&desc, nullptr, index_buffer.get_init_reference());
|
||||
|
||||
// init index buffer
|
||||
const ImDrawIdx indices[] = { 0, 1, 2, 0, 2, 3 };
|
||||
D3D11_MAPPED_SUBRESOURCE index_resource;
|
||||
g_d3d11_device_context->Map(index_buffer.get_reference(), 0, D3D11_MAP_WRITE_DISCARD, 0, &index_resource);
|
||||
memcpy(index_resource.pData, indices, sizeof(indices));
|
||||
g_d3d11_device_context->Unmap(index_buffer.get_reference(), 0);
|
||||
}
|
||||
|
||||
update_view_matrix(width, height);
|
||||
}
|
||||
|
||||
void pixel_shader_drawer_dx11::set_vertex_shader(std::shared_ptr<shader> in_vertex_shader)
|
||||
{
|
||||
vertex_shader = in_vertex_shader;
|
||||
}
|
||||
|
||||
void pixel_shader_drawer_dx11::draw()
|
||||
{
|
||||
#if _DEBUG
|
||||
assert(!(vertex_shader.expired() || pixel_shader.expired()));
|
||||
#endif
|
||||
ImGui::GetWindowDrawList()->AddCallback(ps_dx11_compute_callback, this);
|
||||
ImGui::GetWindowDrawList()->AddCallback(ImDrawCallback_ResetRenderState, nullptr);
|
||||
render_target->draw();
|
||||
}
|
||||
|
||||
void pixel_shader_drawer_dx11::resize(int width, int height)
|
||||
{
|
||||
render_target->resize(width, height);
|
||||
update_view_matrix(width, height);
|
||||
}
|
||||
|
||||
void pixel_shader_drawer_dx11::update_view_matrix(int width, int height) const
|
||||
{
|
||||
#if _DEBUG
|
||||
assert(!(vertex_shader.expired()));
|
||||
#endif
|
||||
const float L = 0;
|
||||
const float R = width;
|
||||
const float T = 0;
|
||||
const float B = height;
|
||||
|
||||
float mvp[4][4] =
|
||||
{
|
||||
{ 2.0f/(R-L), 0.0f, 0.0f, 0.0f },
|
||||
{ 0.0f, 2.0f/(T-B), 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f, -1.0f, 0.0f },
|
||||
{ (R+L)/(L-R), (T+B)/(B-T), 0.0f, 1.0f },
|
||||
};
|
||||
vertex_shader.lock()->set_cbuffer("viewMatrix", mvp, sizeof(mvp));
|
||||
}
|
23
core/rhi/windows/dx11/pixel_shader_drawer_dx11.h
Normal file
23
core/rhi/windows/dx11/pixel_shader_drawer_dx11.h
Normal file
@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
#include "misc/ref_counting.h"
|
||||
#include "rhi/pixel_shader_drawer.h"
|
||||
#include <d3d11.h>
|
||||
|
||||
class render_target_dx11;
|
||||
|
||||
class pixel_shader_drawer_dx11 : public pixel_shader_drawer
|
||||
{
|
||||
public:
|
||||
void init(int width, int height, std::shared_ptr<shader> in_pixel_shader, std::shared_ptr<shader> in_vertex_shader) override;
|
||||
void set_vertex_shader(std::shared_ptr<shader> in_vertex_shader) override;
|
||||
void draw() override;
|
||||
void resize(int width, int height) override;
|
||||
|
||||
std::weak_ptr<shader> pixel_shader;
|
||||
std::weak_ptr<shader> vertex_shader;
|
||||
std::shared_ptr<render_target_dx11> render_target;
|
||||
ref_count_ptr<ID3D11Buffer> vertex_buffer;
|
||||
ref_count_ptr<ID3D11Buffer> index_buffer;
|
||||
protected:
|
||||
void update_view_matrix(int width, int height) const;
|
||||
};
|
@ -6,6 +6,7 @@
|
||||
#include "imgui.h"
|
||||
#include "imgui_impl_dx11.h"
|
||||
#include "imgui_impl_sdl3.h"
|
||||
#include "pixel_shader_drawer_dx11.h"
|
||||
#include "render_target_dx11.h"
|
||||
#include "texture_dx11.h"
|
||||
#include "application/application.h"
|
||||
@ -123,6 +124,11 @@ std::shared_ptr<shader> renderer_dx11::load_shader(const std::string& entry_name
|
||||
return out;
|
||||
}
|
||||
|
||||
std::shared_ptr<pixel_shader_drawer> renderer_dx11::create_pixel_shader_drawer()
|
||||
{
|
||||
return std::make_shared<pixel_shader_drawer_dx11>();
|
||||
}
|
||||
|
||||
void renderer_dx11::new_frame(SDL_Window* window_handle)
|
||||
{
|
||||
ImGui_ImplDX11_NewFrame();
|
||||
|
@ -22,6 +22,7 @@ public:
|
||||
|
||||
void create_slang_session(const std::string& shader_path, slang::ISession** out_session) override;
|
||||
std::shared_ptr<shader> load_shader(const std::string& entry_name) override;
|
||||
std::shared_ptr<pixel_shader_drawer> create_pixel_shader_drawer() override;
|
||||
|
||||
void new_frame(SDL_Window* window_handle) override;
|
||||
void end_frame(SDL_Window* window_handle) override;
|
||||
|
@ -57,138 +57,3 @@ HRESULT shader_ps_dx11::create_shader(ID3DBlob* blob, ID3D11Device* device)
|
||||
{
|
||||
return device->CreatePixelShader(blob->GetBufferPointer(), blob->GetBufferSize(), nullptr, pixel_shader_.writeRef());
|
||||
}
|
||||
|
||||
void ps_dx11_compute_callback(const ImDrawList* parent_list, const ImDrawCmd* cmd)
|
||||
{
|
||||
shader_ps_dx11::ps_data* data = (shader_ps_dx11::ps_data*)cmd->UserCallbackData;
|
||||
auto& ps = data->ps;
|
||||
auto& vertex_buffer = data->vertex_buffer;
|
||||
auto& render_target = data->render_target;
|
||||
auto& index_buffer = data->index_buffer;
|
||||
auto vertex_shader = data->vertex_shader.lock();
|
||||
const int width = render_target->get_width();
|
||||
const int height = render_target->get_height();
|
||||
|
||||
D3D11_MAPPED_SUBRESOURCE vtx_resource;
|
||||
ID3D11Buffer* vb = vertex_buffer;
|
||||
if (g_d3d11_device_context->Map(vb, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK)
|
||||
return;
|
||||
ImDrawVert* vtx_dst = (ImDrawVert*)vtx_resource.pData;
|
||||
vtx_dst[0].pos = ImVec2(0, 0);
|
||||
vtx_dst[0].uv = ImVec2(0, 0);
|
||||
vtx_dst[0].col = 0xffffffff;
|
||||
|
||||
vtx_dst[1].pos = ImVec2(width, 0);
|
||||
vtx_dst[1].uv = ImVec2(1, 0);
|
||||
vtx_dst[1].col = 0xffffffff;
|
||||
|
||||
vtx_dst[2].pos = ImVec2(width, height);
|
||||
vtx_dst[2].uv = ImVec2(1, 1);
|
||||
vtx_dst[2].col = 0xffffffff;
|
||||
|
||||
vtx_dst[3].pos = ImVec2(0, height);
|
||||
vtx_dst[3].uv = ImVec2(0, 1);
|
||||
vtx_dst[3].col = 0xffffffff;
|
||||
g_d3d11_device_context->Unmap(vb, 0);
|
||||
|
||||
const auto target_rtv = render_target->get_render_target_view().get_reference();
|
||||
g_d3d11_device_context->OMSetRenderTargets(1, &target_rtv, nullptr);
|
||||
|
||||
g_d3d11_device_context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
|
||||
|
||||
D3D11_VIEWPORT vp = {};
|
||||
vp.Width = width;
|
||||
vp.Height = height;
|
||||
vp.MinDepth = 0.0f;
|
||||
vp.MaxDepth = 1.0f;
|
||||
vp.TopLeftX = vp.TopLeftY = 0;
|
||||
g_d3d11_device_context->RSSetViewports(1, &vp);
|
||||
|
||||
vertex_shader->bind();
|
||||
|
||||
const unsigned int stride = sizeof(ImDrawVert);
|
||||
const unsigned int offset = 0;
|
||||
g_d3d11_device_context->IASetVertexBuffers(0, 1, &vb, &stride, &offset);
|
||||
g_d3d11_device_context->IASetIndexBuffer(index_buffer, DXGI_FORMAT_R16_UINT, 0);
|
||||
|
||||
// setup new scissors
|
||||
D3D11_RECT new_scissors;
|
||||
new_scissors.left = 0;
|
||||
new_scissors.right = width;
|
||||
new_scissors.top = 0;
|
||||
new_scissors.bottom = height;
|
||||
g_d3d11_device_context->RSSetScissorRects(1, &new_scissors);
|
||||
|
||||
ps->bind();
|
||||
g_d3d11_device_context->DrawIndexed(6, 0, 0);
|
||||
vertex_shader->unbind();
|
||||
ps->unbind();
|
||||
|
||||
ID3D11RenderTargetView* main_render_target = g_main_render_target_view.get_reference();
|
||||
g_d3d11_device_context->OMSetRenderTargets(1, &main_render_target, nullptr);
|
||||
}
|
||||
|
||||
void shader_ps_dx11::draw(int width, int height, std::shared_ptr<shader> in_vertex_shader)
|
||||
{
|
||||
if (!draw_data.initialized)
|
||||
{
|
||||
draw_data.ps = this;
|
||||
{
|
||||
draw_data.render_target = std::static_pointer_cast<render_target_dx11>(application::get()->create_render_target(width, height, texture_format::RGBA8));
|
||||
}
|
||||
{
|
||||
D3D11_BUFFER_DESC desc = {};
|
||||
desc.Usage = D3D11_USAGE_DYNAMIC;
|
||||
desc.ByteWidth = sizeof(ImDrawVert) * 4;
|
||||
desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
|
||||
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
|
||||
g_d3d11_device->CreateBuffer(&desc, nullptr, draw_data.vertex_buffer.get_init_reference());
|
||||
}
|
||||
{
|
||||
D3D11_BUFFER_DESC desc = {};
|
||||
desc.Usage = D3D11_USAGE_DYNAMIC;
|
||||
desc.ByteWidth = sizeof(ImDrawIdx) * 6;
|
||||
desc.BindFlags = D3D11_BIND_INDEX_BUFFER;
|
||||
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
|
||||
g_d3d11_device->CreateBuffer(&desc, nullptr, draw_data.index_buffer.get_init_reference());
|
||||
|
||||
// init index buffer
|
||||
const ImDrawIdx indices[] = { 0, 1, 2, 0, 2, 3 };
|
||||
D3D11_MAPPED_SUBRESOURCE index_resource;
|
||||
g_d3d11_device_context->Map(draw_data.index_buffer.get_reference(), 0, D3D11_MAP_WRITE_DISCARD, 0, &index_resource);
|
||||
memcpy(index_resource.pData, indices, sizeof(indices));
|
||||
g_d3d11_device_context->Unmap(draw_data.index_buffer.get_reference(), 0);
|
||||
}
|
||||
draw_data.initialized = true;
|
||||
}
|
||||
if (!in_vertex_shader)
|
||||
{
|
||||
in_vertex_shader = application::get()->get_renderer()->get_pixel_shader_render_default_vs();
|
||||
const float L = 0;
|
||||
const float R = width;
|
||||
const float T = 0;
|
||||
const float B = height;
|
||||
// float mvp[4][4] =
|
||||
// {
|
||||
// { 2.0f/(R-L), 0.0f, 0.0f, (R+L)/(L-R) },
|
||||
// { 0.0f, 2.0f/(T-B), 0.0f, (T+B)/(B-T) },
|
||||
// { 0.0f, 0.0f, 0.5f, 0.5f },
|
||||
// { 0.0f, 0.0f, 0.0f, 1.0f },
|
||||
// };
|
||||
|
||||
float mvp[4][4] =
|
||||
{
|
||||
{ 2.0f/(R-L), 0.0f, 0.0f, 0.0f },
|
||||
{ 0.0f, 2.0f/(T-B), 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f, -1.0f, 0.0f },
|
||||
{ (R+L)/(L-R), (T+B)/(B-T), 0.0f, 1.0f },
|
||||
};
|
||||
in_vertex_shader->set_cbuffer("viewMatrix", mvp, sizeof(mvp));
|
||||
}
|
||||
draw_data.vertex_shader = in_vertex_shader;
|
||||
|
||||
draw_data.render_target->resize(width, height);
|
||||
ImGui::GetWindowDrawList()->AddCallback(ps_dx11_compute_callback, &draw_data);
|
||||
ImGui::GetWindowDrawList()->AddCallback(ImDrawCallback_ResetRenderState, nullptr);
|
||||
draw_data.render_target->draw();
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
#pragma once
|
||||
#include "shader_dx11.h"
|
||||
#include "slang-com-ptr.h"
|
||||
#include "misc/ref_counting.h"
|
||||
|
||||
class shader_ps_dx11 : public shader_dx11
|
||||
{
|
||||
@ -19,19 +18,6 @@ public:
|
||||
[[nodiscard]] ID3D11DeviceChild* get_shader() override { return pixel_shader_; }
|
||||
[[nodiscard]] const char* get_shader_model() const override { return "ps_5_0"; }
|
||||
[[nodiscard]] bool is_initialized() const override { return pixel_shader_ != nullptr; }
|
||||
|
||||
void draw(int width, int height, std::shared_ptr<shader> in_vertex_shader = nullptr) override;
|
||||
|
||||
struct ps_data
|
||||
{
|
||||
shader_ps_dx11* ps;
|
||||
std::shared_ptr<render_target_dx11> render_target;
|
||||
ref_count_ptr<ID3D11Buffer> vertex_buffer;
|
||||
ref_count_ptr<ID3D11Buffer> index_buffer;
|
||||
std::weak_ptr<shader> vertex_shader;
|
||||
|
||||
bool initialized = false;
|
||||
} draw_data;
|
||||
private:
|
||||
Slang::ComPtr<ID3D11PixelShader> pixel_shader_;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user