Loading...
Searching...
No Matches
CubemapComposer.hpp
1#pragma once
2
3#include <halp/controls.hpp>
4#include <halp/meta.hpp>
5#include <halp/texture.hpp>
6
7#include <Gfx/Graph/RenderList.hpp>
8
9#include <QtGui/private/qrhi_p.h>
10
11namespace Threedim
12{
13
15{
16public:
17 halp_meta(name, "Cubemap Composer")
18 halp_meta(category, "Visuals/3D")
19 halp_meta(c_name, "cubemap_composer")
20 halp_meta(
21 manual_url,
22 "https://ossia.io/score-docs/processes/cubemap-composer.html")
23 halp_meta(uuid, "a7c3e8f1-5b2d-4a9e-8f3c-1d6e9b4a2c5f")
24
25 struct ins
26 {
27 halp::texture_input<"+X", halp::custom_variable_texture> pos_x;
28 halp::texture_input<"-X", halp::custom_variable_texture> neg_x;
29 halp::texture_input<"+Y", halp::custom_variable_texture> pos_y;
30 halp::texture_input<"-Y", halp::custom_variable_texture> neg_y;
31 halp::texture_input<"+Z", halp::custom_variable_texture> pos_z;
32 halp::texture_input<"-Z", halp::custom_variable_texture> neg_z;
33 } inputs;
34
35 struct
36 {
37 halp::gpu_texture_output<"Cubemap"> cubemap;
38 } outputs;
39
40 QRhiTexture* m_cubemapTex{};
41 int m_faceSize{0};
42 bool m_dirty{true};
43
44 void operator()() { }
45
46 void init(score::gfx::RenderList& renderer, QRhiResourceUpdateBatch& res)
47 {
48 m_dirty = true;
49 }
50
51 void update(
52 score::gfx::RenderList& renderer, QRhiResourceUpdateBatch& res,
54 {
55 // Determine face size from the largest input
56 int maxSize = 0;
57 auto checkFace = [&](const auto& tex) {
58 if(tex.texture.bytes && tex.texture.width > 0 && tex.texture.height > 0)
59 {
60 int s = std::max(tex.texture.width, tex.texture.height);
61 maxSize = std::max(maxSize, s);
62 }
63 };
64 checkFace(inputs.pos_x);
65 checkFace(inputs.neg_x);
66 checkFace(inputs.pos_y);
67 checkFace(inputs.neg_y);
68 checkFace(inputs.pos_z);
69 checkFace(inputs.neg_z);
70
71 if(maxSize <= 0)
72 return;
73
74 // Recreate texture if size changed
75 if(maxSize != m_faceSize)
76 {
77 if(m_cubemapTex)
78 {
79 m_cubemapTex->deleteLater();
80 m_cubemapTex = nullptr;
81 }
82 m_faceSize = maxSize;
83 m_dirty = true;
84 }
85
86 if(!m_cubemapTex && m_faceSize > 0)
87 {
88 auto& rhi = *renderer.state.rhi;
89 m_cubemapTex = rhi.newTexture(
90 QRhiTexture::RGBA8, QSize{m_faceSize, m_faceSize}, 1,
91 QRhiTexture::CubeMap | QRhiTexture::MipMapped
92 | QRhiTexture::UsedWithGenerateMips);
93 m_cubemapTex->create();
94 outputs.cubemap.texture.handle = m_cubemapTex;
95 m_dirty = true;
96 }
97 }
98
99 void release(score::gfx::RenderList& r)
100 {
101 if(m_cubemapTex)
102 {
103 m_cubemapTex->deleteLater();
104 m_cubemapTex = nullptr;
105 }
106 m_faceSize = 0;
107 outputs.cubemap.texture.handle = nullptr;
108 }
109
110 void runInitialPasses(
111 score::gfx::RenderList& renderer, QRhiCommandBuffer& commands,
112 QRhiResourceUpdateBatch*& res, score::gfx::Edge& edge)
113 {
114 if(!m_cubemapTex)
115 return;
116
117 if(!m_dirty)
118 return;
119
120 bool anyUploaded = false;
121
122 // Upload each face that has valid data
123 auto uploadFace = [&](const auto& tex, int layer) {
124 if(!tex.texture.bytes || tex.texture.width <= 0 || tex.texture.height <= 0)
125 return;
126
127 // Convert to QImage, scale to face size if needed
128 QImage img(
129 tex.texture.bytes, tex.texture.width, tex.texture.height,
130 QImage::Format_RGBA8888);
131
132 if(img.width() != m_faceSize || img.height() != m_faceSize)
133 img = img.scaled(
134 m_faceSize, m_faceSize, Qt::IgnoreAspectRatio,
135 Qt::SmoothTransformation);
136
137 img = img.convertToFormat(QImage::Format_RGBA8888);
138
139 QRhiTextureSubresourceUploadDescription subresDesc(img);
140 QRhiTextureUploadEntry entry(layer, 0, subresDesc);
141 QRhiTextureUploadDescription desc({entry});
142 res->uploadTexture(m_cubemapTex, desc);
143 anyUploaded = true;
144 };
145
146 uploadFace(inputs.pos_x, 0); // +X
147 uploadFace(inputs.neg_x, 1); // -X
148 uploadFace(inputs.pos_y, 2); // +Y
149 uploadFace(inputs.neg_y, 3); // -Y
150 uploadFace(inputs.pos_z, 4); // +Z
151 uploadFace(inputs.neg_z, 5); // -Z
152
153 if(anyUploaded)
154 {
155 res->generateMips(m_cubemapTex);
156 }
157
158 m_dirty = false;
159 }
160};
161
162}
Definition CubemapComposer.hpp:15
List of nodes to be rendered to an output.
Definition RenderList.hpp:19
RenderState & state
RenderState corresponding to this RenderList.
Definition RenderList.hpp:102
Definition CubemapComposer.hpp:26
Connection between two score::gfx::Port.
Definition score-plugin-gfx/Gfx/Graph/Utils.hpp:75