From 44b9f0f0b1107f7d850dab7ce6218d2655d93f3a Mon Sep 17 00:00:00 2001 From: GameChaos Date: Tue, 26 Nov 2024 17:18:34 +0200 Subject: [PATCH] Fix colour values not being decoded --- src/modules/capture/accumulate.comp | 16 +++++++++++++++- src/modules/capture/accumulate.spv | Bin 2120 -> 2760 bytes src/modules/capture/color_conversion.comp | 7 +++++++ src/modules/capture/color_conversion.spv | Bin 4712 -> 5260 bytes 4 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/modules/capture/accumulate.comp b/src/modules/capture/accumulate.comp index ae697211..8edc04ac 100644 --- a/src/modules/capture/accumulate.comp +++ b/src/modules/capture/accumulate.comp @@ -10,6 +10,17 @@ layout (push_constant) uniform push_constants { float weight; }; +// Transfer functions are the sRGB reference monitor EOTF of x^2.2, explicitly +// not the piecewise functions. +// https://en.wikipedia.org/wiki/SRGB#Transfer_function_(%22gamma%22) +// definitions of terms: https://cie.co.at/e-ilv + +// sRGB electro-optical transfer function +vec3 sRGB_EOTF(vec3 value) +{ + return pow(value, vec3(2.2)); +} + void main() { ivec2 size = imageSize(image_frame); uint width = uint(size.x), height = uint(size.y); @@ -23,6 +34,9 @@ void main() { vec4 frameColor = imageLoad(image_frame, coords); vec4 sampleColor = imageLoad(image_sample, coords); - vec4 newColor = sampleColor + frameColor * weight; + vec4 newColor = vec4( + sampleColor.rgb + sRGB_EOTF(frameColor.rgb) * weight, + sampleColor + frameColor * weight // alpha channel isn't encoded + ); imageStore(image_sample, coords, newColor); } diff --git a/src/modules/capture/accumulate.spv b/src/modules/capture/accumulate.spv index 4eec7c170734e495de72dae240818921c9cfbdd4..c28377bc76b6058eeac1411b9d574fda91d4e037 100644 GIT binary patch literal 2760 zcmZ{lYjcxT5XVoOv=mw>3^zf=6i`91Ubu^5xwN5JZGn0PP17W89?i`rZN>48U%-#y zOFx9K_4DXBqvP-Q^#yeCoTDl$U%6yLx@^2M~=Ty^sj(? z*cXaRrQ-5(acRC(>2yln-m^xn)JR&jQZ?DCReH%zO}~i&zob=ZY*z;z#_$--KSu6J za&#XR@08}3R~OFhY+Sk-sMCxg?35eZ9Gl`}`X%2B!DHbBI%$?SYo(2?a*O1YP`TZ{M7{ao+@pQUy_ z+(K8{?X7CJpL+qEX1&{Pw72@)1GsLv*=f}Jq`iFz*RQd^159gwh;G$(vuL?|ScU79 zX(ja;51)y*yY*6~-Rkzrtsc33L3!8iKwn?9S3uzkAB=^YjXEd5_Zn?v5()h{6~_X}wEtt;-oj6H%_^J{2h;@w=x_T&adCM_&w@zhE5{RPaW(WKA&;7 z=*HT`x9O;WoE z+jAnmj&0pB<_5Mt@;_(iyo2po?)^a>@1k9QQHOi{>q$9hN&D|G614S;dEUpiR`1Ps zm_y{^{%vgQiu-r4)SgackJt>Rzm^jBPIw zuVY(l%vHf2&Q*nzH<$NOLyVI*m)r*8+3r1rv&Kzi4RJ-Tj=hF>2a!uM&O40U*Vvxv zTH$8Q@eSgco?(nW-l4xM?%9*?-9QH4y9xHaW6v#YV=DOT>%N?`eI4<))VJ^*Tzipg j~7OdBgc$MnKsj6UYYpoHceuTLEm)xmUO#mwtRkb zdvl`R*qfM|o+P8gq*2z_shF(njHDWtYw&@jOFUe+1dUK5tzVP$H-W6!WFELxzIypX zQA+--IU!xHhWo{x*N0)XXmd`AJ1XxrN;W2APDz)F<^58FoU}PF{LcDXY%lwjoqQ$Q z4J&K4w^1Q%l%v|(iuI?>Md|m}&KUMwh@!*2dR+USu&ufrRieX~TM$Q;2HyMp$d8788W$J4)sNW?W0Q3>hy`vWV znDh6@=EL7B?R)fo_Lq{-|DZIv+;rkENaKU2J~)uT;U97~IlY?Ds5I-$O0ze=kGry| z3(wvcrT@40ct#nsq!>P8sl6nflkg3?v+}WP;&?-xAF<$d$FWb&X+y$C-<#6Jlkey7 zLN@)5E1Las{%{C0n$ex{XCr85^g|5)1JvZKS(AN&ISbxw5_4CRm^Yimyi1Q+kGJVD zGvsY1G4C>od3)e_)#uK1NVqR0VfaqREvS2X1?RK_?nR#jj{8DBGwYYYe-!472OLK} zdjtFYGqTBNRzCl%Y+HCGf;E zOEA6QyCPu?kFUyR4_{S(RQj5P7##Ox}cH##pN2A+KG9USqz#|M&}!{jeZlKCsb#K4o!J%uBm^&eUOFU|{7 zgR|vrK9=x)HzefnPM=8NKf4~E$|eu~ljF8zvo=2J@*d!P-_K+x`+hD=-@dPH+2j;d MlUV$4oYAc0H_|JF(*OVf diff --git a/src/modules/capture/color_conversion.comp b/src/modules/capture/color_conversion.comp index 5fff3ebb..4e76c1b9 100644 --- a/src/modules/capture/color_conversion.comp +++ b/src/modules/capture/color_conversion.comp @@ -11,6 +11,12 @@ layout (binding = 1) buffer OutputBuffer { uint8_t output_buffer[]; }; +// sRGB opto-electronic transfer function +vec3 sRGB_OETF(vec3 value) +{ + return pow(value, vec3(1.0 / 2.2)); +} + void main() { vec2 size = textureSize(image_sample, 0); uint width = uint(size.x), height = uint(size.y); @@ -20,6 +26,7 @@ void main() { return; vec4 color = texture(image_sample, vec2(x + 0.5, y + 0.5)); + color.rgb = sRGB_OETF(color.rgb); // The OpenGL coordinate system is upside-down compared to the usual video coordinate systems. // Let's invert it here in the shader. diff --git a/src/modules/capture/color_conversion.spv b/src/modules/capture/color_conversion.spv index aed68d6d79ede8743870e6564b9de9c5737dd087..121f919403531107cc9419457a8be7310d98e89b 100644 GIT binary patch literal 5260 zcmZ9Pd30S>6^Cz{G%ci1SPZpLFlmZ{V5>5f0)@1O*Ge>@Ew$C^<7H^_;3Y34FM%Lx zL8#!2;sjN3LInf`C$K85vxpOlh*MQm)PHp;u7%6*yE(h-uAHvD_HY08aQ4~v-22kz zd7TTgtSM{D4$JT!eWTQS&86GmL zEo;qlNOE{hRqW54|6w zC0m%4ddl6~wv;DFDuY84b2@0DJN%{I-cnC@d0>2;=4NU`Rnyq5TutP}pK>R@9e<(+~a8LAGCG_2E{t;D`M_btrlGh8c|YW4m~ zZR6N&*p2kN!@M6xeIk5?utqsiWZo+($yrgOVFtDv{% zxHU7Tcd9Wy)mS&RbLWsHIKhIP7uR!Nxj&rtS=Yf5??(40d<%LY;XUZVgzraRn($uq zR;0w-oYQi|6?Vt0ncLnGpTV-^uc2EJ@5lyrw|AFwb(QEx&YNdF`z+Siw!ZoL|Bkl4 zeH_J&^UigUZNB(eko&bGONi%%$!-1Z*bC8eN(c5K3Co{~ZSLX7s)wFldm5H;ixVfW zSobKjvF>TzqtV97FQw|S=r}j<;PM=<`_y*E zF8etVEoVQ*cc9x5m-UyUXU{yFuYZM3mj08_`t8~J`d@%FA=Y1omWw(1!O$mfzuG=~ zIqUf?5_cd+)72WZb=ITZ!}r!W-wpSbkNIx|vn~j`ch)}Gm+yh+41a&_-_;eiFYjaL ztyvfLPV8syShhawVeIA4UfUJV*LT|-<{}ZdHjKO(f@>5S?qS3{pVt$J&nN6B!SfOGeBQo;#wgyAv+z0tb6nn$ z|G=2zOnf)|-uj%im!mu9*nU@w{*`lVzn$Ut&U6=SpOfFu@LPXJ!9EFGDcI)ko@4tR zjC}oj3by%v55up$H`(WN9^cvH5Z~89Y~Se<5;x2gd^ew)IN#YiF@7i75&5-D%=u_{ z5pVtHA#y7a_h>~wACVu$_BoxLIP;yScI2N5Hs9wH`KN*9Bmae9IrE*rw)wuhrz5`4 zvA_GBk$B^MKH3p~7TEaM&-k+udEThlD6aK?-v@k}oV_apk;qk@);KF7hG z1^Y^{ecX`xo&XyoA32j?@7}Hy(*PSMZ;bbE3URMRSlZKw{VMw6{l5yV?@IEnKwpi> zb&)lLz6SBPY#HJ{omqahu)$O^Ew+A;!ChecXt4*@rPVAaeF0wvQ#~ zHzP}v-GROdDL#Xn6X#uu_xmki`M3*j1w}k-VE+& z7vIY-g5?xf6XLn!d-)L9mOAn{H94%is^$oVeVoZZaI8s9_Ywj&Yqeeez>VtxRY zGbU<30ybA)yk9>AyQjXW^(ff;9<_c1ma|sm{TOVnKJ!}9KS7*n{4V?y?93E>@w@Od zu)g?RcnmBTzY9MH*O6t2`#48AH~v(*0mx*GBSWDBs{ o5Z58d+2k!mABq^i2yL&%9hUe-SlUM*_IezmZ!z*ea^$W5fB8=E=Kufz literal 4712 zcmZ9O=W`Wx6o!{11OyAH5E~kTy&z%(6(t~srbH11+ciB`liWydu%SjQ*n7o>iekau zyI>c4`|Jn*1Rcu^Gd|B|53`faoH_4#PyLnMo63qwBa&oTGLpaFlEG(eQUQ}B>ZzG- z8k;1ek`c+`#xn{F=AKrV)?6$X`pTu{O&x7!jZUi5oQ8#q7f$Xgw@yCd$SLyMCzYzy zw*xW5!Bt3iQ?W;WA7l)?94%5Uwtppm73fVERm|70urO!o>4m<|rq;IQLnatbM82-} zHstmdFH7eePLJ)di`@)d=xgfk?aKJ7qz3-tVr#h*ZQcZQXIrtOv#ed2)L~ze`bMVn zc61dQx=PJWUGsWYlvasc|$6jvqF(JiH}((=rnqpwixS&`b6$$a#( z6jvu_q8Ig-d;80?`rF&vOkv^?DK9RizCv?2oy%Mw@kQw746j7DWOy~YHN%gfmt=T7 z`V6Fj^|~*v(I@PQgJx=bMx&8EGQWA%h-WmH?#}KrX;6_;DyP z{aulrIPnVfL~58X9uKl#EmA`~7dEx^)nboC%PG5Z>Z8yxA8_kqKcC&HXFuc2-&T@G z?%2$BPkhEgz{qbmLlQ&><9-;wH(H;(^J;rWa{BkpusJ(3)nv4Fjz+sLRfuuZ(Ds$Luf7=w&k14A9<;am z7o_$;z4aD?&2g@XUj+X7xMOC8-H83~+C656eJXa{mX-AflWG2Gh&jgTbN`m0JyV|v zRQJBg?Fsg-X*>T?w0kb+K4^Ql;$F05*j)R&AMF_z^Q^&6l7X3FKbqRf)_EVtKD6=M zjp2U+`_Jb$Yzq6yH2(Klv7U9<<`}0h;+_Nl(Z6|X-t*dxdvA=q4OzT#`pk3QPY};5 z?9af%5%VUYe?^Q@yfa7Pb^Ye}R3iVtnByL~uYMOjcWv)x%@Et~U*2Cg#P%B(e(%uq zoNc{1IorEEKW7{7w<@3S_bP9%&e`Vs-3q_<`plle{Jyi>BfhV#*uK+aGp>VG`)=-( zalW%9Vyv}u#vjiPxgXl~#9MziL~a+v9^UcY5&3Rx&&6+{ocZpbcI58`HsAAz{93Sl z6!Nx~F;}1gQjrY8?okiclh&94K1ne4K zq`%*aLlI--BW4QNI$<9McJ9cT3N}Xm>8#G-U~B37n>mg|`~1fo`i?;4yr1GN$*>g5 z*~haz2Jvj8@3CNK@5S%A9EZqVO;7FPGj0Yta!vp{d*sXn%SBE-Sk9bA>Uck9A=c8j z6y|93iHP&)t3YNW?(cN8zUX%n*u4q60c`(O)OP>pBF4xEH!tHoLu>jD$yvkRCnNS* z#2f5)^OTH}_Zfyb(>>WfECw6n_chjeI(Px1&mO*)axv#wVDCZLXM>&N+HCG~z{bc& z%(>t?WFU(<4{V&gF`h{QvDda(+UFzAtLTe&q6vIHauIn;(9MWkJy|X2R%99Cdu$)q zAZJ|6(*|~)8?$*jz;f-#b8z18PDI}K%X@hN+Q)mTuZYNbFU3*&Lhu1d)b0YyE}IoKKXRUq-6_}$kR>$n1( zU&oc$t|R(i1(u8c17NxQ%vWPObKJjGV7dI-ufZPV2fq>5V$0>%aUJ#mqA%8QJ=hub z<=3$iTVJf>25^2IH)6YvnCT|4Tz;mTvE^fJw}9pHYr7RYzqZ@3)96W?IDsQ(z)x#N4e7A&Xu3`1OZd@r8@uSM1& zv6oMSA4T-p;}Nu6^mqoG@9`|QoZ>UI#|v=AY(S#Ni(q@`v&VY0oIS>&UqWhf_RHW2 zNPLrD0UIM9Ij@4vxt_hU#%qXNI}$OkgXbU-^9ESXn5g|G*j#;am)`>0Q(x428|;0L zTJM16tQC3hg3Z-uUN!nX#66AQh4;bknW8U#7d`;%i{FJ0!E*7t@DX?!G6u1a`zU8z z%=j@lzmFTS^ZU37+Zg#+$ERTVPmtJ?&%yGaAyNAaaDKnP#FlgY5%U!|zu#YD%NY~3 zH-pX97yI@N*q-{L*0