Skip to content

Commit

Permalink
Add low level graphics render passes and refactor painter draw methods
Browse files Browse the repository at this point in the history
Add low level graphics render passes and refactor painter draw methods.
This change is needed because there's a need to be able to leverage
the painter draw methods in more elaborate drawing systems when doing
multiple passes over the items and rendering to various different
render targets/buffers. This change splits some rendering state into
"render pass"  objects which are then responsible for setting up the
right device state for writing to color/depth/stencil buffers. Doing
this also simplifies the painter implementation since it no longer
needs to implement different draws such as mask+cover itself but the
caller can create such a setup easily. The legacy functionality for
the simplest draw is kept for backwards compatibility by adding some
default render pass implementations and using those implicitly.

The render pass object is now also added to the environment arguments
passed to the material and drawable when applying program/device state.
This allows the materials and drawables to provide alternative ways
for performing some render pass, such as using simpler shaders when
doing a stencil pass and now actual RGB computation is needed.
  • Loading branch information
ensisoft committed Jan 28, 2023
1 parent a7c4fd9 commit 234aae5
Show file tree
Hide file tree
Showing 11 changed files with 289 additions and 194 deletions.
3 changes: 3 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ add_library(GfxLib
graphics/drawing.cpp
graphics/drawable.cpp
graphics/material.cpp
graphics/renderpass.cpp
graphics/image.cpp
graphics/device.cpp
graphics/opengl_es2_device.cpp
Expand Down Expand Up @@ -200,6 +201,7 @@ add_library(GfxLibTesting
graphics/drawing.cpp
graphics/drawable.cpp
graphics/material.cpp
graphics/renderpass.cpp
graphics/image.cpp
graphics/device.cpp
graphics/opengl_es2_device.cpp
Expand Down Expand Up @@ -583,6 +585,7 @@ install(TARGETS audio_test DESTINATION "${CMAKE_CURRENT_LIST_DIR}/audio/test/")
add_executable(graphics_test
graphics/bitmap.cpp
graphics/material.cpp
graphics/renderpass.cpp
graphics/drawable.cpp
graphics/drawing.cpp
graphics/device.cpp
Expand Down
33 changes: 22 additions & 11 deletions engine/renderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include "graphics/material.h"
#include "graphics/painter.h"
#include "graphics/transform.h"
#include "graphics/renderpass.h"
#include "engine/classlib.h"
#include "game/entity.h"
#include "game/scene.h"
Expand Down Expand Up @@ -573,15 +574,15 @@ void Renderer::CreateDrawResources(PaintNode& paint_node)
{
const auto& material = item->GetMaterialId();
const auto& drawable = item->GetDrawableId();
if (item->GetRenderPass() == RenderPass::Draw && paint_node.item_material_id != material)
if (paint_node.item_material_id != material)
{
paint_node.item_material.reset();
paint_node.item_material_id = material;
auto klass = mClassLib->FindMaterialClassById(material);
if (klass)
paint_node.item_material = gfx::CreateMaterialInstance(klass);
if (!paint_node.item_material)
WARN("No such material class '%1' found for '%2/%3')", material, entity.GetName(), node.GetName());
WARN("No such material class found. [material='%1', entity='%2', node='%3']", material, entity.GetName(), node.GetName());
}
if (paint_node.item_drawable_id != drawable)
{
Expand All @@ -592,7 +593,7 @@ void Renderer::CreateDrawResources(PaintNode& paint_node)
if (klass)
paint_node.item_drawable = gfx::CreateDrawableInstance(klass);
if (!paint_node.item_drawable)
WARN("No such drawable class '%1' found for '%2/%3'", drawable, entity.GetName(), node.GetName());
WARN("No such drawable class found. [drawable='%1', entity='%2, node='%3']", drawable, entity.GetName(), node.GetName());
if (paint_node.item_drawable)
{
gfx::Transform transform;
Expand Down Expand Up @@ -744,7 +745,7 @@ void Renderer::DrawPackets(gfx::Painter& painter, std::vector<DrawPacket>& packe

struct Layer {
std::vector<gfx::Painter::DrawShape> draw_list;
std::vector<gfx::Painter::MaskShape> mask_list;
std::vector<gfx::Painter::DrawShape> mask_list;
};
// Each entity in the scene is assigned to a scene/entity layer and each
// entity node within an entity is assigned to an entity layer.
Expand Down Expand Up @@ -774,25 +775,35 @@ void Renderer::DrawPackets(gfx::Painter& painter, std::vector<DrawPacket>& packe
{
gfx::Painter::DrawShape shape;
shape.transform = &packet.transform;
shape.drawable = packet.drawable.get();
shape.material = packet.material.get();
shape.drawable = packet.drawable.get();
shape.material = packet.material.get();
entity_layer.draw_list.push_back(shape);
}
else if (packet.pass == RenderPass::Mask)
{
gfx::Painter::MaskShape shape;
gfx::Painter::DrawShape shape;
shape.transform = &packet.transform;
shape.drawable = packet.drawable.get();
shape.drawable = packet.drawable.get();
shape.material = packet.material.get();
entity_layer.mask_list.push_back(shape);
}
}
for (const auto& scene_layer : layers)
{
for (const auto& entity_layer : scene_layer)
{
entity_layer.mask_list.empty()
? painter.Draw(entity_layer.draw_list)
: painter.Draw(entity_layer.draw_list, entity_layer.mask_list);
if (!entity_layer.mask_list.empty())
{
const gfx::detail::StencilMaskPass mask(1, 0);
const gfx::detail::StencilTestColorWritePass cover(1);
painter.Draw(entity_layer.mask_list, mask);
painter.Draw(entity_layer.draw_list, cover);
}
else if (!entity_layer.draw_list.empty())
{
const gfx::detail::GenericRenderPass pass;
painter.Draw(entity_layer.draw_list, pass);
}
}
}
}
Expand Down
2 changes: 2 additions & 0 deletions graphics/drawable.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ namespace gfx
class Shader;
class Geometry;
class Program;
class RenderPass;

// DrawableClass defines a new type of drawable.
class DrawableClass
Expand Down Expand Up @@ -88,6 +89,7 @@ namespace gfx
Points
};
struct Environment {
const RenderPass* render_pass = nullptr;
// true if running in an "editor mode", which means that even
// content marked static might have changed and should be checked
// in case it has been modified and should be re-uploaded.
Expand Down
7 changes: 6 additions & 1 deletion graphics/drawing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include "graphics/drawable.h"
#include "graphics/transform.h"
#include "graphics/text.h"
#include "graphics/renderpass.h"

namespace {
gfx::MaterialClassInst MakeMaterial(const gfx::Color4f& color)
Expand Down Expand Up @@ -194,7 +195,11 @@ void DrawShapeOutline(Painter& painter, const FRect& rect, const Drawable& shape
const auto mask_height = height - 2 * line_width;
mask_transform.Resize(mask_width, mask_height);
mask_transform.Translate(x + line_width, y + line_width);
painter.Draw(shape, outline_transform, shape, mask_transform, material);

detail::StencilMaskPass mask(1, 0);
detail::StencilTestColorWritePass cover(1);
painter.Draw(shape, mask_transform, material, mask);
painter.Draw(shape, outline_transform, material, cover);
}

void DrawLine(Painter& painter, const FPoint& a, const FPoint& b, const Color4f& color, float line_width)
Expand Down
2 changes: 2 additions & 0 deletions graphics/material.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ namespace gfx
{
class Device;
class Shader;
class RenderPass;

// Interface for acquiring texture data. Possible implementations
// might load the data from a file or generate it on the fly.
Expand Down Expand Up @@ -1459,6 +1460,7 @@ namespace gfx
virtual ~Material() = default;

struct Environment {
const RenderPass* render_pass = nullptr;
// true if running in an "editing mode", which means that even
// content marked static might have changed and should be checked
// in case it has been modified and should be re-uploaded.
Expand Down
3 changes: 1 addition & 2 deletions graphics/opengl_es2_device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -819,9 +819,8 @@ class OpenGLES2GraphicsDevice : public Device
{
GLenum depth_test;
if (state.depth_test == State::DepthTest::LessOrEQual)
depth_test = GL_LEQUAL;
GL_CALL(glDepthFunc(depth_test));
else BUG("Unknown GL depth test mode.");
GL_CALL(glDepthFunc(depth_test));
}

if (state.bWriteColor) {
Expand Down
Loading

0 comments on commit 234aae5

Please sign in to comment.