22 halp_meta(name,
"Cubemap Composer")
23 halp_meta(category,
"Visuals/3D")
24 halp_meta(c_name,
"cubemap_composer")
27 "https://ossia.io/score-docs/processes/cubemap-composer.html")
28 halp_meta(uuid,
"a7c3e8f1-5b2d-4a9e-8f3c-1d6e9b4a2c5f")
32 halp::texture_input<
"+X", halp::custom_variable_texture> pos_x;
33 halp::texture_input<
"-X", halp::custom_variable_texture> neg_x;
34 halp::texture_input<
"+Y", halp::custom_variable_texture> pos_y;
35 halp::texture_input<
"-Y", halp::custom_variable_texture> neg_y;
36 halp::texture_input<
"+Z", halp::custom_variable_texture> pos_z;
37 halp::texture_input<
"-Z", halp::custom_variable_texture> neg_z;
42 halp::gpu_cubemap_output<
"Cubemap"> cubemap;
47 halp_meta(name,
"Scene");
48 ossia::scene_spec scene;
63 QRhiTexture* m_cubemapTex{};
66 FaceFingerprint m_lastFaces[6]{};
67 std::shared_ptr<ossia::scene_state> m_sceneState;
68 int64_t m_sceneVersion{0};
69 void* m_lastPublishedHandle{};
80 m_cubemapTex->deleteLater();
81 m_cubemapTex =
nullptr;
103 auto checkFace = [&](
auto& tex) {
104 FaceFingerprint cur{tex.texture.width, tex.texture.height};
105 const bool sizeChanged
106 = (cur.width != m_lastFaces[faceIdx].width
107 || cur.height != m_lastFaces[faceIdx].height);
108 const bool contentChanged = tex.texture.changed;
109 if(sizeChanged || contentChanged)
111 m_lastFaces[faceIdx] = cur;
114 tex.texture.changed =
false;
116 if(tex.texture.bytes && tex.texture.width > 0 && tex.texture.height > 0)
118 int s = std::max(tex.texture.width, tex.texture.height);
119 maxSize = std::max(maxSize, s);
122 checkFace(inputs.pos_x);
123 checkFace(inputs.neg_x);
124 checkFace(inputs.pos_y);
125 checkFace(inputs.neg_y);
126 checkFace(inputs.pos_z);
127 checkFace(inputs.neg_z);
133 if(maxSize != m_faceSize)
137 m_cubemapTex->deleteLater();
138 m_cubemapTex =
nullptr;
140 m_faceSize = maxSize;
144 if(!m_cubemapTex && m_faceSize > 0)
146 auto& rhi = *renderer.
state.rhi;
147 m_cubemapTex = rhi.newTexture(
148 QRhiTexture::RGBA8, QSize{m_faceSize, m_faceSize}, 1,
149 QRhiTexture::CubeMap | QRhiTexture::MipMapped
150 | QRhiTexture::UsedWithGenerateMips);
151 m_cubemapTex->create();
152 outputs.cubemap.texture.handle = m_cubemapTex;
160 m_sceneState = std::make_shared<ossia::scene_state>();
161 if(m_lastPublishedHandle != m_cubemapTex)
163 m_sceneState->environment = {};
164 m_sceneState->environment.skybox_texture.native_handle = m_cubemapTex;
165 m_lastPublishedHandle = m_cubemapTex;
167 m_sceneState->version = m_sceneVersion;
168 outputs.scene_out.scene.state = m_sceneState;
169 outputs.scene_out.dirty = ossia::scene_port::dirty_environment;
177 m_cubemapTex->deleteLater();
178 m_cubemapTex =
nullptr;
181 outputs.cubemap.texture.handle =
nullptr;
184 m_sceneState->environment = {};
185 m_lastPublishedHandle =
nullptr;
187 m_sceneState->version = m_sceneVersion;
188 outputs.scene_out.dirty = ossia::scene_port::dirty_environment;
192 void runInitialPasses(
202 bool anyUploaded =
false;
205 auto uploadFace = [&](
const auto& tex,
int layer) {
206 if(!tex.texture.bytes || tex.texture.width <= 0 || tex.texture.height <= 0)
211 tex.texture.bytes, tex.texture.width, tex.texture.height,
212 QImage::Format_RGBA8888);
214 if(img.width() != m_faceSize || img.height() != m_faceSize)
216 m_faceSize, m_faceSize, Qt::IgnoreAspectRatio,
217 Qt::SmoothTransformation);
219 img = img.convertToFormat(QImage::Format_RGBA8888);
221 QRhiTextureSubresourceUploadDescription subresDesc(img);
222 QRhiTextureUploadEntry entry(layer, 0, subresDesc);
223 QRhiTextureUploadDescription desc({entry});
224 res->uploadTexture(m_cubemapTex, desc);
228 uploadFace(inputs.pos_x, 0);
229 uploadFace(inputs.neg_x, 1);
230 uploadFace(inputs.pos_y, 2);
231 uploadFace(inputs.neg_y, 3);
232 uploadFace(inputs.pos_z, 4);
233 uploadFace(inputs.neg_z, 5);
237 res->generateMips(m_cubemapTex);