From 41b02725d7d7e115ed5f5c16ba757239e7d44198 Mon Sep 17 00:00:00 2001 From: luisangelsm Date: Sun, 18 Jan 2026 18:23:04 +0100 Subject: [PATCH] Use the fragment shader to calculate the shading effect for a more uniform shading than the one based on vertex --- YACReader/YACReader.pro | 5 ++++- YACReaderLibrary/YACReaderLibrary.pro | 5 ++++- common/rhi/shaders/flow.frag | 31 ++++++++++++++++++++------ common/rhi/shaders/flow.frag.qsb | Bin 1990 -> 2682 bytes common/rhi/shaders/flow.vert | 25 ++++++++++----------- common/rhi/shaders/flow.vert.qsb | Bin 2957 -> 2892 bytes common/rhi/yacreader_flow_rhi.cpp | 24 +++++++++++--------- 7 files changed, 58 insertions(+), 32 deletions(-) diff --git a/YACReader/YACReader.pro b/YACReader/YACReader.pro index 940ea723..42f78184 100644 --- a/YACReader/YACReader.pro +++ b/YACReader/YACReader.pro @@ -157,7 +157,10 @@ SOURCES += ../common/comic.cpp \ SOURCES += ../common/rhi/yacreader_flow_rhi.cpp SOURCES += ../common/rhi/yacreader_comic_flow_rhi.cpp \ ../common/rhi/yacreader_page_flow_rhi.cpp - RESOURCES += ../common/rhi/shaders/shaders.qrc + RESOURCES += ../common/rhi/shaders/shaders.qrc + # Make raw GLSL shader sources editable in Qt Creator + OTHER_FILES += ../common/rhi/shaders/flow.vert \ + ../common/rhi/shaders/flow.frag } } diff --git a/YACReaderLibrary/YACReaderLibrary.pro b/YACReaderLibrary/YACReaderLibrary.pro index 11952c35..1a79aadb 100644 --- a/YACReaderLibrary/YACReaderLibrary.pro +++ b/YACReaderLibrary/YACReaderLibrary.pro @@ -253,7 +253,10 @@ SOURCES += comic_flow.cpp \ SOURCES += ../common/rhi/yacreader_flow_rhi.cpp SOURCES += ../common/rhi/yacreader_comic_flow_rhi.cpp \ ../common/rhi/yacreader_page_flow_rhi.cpp - RESOURCES += ../common/rhi/shaders/shaders.qrc + RESOURCES += ../common/rhi/shaders/shaders.qrc + # Make raw GLSL shader sources editable in Qt Creator + OTHER_FILES += ../common/rhi/shaders/flow.vert \ + ../common/rhi/shaders/flow.frag } } diff --git a/common/rhi/shaders/flow.frag b/common/rhi/shaders/flow.frag index 01b474d9..5e6f6c40 100644 --- a/common/rhi/shaders/flow.frag +++ b/common/rhi/shaders/flow.frag @@ -2,8 +2,11 @@ // Inputs from vertex shader layout(location = 0) in vec2 vTexCoord; -layout(location = 1) in vec4 vColor; -layout(location = 2) in float vIsReflection; +layout(location = 1) in flat vec4 vInstanceShading; +layout(location = 2) in flat float vInstanceOpacity; +layout(location = 3) in flat float vIsReflection; +layout(location = 4) in flat float vInstanceRotation; +layout(location = 5) in vec2 vLocalPos; // Output layout(location = 0) out vec4 fragColor; @@ -29,16 +32,30 @@ void main() { vec4 texColor = texture(coverTexture, vTexCoord); - // Apply shading: multiply texture by vColor.r to darken - float shadingAmount = vColor.r; + // Compute per-pixel shading using per-instance corner shading values + float leftUp = vInstanceShading.x; + float leftDown = vInstanceShading.y; + float rightUp = vInstanceShading.z; + float rightDown = vInstanceShading.w; - // For reflections, apply gradient fade (darker at bottom, fading to black) + // Use interpolated local vertex position to match original vertex-based shading. + // position.y in vertex ranges [-0.5..0.5], so map to [0..1] with +0.5 + float y = clamp(vLocalPos.y + 0.5, 0.0, 1.0); + float x = clamp(vLocalPos.x + 0.5, 0.0, 1.0); + float leftShading = mix(leftDown, leftUp, y); + float rightShading = mix(rightDown, rightUp, y); + float shading = mix(leftShading, rightShading, x); + + // Combine with per-instance opacity (opacity only darkens RGB, alpha preserved) + float shadingAmount = shading * vInstanceOpacity; + + // For reflections, apply a gradient fade using reflection uniforms (darker further away) if (vIsReflection > 0.5) { - // vTexCoord.y goes from 1 (top of reflection, near cover) to 0 (bottom, far from cover) - // We want it brightest near the cover and fading away + // Legacy reflection fade: ramp from 0.0 to 0.33 using texture V coordinate float gradientFade = mix(0.0, 0.33, vTexCoord.y); shadingAmount *= gradientFade; } + // Final color: shaded RGB, keep source alpha fragColor = vec4(texColor.rgb * shadingAmount, texColor.a); } diff --git a/common/rhi/shaders/flow.frag.qsb b/common/rhi/shaders/flow.frag.qsb index f50613bb41bc80d1f8194c9a3d4b5aabc6de262b..02f9d8a6c07cb8e469453d7f1acaa3e452d97988 100644 GIT binary patch literal 2682 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 literal 1990 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 literal 2957 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 D8729a diff --git a/common/rhi/yacreader_flow_rhi.cpp b/common/rhi/yacreader_flow_rhi.cpp index e325f1c2..d3b7b715 100644 --- a/common/rhi/yacreader_flow_rhi.cpp +++ b/common/rhi/yacreader_flow_rhi.cpp @@ -194,9 +194,9 @@ void YACReaderFlow3D::initialize(QRhiCommandBuffer *cb) // Create instance buffer for per-draw instance data if (!scene.instanceBuffer) { - // Allocate buffer for per-instance data (model matrix + shading + opacity + flipFlag) - // mat4 (16 floats) + vec4 (4 floats) + float (1 float) + float (1 float) = 22 floats - scene.instanceBuffer.reset(m_rhi->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::VertexBuffer, 22 * sizeof(float))); + // Allocate buffer for per-instance data (model matrix + shading + opacity + flipFlag + rotation) + // mat4 (16 floats) + vec4 (4 floats) + float (opacity) + float (flipFlag) + float (rotation) = 23 floats + scene.instanceBuffer.reset(m_rhi->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::VertexBuffer, 23 * sizeof(float))); scene.instanceBuffer->create(); } @@ -333,7 +333,7 @@ void YACReaderFlow3D::ensurePipeline() QRhiVertexInputLayout inputLayout; inputLayout.setBindings({ { 5 * sizeof(float) }, // Per-vertex data (position + texCoord) - { 22 * sizeof(float), QRhiVertexInputBinding::PerInstance } // Per-instance data + { 23 * sizeof(float), QRhiVertexInputBinding::PerInstance } // Per-instance data }); inputLayout.setAttributes({ // Per-vertex attributes @@ -347,7 +347,8 @@ void YACReaderFlow3D::ensurePipeline() { 1, 5, QRhiVertexInputAttribute::Float4, 12 * sizeof(float) }, // row 3 { 1, 6, QRhiVertexInputAttribute::Float4, 16 * sizeof(float) }, // shading vec4 { 1, 7, QRhiVertexInputAttribute::Float, 20 * sizeof(float) }, // opacity - { 1, 8, QRhiVertexInputAttribute::Float, 21 * sizeof(float) } // flipFlag (1.0 = reflection) + { 1, 8, QRhiVertexInputAttribute::Float, 21 * sizeof(float) }, // flipFlag (1.0 = reflection) + { 1, 9, QRhiVertexInputAttribute::Float, 22 * sizeof(float) } // rotation }); scene.pipeline->setVertexInputLayout(inputLayout); @@ -408,7 +409,7 @@ void YACReaderFlow3D::render(QRhiCommandBuffer *cb) bool isReflection; bool isMark; QRhiTexture *texture; - float instanceData[22]; + float instanceData[23]; UniformData uniformData; }; @@ -482,7 +483,7 @@ void YACReaderFlow3D::render(QRhiCommandBuffer *cb) } // Ensure instance buffer is large enough for all draws - auto requiredInstanceSize = static_cast(draws.size() * 22 * sizeof(float)); + auto requiredInstanceSize = static_cast(draws.size() * 23 * sizeof(float)); if (!scene.instanceBuffer || scene.instanceBuffer->size() < requiredInstanceSize) { scene.instanceBuffer.reset(m_rhi->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::VertexBuffer, requiredInstanceSize)); if (!scene.instanceBuffer->create()) { @@ -514,8 +515,8 @@ void YACReaderFlow3D::render(QRhiCommandBuffer *cb) // Update instance buffer with all instance data for (int i = 0; i < draws.size(); ++i) { - int offset = i * 22 * sizeof(float); - batch->updateDynamicBuffer(scene.instanceBuffer.get(), offset, 22 * sizeof(float), draws[i].instanceData); + int offset = i * 23 * sizeof(float); + batch->updateDynamicBuffer(scene.instanceBuffer.get(), offset, 23 * sizeof(float), draws[i].instanceData); } // === PHASE 2: RENDER (DURING PASS) === @@ -601,6 +602,9 @@ void YACReaderFlow3D::prepareDrawData(const YACReader3DImageRHI &image, bool isR outInstanceData[i] = matData[i]; } + // Store per-instance rotation in the instance data (new slot at index 22) + outInstanceData[22] = image.current.rot; + // Prepare uniform data outUniformData.viewProjectionMatrix = viewProjectionMatrix; outUniformData.backgroundColor = QVector3D(backgroundColor.redF(), backgroundColor.greenF(), backgroundColor.blueF()); @@ -637,7 +641,7 @@ void YACReaderFlow3D::executeDrawWithOffset(QRhiCommandBuffer *cb, QRhiTexture * // Bind vertex buffers with offset into instance buffer const QRhiCommandBuffer::VertexInput vbufBindings[] = { { scene.vertexBuffer.get(), 0 }, - { scene.instanceBuffer.get(), quint32(uniformSlot * 22 * sizeof(float)) } + { scene.instanceBuffer.get(), quint32(uniformSlot * 23 * sizeof(float)) } }; cb->setVertexInput(0, 2, vbufBindings);