diff --git a/src/VisualizerWidget.cpp b/src/VisualizerWidget.cpp index 2bfcc02..78a5357 100644 --- a/src/VisualizerWidget.cpp +++ b/src/VisualizerWidget.cpp @@ -390,7 +390,43 @@ void VisualizerWidget::render(QRhiCommandBuffer *cb) { m_lastBuildW = w; m_lastBuildH = h; if (m_mirrored) { - buildVertices(w * 0.55f, h / 2 + 2); + buildVertices(w * 0.55f, h / 2); + + // Expand half-size vertices into all 4 quadrants (eliminates mirror seam) + { + int fillFloats = m_fillVertexCount * 6; + int lineFloats = m_lineVertexCount * 6; + float fw = (float)w, fh = (float)h; + + auto expand = [&](const float *src, int nVerts, std::vector &dst) { + for (int q = 0; q < 4; q++) { + bool fx = (q == 1 || q == 3); + bool fy = (q == 2 || q == 3); + for (int v = 0; v < nVerts; v++) { + int b = v * 6; + dst.push_back(fx ? fw - src[b] : src[b]); + dst.push_back(fy ? fh - src[b + 1] : src[b + 1]); + dst.push_back(src[b + 2]); + dst.push_back(src[b + 3]); + dst.push_back(src[b + 4]); + dst.push_back(src[b + 5]); + } + } + }; + + std::vector expFill, expLine; + expFill.reserve(fillFloats * 4); + expLine.reserve(lineFloats * 4); + expand(m_vertices.data(), m_fillVertexCount, expFill); + expand(m_vertices.data() + fillFloats, m_lineVertexCount, expLine); + + m_vertices.clear(); + m_vertices.insert(m_vertices.end(), expFill.begin(), expFill.end()); + m_vertices.insert(m_vertices.end(), expLine.begin(), expLine.end()); + m_fillVertexCount *= 4; + m_lineVertexCount *= 4; + } + buildCepstrumVertices(w, h); } else { buildVertices(w, h); @@ -398,8 +434,6 @@ void VisualizerWidget::render(QRhiCommandBuffer *cb) { } } - int numPasses = m_mirrored ? 4 : 1; - // Prepare resource updates QRhiResourceUpdateBatch *u = m_rhi->nextResourceUpdateBatch(); @@ -420,43 +454,13 @@ void VisualizerWidget::render(QRhiCommandBuffer *cb) { } } - // Upload MVP matrices + // Upload single full-screen ortho MVP (slot 0) QMatrix4x4 correction = m_rhi->clipSpaceCorrMatrix(); - - for (int i = 0; i < numPasses; i++) { + { QMatrix4x4 proj; proj.ortho(0, (float)w, (float)h, 0, -1, 1); - - if (m_mirrored) { - switch (i) { - case 0: break; - case 1: - proj.translate(w, 0, 0); - proj.scale(-1, 1, 1); - break; - case 2: - proj.translate(0, h, 0); - proj.scale(1, -1, 1); - break; - case 3: - proj.translate(w, h, 0); - proj.scale(-1, -1, 1); - break; - } - } - QMatrix4x4 mvp = correction * proj; - u->updateDynamicBuffer(m_ubuf.get(), i * m_ubufAlign, 64, - mvp.constData()); - } - - // Upload full-screen ortho MVP for cepstrum (slot 4) - if (m_mirrored && m_cepstrumVertexCount > 0) { - QMatrix4x4 cepProj; - cepProj.ortho(0, (float)w, (float)h, 0, -1, 1); - QMatrix4x4 cepMvp = correction * cepProj; - u->updateDynamicBuffer(m_ubuf.get(), 4 * m_ubufAlign, 64, - cepMvp.constData()); + u->updateDynamicBuffer(m_ubuf.get(), 0, 64, mvp.constData()); } // Begin render pass @@ -465,30 +469,26 @@ void VisualizerWidget::render(QRhiCommandBuffer *cb) { (float)outputSize.height()}); const QRhiCommandBuffer::VertexInput vbufBinding(m_vbuf.get(), 0); + QRhiCommandBuffer::DynamicOffset dynOfs(0, 0); - for (int i = 0; i < numPasses; i++) { - QRhiCommandBuffer::DynamicOffset dynOfs(0, quint32(i * m_ubufAlign)); - - if (m_fillVertexCount > 0) { - cb->setGraphicsPipeline(m_fillPipeline.get()); - cb->setShaderResources(m_srb.get(), 1, &dynOfs); - cb->setVertexInput(0, 1, &vbufBinding); - cb->draw(m_fillVertexCount); - } - - if (m_lineVertexCount > 0) { - cb->setGraphicsPipeline(m_linePipeline.get()); - cb->setShaderResources(m_srb.get(), 1, &dynOfs); - cb->setVertexInput(0, 1, &vbufBinding); - cb->draw(m_lineVertexCount, 1, m_fillVertexCount, 0); - } + if (m_fillVertexCount > 0) { + cb->setGraphicsPipeline(m_fillPipeline.get()); + cb->setShaderResources(m_srb.get(), 1, &dynOfs); + cb->setVertexInput(0, 1, &vbufBinding); + cb->draw(m_fillVertexCount); } - // --- Cepstral Thread (single full-screen pass, after mirror loop) --- - if (m_mirrored && m_cepstrumVertexCount > 0) { - QRhiCommandBuffer::DynamicOffset cepOfs(0, quint32(4 * m_ubufAlign)); + if (m_lineVertexCount > 0) { cb->setGraphicsPipeline(m_linePipeline.get()); - cb->setShaderResources(m_srb.get(), 1, &cepOfs); + cb->setShaderResources(m_srb.get(), 1, &dynOfs); + cb->setVertexInput(0, 1, &vbufBinding); + cb->draw(m_lineVertexCount, 1, m_fillVertexCount, 0); + } + + // --- Cepstral Thread --- + if (m_mirrored && m_cepstrumVertexCount > 0) { + cb->setGraphicsPipeline(m_linePipeline.get()); + cb->setShaderResources(m_srb.get(), 1, &dynOfs); cb->setVertexInput(0, 1, &vbufBinding); cb->draw(m_cepstrumVertexCount, 1, m_fillVertexCount + m_lineVertexCount, 0); }