mirror of
https://github.com/aseprite/aseprite.git
synced 2025-03-13 01:13:22 +00:00
Add initial (incomplete) version of ShaderRenderer
This new renderer uses a shader to paint only the checkered background. It can be tested only in ENABLE_DEVMODE and pressing F1 key to switch between the renderers (which is a devmode special key for testing purposes only) We've changed the Renderer::renderSprite(Image*, ...) member function to renderSprite(os::Surface*, ...) so we receive the os::Surface directly to paint the SkCanvas with a SkShader. Probably more refactors will be needed.
This commit is contained in:
parent
a7e155a391
commit
be583f8149
@ -57,7 +57,7 @@ When Aseprite is compiled with `ENABLE_DEVMODE`, you have the
|
||||
following extra commands/features available:
|
||||
|
||||
* `F5`: On Windows shows the amount of used memory.
|
||||
* `F1`: Switch new/old render engine.
|
||||
* `F1`: Switch between new/old/shader renderers.
|
||||
* `Ctrl+F1`: Switch/test Screen/UI Scaling values.
|
||||
* `Ctrl+Alt+Shift+Q`: crashes the application in case that you want to
|
||||
test the anticrash feature or your need a memory dump file.
|
||||
|
@ -641,6 +641,7 @@ add_library(app-lib
|
||||
modules/palettes.cpp
|
||||
pref/preferences.cpp
|
||||
recent_files.cpp
|
||||
render/shader_renderer.cpp
|
||||
render/simple_renderer.cpp
|
||||
res/palettes_loader_delegate.cpp
|
||||
res/resources_loader.cpp
|
||||
|
@ -15,6 +15,10 @@ namespace doc {
|
||||
class Sprite;
|
||||
}
|
||||
|
||||
namespace os {
|
||||
class Surface;
|
||||
}
|
||||
|
||||
namespace app {
|
||||
|
||||
// Abstract class to render images from any editor to be displayed
|
||||
@ -54,7 +58,7 @@ namespace app {
|
||||
virtual void renderSprite(doc::Image* dstImage,
|
||||
const doc::Sprite* sprite,
|
||||
const doc::frame_t frame) = 0;
|
||||
virtual void renderSprite(doc::Image* dstImage,
|
||||
virtual void renderSprite(os::Surface* dstSurface,
|
||||
const doc::Sprite* sprite,
|
||||
const doc::frame_t frame,
|
||||
const gfx::ClipF& area) = 0;
|
||||
|
177
src/app/render/shader_renderer.cpp
Normal file
177
src/app/render/shader_renderer.cpp
Normal file
@ -0,0 +1,177 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2022 Igara Studio S.A.
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
// the End-User License Agreement for Aseprite.
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "app/render/shader_renderer.h"
|
||||
|
||||
#if SK_ENABLE_SKSL
|
||||
|
||||
#include "app/color_utils.h"
|
||||
#include "app/util/shader_helpers.h"
|
||||
#include "os/skia/skia_surface.h"
|
||||
|
||||
#include "include/core/SkCanvas.h"
|
||||
#include "include/effects/SkRuntimeEffect.h"
|
||||
|
||||
namespace app {
|
||||
|
||||
static const char* kBgShaderCode = R"(
|
||||
uniform half3 iRes, iCanvas, iSrcPos;
|
||||
uniform half4 iBg1, iBg2;
|
||||
uniform half2 iStripeSize;
|
||||
|
||||
half4 main(vec2 fragcoord) {
|
||||
vec2 u = (iSrcPos.xy+fragcoord.xy) / iStripeSize.xy;
|
||||
return (mod(mod(floor(u.x), 2) + mod(floor(u.y), 2), 2) != 0.0 ? iBg2: iBg1);
|
||||
}
|
||||
)";
|
||||
|
||||
ShaderRenderer::ShaderRenderer()
|
||||
{
|
||||
auto result = SkRuntimeEffect::MakeForShader(SkString(kBgShaderCode));
|
||||
if (!result.errorText.isEmpty()) {
|
||||
LOG(ERROR, "Shader error: %s\n", result.errorText.c_str());
|
||||
std::printf("Shader error: %s\n", result.errorText.c_str());
|
||||
throw std::runtime_error("Cannot compile shaders for ShaderRenderer");
|
||||
}
|
||||
m_bgEffect = result.effect;
|
||||
}
|
||||
|
||||
ShaderRenderer::~ShaderRenderer() = default;
|
||||
|
||||
void ShaderRenderer::setRefLayersVisiblity(const bool visible)
|
||||
{
|
||||
// TODO impl
|
||||
}
|
||||
|
||||
void ShaderRenderer::setNonactiveLayersOpacity(const int opacity)
|
||||
{
|
||||
// TODO impl
|
||||
}
|
||||
|
||||
void ShaderRenderer::setNewBlendMethod(const bool newBlend)
|
||||
{
|
||||
// TODO impl
|
||||
}
|
||||
|
||||
void ShaderRenderer::setBgOptions(const render::BgOptions& bg)
|
||||
{
|
||||
m_bgOptions = bg;
|
||||
}
|
||||
|
||||
void ShaderRenderer::setProjection(const render::Projection& projection)
|
||||
{
|
||||
// TODO impl
|
||||
}
|
||||
|
||||
void ShaderRenderer::setSelectedLayer(const doc::Layer* layer)
|
||||
{
|
||||
// TODO impl
|
||||
}
|
||||
|
||||
void ShaderRenderer::setPreviewImage(const doc::Layer* layer,
|
||||
const doc::frame_t frame,
|
||||
const doc::Image* image,
|
||||
const doc::Tileset* tileset,
|
||||
const gfx::Point& pos,
|
||||
const doc::BlendMode blendMode)
|
||||
{
|
||||
// TODO impl
|
||||
}
|
||||
|
||||
void ShaderRenderer::removePreviewImage()
|
||||
{
|
||||
// TODO impl
|
||||
}
|
||||
|
||||
void ShaderRenderer::setExtraImage(render::ExtraType type,
|
||||
const doc::Cel* cel,
|
||||
const doc::Image* image,
|
||||
const doc::BlendMode blendMode,
|
||||
const doc::Layer* currentLayer,
|
||||
const doc::frame_t currentFrame)
|
||||
{
|
||||
// TODO impl
|
||||
}
|
||||
|
||||
void ShaderRenderer::removeExtraImage()
|
||||
{
|
||||
// TODO impl
|
||||
}
|
||||
|
||||
void ShaderRenderer::setOnionskin(const render::OnionskinOptions& options)
|
||||
{
|
||||
// TODO impl
|
||||
}
|
||||
|
||||
void ShaderRenderer::disableOnionskin()
|
||||
{
|
||||
// TODO impl
|
||||
}
|
||||
|
||||
void ShaderRenderer::renderSprite(doc::Image* dstImage,
|
||||
const doc::Sprite* sprite,
|
||||
const doc::frame_t frame)
|
||||
{
|
||||
// TODO impl
|
||||
}
|
||||
|
||||
void ShaderRenderer::renderSprite(os::Surface* dstSurface,
|
||||
const doc::Sprite* sprite,
|
||||
const doc::frame_t frame,
|
||||
const gfx::ClipF& area)
|
||||
{
|
||||
SkRuntimeShaderBuilder builder(m_bgEffect);
|
||||
builder.uniform("iRes") = SkV3{float(area.size.w), float(area.size.h), 0.0f};
|
||||
builder.uniform("iCanvas") = SkV3{float(sprite->width()), float(sprite->height()), 0.0f};
|
||||
builder.uniform("iSrcPos") = SkV3{float(area.src.x), float(area.src.y), 0.0f};
|
||||
builder.uniform("iBg1") = gfxColor_to_SkV4(
|
||||
color_utils::color_for_ui(
|
||||
app::Color::fromImage(sprite->pixelFormat(),
|
||||
m_bgOptions.color1)));
|
||||
builder.uniform("iBg2") = gfxColor_to_SkV4(
|
||||
color_utils::color_for_ui(
|
||||
app::Color::fromImage(sprite->pixelFormat(),
|
||||
m_bgOptions.color2)));
|
||||
builder.uniform("iStripeSize") = SkV2{
|
||||
float(m_bgOptions.stripeSize.w),
|
||||
float(m_bgOptions.stripeSize.h)};
|
||||
|
||||
SkCanvas* canvas = &static_cast<os::SkiaSurface*>(dstSurface)->canvas();
|
||||
canvas->save();
|
||||
{
|
||||
SkPaint p;
|
||||
p.setStyle(SkPaint::kFill_Style);
|
||||
p.setShader(builder.makeShader());
|
||||
|
||||
canvas->drawRect(SkRect::MakeXYWH(area.dst.x, area.dst.y, area.size.w, area.size.h), p);
|
||||
}
|
||||
canvas->restore();
|
||||
}
|
||||
|
||||
void ShaderRenderer::renderCheckeredBackground(doc::Image* dstImage,
|
||||
const gfx::Clip& area)
|
||||
{
|
||||
// TODO impl
|
||||
}
|
||||
|
||||
void ShaderRenderer::renderImage(doc::Image* dstImage,
|
||||
const doc::Image* srcImage,
|
||||
const doc::Palette* pal,
|
||||
const int x,
|
||||
const int y,
|
||||
const int opacity,
|
||||
const doc::BlendMode blendMode)
|
||||
{
|
||||
// TODO impl
|
||||
}
|
||||
|
||||
} // namespace app
|
||||
|
||||
#endif // SK_ENABLE_SKSL
|
78
src/app/render/shader_renderer.h
Normal file
78
src/app/render/shader_renderer.h
Normal file
@ -0,0 +1,78 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2022 Igara Studio S.A.
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
// the End-User License Agreement for Aseprite.
|
||||
|
||||
#ifndef APP_RENDER_SHADER_RENDERER_H_INCLUDED
|
||||
#define APP_RENDER_SHADER_RENDERER_H_INCLUDED
|
||||
#pragma once
|
||||
|
||||
#if SK_ENABLE_SKSL
|
||||
|
||||
#include "app/render/renderer.h"
|
||||
|
||||
#include "include/core/SkRefCnt.h"
|
||||
|
||||
class SkRuntimeEffect;
|
||||
|
||||
namespace app {
|
||||
|
||||
// Use SkSL to compose images with Skia shaders on the CPU (with the
|
||||
// SkSL VM) or GPU-accelerated (with native OpenGL/Metal/etc. shaders).
|
||||
class ShaderRenderer : public Renderer {
|
||||
public:
|
||||
ShaderRenderer();
|
||||
~ShaderRenderer();
|
||||
|
||||
void setRefLayersVisiblity(const bool visible) override;
|
||||
void setNonactiveLayersOpacity(const int opacity) override;
|
||||
void setNewBlendMethod(const bool newBlend) override;
|
||||
void setBgOptions(const render::BgOptions& bg) override;
|
||||
void setProjection(const render::Projection& projection) override;
|
||||
|
||||
void setSelectedLayer(const doc::Layer* layer) override;
|
||||
void setPreviewImage(const doc::Layer* layer,
|
||||
const doc::frame_t frame,
|
||||
const doc::Image* image,
|
||||
const doc::Tileset* tileset,
|
||||
const gfx::Point& pos,
|
||||
const doc::BlendMode blendMode) override;
|
||||
void removePreviewImage() override;
|
||||
void setExtraImage(render::ExtraType type,
|
||||
const doc::Cel* cel,
|
||||
const doc::Image* image,
|
||||
const doc::BlendMode blendMode,
|
||||
const doc::Layer* currentLayer,
|
||||
const doc::frame_t currentFrame) override;
|
||||
void removeExtraImage() override;
|
||||
void setOnionskin(const render::OnionskinOptions& options) override;
|
||||
void disableOnionskin() override;
|
||||
|
||||
void renderSprite(doc::Image* dstImage,
|
||||
const doc::Sprite* sprite,
|
||||
const doc::frame_t frame) override;
|
||||
void renderSprite(os::Surface* dstSurface,
|
||||
const doc::Sprite* sprite,
|
||||
const doc::frame_t frame,
|
||||
const gfx::ClipF& area) override;
|
||||
void renderCheckeredBackground(doc::Image* dstImage,
|
||||
const gfx::Clip& area) override;
|
||||
void renderImage(doc::Image* dstImage,
|
||||
const doc::Image* srcImage,
|
||||
const doc::Palette* pal,
|
||||
const int x,
|
||||
const int y,
|
||||
const int opacity,
|
||||
const doc::BlendMode blendMode) override;
|
||||
|
||||
private:
|
||||
render::BgOptions m_bgOptions;
|
||||
sk_sp<SkRuntimeEffect> m_bgEffect;
|
||||
};
|
||||
|
||||
} // namespace app
|
||||
|
||||
#endif // SK_ENABLE_SKSL
|
||||
|
||||
#endif
|
@ -10,8 +10,13 @@
|
||||
|
||||
#include "app/render/simple_renderer.h"
|
||||
|
||||
#include "app/ui/editor/editor_render.h"
|
||||
#include "app/util/conversion_to_surface.h"
|
||||
|
||||
namespace app {
|
||||
|
||||
using namespace doc;
|
||||
|
||||
void SimpleRenderer::setRefLayersVisiblity(const bool visible)
|
||||
{
|
||||
m_render.setRefLayersVisiblity(visible);
|
||||
@ -91,12 +96,18 @@ void SimpleRenderer::renderSprite(doc::Image* dstImage,
|
||||
m_render.renderSprite(dstImage, sprite, frame);
|
||||
}
|
||||
|
||||
void SimpleRenderer::renderSprite(doc::Image* dstImage,
|
||||
void SimpleRenderer::renderSprite(os::Surface* dstSurface,
|
||||
const doc::Sprite* sprite,
|
||||
const doc::frame_t frame,
|
||||
const gfx::ClipF& area)
|
||||
{
|
||||
m_render.renderSprite(dstImage, sprite, frame, area);
|
||||
ImageRef dstImage(Image::create(
|
||||
IMAGE_RGB, area.size.w, area.size.h,
|
||||
EditorRender::getRenderImageBuffer()));
|
||||
m_render.renderSprite(dstImage.get(), sprite, frame, area);
|
||||
|
||||
convert_image_to_surface(dstImage.get(), sprite->palette(frame),
|
||||
dstSurface, 0, 0, 0, 0, area.size.w, area.size.h);
|
||||
}
|
||||
|
||||
void SimpleRenderer::renderCheckeredBackground(doc::Image* dstImage,
|
||||
|
@ -44,7 +44,7 @@ namespace app {
|
||||
void renderSprite(doc::Image* dstImage,
|
||||
const doc::Sprite* sprite,
|
||||
const doc::frame_t frame) override;
|
||||
void renderSprite(doc::Image* dstImage,
|
||||
void renderSprite(os::Surface* dstSurface,
|
||||
const doc::Sprite* sprite,
|
||||
const doc::frame_t frame,
|
||||
const gfx::ClipF& area) override;
|
||||
|
@ -53,7 +53,6 @@
|
||||
#include "app/ui/timeline/timeline.h"
|
||||
#include "app/ui/toolbar.h"
|
||||
#include "app/ui_context.h"
|
||||
#include "app/util/conversion_to_surface.h"
|
||||
#include "app/util/layer_utils.h"
|
||||
#include "base/chrono.h"
|
||||
#include "base/convert_to.h"
|
||||
@ -248,6 +247,11 @@ bool Editor::isUsingNewRenderEngine() const
|
||||
{
|
||||
ASSERT(m_sprite);
|
||||
return
|
||||
// TODO add an option to the ShaderRenderer to works as the "old"
|
||||
// engine (screen pixel by screen pixel) or as the "new"
|
||||
// engine (sprite pixel by sprite pixel)
|
||||
(m_renderEngine->type() == EditorRender::Type::kShaderRenderer)
|
||||
||
|
||||
(Preferences::instance().experimental.newRenderEngine()
|
||||
// Reference layers + zoom > 100% need the old render engine for
|
||||
// sub-pixel rendering.
|
||||
@ -656,16 +660,24 @@ void Editor::drawOneSpriteUnclippedRect(ui::Graphics* g, const gfx::Rect& sprite
|
||||
dest.h = rc.h;
|
||||
}
|
||||
|
||||
std::unique_ptr<Image> rendered(nullptr);
|
||||
// Convert the render to a os::Surface
|
||||
static os::SurfaceRef rendered = nullptr; // TODO move this to other centralized place
|
||||
try {
|
||||
// Generate a "expose sprite pixels" notification. This is used by
|
||||
// tool managers that need to validate this region (copy pixels from
|
||||
// the original cel) before it can be used by the RenderEngine.
|
||||
m_document->notifyExposeSpritePixels(m_sprite, gfx::Region(expose));
|
||||
|
||||
// Create a temporary RGB bitmap to draw all to it
|
||||
rendered.reset(Image::create(IMAGE_RGB, rc2.w, rc2.h,
|
||||
m_renderEngine->getRenderImageBuffer()));
|
||||
// Create a temporary surface to draw the sprite on it
|
||||
if (!rendered ||
|
||||
rendered->width() < rc2.w ||
|
||||
rendered->height() < rc2.h ||
|
||||
rendered->colorSpace() != m_document->osColorSpace()) {
|
||||
const int maxw = std::max(rc2.w, rendered ? rendered->width(): 0);
|
||||
const int maxh = std::max(rc2.h, rendered ? rendered->height(): 0);
|
||||
rendered = os::instance()->makeSurface(
|
||||
maxw, maxh, m_document->osColorSpace());
|
||||
}
|
||||
|
||||
m_renderEngine->setNewBlendMethod(pref.experimental.newBlend());
|
||||
m_renderEngine->setRefLayersVisiblity(true);
|
||||
@ -676,7 +688,7 @@ void Editor::drawOneSpriteUnclippedRect(ui::Graphics* g, const gfx::Rect& sprite
|
||||
m_renderEngine->setNonactiveLayersOpacity(255);
|
||||
m_renderEngine->setProjection(
|
||||
newEngine ? render::Projection(): m_proj);
|
||||
m_renderEngine->setupBackground(m_document, rendered->pixelFormat());
|
||||
m_renderEngine->setupBackground(m_document, IMAGE_RGB);
|
||||
m_renderEngine->disableOnionskin();
|
||||
|
||||
if ((m_flags & kShowOnionskin) == kShowOnionskin) {
|
||||
@ -729,70 +741,36 @@ void Editor::drawOneSpriteUnclippedRect(ui::Graphics* g, const gfx::Rect& sprite
|
||||
Console::showException(e);
|
||||
}
|
||||
|
||||
if (rendered) {
|
||||
// Convert the render to a os::Surface
|
||||
static os::SurfaceRef tmp = nullptr; // TODO move this to other centralized place
|
||||
|
||||
if (!tmp ||
|
||||
tmp->width() < rc2.w ||
|
||||
tmp->height() < rc2.h ||
|
||||
tmp->colorSpace() != m_document->osColorSpace()) {
|
||||
const int maxw = std::max(rc2.w, tmp ? tmp->width(): 0);
|
||||
const int maxh = std::max(rc2.h, tmp ? tmp->height(): 0);
|
||||
tmp = os::instance()->makeSurface(
|
||||
maxw, maxh, m_document->osColorSpace());
|
||||
}
|
||||
|
||||
if (tmp->nativeHandle()) {
|
||||
if (newEngine) {
|
||||
// Without doing something on the "tmp" surface before (like
|
||||
// just drawing a pixel), we get a strange behavior where
|
||||
// pixels are not updated correctly on the editor (e.g. when
|
||||
// zoom < 100%). I didn't have enough time to investigate this
|
||||
// issue yet, but this is a partial fix/hack.
|
||||
//
|
||||
// TODO review why do we need to do this, it looks like some
|
||||
// internal state of a SkCanvas or SkBitmap thing is
|
||||
// updated after this, because convert_image_to_surface()
|
||||
// will overwrite these pixels anyway.
|
||||
os::Paint paint;
|
||||
paint.color(gfx::rgba(0, 0, 0, 255));
|
||||
tmp->drawRect(gfx::Rect(0, 0, 1, 1), paint);
|
||||
}
|
||||
|
||||
convert_image_to_surface(rendered.get(), m_sprite->palette(m_frame),
|
||||
tmp.get(), 0, 0, 0, 0, rc2.w, rc2.h);
|
||||
|
||||
if (newEngine) {
|
||||
os::Sampling sampling;
|
||||
if (m_proj.scaleX() < 1.0) {
|
||||
switch (pref.editor.downsampling()) {
|
||||
case gen::Downsampling::NEAREST:
|
||||
sampling = os::Sampling(os::Sampling::Filter::Nearest);
|
||||
break;
|
||||
case gen::Downsampling::BILINEAR:
|
||||
sampling = os::Sampling(os::Sampling::Filter::Linear);
|
||||
break;
|
||||
case gen::Downsampling::BILINEAR_MIPMAP:
|
||||
sampling = os::Sampling(os::Sampling::Filter::Linear,
|
||||
os::Sampling::Mipmap::Nearest);
|
||||
break;
|
||||
case gen::Downsampling::TRILINEAR_MIPMAP:
|
||||
sampling = os::Sampling(os::Sampling::Filter::Linear,
|
||||
os::Sampling::Mipmap::Linear);
|
||||
break;
|
||||
}
|
||||
if (rendered && rendered->nativeHandle()) {
|
||||
if (newEngine) {
|
||||
os::Sampling sampling;
|
||||
if (m_proj.scaleX() < 1.0) {
|
||||
switch (pref.editor.downsampling()) {
|
||||
case gen::Downsampling::NEAREST:
|
||||
sampling = os::Sampling(os::Sampling::Filter::Nearest);
|
||||
break;
|
||||
case gen::Downsampling::BILINEAR:
|
||||
sampling = os::Sampling(os::Sampling::Filter::Linear);
|
||||
break;
|
||||
case gen::Downsampling::BILINEAR_MIPMAP:
|
||||
sampling = os::Sampling(os::Sampling::Filter::Linear,
|
||||
os::Sampling::Mipmap::Nearest);
|
||||
break;
|
||||
case gen::Downsampling::TRILINEAR_MIPMAP:
|
||||
sampling = os::Sampling(os::Sampling::Filter::Linear,
|
||||
os::Sampling::Mipmap::Linear);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
g->drawSurface(tmp.get(),
|
||||
gfx::Rect(0, 0, rc2.w, rc2.h),
|
||||
dest,
|
||||
sampling,
|
||||
nullptr);
|
||||
}
|
||||
else {
|
||||
g->blit(tmp.get(), 0, 0, dest.x, dest.y, dest.w, dest.h);
|
||||
}
|
||||
g->drawSurface(rendered.get(),
|
||||
gfx::Rect(0, 0, rc2.w, rc2.h),
|
||||
dest,
|
||||
sampling,
|
||||
nullptr);
|
||||
}
|
||||
else {
|
||||
g->blit(rendered.get(), 0, 0, dest.x, dest.y, dest.w, dest.h);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2034,15 +2012,52 @@ bool Editor::onProcessMessage(Message* msg)
|
||||
|
||||
case kKeyDownMessage:
|
||||
#if ENABLE_DEVMODE
|
||||
// Switch render mode
|
||||
// Switch renderer
|
||||
if (!msg->ctrlPressed() &&
|
||||
static_cast<KeyMessage*>(msg)->scancode() == kKeyF1) {
|
||||
Preferences::instance().experimental.newRenderEngine(
|
||||
!Preferences::instance().experimental.newRenderEngine());
|
||||
invalidateCanvas();
|
||||
// TODO replace this experimental flag with a new enum (or
|
||||
// maybe there is no need for user option now that the
|
||||
// new engine allows to disable the bilinear mipmapping
|
||||
// interpolation) as we still need the "old" engine to
|
||||
// render reference layers
|
||||
auto& newRenderEngine = Preferences::instance().experimental.newRenderEngine;
|
||||
|
||||
#if SK_ENABLE_SKSL
|
||||
// Simple (new) -> Simple (old) -> Shader -> Simple (new) -> ...
|
||||
if (m_renderEngine->type() == EditorRender::Type::kShaderRenderer) {
|
||||
newRenderEngine(true);
|
||||
m_renderEngine->setType(EditorRender::Type::kSimpleRenderer);
|
||||
}
|
||||
else {
|
||||
if (newRenderEngine()) {
|
||||
newRenderEngine(false);
|
||||
}
|
||||
else {
|
||||
newRenderEngine(true);
|
||||
m_renderEngine->setType(EditorRender::Type::kShaderRenderer);
|
||||
}
|
||||
}
|
||||
#else
|
||||
// Simple (new) <-> Simple (old)
|
||||
newRenderEngine(!newRenderEngine());
|
||||
#endif
|
||||
|
||||
switch (m_renderEngine->type()) {
|
||||
case EditorRender::Type::kSimpleRenderer:
|
||||
StatusBar::instance()->showTip(
|
||||
1000, fmt::format("Simple Renderer ({})", newRenderEngine() ? "new": "old"));
|
||||
break;
|
||||
case EditorRender::Type::kShaderRenderer:
|
||||
StatusBar::instance()->showTip(
|
||||
1000, fmt::format("Shader Renderer"));
|
||||
break;
|
||||
}
|
||||
|
||||
app_refresh_screen();
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
#endif // ENABLE_DEVMODE
|
||||
|
||||
if (m_sprite) {
|
||||
EditorStatePtr holdState(m_state);
|
||||
bool used = m_state->onKeyDown(this, static_cast<KeyMessage*>(msg));
|
||||
|
@ -13,6 +13,7 @@
|
||||
|
||||
#include "app/color_utils.h"
|
||||
#include "app/pref/preferences.h"
|
||||
#include "app/render/shader_renderer.h"
|
||||
#include "app/render/simple_renderer.h"
|
||||
|
||||
namespace app {
|
||||
@ -20,6 +21,7 @@ namespace app {
|
||||
static doc::ImageBufferPtr g_renderBuffer;
|
||||
|
||||
EditorRender::EditorRender()
|
||||
// TODO create a switch in the preferences
|
||||
: m_renderer(std::make_unique<SimpleRenderer>())
|
||||
{
|
||||
m_renderer->setNewBlendMethod(
|
||||
@ -30,6 +32,31 @@ EditorRender::~EditorRender()
|
||||
{
|
||||
}
|
||||
|
||||
EditorRender::Type EditorRender::type() const
|
||||
{
|
||||
#if SK_ENABLE_SKSL
|
||||
if (dynamic_cast<ShaderRenderer*>(m_renderer.get()))
|
||||
return Type::kShaderRenderer;
|
||||
#endif
|
||||
return Type::kSimpleRenderer;
|
||||
}
|
||||
|
||||
void EditorRender::setType(const Type type)
|
||||
{
|
||||
#if SK_ENABLE_SKSL
|
||||
if (type == Type::kShaderRenderer) {
|
||||
m_renderer = std::make_unique<ShaderRenderer>();
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
m_renderer = std::make_unique<SimpleRenderer>();
|
||||
}
|
||||
|
||||
m_renderer->setNewBlendMethod(
|
||||
Preferences::instance().experimental.newBlend());
|
||||
}
|
||||
|
||||
void EditorRender::setRefLayersVisiblity(const bool visible)
|
||||
{
|
||||
m_renderer->setRefLayersVisiblity(visible);
|
||||
@ -157,12 +184,12 @@ void EditorRender::renderSprite(
|
||||
}
|
||||
|
||||
void EditorRender::renderSprite(
|
||||
doc::Image* dstImage,
|
||||
os::Surface* dstSurface,
|
||||
const doc::Sprite* sprite,
|
||||
doc::frame_t frame,
|
||||
const gfx::ClipF& area)
|
||||
{
|
||||
m_renderer->renderSprite(dstImage, sprite, frame, area);
|
||||
m_renderer->renderSprite(dstSurface, sprite, frame, area);
|
||||
}
|
||||
|
||||
void EditorRender::renderCheckeredBackground(
|
||||
@ -184,7 +211,7 @@ void EditorRender::renderImage(
|
||||
m_renderer->renderImage(dst_image, src_image, pal,
|
||||
x, y, opacity, blendMode);
|
||||
}
|
||||
|
||||
// static
|
||||
doc::ImageBufferPtr EditorRender::getRenderImageBuffer()
|
||||
{
|
||||
if (!g_renderBuffer)
|
||||
|
@ -29,15 +29,27 @@ namespace doc {
|
||||
class Tileset;
|
||||
}
|
||||
|
||||
namespace os {
|
||||
class Surface;
|
||||
}
|
||||
|
||||
namespace app {
|
||||
class Doc;
|
||||
class Renderer;
|
||||
|
||||
class EditorRender {
|
||||
public:
|
||||
enum Type {
|
||||
kSimpleRenderer,
|
||||
kShaderRenderer,
|
||||
};
|
||||
|
||||
EditorRender();
|
||||
~EditorRender();
|
||||
|
||||
Type type() const;
|
||||
void setType(const Type type);
|
||||
|
||||
void setRefLayersVisiblity(const bool visible);
|
||||
void setNonactiveLayersOpacity(const int opacity);
|
||||
void setNewBlendMethod(const bool newBlend);
|
||||
@ -74,7 +86,7 @@ namespace app {
|
||||
const doc::Sprite* sprite,
|
||||
doc::frame_t frame);
|
||||
void renderSprite(
|
||||
doc::Image* dstImage,
|
||||
os::Surface* dstSurface,
|
||||
const doc::Sprite* sprite,
|
||||
doc::frame_t frame,
|
||||
const gfx::ClipF& area);
|
||||
@ -90,7 +102,7 @@ namespace app {
|
||||
const int opacity,
|
||||
const doc::BlendMode blendMode);
|
||||
|
||||
doc::ImageBufferPtr getRenderImageBuffer();
|
||||
static doc::ImageBufferPtr getRenderImageBuffer();
|
||||
|
||||
private:
|
||||
std::unique_ptr<Renderer> m_renderer;
|
||||
|
Loading…
x
Reference in New Issue
Block a user