From da99070786bbe9f9d5c42da8c435059f1f4b54df Mon Sep 17 00:00:00 2001 From: luboslenco Date: Tue, 15 Dec 2020 13:56:38 +0100 Subject: [PATCH] Place decal layer to picked location --- .../Sources/arm/shader/ShaderFunctions.hx | 21 +++ Sources/arm/App.hx | 3 +- Sources/arm/Context.hx | 7 + Sources/arm/Layers.hx | 4 +- Sources/arm/node/MakeColorIdPicker.hx | 30 +++-- Sources/arm/node/MakeTexcoord.hx | 3 +- Sources/arm/render/LineDraw.hx | 2 +- Sources/arm/render/RenderPathPaint.hx | 125 +++++++++++------- Sources/arm/util/RenderUtil.hx | 24 ++++ 9 files changed, 161 insertions(+), 58 deletions(-) diff --git a/Libraries/shaderlib/Sources/arm/shader/ShaderFunctions.hx b/Libraries/shaderlib/Sources/arm/shader/ShaderFunctions.hx index 1328f34b..7485aecf 100644 --- a/Libraries/shaderlib/Sources/arm/shader/ShaderFunctions.hx +++ b/Libraries/shaderlib/Sources/arm/shader/ShaderFunctions.hx @@ -487,6 +487,27 @@ float ltcEvaluate(vec3 N, vec3 V, float dotNV, vec3 P, mat3 Minv, vec3 points0, if (n == 5) sum += integrateEdge(L4, L0); return max(0.0, -sum); } +"; + + public static var str_get_pos_from_depth = " +vec3 get_pos_from_depth(vec2 uv, mat4 invVP) { + #if defined(HLSL) || defined(METAL) || defined(SPIRV) + float depth = textureLod(gbufferD, vec2(uv.x, 1.0 - uv.y), 0.0).r; + #else + float depth = textureLod(gbufferD, uv, 0.0).r; + #endif + vec4 wpos = vec4(uv * 2.0 - 1.0, depth * 2.0 - 1.0, 1.0); + wpos = mul(wpos, invVP); + return wpos.xyz / wpos.w; +} +"; + + public static var str_get_nor_from_depth = " +vec3 get_nor_from_depth(vec3 p0, vec2 uv, mat4 invVP, vec2 texStep) { + vec3 p1 = get_pos_from_depth(uv + vec2(texStep.x * 4.0, 0.0), invVP); + vec3 p2 = get_pos_from_depth(uv + vec2(0.0, texStep.y * 4.0), invVP); + return normalize(cross(p2 - p0, p1 - p0)); +} "; } diff --git a/Sources/arm/App.hx b/Sources/arm/App.hx index f1e58aa5..d051b65c 100644 --- a/Sources/arm/App.hx +++ b/Sources/arm/App.hx @@ -391,7 +391,8 @@ class App { // Material dragged onto viewport or layers tab if (inViewport || inLayers || in2dView) { var uvType = Input.getKeyboard().down("control") ? UVProject : UVMap; - Layers.createFillLayer(uvType); + var decalMat = uvType == UVProject ? RenderUtil.getDecalMat() : null; + Layers.createFillLayer(uvType, decalMat); } else if (inNodes) { var index = 0; diff --git a/Sources/arm/Context.hx b/Sources/arm/Context.hx index 1f01f1ae..b9dc536c 100644 --- a/Sources/arm/Context.hx +++ b/Sources/arm/Context.hx @@ -71,6 +71,13 @@ class Context { public static var uvyPicked = 0.0; public static var pickerSelectMaterial = true; public static var pickerMaskHandle = new Handle(); + public static var pickPosNor = false; + public static var posXPicked = 0.0; + public static var posYPicked = 0.0; + public static var posZPicked = 0.0; + public static var norXPicked = 0.0; + public static var norYPicked = 0.0; + public static var norZPicked = 0.0; public static var defaultEnvmap: Image = null; public static var defaultIrradiance: kha.arrays.Float32Array = null; diff --git a/Sources/arm/Layers.hx b/Sources/arm/Layers.hx index 8f891e86..5384771b 100644 --- a/Sources/arm/Layers.hx +++ b/Sources/arm/Layers.hx @@ -10,6 +10,7 @@ import kha.graphics4.VertexData; import kha.graphics4.BlendingFactor; import kha.graphics4.CompareMode; import iron.RenderPath; +import iron.math.Mat4; import arm.ui.UISidebar; import arm.ui.UIHeader; import arm.data.LayerSlot; @@ -614,11 +615,12 @@ class Layers { return l; } - public static function createFillLayer(uvType = UVMap) { + public static function createFillLayer(uvType = UVMap, decalMat: Mat4 = null) { function _init() { var l = newLayer(false); History.newLayer(); l.uvType = uvType; + if (decalMat != null) l.decalMat = decalMat; l.objectMask = Context.layerFilter; History.toFillLayer(); l.toFillLayer(); diff --git a/Sources/arm/node/MakeColorIdPicker.hx b/Sources/arm/node/MakeColorIdPicker.hx index a048a555..d0bb76b0 100644 --- a/Sources/arm/node/MakeColorIdPicker.hx +++ b/Sources/arm/node/MakeColorIdPicker.hx @@ -1,5 +1,6 @@ package arm.node; +import arm.shader.ShaderFunctions; import arm.shader.NodeShader; import arm.Enums; @@ -28,15 +29,26 @@ class MakeColorIdPicker { frag.write('fragColor = vec4(idcol, 1.0);'); } else if (Context.tool == ToolPicker) { - frag.add_out('vec4 fragColor[3]'); - frag.add_uniform('sampler2D texpaint'); - frag.add_uniform('sampler2D texpaint_nor'); - frag.add_uniform('sampler2D texpaint_pack'); - frag.write('fragColor[0] = textureLod(texpaint, texCoordInp, 0.0);'); - frag.write('fragColor[1] = textureLod(texpaint_nor, texCoordInp, 0.0);'); - frag.write('fragColor[2] = textureLod(texpaint_pack, texCoordInp, 0.0);'); - frag.write('fragColor[0].a = texCoordInp.x;'); - frag.write('fragColor[2].a = texCoordInp.y;'); + if (Context.pickPosNor) { + frag.add_out('vec4 fragColor[2]'); + frag.add_uniform('sampler2D gbufferD'); + frag.add_uniform('mat4 invVP', '_inverseViewProjectionMatrix'); + frag.add_function(ShaderFunctions.str_get_pos_from_depth); + frag.add_function(ShaderFunctions.str_get_nor_from_depth); + frag.write('fragColor[0] = vec4(get_pos_from_depth(vec2(inpLocal.x, 1.0 - inpLocal.y), invVP), 0.0);'); + frag.write('fragColor[1] = vec4(get_nor_from_depth(fragColor[0].rgb, vec2(inpLocal.x, 1.0 - inpLocal.y), invVP, vec2(1.0, 1.0) / gbufferSize), 0.0);'); + } + else { + frag.add_out('vec4 fragColor[3]'); + frag.add_uniform('sampler2D texpaint'); + frag.add_uniform('sampler2D texpaint_nor'); + frag.add_uniform('sampler2D texpaint_pack'); + frag.write('fragColor[0] = textureLod(texpaint, texCoordInp, 0.0);'); + frag.write('fragColor[1] = textureLod(texpaint_nor, texCoordInp, 0.0);'); + frag.write('fragColor[2] = textureLod(texpaint_pack, texCoordInp, 0.0);'); + frag.write('fragColor[0].a = texCoordInp.x;'); + frag.write('fragColor[2].a = texCoordInp.y;'); + } } } } diff --git a/Sources/arm/node/MakeTexcoord.hx b/Sources/arm/node/MakeTexcoord.hx index d4faa360..5cc06f5c 100644 --- a/Sources/arm/node/MakeTexcoord.hx +++ b/Sources/arm/node/MakeTexcoord.hx @@ -22,7 +22,8 @@ class MakeTexcoord { frag.n = true; frag.add_uniform('vec3 decalLayerNor', '_decalLayerNor'); - frag.write('if (abs(dot(n, decalLayerNor) - 1.0) > 0.2) discard;'); + var angle = Context.brushAngleRejectDot; + frag.write('if (abs(dot(n, decalLayerNor) - 1.0) > $angle) discard;'); frag.wposition = true; frag.add_uniform('vec3 decalLayerLoc', '_decalLayerLoc'); diff --git a/Sources/arm/render/LineDraw.hx b/Sources/arm/render/LineDraw.hx index c9356e15..e4afcb21 100644 --- a/Sources/arm/render/LineDraw.hx +++ b/Sources/arm/render/LineDraw.hx @@ -42,7 +42,7 @@ class LineDraw { public static function render(g4: kha.graphics4.Graphics) { - var hide = Operator.shortcut(Config.keymap.stencil_hide, ShortcutDown); + var hide = Operator.shortcut(Config.keymap.stencil_hide, ShortcutDown) || iron.system.Input.getKeyboard().down("control"); var isPaint = UIHeader.inst.worktab.position == SpacePaint; var isDecal = isPaint && Context.layer.fill_layer != null && Context.layer.uvType == UVProject; if (!isDecal || hide) return; diff --git a/Sources/arm/render/RenderPathPaint.hx b/Sources/arm/render/RenderPathPaint.hx index af1bb636..e12a74c3 100644 --- a/Sources/arm/render/RenderPathPaint.hx +++ b/Sources/arm/render/RenderPathPaint.hx @@ -86,6 +86,22 @@ class RenderPathPaint { t.format = "RGBA32"; path.createRenderTarget(t); } + { + var t = new RenderTargetRaw(); + t.name = "texpaint_posnor_picker0"; + t.width = 1; + t.height = 1; + t.format = "RGBA128"; + path.createRenderTarget(t); + } + { + var t = new RenderTargetRaw(); + t.name = "texpaint_posnor_picker1"; + t.width = 1; + t.height = 1; + t.format = "RGBA128"; + path.createRenderTarget(t); + } path.loadShader("shader_datas/copy_mrt3_pass/copy_mrt3_pass"); path.loadShader("shader_datas/dilate_pass/dilate_pass"); @@ -125,52 +141,71 @@ class RenderPathPaint { UIHeader.inst.headerHandle.redraws = 2; } else if (Context.tool == ToolPicker) { - #if kha_metal - //path.setTarget("texpaint_picker"); - //path.clearTarget(0xff000000); - //path.setTarget("texpaint_nor_picker"); - //path.clearTarget(0xff000000); - //path.setTarget("texpaint_pack_picker"); - //path.clearTarget(0xff000000); - path.setTarget("texpaint_picker", ["texpaint_nor_picker", "texpaint_pack_picker"]); - #else - path.setTarget("texpaint_picker", ["texpaint_nor_picker", "texpaint_pack_picker"]); - //path.clearTarget(0xff000000); - #end - path.bindTarget("gbuffer2", "gbuffer2"); - tid = Context.layer.id; - path.bindTarget("texpaint" + tid, "texpaint"); - path.bindTarget("texpaint_nor" + tid, "texpaint_nor"); - path.bindTarget("texpaint_pack" + tid, "texpaint_pack"); - path.drawMeshes("paint"); - UIHeader.inst.headerHandle.redraws = 2; + if (Context.pickPosNor) { + path.setTarget("texpaint_posnor_picker0", ["texpaint_posnor_picker1"]); + path.bindTarget("gbuffer2", "gbuffer2"); + path.bindTarget("_main", "gbufferD"); + path.drawMeshes("paint"); + var texpaint_posnor_picker0 = path.renderTargets.get("texpaint_posnor_picker0").image; + var texpaint_posnor_picker1 = path.renderTargets.get("texpaint_posnor_picker1").image; + var a = texpaint_posnor_picker0.getPixels(); + var b = texpaint_posnor_picker1.getPixels(); + Context.posXPicked = a.getFloat(0); + Context.posYPicked = a.getFloat(4); + Context.posZPicked = a.getFloat(8); + Context.norXPicked = b.getFloat(0); + Context.norYPicked = b.getFloat(4); + Context.norZPicked = b.getFloat(8); + } + else { + #if kha_metal + //path.setTarget("texpaint_picker"); + //path.clearTarget(0xff000000); + //path.setTarget("texpaint_nor_picker"); + //path.clearTarget(0xff000000); + //path.setTarget("texpaint_pack_picker"); + //path.clearTarget(0xff000000); + path.setTarget("texpaint_picker", ["texpaint_nor_picker", "texpaint_pack_picker"]); + #else + path.setTarget("texpaint_picker", ["texpaint_nor_picker", "texpaint_pack_picker"]); + //path.clearTarget(0xff000000); + #end + path.bindTarget("gbuffer2", "gbuffer2"); + tid = Context.layer.id; + path.bindTarget("texpaint" + tid, "texpaint"); + path.bindTarget("texpaint_nor" + tid, "texpaint_nor"); + path.bindTarget("texpaint_pack" + tid, "texpaint_pack"); + path.drawMeshes("paint"); + UIHeader.inst.headerHandle.redraws = 2; - var texpaint_picker = path.renderTargets.get("texpaint_picker").image; - var texpaint_nor_picker = path.renderTargets.get("texpaint_nor_picker").image; - var texpaint_pack_picker = path.renderTargets.get("texpaint_pack_picker").image; - var a = texpaint_picker.getPixels(); - var b = texpaint_nor_picker.getPixels(); - var c = texpaint_pack_picker.getPixels(); - // Picked surface values - Context.baseRPicked = a.get(0) / 255; - Context.baseGPicked = a.get(1) / 255; - Context.baseBPicked = a.get(2) / 255; - Context.uvxPicked = a.get(3) / 255; - Context.normalRPicked = b.get(0) / 255; - Context.normalGPicked = b.get(1) / 255; - Context.normalBPicked = b.get(2) / 255; - Context.uvyPicked = c.get(3) / 255; - Context.occlusionPicked = c.get(0) / 255; - Context.roughnessPicked = c.get(1) / 255; - Context.metallicPicked = c.get(2) / 255; - // Pick material - if (Context.pickerSelectMaterial) { - var matid = b.get(3); - for (m in Project.materials) { - if (m.id == matid) { - Context.setMaterial(m); - Context.materialIdPicked = matid; - break; + var texpaint_picker = path.renderTargets.get("texpaint_picker").image; + var texpaint_nor_picker = path.renderTargets.get("texpaint_nor_picker").image; + var texpaint_pack_picker = path.renderTargets.get("texpaint_pack_picker").image; + var a = texpaint_picker.getPixels(); + var b = texpaint_nor_picker.getPixels(); + var c = texpaint_pack_picker.getPixels(); + + // Picked surface values + Context.baseRPicked = a.get(0) / 255; + Context.baseGPicked = a.get(1) / 255; + Context.baseBPicked = a.get(2) / 255; + Context.uvxPicked = a.get(3) / 255; + Context.normalRPicked = b.get(0) / 255; + Context.normalGPicked = b.get(1) / 255; + Context.normalBPicked = b.get(2) / 255; + Context.uvyPicked = c.get(3) / 255; + Context.occlusionPicked = c.get(0) / 255; + Context.roughnessPicked = c.get(1) / 255; + Context.metallicPicked = c.get(2) / 255; + // Pick material + if (Context.pickerSelectMaterial) { + var matid = b.get(3); + for (m in Project.materials) { + if (m.id == matid) { + Context.setMaterial(m); + Context.materialIdPicked = matid; + break; + } } } } diff --git a/Sources/arm/util/RenderUtil.hx b/Sources/arm/util/RenderUtil.hx index 3829de09..3c621a2f 100644 --- a/Sources/arm/util/RenderUtil.hx +++ b/Sources/arm/util/RenderUtil.hx @@ -14,6 +14,7 @@ import iron.RenderPath; import iron.object.MeshObject; import iron.math.Mat4; import iron.math.Vec4; +import iron.math.Quat; import iron.data.MaterialData; import iron.data.ShaderData; import arm.ui.UIHeader; @@ -462,4 +463,27 @@ class RenderUtil { Context.paintObject.transform.scaleWorld = _scaleWorld; Context.paintObject.transform.buildMatrix(); } + + public static function pickPositionAndNormal() { + Context.pickPosNor = true; + Context.pdirty = 1; + var _tool = Context.tool; + Context.tool = ToolPicker; + MakeMaterial.parsePaintMaterial(); + arm.render.RenderPathPaint.commandsPaint(false); + Context.tool = _tool; + Context.pickPosNor = false; + MakeMaterial.parsePaintMaterial(); + Context.pdirty = 0; + } + + public static function getDecalMat(): Mat4 { + RenderUtil.pickPositionAndNormal(); + var decalMat = Mat4.identity(); + var loc = new Vec4(Context.posXPicked, Context.posYPicked, Context.posZPicked); + var rot = new Quat().fromTo(new Vec4(0.0, 0.0, -1.0), new Vec4(Context.norXPicked, Context.norYPicked, Context.norZPicked)); + var scale = new Vec4(0.5, 0.5, 0.5); + decalMat.compose(loc, rot, scale); + return decalMat; + } }