From 636c8c19b174ab6faec3f9d2655dae7cc9a1a2cf Mon Sep 17 00:00:00 2001 From: luboslenco Date: Thu, 12 Dec 2019 14:34:11 +0100 Subject: [PATCH] Reduce gpu mem usage --- Shaders/painter/glsl/layer_merge.frag.glsl | 57 ++++---- Shaders/painter/hlsl/layer_merge.frag.glsl | Bin 10457 -> 10029 bytes .../painter/hlsl/src/layer_merge.frag.hlsl | 23 ++-- Sources/arm/Layers.hx | 127 +++++++++--------- Sources/arm/data/LayerSlot.hx | 4 +- Sources/arm/io/ExportTexture.hx | 77 ++++++----- Sources/arm/render/RenderPathPaint.hx | 2 +- Sources/arm/ui/BoxPreferences.hx | 2 +- 8 files changed, 144 insertions(+), 148 deletions(-) diff --git a/Shaders/painter/glsl/layer_merge.frag.glsl b/Shaders/painter/glsl/layer_merge.frag.glsl index ba7d9b05..531f60b1 100644 --- a/Shaders/painter/glsl/layer_merge.frag.glsl +++ b/Shaders/painter/glsl/layer_merge.frag.glsl @@ -1,14 +1,12 @@ #version 330 uniform sampler2D tex0; uniform sampler2D tex1; -uniform sampler2D tex2; +uniform sampler2D texmask; uniform sampler2D texa; -uniform sampler2D texb; -uniform sampler2D texc; uniform float opac; uniform int blending; in vec2 texCoord; -out vec4 FragColor[3]; +out vec4 FragColor; vec3 hsv_to_rgb(const vec3 c) { const vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0); vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www); @@ -24,67 +22,66 @@ vec3 rgb_to_hsv(const vec3 c) { } void main() { vec4 col0 = textureLod(tex0, texCoord, 0); - vec4 col1 = textureLod(tex1, texCoord, 0); - vec4 col2 = textureLod(tex2, texCoord, 0); vec4 cola = textureLod(texa, texCoord, 0); - vec4 colb = textureLod(texb, texCoord, 0); - vec4 colc = textureLod(texc, texCoord, 0); float str = col0.a * opac; - if (blending == 0) { // Mix - FragColor[0] = vec4(mix(cola.rgb, col0.rgb, str), max(col0.a, cola.a)); + str *= textureLod(texmask, texCoord, 0).r; + if (blending == -1) { // Merging _nor and _pack + vec4 col1 = textureLod(tex1, texCoord, 0); + FragColor = vec4(mix(cola, col1, str)); + } + else if (blending == 0) { // Mix + FragColor = vec4(mix(cola.rgb, col0.rgb, str), max(col0.a, cola.a)); } else if (blending == 1) { // Darken - FragColor[0] = vec4(mix(cola.rgb, min(cola.rgb, col0.rgb), str), max(col0.a, cola.a)); + FragColor = vec4(mix(cola.rgb, min(cola.rgb, col0.rgb), str), max(col0.a, cola.a)); } else if (blending == 2) { // Multiply - FragColor[0] = vec4(mix(cola.rgb, cola.rgb * col0.rgb, str), max(col0.a, cola.a)); + FragColor = vec4(mix(cola.rgb, cola.rgb * col0.rgb, str), max(col0.a, cola.a)); } else if (blending == 3) { // Burn - FragColor[0] = vec4(mix(cola.rgb, vec3(1.0, 1.0, 1.0) - (vec3(1.0, 1.0, 1.0) - cola.rgb) / col0.rgb, str), max(col0.a, cola.a)); + FragColor = vec4(mix(cola.rgb, vec3(1.0, 1.0, 1.0) - (vec3(1.0, 1.0, 1.0) - cola.rgb) / col0.rgb, str), max(col0.a, cola.a)); } else if (blending == 4) { // Lighten - FragColor[0] = vec4(max(cola.rgb, col0.rgb * str), max(col0.a, cola.a)); + FragColor = vec4(max(cola.rgb, col0.rgb * str), max(col0.a, cola.a)); } else if (blending == 5) { // Screen - FragColor[0] = vec4((vec3(1.0, 1.0, 1.0) - (vec3(1.0 - str, 1.0 - str, 1.0 - str) + str * (vec3(1.0, 1.0, 1.0) - col0.rgb)) * (vec3(1.0, 1.0, 1.0) - cola.rgb)), max(col0.a, cola.a)); + FragColor = vec4((vec3(1.0, 1.0, 1.0) - (vec3(1.0 - str, 1.0 - str, 1.0 - str) + str * (vec3(1.0, 1.0, 1.0) - col0.rgb)) * (vec3(1.0, 1.0, 1.0) - cola.rgb)), max(col0.a, cola.a)); } else if (blending == 6) { // Dodge - FragColor[0] = vec4(mix(cola.rgb, cola.rgb / (vec3(1.0, 1.0, 1.0) - col0.rgb), str), max(col0.a, cola.a)); + FragColor = vec4(mix(cola.rgb, cola.rgb / (vec3(1.0, 1.0, 1.0) - col0.rgb), str), max(col0.a, cola.a)); } else if (blending == 7) { // Add - FragColor[0] = vec4(mix(cola.rgb, cola.rgb + col0.rgb, str), max(col0.a, cola.a)); + FragColor = vec4(mix(cola.rgb, cola.rgb + col0.rgb, str), max(col0.a, cola.a)); } else if (blending == 8) { // Overlay - //FragColor[0] = vec4(mix(cola.rgb, (cola.rgb < vec3(0.5, 0.5, 0.5) ? vec3(2.0, 2.0, 2.0) * cola.rgb * col0.rgb : vec3(1.0, 1.0, 1.0) - vec3(2.0, 2.0, 2.0) * (vec3(1.0, 1.0, 1.0) - col0.rgb) * (vec3(1.0, 1.0, 1.0) - cola.rgb)), str), max(col0.a, cola.a)); // TODO - FragColor[0] = vec4(mix(cola.rgb, col0.rgb, str), max(col0.a, cola.a)); + //FragColor = vec4(mix(cola.rgb, (cola.rgb < vec3(0.5, 0.5, 0.5) ? vec3(2.0, 2.0, 2.0) * cola.rgb * col0.rgb : vec3(1.0, 1.0, 1.0) - vec3(2.0, 2.0, 2.0) * (vec3(1.0, 1.0, 1.0) - col0.rgb) * (vec3(1.0, 1.0, 1.0) - cola.rgb)), str), max(col0.a, cola.a)); // TODO + FragColor = vec4(mix(cola.rgb, col0.rgb, str), max(col0.a, cola.a)); } else if (blending == 9) { // Soft Light - FragColor[0] = vec4(((1.0 - str) * cola.rgb + str * ((vec3(1.0, 1.0, 1.0) - cola.rgb) * col0.rgb * cola.rgb + cola.rgb * (vec3(1.0, 1.0, 1.0) - (vec3(1.0, 1.0, 1.0) - col0.rgb) * (vec3(1.0, 1.0, 1.0) - cola.rgb)))), max(col0.a, cola.a)); + FragColor = vec4(((1.0 - str) * cola.rgb + str * ((vec3(1.0, 1.0, 1.0) - cola.rgb) * col0.rgb * cola.rgb + cola.rgb * (vec3(1.0, 1.0, 1.0) - (vec3(1.0, 1.0, 1.0) - col0.rgb) * (vec3(1.0, 1.0, 1.0) - cola.rgb)))), max(col0.a, cola.a)); } else if (blending == 10) { // Linear Light - FragColor[0] = vec4((cola.rgb + str * (vec3(2.0, 2.0, 2.0) * (col0.rgb - vec3(0.5, 0.5, 0.5)))), max(col0.a, cola.a)); + FragColor = vec4((cola.rgb + str * (vec3(2.0, 2.0, 2.0) * (col0.rgb - vec3(0.5, 0.5, 0.5)))), max(col0.a, cola.a)); } else if (blending == 11) { // Difference - FragColor[0] = vec4(mix(cola.rgb, abs(cola.rgb - col0.rgb), str), max(col0.a, cola.a)); + FragColor = vec4(mix(cola.rgb, abs(cola.rgb - col0.rgb), str), max(col0.a, cola.a)); } else if (blending == 12) { // Subtract - FragColor[0] = vec4(mix(cola.rgb, cola.rgb - col0.rgb, str), max(col0.a, cola.a)); + FragColor = vec4(mix(cola.rgb, cola.rgb - col0.rgb, str), max(col0.a, cola.a)); } else if (blending == 13) { // Divide - FragColor[0] = vec4(vec3(1.0 - str, 1.0 - str, 1.0 - str) * cola.rgb + vec3(str, str, str) * cola.rgb / col0.rgb, max(col0.a, cola.a)); + FragColor = vec4(vec3(1.0 - str, 1.0 - str, 1.0 - str) * cola.rgb + vec3(str, str, str) * cola.rgb / col0.rgb, max(col0.a, cola.a)); } else if (blending == 14) { // Hue - FragColor[0] = vec4(mix(cola.rgb, hsv_to_rgb(vec3(rgb_to_hsv(col0.rgb).r, rgb_to_hsv(cola.rgb).g, rgb_to_hsv(cola.rgb).b)), str), max(col0.a, cola.a)); + FragColor = vec4(mix(cola.rgb, hsv_to_rgb(vec3(rgb_to_hsv(col0.rgb).r, rgb_to_hsv(cola.rgb).g, rgb_to_hsv(cola.rgb).b)), str), max(col0.a, cola.a)); } else if (blending == 15) { // Saturation - FragColor[0] = vec4(mix(cola.rgb, hsv_to_rgb(vec3(rgb_to_hsv(cola.rgb).r, rgb_to_hsv(col0.rgb).g, rgb_to_hsv(cola.rgb).b)), str), max(col0.a, cola.a)); + FragColor = vec4(mix(cola.rgb, hsv_to_rgb(vec3(rgb_to_hsv(cola.rgb).r, rgb_to_hsv(col0.rgb).g, rgb_to_hsv(cola.rgb).b)), str), max(col0.a, cola.a)); } else if (blending == 16) { // Color - FragColor[0] = vec4(mix(cola.rgb, hsv_to_rgb(vec3(rgb_to_hsv(col0.rgb).r, rgb_to_hsv(col0.rgb).g, rgb_to_hsv(cola.rgb).b)), str), max(col0.a, cola.a)); + FragColor = vec4(mix(cola.rgb, hsv_to_rgb(vec3(rgb_to_hsv(col0.rgb).r, rgb_to_hsv(col0.rgb).g, rgb_to_hsv(cola.rgb).b)), str), max(col0.a, cola.a)); } else { // Value - FragColor[0] = vec4(mix(cola.rgb, hsv_to_rgb(vec3(rgb_to_hsv(cola.rgb).r, rgb_to_hsv(cola.rgb).g, rgb_to_hsv(col0.rgb).b)), str), max(col0.a, cola.a)); + FragColor = vec4(mix(cola.rgb, hsv_to_rgb(vec3(rgb_to_hsv(cola.rgb).r, rgb_to_hsv(cola.rgb).g, rgb_to_hsv(col0.rgb).b)), str), max(col0.a, cola.a)); } - FragColor[1] = vec4(mix(colb, col1, str)); - FragColor[2] = vec4(mix(colc, col2, str)); } diff --git a/Shaders/painter/hlsl/layer_merge.frag.glsl b/Shaders/painter/hlsl/layer_merge.frag.glsl index a04948c6b40ad44db383ccd0cfedbf46b06691f5..e0389d52d4f6119eae7354aa9112594a05367cc3 100644 GIT binary patch literal 10029 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 B3-bT~ literal 10457 zcmeI2&ud-B702gY{qXa%9Sf&UQ$xu^HO&t~kdz-Sro=avtT^Dt#j=G`3ht94#}0}m zWK+5*<<$`ArlpJGMgIUVtX&pe6)aM^>tE1zWodEMIneQhwm>HmT7dQvIsiJK&_U3JgboQC zb58GZ*V22!6?*sFfZp?NQ11mdbo|Yw<@w&yb?1uZmEM8_2KBUB^Gl1@-o1M5J&%T| zsku{=-~89`A3pr>=;X%yXzS1a{pgP^F~9hnb3+)iRN)6-{# z!#7trcSz$8^thq>_nAB{+WD#Raps=Z)72w&?zoXs zCDDh4)b)d#{5KltJ|f})MjPnF!{oFP1CIv&u+h0}AB=gyshZeU_0=wFo28{N&{ z*s*zRTv38M8qYZQn~$CAPhLFgHey9iM?JTG5p>x4Tcrd9bs2P<%=9luLOv8T=C_i; zhg=36JB(Y&5Q|&}92v%~WQbQT1C9*iRx-pimjOqH(PX}_vOMBO+_2_OXaqX_t{-_l zqdGd4;hJjSi~P3-1OM>;k^UPZ;Qxek`&YYhKJwk#7xYgTVU0Sk_T7v;W|I;5BXX@P z8>3M+w~f!_;u$wMa4gbamaYbWye_dOUvnR4p9uc!wXf7b?yKx|%vbs2eS8=(B+j{C zLJwqqrCb)JC?5JJwYB{7L>6z0qpd-#`nPS3^=dV3HEcD#n_6Zc=00f62S%e!?FSz-qLS}N_CSb}JFqI=eZsyQ_aBs^)GLc4 z7_m%wiTbHOWM_xMUeIUKr#04Upvp_scgW(QIHcSX8*~<>UNs+f6DR5>kCV_;ud2Ni zr=k?aL*;K?ueRr`?!@{~`vbAc*VR<>%B^3K)!lC5sH?#yd*j(&wAd7-H^)o+Jv{7< ztkyh(`6DFJEdMr&=4%SOT1PEURgS#Es0Uu;^U?I|544?YQ#BstJ+J9Pz9{vo)#mrI z{b991Jjf3t@`8t2EBIckmH(+%D7M?i&vMP0l{41u^Fb^GKA-rqQ$AJ8hpcAIX3XD~ zJ;H2biyGjZVg&blBlbJyET=h7EDf*F%+5`V{ce2bZ{*x(+3Q%mEdP0(eib(P9i?XTOYg(HKFt^NlXEKDFTUn&|K)Mq zi`td#O>6qLe6f2-N3{rW-v)I5PBgoN+nwY!{nRocKKAQVx>o?2YkwT)ijoX)5}S>vKgCA(d#_I;I`Z|r5N)t7XgjTkoOoRW zfuA+rjB}=oxsRg0pNS8CLEHSAj`!c(r>*?PC-Hk7{B2`-AlA@yFZ3h&Gn((|>^WN( z^i$$xPO_e!%VR&2_k1Cb>m}p;PyYTAHEBGoHR|%C)FztM0X*0s-kELRFQCykh_}&9 zr`35|(54HNs_rR#~PM>FvkzBJbdWrQ=tLX>nq1-coz3id+zM^(_(?ddi|JA`d{u7XEr(+$&=BH-|9}}_K|2u z{ORsNeIiTmt;?EUrXSm;0~&J4PL1a4rWAwU%i(VX<}$f-&&+L`P5gr2^y}0A=EI!& zbL}o!-6KWTo^wO1QJ%kVk&%tV^|_)HA-hL{6{TKwhxDUR-6bO`C61hvK|N~{&bi8>~P@cT*41K&n%Di-yRKJoj$!nf(5zZ{8rte+Uo z^jpm%N38?KV>Qp5@wZAa?kVBk2PXbx+jQi%P1b0pU!tkM{J-?Jdx{}7WxdUMRZ(iv z!{$34y%6B8v7__1;F$1nhUr?S98SsxsQ`BUAqOG;dSC6{t4&oy_~lzvbfN zMmNl}7T?#!XZ-&Em#FFB-{(yS{}yXHm~YYn&+A&t%!M~D{9fO$$O(S;2hhK+2a7yU W#!*8f;9m~k62h9IpE>D)zCQ<@z)&Ip diff --git a/Shaders/painter/hlsl/src/layer_merge.frag.hlsl b/Shaders/painter/hlsl/src/layer_merge.frag.hlsl index 5fa50bd5..a422f0a7 100644 --- a/Shaders/painter/hlsl/src/layer_merge.frag.hlsl +++ b/Shaders/painter/hlsl/src/layer_merge.frag.hlsl @@ -2,14 +2,10 @@ Texture2D tex0; SamplerState _tex0_sampler; Texture2D tex1; SamplerState _tex1_sampler; -Texture2D tex2; -SamplerState _tex2_sampler; +Texture2D texmask; +SamplerState _texmask_sampler; Texture2D texa; SamplerState _texa_sampler; -Texture2D texb; -SamplerState _texb_sampler; -Texture2D texc; -SamplerState _texc_sampler; uniform float opac; uniform int blending; float3 hsv_to_rgb(const float3 c) { @@ -25,17 +21,18 @@ float3 rgb_to_hsv(const float3 c) { float e = 1.0e-10; return float3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x); } -struct SPIRV_Cross_Output { float4 color0 : SV_Target0; float4 color1 : SV_Target1; float4 color2 : SV_Target2; }; +struct SPIRV_Cross_Output { float4 color0 : SV_Target0; }; SPIRV_Cross_Output main(float2 texCoord : TEXCOORD0) { float4 col0 = tex0.SampleLevel(_tex0_sampler, texCoord, 0); - float4 col1 = tex1.SampleLevel(_tex1_sampler, texCoord, 0); - float4 col2 = tex2.SampleLevel(_tex2_sampler, texCoord, 0); float4 cola = texa.SampleLevel(_texa_sampler, texCoord, 0); - float4 colb = texb.SampleLevel(_texb_sampler, texCoord, 0); - float4 colc = texc.SampleLevel(_texc_sampler, texCoord, 0); float str = col0.a * opac; + str *= texmask.SampleLevel(_texmask_sampler, texCoord, 0).r; SPIRV_Cross_Output stage_output; - if (blending == 0) { // Mix + if (blending == -1) { // Merging _nor and _pack + float4 col1 = tex1.SampleLevel(_tex1_sampler, texCoord, 0); + stage_output.color0 = float4(lerp(cola, col1, str)); + } + else if (blending == 0) { // Mix stage_output.color0 = float4(lerp(cola.rgb, col0.rgb, str), max(col0.a, cola.a)); } else if (blending == 1) { // Darken @@ -89,7 +86,5 @@ SPIRV_Cross_Output main(float2 texCoord : TEXCOORD0) { else { // Value stage_output.color0 = float4(lerp(cola.rgb, hsv_to_rgb(float3(rgb_to_hsv(cola.rgb).r, rgb_to_hsv(cola.rgb).g, rgb_to_hsv(col0.rgb).b)), str), max(col0.a, cola.a)); } - stage_output.color1 = float4(lerp(colb, col1, str)); - stage_output.color2 = float4(lerp(colc, col2, str)); return stage_output; } diff --git a/Sources/arm/Layers.hx b/Sources/arm/Layers.hx index a9dd1a71..b1a8db41 100644 --- a/Sources/arm/Layers.hx +++ b/Sources/arm/Layers.hx @@ -20,26 +20,21 @@ import arm.Project; class Layers { - public static var pipe: PipelineState = null; + public static var pipeMerge: PipelineState = null; public static var pipeCopy: PipelineState; public static var pipeMask: PipelineState; public static var tex0: TextureUnit; public static var tex1: TextureUnit; - public static var tex2: TextureUnit; + public static var texmask: TextureUnit; public static var texa: TextureUnit; - public static var texb: TextureUnit; - public static var texc: TextureUnit; public static var opac: ConstantLocation; public static var blending: ConstantLocation; public static var tex0Mask: TextureUnit; public static var texaMask: TextureUnit; public static var imga: Image = null; - public static var imgb: Image = null; - public static var imgc: Image = null; public static var expa: Image = null; public static var expb: Image = null; public static var expc: Image = null; - public static var expd: Image = null; public static var pipeCursor: PipelineState; public static var cursorVP: ConstantLocation; public static var cursorInvVP: ConstantLocation; @@ -79,7 +74,7 @@ class Layers { public static function resizeLayers(g: kha.graphics4.Graphics) { var C = Config.raw; if (App.resHandle.position >= 4) { // Save memory for >=16k - C.undo_steps = 2; + C.undo_steps = 1; if (UITrait.inst.undoHandle != null) UITrait.inst.undoHandle.value = C.undo_steps; while (History.undoLayers.length > C.undo_steps) { var l = History.undoLayers.pop(); l.unload(); } } @@ -120,21 +115,19 @@ class Layers { } public static function makePipe() { - pipe = new PipelineState(); - pipe.vertexShader = Reflect.field(kha.Shaders, "layer_merge_vert"); - pipe.fragmentShader = Reflect.field(kha.Shaders, "layer_merge_frag"); + pipeMerge = new PipelineState(); + pipeMerge.vertexShader = Reflect.field(kha.Shaders, "layer_merge_vert"); + pipeMerge.fragmentShader = Reflect.field(kha.Shaders, "layer_merge_frag"); var vs = new VertexStructure(); vs.add("pos", VertexData.Float2); - pipe.inputLayout = [vs]; - pipe.compile(); - tex0 = pipe.getTextureUnit("tex0"); - tex1 = pipe.getTextureUnit("tex1"); - tex2 = pipe.getTextureUnit("tex2"); - texa = pipe.getTextureUnit("texa"); - texb = pipe.getTextureUnit("texb"); - texc = pipe.getTextureUnit("texc"); - opac = pipe.getConstantLocation("opac"); - blending = pipe.getConstantLocation("blending"); + pipeMerge.inputLayout = [vs]; + pipeMerge.compile(); + tex0 = pipeMerge.getTextureUnit("tex0"); // Always binding texpaint.a for blending + tex1 = pipeMerge.getTextureUnit("tex1"); + texmask = pipeMerge.getTextureUnit("texmask"); + texa = pipeMerge.getTextureUnit("texa"); + opac = pipeMerge.getConstantLocation("opac"); + blending = pipeMerge.getConstantLocation("blending"); pipeCopy = new PipelineState(); pipeCopy.vertexShader = Reflect.field(kha.Shaders, "layer_view_vert"); @@ -185,14 +178,8 @@ class Layers { var l = Project.layers[0]; if (imga != null && imga.width != l.texpaint.width) { RenderPath.active.renderTargets.get("temptex0").unload(); - RenderPath.active.renderTargets.get("temptex1").unload(); - RenderPath.active.renderTargets.get("temptex2").unload(); RenderPath.active.renderTargets.remove("temptex0"); - RenderPath.active.renderTargets.remove("temptex1"); - RenderPath.active.renderTargets.remove("temptex2"); imga = null; - imgb = null; - imgc = null; } if (imga == null) { { @@ -204,24 +191,6 @@ class Layers { var rt = RenderPath.active.createRenderTarget(t); imga = rt.image; } - { - var t = new RenderTargetRaw(); - t.name = "temptex1"; - t.width = l.texpaint.width; - t.height = l.texpaint.height; - t.format = "RGBA32"; - var rt = RenderPath.active.createRenderTarget(t); - imgb = rt.image; - } - { - var t = new RenderTargetRaw(); - t.name = "temptex2"; - t.width = l.texpaint.width; - t.height = l.texpaint.height; - t.format = "RGBA32"; - var rt = RenderPath.active.createRenderTarget(t); - imgc = rt.image; - } } } @@ -231,22 +200,19 @@ class Layers { expa.unload(); expb.unload(); expc.unload(); - expd.unload(); expa = null; expb = null; expc = null; - expd = null; } if (expa == null) { expa = Image.createRenderTarget(l.texpaint.width, l.texpaint.height); expb = Image.createRenderTarget(l.texpaint.width, l.texpaint.height); expc = Image.createRenderTarget(l.texpaint.width, l.texpaint.height); - expd = Image.createRenderTarget(l.texpaint.width, l.texpaint.height); } } public static function mergeSelectedLayer(g: kha.graphics4.Graphics) { - if (pipe == null) makePipe(); + if (pipeMerge == null) makePipe(); var l0 = Project.layers[0]; var l1 = Context.layer; @@ -266,30 +232,21 @@ class Layers { l1.applyMask(); } - // Copy layer0 to temp - imga.g2.begin(false); + // Merge into layer below + if (iron.data.ConstData.screenAlignedVB == null) iron.data.ConstData.createScreenAlignedData(); + + imga.g2.begin(false); // Copy to temp imga.g2.pipeline = pipeCopy; imga.g2.drawImage(l0.texpaint, 0, 0); imga.g2.end(); - imgb.g2.begin(false); - imgb.g2.pipeline = pipeCopy; - imgb.g2.drawImage(l0.texpaint_nor, 0, 0); - imgb.g2.end(); - imgc.g2.begin(false); - imgc.g2.pipeline = pipeCopy; - imgc.g2.drawImage(l0.texpaint_pack, 0, 0); - imgc.g2.end(); - // Merge into layer0 - if (iron.data.ConstData.screenAlignedVB == null) iron.data.ConstData.createScreenAlignedData(); - l0.texpaint.g4.begin([l0.texpaint_nor, l0.texpaint_pack]); - l0.texpaint.g4.setPipeline(pipe); + l0.texpaint.g4.begin(); + l0.texpaint.g4.setPipeline(pipeMerge); l0.texpaint.g4.setTexture(tex0, l1.texpaint); - l0.texpaint.g4.setTexture(tex1, l1.texpaint_nor); - l0.texpaint.g4.setTexture(tex2, l1.texpaint_pack); + var empty = RenderPath.active.renderTargets.get("empty_white").image; + l0.texpaint.g4.setTexture(tex1, empty); + l0.texpaint.g4.setTexture(texmask, empty); l0.texpaint.g4.setTexture(texa, imga); - l0.texpaint.g4.setTexture(texb, imgb); - l0.texpaint.g4.setTexture(texc, imgc); l0.texpaint.g4.setFloat(opac, l1.maskOpacity); l0.texpaint.g4.setInt(blending, l1.blending); l0.texpaint.g4.setVertexBuffer(iron.data.ConstData.screenAlignedVB); @@ -297,6 +254,42 @@ class Layers { l0.texpaint.g4.drawIndexedVertices(); l0.texpaint.g4.end(); + imga.g2.begin(false); + imga.g2.pipeline = pipeCopy; + imga.g2.drawImage(l0.texpaint_nor, 0, 0); + imga.g2.end(); + + l0.texpaint_nor.g4.begin(); + l0.texpaint_nor.g4.setPipeline(pipeMerge); + l0.texpaint_nor.g4.setTexture(tex0, l1.texpaint); + l0.texpaint_nor.g4.setTexture(tex1, l1.texpaint_nor); + l0.texpaint_nor.g4.setTexture(texmask, empty); + l0.texpaint_nor.g4.setTexture(texa, imga); + l0.texpaint_nor.g4.setFloat(opac, l1.maskOpacity); + l0.texpaint.g4.setInt(blending, -1); + l0.texpaint_nor.g4.setVertexBuffer(iron.data.ConstData.screenAlignedVB); + l0.texpaint_nor.g4.setIndexBuffer(iron.data.ConstData.screenAlignedIB); + l0.texpaint_nor.g4.drawIndexedVertices(); + l0.texpaint_nor.g4.end(); + + imga.g2.begin(false); + imga.g2.pipeline = pipeCopy; + imga.g2.drawImage(l0.texpaint_pack, 0, 0); + imga.g2.end(); + + l0.texpaint_pack.g4.begin(); + l0.texpaint_pack.g4.setPipeline(pipeMerge); + l0.texpaint_pack.g4.setTexture(tex0, l1.texpaint); + l0.texpaint_pack.g4.setTexture(tex1, l1.texpaint_pack); + l0.texpaint_pack.g4.setTexture(texmask, empty); + l0.texpaint_pack.g4.setTexture(texa, imga); + l0.texpaint_pack.g4.setFloat(opac, l1.maskOpacity); + l0.texpaint.g4.setInt(blending, -1); + l0.texpaint_pack.g4.setVertexBuffer(iron.data.ConstData.screenAlignedVB); + l0.texpaint_pack.g4.setIndexBuffer(iron.data.ConstData.screenAlignedIB); + l0.texpaint_pack.g4.drawIndexedVertices(); + l0.texpaint_pack.g4.end(); + g.begin(); Context.layer.delete(); diff --git a/Sources/arm/data/LayerSlot.hx b/Sources/arm/data/LayerSlot.hx index 8470c2f1..d1515208 100644 --- a/Sources/arm/data/LayerSlot.hx +++ b/Sources/arm/data/LayerSlot.hx @@ -185,7 +185,7 @@ class LayerSlot { public function applyMask() { if (texpaint_mask == null) return; - if (Layers.pipe == null) Layers.makePipe(); + if (Layers.pipeMerge == null) Layers.makePipe(); Layers.makeTempImg(); // Copy layer to temp @@ -217,7 +217,7 @@ class LayerSlot { var l = new LayerSlot(); layers.insert(i, l); - if (Layers.pipe == null) Layers.makePipe(); + if (Layers.pipeMerge == null) Layers.makePipe(); l.texpaint.g2.begin(false); l.texpaint.g2.pipeline = Layers.pipeCopy; l.texpaint.g2.drawImage(texpaint, 0, 0); diff --git a/Sources/arm/io/ExportTexture.hx b/Sources/arm/io/ExportTexture.hx index 0dd24e3d..c05776fb 100644 --- a/Sources/arm/io/ExportTexture.hx +++ b/Sources/arm/io/ExportTexture.hx @@ -63,7 +63,7 @@ class ExportTexture { if (UITrait.inst.layersExport == 0 && layers.length > 1) { Layers.makeTempImg(); Layers.makeExportImg(); - if (Layers.pipe == null) Layers.makePipe(); + if (Layers.pipeMerge == null) Layers.makePipe(); if (iron.data.ConstData.screenAlignedVB == null) iron.data.ConstData.createScreenAlignedData(); // Duplicate base layer @@ -101,48 +101,59 @@ class ExportTexture { if (!Project.paintObjects[l1.objectMask - 1].name.endsWith(udimTile)) continue; } - // Apply mask - var hasMask = l1.texpaint_mask != null; - if (hasMask) { - Layers.expd.g4.begin(); - Layers.expd.g4.setPipeline(Layers.pipeMask); - Layers.expd.g4.setTexture(Layers.tex0Mask, l1.texpaint); - Layers.expd.g4.setTexture(Layers.texaMask, l1.texpaint_mask); - Layers.expd.g4.setVertexBuffer(iron.data.ConstData.screenAlignedVB); - Layers.expd.g4.setIndexBuffer(iron.data.ConstData.screenAlignedIB); - Layers.expd.g4.drawIndexedVertices(); - Layers.expd.g4.end(); - } - - // Copy layer0 to temp - Layers.imga.g2.begin(false); + // Merge into layer0 + Layers.imga.g2.begin(false); // Copy to temp Layers.imga.g2.pipeline = Layers.pipeCopy; Layers.imga.g2.drawImage(Layers.expa, 0, 0); Layers.imga.g2.end(); - Layers.imgb.g2.begin(false); - Layers.imgb.g2.pipeline = Layers.pipeCopy; - Layers.imgb.g2.drawImage(Layers.expb, 0, 0); - Layers.imgb.g2.end(); - Layers.imgc.g2.begin(false); - Layers.imgc.g2.pipeline = Layers.pipeCopy; - Layers.imgc.g2.drawImage(Layers.expc, 0, 0); - Layers.imgc.g2.end(); - - // Merge into layer0 - Layers.expa.g4.begin([Layers.expb, Layers.expc]); - Layers.expa.g4.setPipeline(Layers.pipe); - Layers.expa.g4.setTexture(Layers.tex0, hasMask ? Layers.expd : l1.texpaint); - Layers.expa.g4.setTexture(Layers.tex1, l1.texpaint_nor); - Layers.expa.g4.setTexture(Layers.tex2, l1.texpaint_pack); + Layers.expa.g4.begin(); + Layers.expa.g4.setPipeline(Layers.pipeMerge); + Layers.expa.g4.setTexture(Layers.tex0, l1.texpaint); + var empty = iron.RenderPath.active.renderTargets.get("empty_white").image; + Layers.expa.g4.setTexture(Layers.tex1, empty); + var hasMask = l1.texpaint_mask != null; + Layers.expa.g4.setTexture(Layers.texmask, hasMask ? l1.texpaint_mask : empty); Layers.expa.g4.setTexture(Layers.texa, Layers.imga); - Layers.expa.g4.setTexture(Layers.texb, Layers.imgb); - Layers.expa.g4.setTexture(Layers.texc, Layers.imgc); Layers.expa.g4.setFloat(Layers.opac, l1.maskOpacity); Layers.expa.g4.setInt(Layers.blending, l1.blending); Layers.expa.g4.setVertexBuffer(iron.data.ConstData.screenAlignedVB); Layers.expa.g4.setIndexBuffer(iron.data.ConstData.screenAlignedIB); Layers.expa.g4.drawIndexedVertices(); Layers.expa.g4.end(); + + Layers.imga.g2.begin(false); + Layers.imga.g2.pipeline = Layers.pipeCopy; + Layers.imga.g2.drawImage(Layers.expb, 0, 0); + Layers.imga.g2.end(); + Layers.expb.g4.begin(); + Layers.expb.g4.setPipeline(Layers.pipeMerge); + Layers.expb.g4.setTexture(Layers.tex0, l1.texpaint); + Layers.expb.g4.setTexture(Layers.tex1, l1.texpaint_nor); + Layers.expb.g4.setTexture(Layers.texmask, empty); + Layers.expb.g4.setTexture(Layers.texa, Layers.imga); + Layers.expb.g4.setFloat(Layers.opac, l1.maskOpacity); + Layers.expa.g4.setInt(Layers.blending, -1); + Layers.expb.g4.setVertexBuffer(iron.data.ConstData.screenAlignedVB); + Layers.expb.g4.setIndexBuffer(iron.data.ConstData.screenAlignedIB); + Layers.expb.g4.drawIndexedVertices(); + Layers.expb.g4.end(); + + Layers.imga.g2.begin(false); + Layers.imga.g2.pipeline = Layers.pipeCopy; + Layers.imga.g2.drawImage(Layers.expc, 0, 0); + Layers.imga.g2.end(); + Layers.expc.g4.begin(); + Layers.expc.g4.setPipeline(Layers.pipeMerge); + Layers.expc.g4.setTexture(Layers.tex0, l1.texpaint); + Layers.expc.g4.setTexture(Layers.tex1, l1.texpaint_pack); + Layers.expc.g4.setTexture(Layers.texmask, empty); + Layers.expc.g4.setTexture(Layers.texa, Layers.imga); + Layers.expc.g4.setFloat(Layers.opac, l1.maskOpacity); + Layers.expa.g4.setInt(Layers.blending, -1); + Layers.expc.g4.setVertexBuffer(iron.data.ConstData.screenAlignedVB); + Layers.expc.g4.setIndexBuffer(iron.data.ConstData.screenAlignedIB); + Layers.expc.g4.drawIndexedVertices(); + Layers.expc.g4.end(); } texpaint = Layers.expa; diff --git a/Sources/arm/render/RenderPathPaint.hx b/Sources/arm/render/RenderPathPaint.hx index 5e83b872..642512bb 100644 --- a/Sources/arm/render/RenderPathPaint.hx +++ b/Sources/arm/render/RenderPathPaint.hx @@ -525,7 +525,7 @@ class RenderPathPaint { public static function finishPaint() { if (Context.tool == ToolBake && !dilated && UITrait.inst.dilateRadius > 0) { - if (Layers.imga == null) Layers.makeTempImg(); + Layers.makeTempImg(); dilated = true; path.setTarget("temptex0"); path.bindTarget("texpaint0", "tex"); diff --git a/Sources/arm/ui/BoxPreferences.hx b/Sources/arm/ui/BoxPreferences.hx index db538145..bd8890b9 100644 --- a/Sources/arm/ui/BoxPreferences.hx +++ b/Sources/arm/ui/BoxPreferences.hx @@ -87,7 +87,7 @@ class BoxPreferences { } if (ui.tab(htab, "Usage")) { UITrait.inst.undoHandle = Id.handle({value: Config.raw.undo_steps}); - Config.raw.undo_steps = Std.int(ui.slider(UITrait.inst.undoHandle, "Undo Steps", 2, 64, false, 1)); + Config.raw.undo_steps = Std.int(ui.slider(UITrait.inst.undoHandle, "Undo Steps", 1, 64, false, 1)); if (UITrait.inst.undoHandle.changed) { ui.g.end(); while (History.undoLayers.length < Config.raw.undo_steps) {