mirror of
https://github.com/rive-app/rive-cpp.git
synced 2026-01-18 13:11:19 +01:00
DrawImage for Tess Renderer
drawImage (without a Rive provided mesh) wasn't implemented in Tess. For now this just builds a tiny vertex buffer when it uploads the image. I'll rework this when I add batching to this renderer (the vertex buffer will only be generated on demand and placed into the batched vertex buffer for the whole frame/artboard depending on where we'll create the batching boundary) Diffs= c9f97f7c1 DrawImage for Tess Renderer
This commit is contained in:
@@ -1 +1 @@
|
||||
e617e4448d1028f08ccaecf24d02cab2d019e40e
|
||||
c9f97f7c18a92cd0d417b76b235f841b1e577cac
|
||||
|
||||
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
@@ -102,7 +102,8 @@
|
||||
"scoped_allocator": "cpp",
|
||||
"span": "cpp",
|
||||
"typeindex": "cpp",
|
||||
"filesystem": "cpp"
|
||||
"filesystem": "cpp",
|
||||
"*.idl": "cpp"
|
||||
},
|
||||
"git.ignoreLimitWarning": true
|
||||
}
|
||||
@@ -13,10 +13,15 @@ namespace rive {
|
||||
class SokolRenderImage : public RenderImage {
|
||||
private:
|
||||
sg_image m_image;
|
||||
sg_buffer m_vertexBuffer;
|
||||
|
||||
public:
|
||||
SokolRenderImage(sg_image image);
|
||||
// bytes is expected to be tightly packed RGBA*width*height.
|
||||
SokolRenderImage(const uint8_t* bytes, uint32_t width, uint32_t height);
|
||||
~SokolRenderImage() override;
|
||||
|
||||
sg_image image() const { return m_image; }
|
||||
sg_buffer vertexBuffer() const { return m_vertexBuffer; }
|
||||
};
|
||||
|
||||
class SokolTessRenderer : public TessRenderer {
|
||||
@@ -41,6 +46,7 @@ private:
|
||||
sg_pipeline m_incClipPipeline;
|
||||
sg_pipeline m_decClipPipeline;
|
||||
sg_buffer m_boundsIndices;
|
||||
sg_buffer m_defaultUV;
|
||||
|
||||
std::vector<SubPath> m_ClipPaths;
|
||||
|
||||
|
||||
@@ -134,8 +134,6 @@ std::unique_ptr<RenderPath> SokolFactory::makeEmptyRenderPath() {
|
||||
return std::make_unique<SokolRenderPath>();
|
||||
}
|
||||
|
||||
SokolRenderImage::SokolRenderImage(sg_image image) : m_image(image) {}
|
||||
|
||||
class SokolBuffer : public RenderBuffer {
|
||||
private:
|
||||
sg_buffer m_Buffer;
|
||||
@@ -468,9 +466,24 @@ SokolTessRenderer::SokolTessRenderer() {
|
||||
.type = SG_BUFFERTYPE_INDEXBUFFER,
|
||||
.data = SG_RANGE(indices),
|
||||
});
|
||||
|
||||
// The UV buffer used by drawImage. Consider this the "default uv
|
||||
// vertex buffer" used when a mesh isn't provided by Rive.
|
||||
Vec2D defUV[] = {
|
||||
Vec2D(0.0f, 0.0f),
|
||||
Vec2D(1.0f, 0.0f),
|
||||
Vec2D(1.0f, 1.0f),
|
||||
Vec2D(0.0f, 1.0f),
|
||||
};
|
||||
|
||||
m_defaultUV = sg_make_buffer((sg_buffer_desc){
|
||||
.type = SG_BUFFERTYPE_VERTEXBUFFER,
|
||||
.data = SG_RANGE(defUV),
|
||||
});
|
||||
}
|
||||
|
||||
SokolTessRenderer::~SokolTessRenderer() {
|
||||
sg_destroy_buffer(m_defaultUV);
|
||||
sg_destroy_buffer(m_boundsIndices);
|
||||
sg_destroy_pipeline(m_meshPipeline);
|
||||
sg_destroy_pipeline(m_incClipPipeline);
|
||||
@@ -530,7 +543,26 @@ void SokolTessRenderer::orthographicProjection(float left,
|
||||
// }
|
||||
}
|
||||
|
||||
void SokolTessRenderer::drawImage(const RenderImage*, BlendMode, float opacity) {}
|
||||
void SokolTessRenderer::drawImage(const RenderImage* image, BlendMode, float opacity) {
|
||||
vs_params_t vs_params;
|
||||
|
||||
const Mat2D& world = transform();
|
||||
vs_params.mvp = m_Projection * world;
|
||||
|
||||
auto sokolImage = static_cast<const SokolRenderImage*>(image);
|
||||
setPipeline(m_meshPipeline);
|
||||
sg_bindings bind = {
|
||||
.vertex_buffers[0] = sokolImage->vertexBuffer(),
|
||||
.vertex_buffers[1] = m_defaultUV,
|
||||
.index_buffer = m_boundsIndices,
|
||||
.fs_images[SLOT_tex] = sokolImage->image(),
|
||||
};
|
||||
|
||||
sg_apply_bindings(&bind);
|
||||
sg_apply_uniforms(SG_SHADERSTAGE_VS, SLOT_vs_params, SG_RANGE_REF(vs_params));
|
||||
sg_draw(0, 6, 1);
|
||||
}
|
||||
|
||||
void SokolTessRenderer::drawImageMesh(const RenderImage* renderImage,
|
||||
rcp<RenderBuffer> vertices_f32,
|
||||
rcp<RenderBuffer> uvCoords_f32,
|
||||
@@ -915,3 +947,31 @@ void SokolTessRenderer::drawPath(RenderPath* path, RenderPaint* paint) {
|
||||
|
||||
static_cast<SokolRenderPaint*>(paint)->draw(static_cast<SokolRenderPath*>(path));
|
||||
}
|
||||
|
||||
SokolRenderImage::SokolRenderImage(const uint8_t* bytes, uint32_t width, uint32_t height) :
|
||||
m_image(sg_make_image((sg_image_desc){
|
||||
.width = (int)width,
|
||||
.height = (int)height,
|
||||
.data.subimage[0][0] = {bytes, width * height * 4},
|
||||
.pixel_format = SG_PIXELFORMAT_RGBA8,
|
||||
}))
|
||||
|
||||
{
|
||||
float halfWidth = width / 2.0f;
|
||||
float halfHeight = height / 2.0f;
|
||||
Vec2D points[] = {
|
||||
Vec2D(-halfWidth, -halfHeight),
|
||||
Vec2D(halfWidth, -halfHeight),
|
||||
Vec2D(halfWidth, halfHeight),
|
||||
Vec2D(-halfWidth, halfHeight),
|
||||
};
|
||||
m_vertexBuffer = sg_make_buffer((sg_buffer_desc){
|
||||
.type = SG_BUFFERTYPE_VERTEXBUFFER,
|
||||
.data = SG_RANGE(points),
|
||||
});
|
||||
}
|
||||
|
||||
SokolRenderImage::~SokolRenderImage() {
|
||||
sg_destroy_buffer(m_vertexBuffer);
|
||||
sg_destroy_image(m_image);
|
||||
}
|
||||
@@ -4,30 +4,20 @@
|
||||
#include "rive/tess/sokol/sokol_tess_renderer.hpp"
|
||||
#include "sokol_gfx.h"
|
||||
|
||||
sg_pixel_format SgPixelFormat(Bitmap* bitmap) {
|
||||
switch (bitmap->pixelFormat()) {
|
||||
case Bitmap::PixelFormat::R: return SG_PIXELFORMAT_R8;
|
||||
case Bitmap::PixelFormat::RGBA: return SG_PIXELFORMAT_RGBA8;
|
||||
default: return SG_PIXELFORMAT_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<rive::RenderImage>
|
||||
ViewerSokolFactory::decodeImage(rive::Span<const uint8_t> bytes) {
|
||||
auto bitmap = Bitmap::decode(bytes);
|
||||
if (bitmap) {
|
||||
// We have a bitmap, let's make an image.
|
||||
|
||||
// Sokol doesn't support an RGB pixel format, so we have to bump RGB to RGBA.
|
||||
if (bitmap->pixelFormat() == Bitmap::PixelFormat::RGB) {
|
||||
// For now our SokolRenderImage only works with RGBA.
|
||||
if (bitmap->pixelFormat() != Bitmap::PixelFormat::RGBA) {
|
||||
bitmap->pixelFormat(Bitmap::PixelFormat::RGBA);
|
||||
}
|
||||
return std::make_unique<rive::SokolRenderImage>(sg_make_image((sg_image_desc){
|
||||
.width = (int)bitmap->width(),
|
||||
.height = (int)bitmap->height(),
|
||||
.data.subimage[0][0] = {bitmap->bytes(), bitmap->byteSize()},
|
||||
.pixel_format = SgPixelFormat(bitmap.get()),
|
||||
}));
|
||||
|
||||
return std::make_unique<rive::SokolRenderImage>(bitmap->bytes(),
|
||||
bitmap->width(),
|
||||
bitmap->height());
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user