3#include <Gfx/Graph/Node.hpp>
4#include <Gfx/Graph/NodeRenderer.hpp>
5#include <Gfx/Graph/PointerState.hpp>
6#include <Gfx/Graph/RenderList.hpp>
7#include <Gfx/Graph/RenderState.hpp>
8#include <Gfx/Graph/Utils.hpp>
10#include <QtCore/qfloat16.h>
12#include <score_plugin_gfx_export.h>
47 static constexpr int columns = 32;
48 static constexpr int rows = 240;
51 : pointers{std::move(pointers)}
53 output.push_back(
new Port{
this, {}, Types::Image, {}});
59 const std::chrono::steady_clock::time_point epoch = std::chrono::steady_clock::now();
71 m_outputPremultiplied =
true;
74 void initState(
RenderList& renderer, QRhiResourceUpdateBatch& res)
override;
75 void update(
RenderList& renderer, QRhiResourceUpdateBatch& res,
Edge* edge)
override;
79 const std::vector<float>&
history() const noexcept {
return m_history; }
82 void upload(QRhiResourceUpdateBatch& res);
84 QRhiTexture* m_texture{};
87 std::vector<float> m_history;
95namespace touch_history_shaders
97static const constexpr auto vertex = R
"_(#version 450
98layout(location = 0) in vec2 position;
99layout(location = 1) in vec2 texcoord;
100layout(location = 0) out vec2 v_texcoord;
102layout(std140, binding = 0) uniform renderer_t {
103 mat4 clipSpaceCorrMatrix;
107out gl_PerVertex { vec4 gl_Position; };
111 v_texcoord = texcoord;
112 gl_Position = renderer.clipSpaceCorrMatrix * vec4(position.xy, 0.0, 1.);
113// The uploaded buffer's row 0 is the top of the image on every backend (the
114// same correction as TexgenNode).
115#if !(defined(QSHADER_HLSL) || defined(QSHADER_MSL))
116 gl_Position.y = - gl_Position.y;
121static const constexpr auto fragment = R
"_(#version 450
122layout(location = 0) in vec2 v_texcoord;
123layout(location = 0) out vec4 fragColor;
125layout(std140, binding = 0) uniform renderer_t {
126 mat4 clipSpaceCorrMatrix;
130layout(binding = 3) uniform sampler2D history;
132void main() { fragColor = texture(history, v_texcoord); }
139 m_mesh = &renderer.defaultTriangle();
140 defaultMeshInit(renderer, *m_mesh, res);
141 processUBOInit(renderer);
142 m_material.init(renderer, node.
input, m_samplers);
144 renderer.state, touch_history_shaders::vertex, touch_history_shaders::fragment);
146 auto& rhi = *renderer.state.rhi;
149 m_half = !rhi.isTextureFormatSupported(QRhiTexture::RGBA32F)
150 && rhi.isTextureFormatSupported(QRhiTexture::RGBA16F);
151 m_texture = rhi.newTexture(
152 m_half ? QRhiTexture::RGBA16F : QRhiTexture::RGBA32F,
153 QSize{TouchHistoryNode::columns, TouchHistoryNode::rows}, 1);
154 m_texture->setName(
"TouchHistoryRenderer::m_texture");
158 auto sampler = rhi.newSampler(
159 QRhiSampler::Nearest, QRhiSampler::Nearest, QRhiSampler::None,
160 QRhiSampler::ClampToEdge, QRhiSampler::ClampToEdge);
161 sampler->setName(
"TouchHistoryRenderer::sampler");
163 m_samplers.push_back({sampler, m_texture});
166 std::size_t(TouchHistoryNode::columns) * TouchHistoryNode::rows * 4, 0.f);
172inline void TouchHistoryRenderer::upload(QRhiResourceUpdateBatch& res)
179 bytes.resize(qsizetype(m_history.size() *
sizeof(qfloat16)));
181 reinterpret_cast<qfloat16*
>(bytes.data()), m_history.data(),
182 qsizetype(m_history.size()));
187 reinterpret_cast<const char*
>(m_history.data()),
188 qsizetype(m_history.size() *
sizeof(
float)));
190 QRhiTextureSubresourceUploadDescription desc{bytes};
191 res.uploadTexture(m_texture, QRhiTextureUploadDescription{{0, 0, desc}});
195TouchHistoryRenderer::update(RenderList& renderer, QRhiResourceUpdateBatch& res, Edge*)
197 defaultUBOUpdate(renderer, res);
198 if(m_frame == renderer.frame)
200 m_frame = renderer.frame;
205 auto& n =
static_cast<const TouchHistoryNode&
>(node);
206 constexpr int rowFloats = TouchHistoryNode::columns * 4;
207 constexpr int last = TouchHistoryNode::rows - 1;
208 float* h = m_history.data();
209 std::memmove(h, h + rowFloats, std::size_t(last) * rowFloats *
sizeof(
float));
210 std::array<PointerState::Slot, PointerState::slots> slots{};
212 slots = n.pointers->snapshot();
213 const float t = std::chrono::duration<float>(std::chrono::steady_clock::now() - n.epoch)
215 float* row = h + std::size_t(last) * rowFloats;
216 for(
int c = 0; c < TouchHistoryNode::columns; c++)
218 row[c * 4 + 0] = slots[c].x;
219 row[c * 4 + 1] = slots[c].y;
220 row[c * 4 + 2] = slots[c].pressure;
229 m_texture->deleteLater();
Generic renderer.
Definition NodeRenderer.hpp:330
void releaseState(RenderList &renderer) override
Definition NodeRenderer.cpp:421
std::vector< Port * > input
Input ports of that node.
Definition score-plugin-gfx/Gfx/Graph/Node.hpp:134
Common base class for most single-pass, simple nodes.
Definition score-plugin-gfx/Gfx/Graph/Node.hpp:313
Renderer for a given node.
Definition NodeRenderer.hpp:11
bool m_initialized
Definition NodeRenderer.hpp:260
List of nodes to be rendered to an output.
Definition RenderList.hpp:33
Definition TouchHistoryNode.hpp:65
void initState(RenderList &renderer, QRhiResourceUpdateBatch &res) override
Definition TouchHistoryNode.hpp:137
const std::vector< float > & history() const noexcept
The history, newest row last (the bottom of the image), as uploaded.
Definition TouchHistoryNode.hpp:79
void releaseState(RenderList &r) override
Definition TouchHistoryNode.hpp:226
Graphics rendering pipeline for ossia score.
Definition Filter/PreviewWidget.hpp:11
std::pair< QShader, QShader > makeShaders(const RenderState &v, QString vert, QString frag, int multiViewCount)
Get a pair of compiled vertex / fragment shaders from GLSL 4.5 sources.
Definition score-plugin-gfx/Gfx/Graph/Utils.cpp:1523
Connection between two score::gfx::Port.
Definition score-plugin-gfx/Gfx/Graph/Utils.hpp:236
Port of a score::gfx::Node.
Definition score-plugin-gfx/Gfx/Graph/Utils.hpp:215
The pointers of an output as a texture: vertexshaderart's touch history (greggman/vertexshaderart,...
Definition TouchHistoryNode.hpp:46
std::shared_ptr< PointerState > pointers
What the history records every frame.
Definition TouchHistoryNode.hpp:58
NodeRenderer * createRenderer(RenderList &r) const noexcept override
Create a renderer in a given context for this node.
Definition TouchHistoryNode.hpp:90