diff --git a/Bundled/default_material.json b/Bundled/default_material.json index f7d36349..d2d04e09 100644 --- a/Bundled/default_material.json +++ b/Bundled/default_material.json @@ -1 +1 @@ -{"nodes":[{"id":1,"name":"RGB","type":"RGB","x":72,"y":192,"color":-5025958,"inputs":[],"outputs":[{"id":1,"node_id":1,"name":"Color","type":"RGBA","color":-3684567,"default_value":[0.7,0.7,0.7,1]}],"buttons":[{"name":"default_value","type":"RGBA","output":0}]},{"id":2,"name":"Material Output","type":"OUTPUT_MATERIAL_PBR","x":316,"y":192,"color":-5025958,"inputs":[{"id":2,"node_id":2,"name":"Base Color","type":"RGBA","color":-3684567,"default_value":[0.8,0.8,0.8,1]},{"id":2,"node_id":2,"name":"Opacity","type":"VALUE","color":-6184543,"default_value":1},{"id":2,"node_id":2,"name":"Occlusion","type":"VALUE","color":-6184543,"default_value":1},{"id":2,"node_id":2,"name":"Roughness","type":"VALUE","color":-6184543,"default_value":0.4},{"id":2,"node_id":2,"name":"Metallic","type":"VALUE","color":-6184543,"default_value":0},{"id":2,"node_id":2,"name":"Normal Map","type":"VECTOR","color":-10238109,"default_value":[0.5,0.5,1]},{"id":2,"node_id":2,"name":"Emission","type":"VALUE","color":-6184543,"default_value":0},{"id":2,"node_id":2,"name":"Height","type":"VALUE","color":-6184543,"default_value":0},{"id":2,"node_id":2,"name":"Subsurface","type":"VALUE","color":-6184543,"default_value":0}],"outputs":[],"buttons":[]}],"links":[{"id":0,"from_id":1,"from_socket":0,"to_id":2,"to_socket":0}]} \ No newline at end of file +{"nodes":[{"id":1,"name":"RGB","type":"RGB","x":72,"y":192,"color":-5025958,"inputs":[],"outputs":[{"id":1,"node_id":1,"name":"Color","type":"RGBA","color":-3684567,"default_value":[0.7,0.7,0.7,1]}],"buttons":[{"name":"default_value","type":"RGBA","output":0}]},{"id":2,"name":"Material Output","type":"OUTPUT_MATERIAL_PBR","x":316,"y":192,"color":-5025958,"inputs":[{"id":2,"node_id":2,"name":"Base Color","type":"RGBA","color":-3684567,"default_value":[0.8,0.8,0.8,1]},{"id":2,"node_id":2,"name":"Opacity","type":"VALUE","color":-6184543,"default_value":1},{"id":2,"node_id":2,"name":"Occlusion","type":"VALUE","color":-6184543,"default_value":1},{"id":2,"node_id":2,"name":"Roughness","type":"VALUE","color":-6184543,"default_value":0.3},{"id":2,"node_id":2,"name":"Metallic","type":"VALUE","color":-6184543,"default_value":0},{"id":2,"node_id":2,"name":"Normal Map","type":"VECTOR","color":-10238109,"default_value":[0.5,0.5,1]},{"id":2,"node_id":2,"name":"Emission","type":"VALUE","color":-6184543,"default_value":0},{"id":2,"node_id":2,"name":"Height","type":"VALUE","color":-6184543,"default_value":0},{"id":2,"node_id":2,"name":"Subsurface","type":"VALUE","color":-6184543,"default_value":0}],"outputs":[],"buttons":[]}],"links":[{"id":0,"from_id":1,"from_socket":0,"to_id":2,"to_socket":0}]} \ No newline at end of file diff --git a/Libraries/paint/blender.py b/Libraries/paint/blender.py index c0150d1c..c2357601 100644 --- a/Libraries/paint/blender.py +++ b/Libraries/paint/blender.py @@ -5,7 +5,8 @@ import arm.make_renderpath def on_make_renderpath(): arm.assets.add_shader_pass('max_luminance_pass') - arm.assets.add_shader_pass('copy_mrt_pass') + arm.assets.add_shader_pass('copy_mrt3_pass') + arm.assets.add_shader_pass('copy_mrt4_pass') def register(): diff --git a/Sources/arm/UINodes.hx b/Sources/arm/UINodes.hx index 84c75373..cd91c2cd 100644 --- a/Sources/arm/UINodes.hx +++ b/Sources/arm/UINodes.hx @@ -380,7 +380,8 @@ class UINodes extends iron.Trait { return con_paint; } - frag.add_out('vec4 fragColor[4]'); + var numTex = UITrait.inst.paintHeight ? 4 : 3; + frag.add_out('vec4 fragColor[$numTex]'); frag.add_uniform('float brushRadius', '_brushRadius'); frag.add_uniform('float brushOpacity', '_brushOpacity'); @@ -485,11 +486,14 @@ class UINodes extends iron.Trait { frag.write(' fragColor[1] = vec4(nortan, 1.0);'); // frag.write(' fragColor[1] = vec4(nortan, str);'); frag.write(' fragColor[2] = vec4(occlusion, roughness, metallic, str);'); - frag.write(' fragColor[3] = vec4(1.0, 0.0, height, str);'); + if (UITrait.inst.paintHeight) { + frag.write(' fragColor[3] = vec4(1.0, 0.0, height, str);'); + } if (!UITrait.inst.paintBase) frag.write('fragColor[0].a = 0.0;'); if (!UITrait.inst.paintNor) frag.write('fragColor[1].a = 0.0;'); if (!UITrait.inst.paintRough) frag.write('fragColor[2].a = 0.0;'); + // if (!UITrait.inst.paintHeight) frag.write('fragColor[3].a = 0.0;'); if (UITrait.inst.brushType == 3) { // Bake AO frag.write('fragColor[0].a = 0.0;'); @@ -592,13 +596,15 @@ class UINodes extends iron.Trait { vert.add_uniform('mat4 W', '_worldMatrix'); vert.add_uniform('mat3 N', '_normalMatrix'); vert.add_uniform('mat4 LVP', '_lampViewProjectionMatrix'); - vert.add_uniform('sampler2D texpaint_opt'); - vert.write('vec4 opt = texture(texpaint_opt, tex);'); - vert.write('float height = opt.b;'); - vert.write('vec3 wnormal = normalize(N * nor);'); vert.write('vec4 wposition = W * vec4(pos, 1.0);'); - var displaceStrength = UITrait.inst.displaceStrength; - vert.write('wposition.xyz += wnormal * height * $displaceStrength;'); + if (UITrait.inst.paintHeight) { + vert.add_uniform('sampler2D texpaint_opt'); + vert.write('vec4 opt = texture(texpaint_opt, tex);'); + vert.write('float height = opt.b;'); + vert.write('vec3 wnormal = normalize(N * nor);'); + var displaceStrength = UITrait.inst.displaceStrength * 0.1; + vert.write('wposition.xyz += wnormal * height * $displaceStrength;'); + } vert.write('gl_Position = LVP * vec4(wposition.xyz, 1.0);'); } else { @@ -641,11 +647,13 @@ class UINodes extends iron.Trait { // Height // TODO: can cause TAA issues - vert.add_uniform('sampler2D texpaint_opt'); - vert.write('vec4 opt = texture(texpaint_opt, tex);'); - vert.write('float height = opt.b;'); - var displaceStrength = UITrait.inst.displaceStrength; - vert.write('wposition.xyz += wnormal * height * $displaceStrength;'); + if (UITrait.inst.paintHeight) { + vert.add_uniform('sampler2D texpaint_opt'); + vert.write('vec4 opt = texture(texpaint_opt, tex);'); + vert.write('float height = opt.b;'); + var displaceStrength = UITrait.inst.displaceStrength * 0.1; + vert.write('wposition.xyz += wnormal * height * $displaceStrength;'); + } // vert.write('gl_Position = VP * wposition;'); @@ -692,18 +700,20 @@ class UINodes extends iron.Trait { frag.write('n = normalize(TBN * normalize(n));'); // Height - frag.add_uniform('sampler2D texpaint_opt'); - frag.write('vec4 vech;'); - frag.write('vech.x = textureOffset(texpaint_opt, texCoord, ivec2(-1, 0)).b;'); - frag.write('vech.y = textureOffset(texpaint_opt, texCoord, ivec2(1, 0)).b;'); - frag.write('vech.z = textureOffset(texpaint_opt, texCoord, ivec2(0, -1)).b;'); - frag.write('vech.w = textureOffset(texpaint_opt, texCoord, ivec2(0, 1)).b;'); - // Displace normal strength - frag.write('vech *= 15 * 7; float h1 = vech.x - vech.y; float h2 = vech.z - vech.w;'); - frag.write('vec3 va = normalize(vec3(2.0, 0.0, h1));'); - frag.write('vec3 vb = normalize(vec3(0.0, 2.0, h2));'); - frag.write('vec3 vc = normalize(vec3(h1, h2, 2.0));'); - frag.write('n = normalize(mat3(va, vb, vc) * n);'); + if (UITrait.inst.paintHeight) { + frag.add_uniform('sampler2D texpaint_opt'); + frag.write('vec4 vech;'); + frag.write('vech.x = textureOffset(texpaint_opt, texCoord, ivec2(-1, 0)).b;'); + frag.write('vech.y = textureOffset(texpaint_opt, texCoord, ivec2(1, 0)).b;'); + frag.write('vech.z = textureOffset(texpaint_opt, texCoord, ivec2(0, -1)).b;'); + frag.write('vech.w = textureOffset(texpaint_opt, texCoord, ivec2(0, 1)).b;'); + // Displace normal strength + frag.write('vech *= 15 * 7; float h1 = vech.x - vech.y; float h2 = vech.z - vech.w;'); + frag.write('vec3 va = normalize(vec3(2.0, 0.0, h1));'); + frag.write('vec3 vb = normalize(vec3(0.0, 2.0, h2));'); + frag.write('vec3 vc = normalize(vec3(h1, h2, 2.0));'); + frag.write('n = normalize(mat3(va, vb, vc) * n);'); + } // frag.write('vec4 pack = texture(texpaint_pack, texCoord);'); diff --git a/Sources/arm/UITrait.hx b/Sources/arm/UITrait.hx index ac6a5e92..4aeed679 100644 --- a/Sources/arm/UITrait.hx +++ b/Sources/arm/UITrait.hx @@ -65,6 +65,7 @@ class LayerSlot { } public function set_texpaint_opt(img:kha.Image) { + if (texpaint_opt == null) return; RenderPath.active.renderTargets.get("texpaint_opt" + ext).image = img; texpaint_opt = img; } @@ -100,6 +101,13 @@ class LayerSlot { t.format = 'RGBA32'; texpaint_pack = RenderPath.active.createRenderTarget(t).image; } + + if (UITrait.inst.paintHeight) make_texpaint_opt(); + } + + public function make_texpaint_opt() { + if (texpaint_opt != null) return; + { var t = new RenderTargetRaw(); t.name = "texpaint_opt" + ext; @@ -114,8 +122,7 @@ class LayerSlot { texpaint.unload(); texpaint_nor.unload(); texpaint_pack.unload(); - - texpaint_opt.unload(); + if (texpaint_opt != null) texpaint_opt.unload(); } } @@ -162,6 +169,7 @@ class UITrait extends iron.Trait { var isRough = true; var isMet = true; var isNor = true; + var isHeight = true; var hwnd = Id.handle(); var materials:Array = null; public var selectedMaterial:MaterialSlot; @@ -256,6 +264,7 @@ class UITrait extends iron.Trait { public var paintRough = true; public var paintMet = true; public var paintNor = true; + public var paintHeight = false; public var paintVisible = true; @@ -667,12 +676,19 @@ class UITrait extends iron.Trait { layers[0].texpaint_pack.g4.clear(kha.Color.fromFloats(1.0, 0.4, 0.0, 1.0)); // Occ, rough, met layers[0].texpaint_pack.g4.end(); + g.begin(); + iron.App.removeRender(initLayers); + } + + function initHeightLayer(g:kha.graphics4.Graphics) { + g.end(); + layers[0].texpaint_opt.g4.begin(); layers[0].texpaint_opt.g4.clear(kha.Color.fromFloats(1.0, 0.0, 0.0, 0.0)); // Opac, emis, height layers[0].texpaint_opt.g4.end(); g.begin(); - iron.App.removeRender(initLayers); + iron.App.removeRender(initHeightLayer); } function clearLastLayer(g:kha.graphics4.Graphics) { @@ -691,9 +707,11 @@ class UITrait extends iron.Trait { layers[i].texpaint_pack.g4.clear(kha.Color.fromFloats(1.0, 0.0, 0.0, 0.0)); // Occ, rough, met layers[i].texpaint_pack.g4.end(); - layers[i].texpaint_opt.g4.begin(); - layers[i].texpaint_opt.g4.clear(kha.Color.fromFloats(0.0, 0.0, 0.0, 0.0)); // Opac, emis, height - layers[i].texpaint_opt.g4.end(); + if (layers[i].texpaint_opt != null) { + layers[i].texpaint_opt.g4.begin(); + layers[i].texpaint_opt.g4.clear(kha.Color.fromFloats(0.0, 0.0, 0.0, 0.0)); // Opac, emis, height + layers[i].texpaint_opt.g4.end(); + } g.begin(); iron.App.removeRender(clearLastLayer); @@ -713,7 +731,7 @@ class UITrait extends iron.Trait { rttexpaint.image = kha.Image.createRenderTarget(res, res, kha.graphics4.TextureFormat.RGBA32, kha.graphics4.DepthStencilFormat.Depth16); rttexpaint_nor.image = kha.Image.createRenderTarget(res, res, kha.graphics4.TextureFormat.RGBA32, kha.graphics4.DepthStencilFormat.NoDepthAndStencil); rttexpaint_pack.image = kha.Image.createRenderTarget(res, res, kha.graphics4.TextureFormat.RGBA32, kha.graphics4.DepthStencilFormat.NoDepthAndStencil); - rttexpaint_opt.image = kha.Image.createRenderTarget(res, res, kha.graphics4.TextureFormat.RGBA32, kha.graphics4.DepthStencilFormat.NoDepthAndStencil); + if (rttexpaint_opt != null) rttexpaint_opt.image = kha.Image.createRenderTarget(res, res, kha.graphics4.TextureFormat.RGBA32, kha.graphics4.DepthStencilFormat.NoDepthAndStencil); g.end(); rttexpaint.image.g2.begin(); @@ -728,9 +746,11 @@ class UITrait extends iron.Trait { rttexpaint_pack.image.g2.drawScaledImage(l.texpaint_pack, 0, 0, res, res); rttexpaint_pack.image.g2.end(); - rttexpaint_opt.image.g2.begin(); - rttexpaint_opt.image.g2.drawScaledImage(l.texpaint_opt, 0, 0, res, res); - rttexpaint_opt.image.g2.end(); + if (rttexpaint_opt != null) { + rttexpaint_opt.image.g2.begin(); + rttexpaint_opt.image.g2.drawScaledImage(l.texpaint_opt, 0, 0, res, res); + rttexpaint_opt.image.g2.end(); + } g.begin(); l.unload(); @@ -797,10 +817,12 @@ class UITrait extends iron.Trait { l0.texpaint_pack.g2.drawImage(l1.texpaint_pack, 0, 0); l0.texpaint_pack.g2.end(); - l0.texpaint_opt.g2.begin(false); - l0.texpaint_opt.g2.drawImage(l1.texpaint_opt, 0, 0); - l0.texpaint_opt.g2.end(); - + if (l0.texpaint_opt != null) { + l0.texpaint_opt.g2.begin(false); + l0.texpaint_opt.g2.drawImage(l1.texpaint_opt, 0, 0); + l0.texpaint_opt.g2.end(); + } + g.begin(); deleteSelectedLayer(); @@ -978,17 +1000,17 @@ class UITrait extends iron.Trait { brushScale = ui.slider(Id.handle({value: brushScale}), "UV Scale", 0.0, 2.0, true); brushStrength = ui.slider(Id.handle({value: brushStrength}), "Strength", 0.0, 1.0, true); - ui.row([1/3,1/3,1/3]); + ui.row([1/4,1/4,1/4,1/4]); var baseHandle = Id.handle({selected: paintBase}); - paintBase = ui.check(baseHandle, "Base Color"); + paintBase = ui.check(baseHandle, "Base"); if (baseHandle.changed) { UINodes.inst.updateCanvasMap(); UINodes.inst.parsePaintMaterial(); } var norHandle = Id.handle({selected: paintNor}); - paintNor = ui.check(norHandle, "Normal Map"); + paintNor = ui.check(norHandle, "Normal"); if (norHandle.changed) { UINodes.inst.updateCanvasMap(); UINodes.inst.parsePaintMaterial(); @@ -1002,6 +1024,16 @@ class UITrait extends iron.Trait { UINodes.inst.parsePaintMaterial(); } + var heightHandle = Id.handle({selected: paintHeight}); + paintHeight = ui.check(heightHandle, "Height"); + if (heightHandle.changed) { + for (l in layers) l.make_texpaint_opt(); + for (l in undoLayers) l.make_texpaint_opt(); + iron.App.notifyOnRender(initHeightLayer); + UINodes.inst.updateCanvasMap(); + UINodes.inst.parsePaintMaterial(); + } + paintVisible = ui.check(Id.handle({selected: paintVisible}), "Visible Only"); } } @@ -1307,18 +1339,24 @@ class UITrait extends iron.Trait { #end } - pixels = selectedLayer.texpaint_opt.getPixels(); - for (i in 0...textureSize * textureSize) { - rgb.set(i * 3 + 0, pixels.get(i * 4 + 2)); - rgb.set(i * 3 + 1, pixels.get(i * 4 + 2)); - rgb.set(i * 3 + 2, pixels.get(i * 4 + 2)); + if (isHeight && selectedLayer.texpaint_opt != null) { + pixels = selectedLayer.texpaint_opt.getPixels(); + for (i in 0...textureSize * textureSize) { + rgb.set(i * 3 + 0, pixels.get(i * 4 + 2)); + rgb.set(i * 3 + 1, pixels.get(i * 4 + 2)); + rgb.set(i * 3 + 2, pixels.get(i * 4 + 2)); + } + bo = new haxe.io.BytesOutput(); + var pngwriter = new iron.format.png.Writer(bo); + pngwriter.write(iron.format.png.Tools.buildRGB(textureSize, textureSize, rgb)); + #if kha_krom + Krom.fileSaveBytes(path + "/tex_height.png", bo.getBytes().getData()); + #end } - bo = new haxe.io.BytesOutput(); - var pngwriter = new iron.format.png.Writer(bo); - pngwriter.write(iron.format.png.Tools.buildRGB(textureSize, textureSize, rgb)); - #if kha_krom - if (isMet) Krom.fileSaveBytes(path + "/tex_oeh.png", bo.getBytes().getData()); - #end + + // if (isOpac) Krom.fileSaveBytes(path + "/tex_opac.png", bo.getBytes().getData()); + // if (isEmis) Krom.fileSaveBytes(path + "/tex_emis.png", bo.getBytes().getData()); + // if (isSubs) Krom.fileSaveBytes(path + "/tex_subs.png", bo.getBytes().getData()); } } @@ -1340,6 +1378,7 @@ class UITrait extends iron.Trait { ui.row([1/2, 1/2]); isMet = ui.check(Id.handle({selected: isMet}), "Metallic"); isNor = ui.check(Id.handle({selected: isNor}), "Normal Map"); + isHeight = ui.check(Id.handle({selected: isHeight}), "Height"); } if (ui.tab(htab, "Preferences")) { @@ -1459,6 +1498,7 @@ class UITrait extends iron.Trait { new MeshData(raw, function(md:MeshData) { currentObject.data.delete(); iron.App.notifyOnRender(initLayers); + if (paintHeight) iron.App.notifyOnRender(initHeightLayer); currentObject.setData(md); diff --git a/Sources/arm/renderpath/RenderPathDeferred.hx b/Sources/arm/renderpath/RenderPathDeferred.hx index f37b9e76..627d5a4c 100644 --- a/Sources/arm/renderpath/RenderPathDeferred.hx +++ b/Sources/arm/renderpath/RenderPathDeferred.hx @@ -396,7 +396,8 @@ class RenderPathDeferred { } path.loadShader("shader_datas/max_luminance_pass/max_luminance_pass"); - path.loadShader("shader_datas/copy_mrt_pass/copy_mrt_pass"); + path.loadShader("shader_datas/copy_mrt3_pass/copy_mrt3_pass"); + path.loadShader("shader_datas/copy_mrt4_pass/copy_mrt4_pass"); { // Material preview @@ -421,7 +422,7 @@ class RenderPathDeferred { path.setTarget(Inc.getShadowMap()); // Paint - if (arm.UINodes.inst.materialParsed) { + if (arm.UINodes.inst.materialParsed && arm.UITrait.inst.paintHeight) { var tid = arm.UITrait.inst.layers[0].id; path.bindTarget("texpaint_opt" + tid, "texpaint_opt"); } @@ -479,12 +480,23 @@ class RenderPathDeferred { var tid = arm.UITrait.inst.selectedLayer.id; if (arm.UITrait.inst.pushUndo) { - path.setTarget("texpaint_undo", ["texpaint_nor_undo", "texpaint_pack_undo", "texpaint_opt_undo"]); + if (arm.UITrait.inst.paintHeight) { + path.setTarget("texpaint_undo", ["texpaint_nor_undo", "texpaint_pack_undo", "texpaint_opt_undo"]); + } + else { + path.setTarget("texpaint_undo", ["texpaint_nor_undo", "texpaint_pack_undo"]); + } + path.bindTarget("texpaint" + tid, "tex0"); path.bindTarget("texpaint_nor" + tid, "tex1"); path.bindTarget("texpaint_pack" + tid, "tex2"); - path.bindTarget("texpaint_opt" + tid, "tex3"); - path.drawShader("shader_datas/copy_mrt_pass/copy_mrt_pass"); + if (arm.UITrait.inst.paintHeight) { + path.bindTarget("texpaint_opt" + tid, "tex3"); + path.drawShader("shader_datas/copy_mrt4_pass/copy_mrt4_pass"); + } + else { + path.drawShader("shader_datas/copy_mrt3_pass/copy_mrt3_pass"); + } arm.UITrait.inst.pushUndo = false; } @@ -529,7 +541,12 @@ class RenderPathDeferred { path.drawMeshes("voxel"); path.generateMipmaps("voxels"); } - path.setTarget("texpaint" + tid, ["texpaint_nor" + tid, "texpaint_pack" + tid, "texpaint_opt" + tid]); + if (arm.UITrait.inst.paintHeight) { + path.setTarget("texpaint" + tid, ["texpaint_nor" + tid, "texpaint_pack" + tid, "texpaint_opt" + tid]); + } + else { + path.setTarget("texpaint" + tid, ["texpaint_nor" + tid, "texpaint_pack" + tid]); + } path.bindTarget("_paintdb", "paintdb"); if (arm.UITrait.inst.brushType == 3) { // Bake AO path.bindTarget("voxels", "voxels"); @@ -580,13 +597,13 @@ class RenderPathDeferred { path.bindTarget("texpaint" + tid, "texpaint"); path.bindTarget("texpaint_nor" + tid, "texpaint_nor"); path.bindTarget("texpaint_pack" + tid, "texpaint_pack"); - path.bindTarget("texpaint_opt" + tid, "texpaint_opt"); + if (arm.UITrait.inst.paintHeight) path.bindTarget("texpaint_opt" + tid, "texpaint_opt"); if (arm.UITrait.inst.layers.length > 1) { tid = arm.UITrait.inst.layers[1].id; path.bindTarget("texpaint" + tid, "texpaint1"); path.bindTarget("texpaint_nor" + tid, "texpaint_nor1"); path.bindTarget("texpaint_pack" + tid, "texpaint_pack1"); - path.bindTarget("texpaint_opt" + tid, "texpaint_opt1"); + if (arm.UITrait.inst.paintHeight) path.bindTarget("texpaint_opt" + tid, "texpaint_opt1"); } // diff --git a/armorpaint.blend b/armorpaint.blend index 523475db..d73fa6c1 100644 Binary files a/armorpaint.blend and b/armorpaint.blend differ