Details
-
Bug
-
Resolution: Fixed
-
P2: Important
-
Qt 3D Studio 1.0
-
None
-
14f585e6453161ac4531cdd62810bddf1a9bb982
Description
As discussed in QT3DS-657, the fallback advanced blend shaders themselves are incorrect. For opaque objects the output is good since the base formulas themselves are good, but once there are semi-transparent objects involved, the results go haywire.
We now have working versions in the new Runtime that produce identical results to what the editor shows with the NV or KHR extension present.
For reference, here are the revised fragment shaders we are using. These follow https://www.khronos.org/registry/OpenGL/extensions/KHR/KHR_blend_equation_advanced.txt properly.
overlay uniform sampler2D base_layer; uniform sampler2D blend_layer; void main() { vec4 base = texture2D( base_layer, uv_coords ); if (base.a != 0.0) base.rgb /= base.a; else base = vec4(0.0); vec4 blend = texture2D( blend_layer, uv_coords ); if (blend.a != 0.0) blend.rgb /= blend.a; else blend = vec4(0.0); vec4 res = vec4(0.0); float p0 = base.a * blend.a; float p1 = base.a * (1 - blend.a); float p2 = blend.a * (1 - base.a); res.a = p0 + p1 + p2; // overlay = 2 * bottom * top if bottom < 0.5, 1 - 2 * (1 - bottom) * (1 - top) otherwise float f_rs_rd = (base.r < 0.5 ? (2.0 * base.r * blend.r) : (1.0 - 2.0 * (1.0 - base.r) * (1.0 - blend.r))); float f_gs_gd = (base.g < 0.5 ? (2.0 * base.g * blend.g) : (1.0 - 2.0 * (1.0 - base.g) * (1.0 - blend.g))); float f_bs_bd = (base.b < 0.5 ? (2.0 * base.b * blend.b) : (1.0 - 2.0 * (1.0 - base.b) * (1.0 - blend.b))); res.r = f_rs_rd * p0 + base.r * p1 + blend.r * p2; res.g = f_gs_gd * p0 + base.g * p1 + blend.g * p2; res.b = f_bs_bd * p0 + base.b * p1 + blend.b * p2; fragOutput = vec4(res.rgb * res.a, res.a); } color burn uniform sampler2D base_layer; uniform sampler2D blend_layer; void main() { vec4 base = texture2D( base_layer, uv_coords ); if (base.a != 0.0) base.rgb /= base.a; else base = vec4(0.0); vec4 blend = texture2D( blend_layer, uv_coords ); if (blend.a != 0.0) blend.rgb /= blend.a; else blend = vec4(0.0); vec4 res = vec4(0.0); float p0 = base.a * blend.a; float p1 = base.a * (1 - blend.a); float p2 = blend.a * (1 - base.a); res.a = p0 + p1 + p2; // color burn = invert the bottom layer, divide it by the top layer, then invert float f_rs_rd = ((base.r == 1.0) ? 1.0 : (blend.r == 0.0) ? 0.0 : 1.0 - min(1.0, ((1.0 - base.r) / blend.r))); float f_gs_gd = ((base.g == 1.0) ? 1.0 : (blend.g == 0.0) ? 0.0 : 1.0 - min(1.0, ((1.0 - base.g) / blend.g))); float f_bs_bd = ((base.b == 1.0) ? 1.0 : (blend.b == 0.0) ? 0.0 : 1.0 - min(1.0, ((1.0 - base.b) / blend.b))); res.r = f_rs_rd * p0 + base.r * p1 + blend.r * p2; res.g = f_gs_gd * p0 + base.g * p1 + blend.g * p2; res.b = f_bs_bd * p0 + base.b * p1 + blend.b * p2; fragOutput = vec4(res.rgb * res.a, res.a); } color dodge uniform sampler2D base_layer; uniform sampler2D blend_layer; void main() { vec4 base = texture2D( base_layer, uv_coords ); if (base.a != 0.0) base.rgb /= base.a; else base = vec4(0.0); vec4 blend = texture2D( blend_layer, uv_coords ); if (blend.a != 0.0) blend.rgb /= blend.a; else blend = vec4(0.0); vec4 res = vec4(0.0); float p0 = base.a * blend.a; float p1 = base.a * (1 - blend.a); float p2 = blend.a * (1 - base.a); res.a = p0 + p1 + p2; // color dodge = divide bottom layer by inverted top layer float f_rs_rd = ((base.r == 0.0) ? 0.0 : (blend.r == 1.0) ? 1.0 : min(base.r / (1.0 - blend.r), 1.0)); float f_gs_gd = ((base.g == 0.0) ? 0.0 : (blend.g == 1.0) ? 1.0 : min(base.g / (1.0 - blend.g), 1.0)); float f_bs_bd = ((base.b == 0.0) ? 0.0 : (blend.b == 1.0) ? 1.0 : min(base.b / (1.0 - blend.b), 1.0)); res.r = f_rs_rd * p0 + base.r * p1 + blend.r * p2; res.g = f_gs_gd * p0 + base.g * p1 + blend.g * p2; res.b = f_bs_bd * p0 + base.b * p1 + blend.b * p2; fragOutput = vec4(res.rgb * res.a, res.a); }
Attachments
Issue Links
- relates to
-
QT3DS-690 Advanced (layer) blend modes produce incorrect results
-
- Closed
-