From fc7c8d46f633d4642994142cd90f331f97f4a8d6 Mon Sep 17 00:00:00 2001 From: machine <@baktrian> Date: Fri, 24 Nov 2023 13:05:51 +0000 Subject: [PATCH 01/21] uv seam fix attempt --- .../core/src/Meshes/meshUVSpaceRenderer.ts | 127 +++++++++++++++++- .../Shaders/meshUVSpaceRenderer.fragment.fx | 49 ++++++- .../src/Shaders/meshUVSpaceRenderer.vertex.fx | 4 + .../meshUVSpaceRendererMasker.fragment.fx | 20 +++ .../meshUVSpaceRendererMasker.vertex.fx | 8 ++ 5 files changed, 198 insertions(+), 10 deletions(-) create mode 100644 packages/dev/core/src/Shaders/meshUVSpaceRendererMasker.fragment.fx create mode 100644 packages/dev/core/src/Shaders/meshUVSpaceRendererMasker.vertex.fx diff --git a/packages/dev/core/src/Meshes/meshUVSpaceRenderer.ts b/packages/dev/core/src/Meshes/meshUVSpaceRenderer.ts index 28ce2f0a608..ff103218750 100644 --- a/packages/dev/core/src/Meshes/meshUVSpaceRenderer.ts +++ b/packages/dev/core/src/Meshes/meshUVSpaceRenderer.ts @@ -5,16 +5,25 @@ import type { AbstractMesh } from "./abstractMesh"; import type { ThinTexture } from "core/Materials/Textures/thinTexture"; import type { BaseTexture } from "core/Materials/Textures/baseTexture"; import type { Nullable } from "core/types"; -import { Matrix } from "core/Maths/math.vector"; +import { Matrix, Vector2 } from "core/Maths/math.vector"; import { Constants } from "core/Engines/constants"; import { ShaderMaterial } from "core/Materials/shaderMaterial"; import { RenderTargetTexture } from "core/Materials/Textures/renderTargetTexture"; -import { Color4 } from "core/Maths/math.color"; +import { Color3, Color4 } from "core/Maths/math.color"; import "../Shaders/meshUVSpaceRenderer.vertex"; import "../Shaders/meshUVSpaceRenderer.fragment"; +import "../Shaders/meshUVSpaceRendererMasker.vertex"; +import "../Shaders/meshUVSpaceRendererMasker.fragment"; +import { MeshBuilder } from "./meshBuilder"; +import { PBRMaterial } from ".."; + + declare module "../scene" { + /** + * + */ export interface Scene { /** @internal */ _meshUVSpaceRendererShader: Nullable; @@ -58,6 +67,10 @@ export class MeshUVSpaceRenderer { private _scene: Scene; private _options: Required; private _textureCreatedInternally = false; + /** + * + */ + _maskTexture: any; private static _GetShader(scene: Scene): ShaderMaterial { if (!scene._meshUVSpaceRendererShader) { @@ -76,7 +89,7 @@ export class MeshUVSpaceRenderer { } ); shader.backFaceCulling = false; - shader.alphaMode = Constants.ALPHA_COMBINE; + shader.alphaMode = 0; scene.onDisposeObservable.add(() => { scene._meshUVSpaceRendererShader?.dispose(); @@ -136,7 +149,7 @@ export class MeshUVSpaceRenderer { return MeshUVSpaceRenderer._IsRenderTargetTexture(this.texture) ? this.texture.isReadyForRendering() : this.texture.isReady(); } - /** +/** * Projects and renders a texture in the mesh UV space * @param texture The texture * @param position The position of the center of projection (world space coordinates) @@ -144,7 +157,7 @@ export class MeshUVSpaceRenderer { * @param size The size of the projection * @param angle The rotation angle around the direction of the projection */ - public renderTexture(texture: BaseTexture, position: Vector3, normal: Vector3, size: Vector3, angle = 0): void { + public renderTextureOLD(texture: BaseTexture, position: Vector3, normal: Vector3, size: Vector3, angle = 0): void { if (!this.texture) { this._createDiffuseRTT(); } @@ -160,6 +173,108 @@ export class MeshUVSpaceRenderer { } } + // Method to use the mask texture to fix UV seams + public renderTexture(texture: BaseTexture, position: Vector3, normal: Vector3, size: Vector3, angle = 0): void { + // Create the diffuse render target texture if it doesn't exist + if (!this.texture) { + this._createDiffuseRTT(); + } + + // Ensure the mask texture is ready for seam fixing + this._createMaskTexture(); + + // const plane = MeshBuilder.CreatePlane("image", {size: 1}, this._scene); + // const pbr = new PBRMaterial("P", this._scene); + // pbr.roughness = 1; + // pbr.emissiveTexture = this._maskTexture; + // pbr.emissiveIntensity = 1; + // pbr.emissiveColor = new Color3(1, 1, 1); + // pbr.albedoTexture = this._maskTexture; + // plane.material = pbr; + // pbr.disableLighting = true; + + // Prepare the shader with the decal texture, mask texture, and necessary uniforms + const shader = MeshUVSpaceRenderer._GetShader(this._scene); + shader.setTexture("textureSampler", texture); // Decal texture + shader.setTexture("maskTexture", this._maskTexture); // Mask texture for seam fixing + shader.setVector2("texelSize", new Vector2(1.0 / this._options.width, 1.0 / this._options.height)); + + + + // const plane2 = MeshBuilder.CreateSphere("image", {diameter:0.2}, this._scene); + // const pbr2 = new PBRMaterial("P", this._scene); + // pbr2.roughness = 1; + // // pbr2.emissiveTexture = this._maskTexture; + // // pbr2.emissiveIntensity = 1; + // // pbr2.emissiveColor = new Color3(1, 1, 1); + // // pbr2.albedoTexture = this._maskTexture; + // plane2.material = shader; + // pbr2.disableLighting = true; + + + // Calculate and set the projection matrix + const projectionMatrix = this._createProjectionMatrix(position, normal, size, angle); + shader.setMatrix("projMatrix", projectionMatrix); + + // Render the decal with the updated material that includes seam fix logic + if (MeshUVSpaceRenderer._IsRenderTargetTexture(this.texture)) { + this.texture.render(); + } + } + + private _createMaskTexture(): void { + if (this._maskTexture) { + return; // Mask texture already created + } + + try { + this._scene.clearColor = new Color4(0,0,0,1); + // Create a new render target texture for the mask + this._maskTexture = new RenderTargetTexture( + "maskTexture", + { width: this._options.width, height: this._options.height }, + this._scene, + false, // No mipmaps for the mask texture + true, + this._options.textureType + ); + + // Set up the mask material + const maskMaterial = new ShaderMaterial( + "meshUVSpaceRendererMaskerShader", + this._scene, + { + vertex: "meshUVSpaceRendererMasker", + fragment: "meshUVSpaceRendererMasker", + }, + { + attributes: ["position", "uv"], + uniforms: ["worldViewProjection"] + } + ); + + // Save the original material of the mesh + const originalMaterial = this._mesh.material; + this._mesh.material = this._mesh.material as PBRMaterial; + maskMaterial.setTexture("textureSampler", this._mesh.material.albedoTexture); + maskMaterial.backFaceCulling = false; + + + // Render the mesh with the mask material to the mask texture + this._maskTexture.renderList.push(this._mesh); + this._maskTexture.setMaterialForRendering(this._mesh, maskMaterial); + + // Ensure the mask texture is updated + this._maskTexture.refreshRate = RenderTargetTexture.REFRESHRATE_RENDER_ONCE; + this._scene.customRenderTargets.push(this._maskTexture); + + } catch (error) { + console.error("Error creating mask texture:", error); + } + } + + + /** * Clears the texture map */ @@ -183,6 +298,8 @@ export class MeshUVSpaceRenderer { } } + + private _createDiffuseRTT(): void { this._textureCreatedInternally = true; diff --git a/packages/dev/core/src/Shaders/meshUVSpaceRenderer.fragment.fx b/packages/dev/core/src/Shaders/meshUVSpaceRenderer.fragment.fx index 9fdb76b62d0..2f980b877fc 100644 --- a/packages/dev/core/src/Shaders/meshUVSpaceRenderer.fragment.fx +++ b/packages/dev/core/src/Shaders/meshUVSpaceRenderer.fragment.fx @@ -1,13 +1,52 @@ precision highp float; varying vec2 vDecalTC; +varying vec2 vUV; uniform sampler2D textureSampler; +uniform sampler2D maskTexture; // Uniform for the mask texture +uniform vec2 texelSize; // Uniform for the texel size void main(void) { - if (vDecalTC.x < 0. || vDecalTC.x > 1. || vDecalTC.y < 0. || vDecalTC.y > 1.) { - discard; - } + // Sample the texture color + vec4 textureColor = texture2D(textureSampler, vDecalTC); + vec4 maskColour = texture2D(maskTexture, vDecalTC); + // Sample the mask texture to determine border status + float maskValue = texture2D(maskTexture, vUV).r; + // gl_FragColor = vec4(maskValue, maskValue, maskValue, 1.0); + // gl_FragColor = maskColour; + // If we are within the UV borders, use the original color + if (maskValue > 0.5) { + gl_FragColor = maskColour; + } else { + gl_FragColor = textureColor; + + // vec4 colorSum = vec4(0.0); + // float totalWeight = 0.0; + + // // Offset for neighboring texel coordinates + // vec2 offsets[4] = vec2[](vec2(-texelSize.x, 0.0), vec2(texelSize.x, 0.0), vec2(0.0, -texelSize.y), vec2(0.0, texelSize.y)); - gl_FragColor = texture2D(textureSampler, vDecalTC); -} + // // Sample neighboring texels + // for (int i = 0; i < 4; i++) { + // vec2 neighborUV = vDecalTC + offsets[i]; + // float neighborMaskValue = texture2D(maskTexture, neighborUV).r; + // if (neighborMaskValue > 0.5) { + // colorSum += texture2D(textureSampler, neighborUV); + // totalWeight += 1.0; + // } + // } + // gl_FragColor = colorSum / totalWeight; + + // // Only average if we have valid neighbors + // if (totalWeight > 0.0) { + // gl_FragColor = colorSum / totalWeight; + // } else { + // // Use the background color or discard the fragment + // // gl_FragColor = backgroundColor; // Define a background color if needed + // discard; + // } + // gl_FragColor = maskColour; + // gl_FragColor = maskColour; + } +} \ No newline at end of file diff --git a/packages/dev/core/src/Shaders/meshUVSpaceRenderer.vertex.fx b/packages/dev/core/src/Shaders/meshUVSpaceRenderer.vertex.fx index b04b384c92a..9ae326f237c 100644 --- a/packages/dev/core/src/Shaders/meshUVSpaceRenderer.vertex.fx +++ b/packages/dev/core/src/Shaders/meshUVSpaceRenderer.vertex.fx @@ -7,6 +7,8 @@ attribute vec2 uv; uniform mat4 projMatrix; varying vec2 vDecalTC; +varying vec2 vUV; + #include #include @@ -16,6 +18,7 @@ varying vec2 vDecalTC; #include + void main(void) { vec3 positionUpdated = position; vec3 normalUpdated = normal; @@ -48,6 +51,7 @@ void main(void) { vec3 decalTC = (projMatrix * worldPos).xyz; vDecalTC = decalTC.xy; + vUV = uv; gl_Position = vec4(uv * 2.0 - 1.0, normalView.z > 0.0 ? 2. : decalTC.z, 1.0); } diff --git a/packages/dev/core/src/Shaders/meshUVSpaceRendererMasker.fragment.fx b/packages/dev/core/src/Shaders/meshUVSpaceRendererMasker.fragment.fx new file mode 100644 index 00000000000..ea74551c041 --- /dev/null +++ b/packages/dev/core/src/Shaders/meshUVSpaceRendererMasker.fragment.fx @@ -0,0 +1,20 @@ +// varying vec2 vUV; + +// uniform sampler2D textureSampler; + +// void main(void) { +// gl_FragColor = vec4(vUV.x, vUV.y, 0.0, 1.0); +// } + +varying vec2 vUV; + +void main(void) { + // Check if the UV coordinates are within the 0 to 1 range + if (vUV.x >= 0.0 && vUV.x <= 1.0 && vUV.y >= 0.0 && vUV.y <= 1.0) { + // If inside the UV range, draw white + gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0); + } else { + // If outside the UV range, draw black + gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); + } +} diff --git a/packages/dev/core/src/Shaders/meshUVSpaceRendererMasker.vertex.fx b/packages/dev/core/src/Shaders/meshUVSpaceRendererMasker.vertex.fx new file mode 100644 index 00000000000..88d8bd384b4 --- /dev/null +++ b/packages/dev/core/src/Shaders/meshUVSpaceRendererMasker.vertex.fx @@ -0,0 +1,8 @@ +attribute vec2 uv; + +varying vec2 vUV; + +void main(void) { + gl_Position = vec4(vec2(uv.x, uv.y) * 2.0 - 1.0, 0., 1.0); + vUV = uv; +} \ No newline at end of file From 85d4a355562dece56a696d9db330d14be08a21fc Mon Sep 17 00:00:00 2001 From: machine <@baktrian> Date: Sat, 25 Nov 2023 04:01:06 +0000 Subject: [PATCH 02/21] red edges where the uv seams are --- .../core/src/Meshes/meshUVSpaceRenderer.ts | 31 +++++----- .../Shaders/meshUVSpaceRenderer.fragment.fx | 60 ++++++------------- 2 files changed, 34 insertions(+), 57 deletions(-) diff --git a/packages/dev/core/src/Meshes/meshUVSpaceRenderer.ts b/packages/dev/core/src/Meshes/meshUVSpaceRenderer.ts index ff103218750..c2cbd9d6385 100644 --- a/packages/dev/core/src/Meshes/meshUVSpaceRenderer.ts +++ b/packages/dev/core/src/Meshes/meshUVSpaceRenderer.ts @@ -83,13 +83,13 @@ export class MeshUVSpaceRenderer { }, { attributes: ["position", "normal", "uv"], - uniforms: ["world", "projMatrix"], - samplers: ["textureSampler"], + uniforms: ["world", "projMatrix", "texelSize"], + samplers: ["textureSampler", "maskTexture"], needAlphaBlending: true, } ); shader.backFaceCulling = false; - shader.alphaMode = 0; + shader.alphaMode = Constants.ALPHA_COMBINE; scene.onDisposeObservable.add(() => { scene._meshUVSpaceRendererShader?.dispose(); @@ -175,23 +175,23 @@ export class MeshUVSpaceRenderer { // Method to use the mask texture to fix UV seams public renderTexture(texture: BaseTexture, position: Vector3, normal: Vector3, size: Vector3, angle = 0): void { + // Ensure the mask texture is ready for seam fixing + this._createMaskTexture(); + // Create the diffuse render target texture if it doesn't exist if (!this.texture) { this._createDiffuseRTT(); } - // Ensure the mask texture is ready for seam fixing - this._createMaskTexture(); - - // const plane = MeshBuilder.CreatePlane("image", {size: 1}, this._scene); - // const pbr = new PBRMaterial("P", this._scene); - // pbr.roughness = 1; - // pbr.emissiveTexture = this._maskTexture; - // pbr.emissiveIntensity = 1; - // pbr.emissiveColor = new Color3(1, 1, 1); - // pbr.albedoTexture = this._maskTexture; - // plane.material = pbr; - // pbr.disableLighting = true; + const plane = MeshBuilder.CreatePlane("image", {size: 1}, this._scene); + const pbr = new PBRMaterial("P", this._scene); + pbr.roughness = 1; + pbr.emissiveTexture = this._maskTexture; + pbr.emissiveIntensity = 1; + pbr.emissiveColor = new Color3(1, 1, 1); + pbr.albedoTexture = this._maskTexture; + plane.material = pbr; + pbr.disableLighting = true; // Prepare the shader with the decal texture, mask texture, and necessary uniforms const shader = MeshUVSpaceRenderer._GetShader(this._scene); @@ -267,6 +267,7 @@ export class MeshUVSpaceRenderer { // Ensure the mask texture is updated this._maskTexture.refreshRate = RenderTargetTexture.REFRESHRATE_RENDER_ONCE; this._scene.customRenderTargets.push(this._maskTexture); + return this._maskTexture; } catch (error) { console.error("Error creating mask texture:", error); diff --git a/packages/dev/core/src/Shaders/meshUVSpaceRenderer.fragment.fx b/packages/dev/core/src/Shaders/meshUVSpaceRenderer.fragment.fx index 2f980b877fc..a3075c93a8c 100644 --- a/packages/dev/core/src/Shaders/meshUVSpaceRenderer.fragment.fx +++ b/packages/dev/core/src/Shaders/meshUVSpaceRenderer.fragment.fx @@ -4,49 +4,25 @@ varying vec2 vDecalTC; varying vec2 vUV; uniform sampler2D textureSampler; -uniform sampler2D maskTexture; // Uniform for the mask texture -uniform vec2 texelSize; // Uniform for the texel size +uniform sampler2D maskTexture; // The mask texture void main(void) { - // Sample the texture color - vec4 textureColor = texture2D(textureSampler, vDecalTC); - vec4 maskColour = texture2D(maskTexture, vDecalTC); - // Sample the mask texture to determine border status - float maskValue = texture2D(maskTexture, vUV).r; - // gl_FragColor = vec4(maskValue, maskValue, maskValue, 1.0); - // gl_FragColor = maskColour; - // If we are within the UV borders, use the original color - if (maskValue > 0.5) { - gl_FragColor = maskColour; - } else { - gl_FragColor = textureColor; - - // vec4 colorSum = vec4(0.0); - // float totalWeight = 0.0; - - // // Offset for neighboring texel coordinates - // vec2 offsets[4] = vec2[](vec2(-texelSize.x, 0.0), vec2(texelSize.x, 0.0), vec2(0.0, -texelSize.y), vec2(0.0, texelSize.y)); + // Hard-coded texel size for a 1024x1024 texture + vec2 texelSize = vec2(1.0 / 1024.0, 1.0 / 1024.0); + + // Sample the center pixel and surrounding pixels + float centerPixel = texture2D(maskTexture, vUV).r; + float rightPixel = texture2D(maskTexture, vUV + vec2(texelSize.x, 0.0)).r; + float leftPixel = texture2D(maskTexture, vUV - vec2(texelSize.x, 0.0)).r; + float topPixel = texture2D(maskTexture, vUV + vec2(0.0, texelSize.y)).r; + float bottomPixel = texture2D(maskTexture, vUV - vec2(0.0, texelSize.y)).r; - // // Sample neighboring texels - // for (int i = 0; i < 4; i++) { - // vec2 neighborUV = vDecalTC + offsets[i]; - // float neighborMaskValue = texture2D(maskTexture, neighborUV).r; - // if (neighborMaskValue > 0.5) { - // colorSum += texture2D(textureSampler, neighborUV); - // totalWeight += 1.0; - // } - // } - // gl_FragColor = colorSum / totalWeight; - - // // Only average if we have valid neighbors - // if (totalWeight > 0.0) { - // gl_FragColor = colorSum / totalWeight; - // } else { - // // Use the background color or discard the fragment - // // gl_FragColor = backgroundColor; // Define a background color if needed - // discard; - // } - // gl_FragColor = maskColour; - // gl_FragColor = maskColour; + // Detect edges by checking if the center pixel is white but at least one of the neighbors is not + if (centerPixel > 0.5 && (rightPixel < 0.5 || leftPixel < 0.5 || topPixel < 0.5 || bottomPixel < 0.5)) { + // Current pixel is on the edge of a UV island + gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); // Red + } else { + // Current pixel is not on the edge of a UV island + gl_FragColor = vec4(centerPixel, centerPixel, centerPixel, 1.0); // Original color } -} \ No newline at end of file +} From 18ad00a2ed48bc9e7fa96167d5452a67f4f553a5 Mon Sep 17 00:00:00 2001 From: machine <@baktrian> Date: Sat, 25 Nov 2023 04:02:31 +0000 Subject: [PATCH 03/21] increase edge size for debugging --- packages/dev/core/src/Shaders/meshUVSpaceRenderer.fragment.fx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/dev/core/src/Shaders/meshUVSpaceRenderer.fragment.fx b/packages/dev/core/src/Shaders/meshUVSpaceRenderer.fragment.fx index a3075c93a8c..86d5ebffadd 100644 --- a/packages/dev/core/src/Shaders/meshUVSpaceRenderer.fragment.fx +++ b/packages/dev/core/src/Shaders/meshUVSpaceRenderer.fragment.fx @@ -8,7 +8,7 @@ uniform sampler2D maskTexture; // The mask texture void main(void) { // Hard-coded texel size for a 1024x1024 texture - vec2 texelSize = vec2(1.0 / 1024.0, 1.0 / 1024.0); + vec2 texelSize = vec2(4.0 / 1024.0, 4.0 / 1024.0); // Sample the center pixel and surrounding pixels float centerPixel = texture2D(maskTexture, vUV).r; From 28d275ea89c5a1e245131561a0345ae4dc6a5d55 Mon Sep 17 00:00:00 2001 From: machine <@baktrian> Date: Sat, 25 Nov 2023 04:36:27 +0000 Subject: [PATCH 04/21] seam cover --- .../Shaders/meshUVSpaceRenderer.fragment.fx | 36 ++++++++++++------- 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/packages/dev/core/src/Shaders/meshUVSpaceRenderer.fragment.fx b/packages/dev/core/src/Shaders/meshUVSpaceRenderer.fragment.fx index 86d5ebffadd..85ff0a8c758 100644 --- a/packages/dev/core/src/Shaders/meshUVSpaceRenderer.fragment.fx +++ b/packages/dev/core/src/Shaders/meshUVSpaceRenderer.fragment.fx @@ -1,28 +1,40 @@ precision highp float; -varying vec2 vDecalTC; -varying vec2 vUV; +varying vec2 vDecalTC; // Texture coordinates from the decal +varying vec2 vUV; // Original UV coordinates -uniform sampler2D textureSampler; -uniform sampler2D maskTexture; // The mask texture +uniform sampler2D textureSampler; // The main texture sampler for decals +uniform sampler2D maskTexture; // The mask texture for seams void main(void) { + if (vDecalTC.x < 0. || vDecalTC.x > 1. || vDecalTC.y < 0. || vDecalTC.y > 1.) { + discard; // Discard fragment outside of the decal texture coordinates + } + // Hard-coded texel size for a 1024x1024 texture vec2 texelSize = vec2(4.0 / 1024.0, 4.0 / 1024.0); - - // Sample the center pixel and surrounding pixels + + // Sample the center pixel and surrounding pixels from the mask texture float centerPixel = texture2D(maskTexture, vUV).r; float rightPixel = texture2D(maskTexture, vUV + vec2(texelSize.x, 0.0)).r; float leftPixel = texture2D(maskTexture, vUV - vec2(texelSize.x, 0.0)).r; float topPixel = texture2D(maskTexture, vUV + vec2(0.0, texelSize.y)).r; float bottomPixel = texture2D(maskTexture, vUV - vec2(0.0, texelSize.y)).r; - // Detect edges by checking if the center pixel is white but at least one of the neighbors is not - if (centerPixel > 0.5 && (rightPixel < 0.5 || leftPixel < 0.5 || topPixel < 0.5 || bottomPixel < 0.5)) { - // Current pixel is on the edge of a UV island - gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); // Red + // Check if the current pixel is near a seam + bool nearSeam = centerPixel > 0.5 && (rightPixel < 0.5 || leftPixel < 0.5 || topPixel < 0.5 || bottomPixel < 0.5); + + // Sample the decal texture + vec4 decalColor = texture2D(textureSampler, vDecalTC); + + // Determine if the pixel is part of a decal (non-transparent pixel in the decal texture) + bool isDecal = decalColor.a > 0.5; + + // If the pixel is part of a decal and near a seam, draw the green line + if (isDecal && nearSeam) { + gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0); // Draw green line over the seam } else { - // Current pixel is not on the edge of a UV island - gl_FragColor = vec4(centerPixel, centerPixel, centerPixel, 1.0); // Original color + // Otherwise, render the decal color + gl_FragColor = decalColor; } } From 5d1619a9bef274528b7b15591ea45eab52413e83 Mon Sep 17 00:00:00 2001 From: machine <@baktrian> Date: Tue, 28 Nov 2023 01:59:09 +0000 Subject: [PATCH 05/21] update experiments --- .../core/src/Meshes/meshUVSpaceRenderer.ts | 122 ++++++++++++++---- .../Shaders/meshUVSpaceRenderer.fragment.fx | 11 +- .../src/Shaders/meshUVSpaceRenderer.vertex.fx | 2 +- .../meshUVSpaceRendererCombine.fragment.fx | 22 ++++ .../meshUVSpaceRendererCombine.vertex.fx | 17 +++ .../meshUVSpaceRendererMasker.fragment.fx | 9 +- .../meshUVSpaceRendererSeam.fragment.fx | 46 +++++++ 7 files changed, 185 insertions(+), 44 deletions(-) create mode 100644 packages/dev/core/src/Shaders/meshUVSpaceRendererCombine.fragment.fx create mode 100644 packages/dev/core/src/Shaders/meshUVSpaceRendererCombine.vertex.fx create mode 100644 packages/dev/core/src/Shaders/meshUVSpaceRendererSeam.fragment.fx diff --git a/packages/dev/core/src/Meshes/meshUVSpaceRenderer.ts b/packages/dev/core/src/Meshes/meshUVSpaceRenderer.ts index c2cbd9d6385..9a3c185b08a 100644 --- a/packages/dev/core/src/Meshes/meshUVSpaceRenderer.ts +++ b/packages/dev/core/src/Meshes/meshUVSpaceRenderer.ts @@ -16,6 +16,12 @@ import "../Shaders/meshUVSpaceRenderer.fragment"; import "../Shaders/meshUVSpaceRendererMasker.vertex"; import "../Shaders/meshUVSpaceRendererMasker.fragment"; + +import "../Shaders/meshUVSpaceRendererSeam.fragment"; + +import "../Shaders/meshUVSpaceRendererCombine.vertex"; +import "../Shaders/meshUVSpaceRendererCombine.fragment"; + import { MeshBuilder } from "./meshBuilder"; import { PBRMaterial } from ".."; @@ -71,6 +77,7 @@ export class MeshUVSpaceRenderer { * */ _maskTexture: any; + private _seamTexture: any; private static _GetShader(scene: Scene): ShaderMaterial { if (!scene._meshUVSpaceRendererShader) { @@ -174,9 +181,12 @@ export class MeshUVSpaceRenderer { } // Method to use the mask texture to fix UV seams - public renderTexture(texture: BaseTexture, position: Vector3, normal: Vector3, size: Vector3, angle = 0): void { + public async renderTexture(texture: BaseTexture, position: Vector3, normal: Vector3, size: Vector3, angle = 0): void { // Ensure the mask texture is ready for seam fixing - this._createMaskTexture(); + //todo flag + await this._createMaskTexture(); + + this._createSeamTexture(); // Create the diffuse render target texture if it doesn't exist if (!this.texture) { @@ -193,41 +203,62 @@ export class MeshUVSpaceRenderer { plane.material = pbr; pbr.disableLighting = true; + const plane2 = MeshBuilder.CreatePlane("image", {size: 1}, this._scene); + const pbr2 = new PBRMaterial("P2", this._scene); + pbr2.roughness = 1; + pbr2.emissiveTexture = this._seamTexture; + pbr2.emissiveIntensity = 1; + pbr2.emissiveColor = new Color3(1, 1, 1); + pbr2.albedoTexture = this._seamTexture; + plane2.material = pbr2; + pbr2.disableLighting = true; + plane2.position.y -= 1; + // Prepare the shader with the decal texture, mask texture, and necessary uniforms const shader = MeshUVSpaceRenderer._GetShader(this._scene); shader.setTexture("textureSampler", texture); // Decal texture shader.setTexture("maskTexture", this._maskTexture); // Mask texture for seam fixing + shader.setTexture("seamTexture", this._seamTexture); // Mask texture for seam fixing + //todo use this shader.setVector2("texelSize", new Vector2(1.0 / this._options.width, 1.0 / this._options.height)); - - - // const plane2 = MeshBuilder.CreateSphere("image", {diameter:0.2}, this._scene); - // const pbr2 = new PBRMaterial("P", this._scene); - // pbr2.roughness = 1; - // // pbr2.emissiveTexture = this._maskTexture; - // // pbr2.emissiveIntensity = 1; - // // pbr2.emissiveColor = new Color3(1, 1, 1); - // // pbr2.albedoTexture = this._maskTexture; - // plane2.material = shader; - // pbr2.disableLighting = true; - - // Calculate and set the projection matrix const projectionMatrix = this._createProjectionMatrix(position, normal, size, angle); shader.setMatrix("projMatrix", projectionMatrix); - + // this.texture = this._maskTexture; // Render the decal with the updated material that includes seam fix logic if (MeshUVSpaceRenderer._IsRenderTargetTexture(this.texture)) { this.texture.render(); } } + private combineTextures(t1: RenderTargetTexture, t2: RenderTargetTexture): void { + const shaderMaterial = new ShaderMaterial("shaderMaterial", this._scene, { + vertex: "custom", // Replace with your vertex shader path or string + fragment: "custom", // Replace with your fragment shader path or string + }, { + attributes: ["position", "uv"], + uniforms: ["worldViewProjection", "texture1", "texture2", "blendFactor"] + }); + + // Assign textures + shaderMaterial.setTexture("texture1", t1); + shaderMaterial.setTexture("texture2", t2); + + // Set blend factor (0.0 to 1.0) + shaderMaterial.setFloat("blendFactor", 0.5); + + // Create a plane and apply the material + const plane = MeshBuilder.CreatePlane("plane", {size: 1}, this._scene); + plane.material = shaderMaterial; + } + private _createMaskTexture(): void { if (this._maskTexture) { return; // Mask texture already created - } - + } try { + this._scene.clearColor = new Color4(0,0,0,1); // Create a new render target texture for the mask this._maskTexture = new RenderTargetTexture( @@ -236,7 +267,7 @@ export class MeshUVSpaceRenderer { this._scene, false, // No mipmaps for the mask texture true, - this._options.textureType + Constants.TEXTURETYPE_FLOAT ); // Set up the mask material @@ -252,13 +283,9 @@ export class MeshUVSpaceRenderer { uniforms: ["worldViewProjection"] } ); - - // Save the original material of the mesh - const originalMaterial = this._mesh.material; + this._mesh.material = this._mesh.material as PBRMaterial; - maskMaterial.setTexture("textureSampler", this._mesh.material.albedoTexture); maskMaterial.backFaceCulling = false; - // Render the mesh with the mask material to the mask texture this._maskTexture.renderList.push(this._mesh); @@ -267,14 +294,55 @@ export class MeshUVSpaceRenderer { // Ensure the mask texture is updated this._maskTexture.refreshRate = RenderTargetTexture.REFRESHRATE_RENDER_ONCE; this._scene.customRenderTargets.push(this._maskTexture); - return this._maskTexture; - + Promise.resolve(); } catch (error) { console.error("Error creating mask texture:", error); } } + + private _createSeamTexture(): void { + if (this._seamTexture) { + return; // Seam texture already created + } + try { + this._scene.clearColor = new Color4(0,0,0,1); + // Create a new render target texture for the mask + this._seamTexture = new RenderTargetTexture( + "seamTexture", + { width: this._options.width, height: this._options.height }, + this._scene, + false, // No mipmaps for the mask texture + true, + this._options.textureType + ); - + // Set up the mask material + const maskMaterial = new ShaderMaterial( + "meshUVSpaceRendererSeamShader", + this._scene, + { + vertex: "meshUVSpaceRendererMasker", + fragment: "meshUVSpaceRendererSeam", + }, + { + attributes: ["position", "uv"], + uniforms: ["worldViewProjection"], + samplers: ["maskTexture"] + } + ); + maskMaterial.setTexture("maskTexture", this._maskTexture); + + maskMaterial.backFaceCulling = false; + // Render the mesh with the mask material to the mask texture + this._seamTexture.renderList.push(this._mesh); + this._seamTexture.setMaterialForRendering(this._mesh, maskMaterial); + // Ensure the mask texture is updated + this._seamTexture.refreshRate = RenderTargetTexture.REFRESHRATE_RENDER_ONCE; + this._scene.customRenderTargets.push(this._seamTexture); + } catch (error) { + console.error("Error creating mask texture:", error); + } + } /** * Clears the texture map diff --git a/packages/dev/core/src/Shaders/meshUVSpaceRenderer.fragment.fx b/packages/dev/core/src/Shaders/meshUVSpaceRenderer.fragment.fx index 85ff0a8c758..21b24311b10 100644 --- a/packages/dev/core/src/Shaders/meshUVSpaceRenderer.fragment.fx +++ b/packages/dev/core/src/Shaders/meshUVSpaceRenderer.fragment.fx @@ -7,12 +7,8 @@ uniform sampler2D textureSampler; // The main texture sampler for decals uniform sampler2D maskTexture; // The mask texture for seams void main(void) { - if (vDecalTC.x < 0. || vDecalTC.x > 1. || vDecalTC.y < 0. || vDecalTC.y > 1.) { - discard; // Discard fragment outside of the decal texture coordinates - } - // Hard-coded texel size for a 1024x1024 texture - vec2 texelSize = vec2(4.0 / 1024.0, 4.0 / 1024.0); + vec2 texelSize = vec2(1.0 / 1024.0, 1.0 / 1024.0); // Sample the center pixel and surrounding pixels from the mask texture float centerPixel = texture2D(maskTexture, vUV).r; @@ -22,7 +18,7 @@ void main(void) { float bottomPixel = texture2D(maskTexture, vUV - vec2(0.0, texelSize.y)).r; // Check if the current pixel is near a seam - bool nearSeam = centerPixel > 0.5 && (rightPixel < 0.5 || leftPixel < 0.5 || topPixel < 0.5 || bottomPixel < 0.5); + bool nearSeam = centerPixel >= 0.5 && (rightPixel < 0.5 || leftPixel < 0.5 || topPixel < 0.5 || bottomPixel < 0.5); // Sample the decal texture vec4 decalColor = texture2D(textureSampler, vDecalTC); @@ -30,11 +26,10 @@ void main(void) { // Determine if the pixel is part of a decal (non-transparent pixel in the decal texture) bool isDecal = decalColor.a > 0.5; - // If the pixel is part of a decal and near a seam, draw the green line + // Apply edge bleeding if (isDecal && nearSeam) { gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0); // Draw green line over the seam } else { - // Otherwise, render the decal color gl_FragColor = decalColor; } } diff --git a/packages/dev/core/src/Shaders/meshUVSpaceRenderer.vertex.fx b/packages/dev/core/src/Shaders/meshUVSpaceRenderer.vertex.fx index 9ae326f237c..0a6afb2e0c1 100644 --- a/packages/dev/core/src/Shaders/meshUVSpaceRenderer.vertex.fx +++ b/packages/dev/core/src/Shaders/meshUVSpaceRenderer.vertex.fx @@ -7,7 +7,7 @@ attribute vec2 uv; uniform mat4 projMatrix; varying vec2 vDecalTC; -varying vec2 vUV; +varying highp vec2 vUV; #include diff --git a/packages/dev/core/src/Shaders/meshUVSpaceRendererCombine.fragment.fx b/packages/dev/core/src/Shaders/meshUVSpaceRendererCombine.fragment.fx new file mode 100644 index 00000000000..7be8bec9036 --- /dev/null +++ b/packages/dev/core/src/Shaders/meshUVSpaceRendererCombine.fragment.fx @@ -0,0 +1,22 @@ +// Simple fragment shader to blend two textures +precision highp float; + +// Varying: received from the vertex shader +varying vec2 vUV; + +// Uniforms: the two textures and the blend factor +uniform sampler2D texture1; +uniform sampler2D texture2; +uniform float blendFactor; // Ranges from 0.0 (only texture1) to 1.0 (only texture2) + +void main(void) { + // Sample the pixel from both textures + vec4 color1 = texture2D(texture1, vUV); + vec4 color2 = texture2D(texture2, vUV); + + // Linearly interpolate between the two textures based on the blendFactor + vec4 blendedColor = mix(color1, color2, blendFactor); + + // Set the final color + gl_FragColor = blendedColor; +} diff --git a/packages/dev/core/src/Shaders/meshUVSpaceRendererCombine.vertex.fx b/packages/dev/core/src/Shaders/meshUVSpaceRendererCombine.vertex.fx new file mode 100644 index 00000000000..74cf5a1d418 --- /dev/null +++ b/packages/dev/core/src/Shaders/meshUVSpaceRendererCombine.vertex.fx @@ -0,0 +1,17 @@ +// Simple vertex shader +precision highp float; + +// Attributes +attribute vec3 position; +attribute vec2 uv; + +// Uniforms +uniform mat4 worldViewProjection; + +// Varying: will be passed to the fragment shader +varying vec2 vUV; + +void main(void) { + gl_Position = worldViewProjection * vec4(position, 1.0); + vUV = uv; +} \ No newline at end of file diff --git a/packages/dev/core/src/Shaders/meshUVSpaceRendererMasker.fragment.fx b/packages/dev/core/src/Shaders/meshUVSpaceRendererMasker.fragment.fx index ea74551c041..35fcf6e926f 100644 --- a/packages/dev/core/src/Shaders/meshUVSpaceRendererMasker.fragment.fx +++ b/packages/dev/core/src/Shaders/meshUVSpaceRendererMasker.fragment.fx @@ -9,12 +9,5 @@ varying vec2 vUV; void main(void) { - // Check if the UV coordinates are within the 0 to 1 range - if (vUV.x >= 0.0 && vUV.x <= 1.0 && vUV.y >= 0.0 && vUV.y <= 1.0) { - // If inside the UV range, draw white - gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0); - } else { - // If outside the UV range, draw black - gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); - } + gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0); } diff --git a/packages/dev/core/src/Shaders/meshUVSpaceRendererSeam.fragment.fx b/packages/dev/core/src/Shaders/meshUVSpaceRendererSeam.fragment.fx new file mode 100644 index 00000000000..f8b3e1f171a --- /dev/null +++ b/packages/dev/core/src/Shaders/meshUVSpaceRendererSeam.fragment.fx @@ -0,0 +1,46 @@ +precision highp float; + +varying vec2 vUV; + +uniform sampler2D maskTexture; // The mask texture for seams + +void main(void) { + + // Hard-coded texel size for a 1024x1024 texture + vec2 texelSize = vec2(1.0 / 1024.0, 1.0 / 1024.0); + + // Sample the center pixel and surrounding pixels + float centerPixel = texture2D(maskTexture, vUV).r; + float rightPixel = texture2D(maskTexture, vUV + vec2(texelSize.x, 0.0)).r; + float leftPixel = texture2D(maskTexture, vUV - vec2(texelSize.x, 0.0)).r; + float topPixel = texture2D(maskTexture, vUV + vec2(0.0, texelSize.y)).r; + float bottomPixel = texture2D(maskTexture, vUV - vec2(0.0, texelSize.y)).r; + + // Sample the corner pixels + float topLeftPixel = texture2D(maskTexture, vUV + vec2(-texelSize.x, texelSize.y)).r; + float topRightPixel = texture2D(maskTexture, vUV + vec2(texelSize.x, texelSize.y)).r; + float bottomLeftPixel = texture2D(maskTexture, vUV + vec2(-texelSize.x, -texelSize.y)).r; + float bottomRightPixel = texture2D(maskTexture, vUV + vec2(texelSize.x, -texelSize.y)).r; + + // Detect edges by checking if the center pixel is white but at least one of the neighbors is not + if (centerPixel > 0.5 && (rightPixel < 0.5 || leftPixel < 0.5 || topPixel < 0.5 || bottomPixel < 0.5 || topLeftPixel < 0.5 || topRightPixel < 0.5 || bottomLeftPixel < 0.5 || bottomRightPixel < 0.5)) { + // Current pixel is on the edge of a UV island + gl_FragColor = vec4(1.0, 1.0, 0.0, 1.0); // YELLOW + } else { + // Current pixel is not on the edge of a UV island + gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0); // GRN + } + + // Add padding to the edge of the UV island + vec2 offsets[4]; + offsets[0] = vec2(texelSize.x, 0.0); // right + offsets[1] = vec2(-texelSize.x, 0.0); // left + offsets[2] = vec2(0.0, texelSize.y); // top + offsets[3] = vec2(0.0, -texelSize.y); // bottom + + for (int i = 0; i < 4; i++) { + if (texture2D(maskTexture, vUV + offsets[i]).r < 0.1 && texture2D(maskTexture, vUV).r > 0.1) { + gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); // RED + } + } +} From a49d264b6cde08bbea7ef2f9cf2198fcdc2dd156 Mon Sep 17 00:00:00 2001 From: machine <@baktrian> Date: Sun, 3 Dec 2023 16:40:15 +0000 Subject: [PATCH 06/21] revert main shaders, introduce final texture composed of decal and mask + beginning of blending --- .../core/src/Meshes/meshUVSpaceRenderer.ts | 88 ++++++++++++++----- .../Shaders/meshUVSpaceRenderer.fragment.fx | 47 +--------- .../src/Shaders/meshUVSpaceRenderer.vertex.fx | 6 +- .../meshUVSpaceRendererFinaliser.fragment.fx | 7 ++ .../meshUVSpaceRendererFinaliser.vertex.fx | 8 ++ 5 files changed, 88 insertions(+), 68 deletions(-) create mode 100644 packages/dev/core/src/Shaders/meshUVSpaceRendererFinaliser.fragment.fx create mode 100644 packages/dev/core/src/Shaders/meshUVSpaceRendererFinaliser.vertex.fx diff --git a/packages/dev/core/src/Meshes/meshUVSpaceRenderer.ts b/packages/dev/core/src/Meshes/meshUVSpaceRenderer.ts index ff103218750..5db27603c13 100644 --- a/packages/dev/core/src/Meshes/meshUVSpaceRenderer.ts +++ b/packages/dev/core/src/Meshes/meshUVSpaceRenderer.ts @@ -1,3 +1,4 @@ +//@ts-nocheck import type { Texture } from "core/Materials/Textures/texture"; import type { Vector3 } from "core/Maths/math.vector"; import type { Scene } from "core/scene"; @@ -5,19 +6,23 @@ import type { AbstractMesh } from "./abstractMesh"; import type { ThinTexture } from "core/Materials/Textures/thinTexture"; import type { BaseTexture } from "core/Materials/Textures/baseTexture"; import type { Nullable } from "core/types"; -import { Matrix, Vector2 } from "core/Maths/math.vector"; +import { Matrix } from "core/Maths/math.vector"; import { Constants } from "core/Engines/constants"; import { ShaderMaterial } from "core/Materials/shaderMaterial"; import { RenderTargetTexture } from "core/Materials/Textures/renderTargetTexture"; -import { Color3, Color4 } from "core/Maths/math.color"; +import { Color4 } from "core/Maths/math.color"; import "../Shaders/meshUVSpaceRenderer.vertex"; import "../Shaders/meshUVSpaceRenderer.fragment"; import "../Shaders/meshUVSpaceRendererMasker.vertex"; import "../Shaders/meshUVSpaceRendererMasker.fragment"; -import { MeshBuilder } from "./meshBuilder"; -import { PBRMaterial } from ".."; + +import "../Shaders/meshUVSpaceRendererFinaliser.fragment"; +import "../Shaders/meshUVSpaceRendererFinaliser.vertex"; +// import { MeshBuilder } from "./meshBuilder"; +import type { PBRMaterial} from ".."; +// import { TextureFormat } from ".."; declare module "../scene" { @@ -71,6 +76,10 @@ export class MeshUVSpaceRenderer { * */ _maskTexture: any; + /** + * + */ + _finalTexture: any; private static _GetShader(scene: Scene): ShaderMaterial { if (!scene._meshUVSpaceRendererShader) { @@ -176,7 +185,7 @@ export class MeshUVSpaceRenderer { // Method to use the mask texture to fix UV seams public renderTexture(texture: BaseTexture, position: Vector3, normal: Vector3, size: Vector3, angle = 0): void { // Create the diffuse render target texture if it doesn't exist - if (!this.texture) { + if (!this.decalTexture) { this._createDiffuseRTT(); } @@ -197,8 +206,6 @@ export class MeshUVSpaceRenderer { const shader = MeshUVSpaceRenderer._GetShader(this._scene); shader.setTexture("textureSampler", texture); // Decal texture shader.setTexture("maskTexture", this._maskTexture); // Mask texture for seam fixing - shader.setVector2("texelSize", new Vector2(1.0 / this._options.width, 1.0 / this._options.height)); - // const plane2 = MeshBuilder.CreateSphere("image", {diameter:0.2}, this._scene); @@ -210,16 +217,17 @@ export class MeshUVSpaceRenderer { // // pbr2.albedoTexture = this._maskTexture; // plane2.material = shader; // pbr2.disableLighting = true; - + // this.finalTexture = // Calculate and set the projection matrix const projectionMatrix = this._createProjectionMatrix(position, normal, size, angle); shader.setMatrix("projMatrix", projectionMatrix); - // Render the decal with the updated material that includes seam fix logic - if (MeshUVSpaceRenderer._IsRenderTargetTexture(this.texture)) { - this.texture.render(); + if (MeshUVSpaceRenderer._IsRenderTargetTexture(this.decalTexture)) { + this.decalTexture.render(); } + + this._createFinalTexture(); } private _createMaskTexture(): void { @@ -236,7 +244,8 @@ export class MeshUVSpaceRenderer { this._scene, false, // No mipmaps for the mask texture true, - this._options.textureType + Constants.TEXTURETYPE_UNSIGNED_BYTE, + false, undefined, undefined, undefined, undefined, Constants.TEXTUREFORMAT_R ); // Set up the mask material @@ -252,9 +261,7 @@ export class MeshUVSpaceRenderer { uniforms: ["worldViewProjection"] } ); - - // Save the original material of the mesh - const originalMaterial = this._mesh.material; + this._mesh.material = this._mesh.material as PBRMaterial; maskMaterial.setTexture("textureSampler", this._mesh.material.albedoTexture); maskMaterial.backFaceCulling = false; @@ -272,8 +279,51 @@ export class MeshUVSpaceRenderer { console.error("Error creating mask texture:", error); } } + + private _createFinalTexture(): void { + if (!this.texture) { + this.texture = new RenderTargetTexture( + "finalTexture", + { width: this._options.width, height: this._options.height }, + this._scene, + false, + true, + this._options.textureType + ); + } + + try { + this._scene.clearColor = new Color4(0,0,0,1); + // Set up the mask material + const maskMaterial = new ShaderMaterial( + "meshUVSpaceRendererFinaliserShader", + this._scene, + { + vertex: "meshUVSpaceRendererFinaliser", + fragment: "meshUVSpaceRendererFinaliser", + }, + { + attributes: ["position", "uv"], + uniforms: ["worldViewProjection"], + samplers: ["decalTexture", "maskTexture"] + } + ); + + this._mesh.material = this._mesh.material as PBRMaterial; + maskMaterial.setTexture("decalTexture", this.texture); + maskMaterial.setTexture("maskTexture", this._maskTexture); + maskMaterial.backFaceCulling = false; - + this.texture.renderList.push(this._mesh); + this.texture.setMaterialForRendering(this._mesh, maskMaterial); + + // Ensure the mask texture is updated + this._scene.customRenderTargets.push(this.texture); + this.texture.render(); + } catch (error) { + console.error("Error creating mask texture:", error); + } + } /** * Clears the texture map @@ -296,9 +346,7 @@ export class MeshUVSpaceRenderer { this.texture.dispose(); this._textureCreatedInternally = false; } - } - - + } private _createDiffuseRTT(): void { this._textureCreatedInternally = true; @@ -307,7 +355,7 @@ export class MeshUVSpaceRenderer { texture.setMaterialForRendering(this._mesh, MeshUVSpaceRenderer._GetShader(this._scene)); - this.texture = texture; + this.decalTexture = texture; } private _createRenderTargetTexture(width: number, height: number): RenderTargetTexture { diff --git a/packages/dev/core/src/Shaders/meshUVSpaceRenderer.fragment.fx b/packages/dev/core/src/Shaders/meshUVSpaceRenderer.fragment.fx index 2f980b877fc..32b6b56890c 100644 --- a/packages/dev/core/src/Shaders/meshUVSpaceRenderer.fragment.fx +++ b/packages/dev/core/src/Shaders/meshUVSpaceRenderer.fragment.fx @@ -1,52 +1,13 @@ precision highp float; varying vec2 vDecalTC; -varying vec2 vUV; uniform sampler2D textureSampler; -uniform sampler2D maskTexture; // Uniform for the mask texture -uniform vec2 texelSize; // Uniform for the texel size void main(void) { - // Sample the texture color - vec4 textureColor = texture2D(textureSampler, vDecalTC); - vec4 maskColour = texture2D(maskTexture, vDecalTC); - // Sample the mask texture to determine border status - float maskValue = texture2D(maskTexture, vUV).r; - // gl_FragColor = vec4(maskValue, maskValue, maskValue, 1.0); - // gl_FragColor = maskColour; - // If we are within the UV borders, use the original color - if (maskValue > 0.5) { - gl_FragColor = maskColour; - } else { - gl_FragColor = textureColor; - - // vec4 colorSum = vec4(0.0); - // float totalWeight = 0.0; - - // // Offset for neighboring texel coordinates - // vec2 offsets[4] = vec2[](vec2(-texelSize.x, 0.0), vec2(texelSize.x, 0.0), vec2(0.0, -texelSize.y), vec2(0.0, texelSize.y)); - - // // Sample neighboring texels - // for (int i = 0; i < 4; i++) { - // vec2 neighborUV = vDecalTC + offsets[i]; - // float neighborMaskValue = texture2D(maskTexture, neighborUV).r; - // if (neighborMaskValue > 0.5) { - // colorSum += texture2D(textureSampler, neighborUV); - // totalWeight += 1.0; - // } - // } - // gl_FragColor = colorSum / totalWeight; - - // // Only average if we have valid neighbors - // if (totalWeight > 0.0) { - // gl_FragColor = colorSum / totalWeight; - // } else { - // // Use the background color or discard the fragment - // // gl_FragColor = backgroundColor; // Define a background color if needed - // discard; - // } - // gl_FragColor = maskColour; - // gl_FragColor = maskColour; + if (vDecalTC.x < 0. || vDecalTC.x > 1. || vDecalTC.y < 0. || vDecalTC.y > 1.) { + discard; } + + gl_FragColor = texture2D(textureSampler, vDecalTC); } \ No newline at end of file diff --git a/packages/dev/core/src/Shaders/meshUVSpaceRenderer.vertex.fx b/packages/dev/core/src/Shaders/meshUVSpaceRenderer.vertex.fx index 9ae326f237c..8f62ed25e4a 100644 --- a/packages/dev/core/src/Shaders/meshUVSpaceRenderer.vertex.fx +++ b/packages/dev/core/src/Shaders/meshUVSpaceRenderer.vertex.fx @@ -7,8 +7,6 @@ attribute vec2 uv; uniform mat4 projMatrix; varying vec2 vDecalTC; -varying vec2 vUV; - #include #include @@ -18,7 +16,6 @@ varying vec2 vUV; #include - void main(void) { vec3 positionUpdated = position; vec3 normalUpdated = normal; @@ -51,7 +48,6 @@ void main(void) { vec3 decalTC = (projMatrix * worldPos).xyz; vDecalTC = decalTC.xy; - vUV = uv; gl_Position = vec4(uv * 2.0 - 1.0, normalView.z > 0.0 ? 2. : decalTC.z, 1.0); -} +} \ No newline at end of file diff --git a/packages/dev/core/src/Shaders/meshUVSpaceRendererFinaliser.fragment.fx b/packages/dev/core/src/Shaders/meshUVSpaceRendererFinaliser.fragment.fx new file mode 100644 index 00000000000..f144431572c --- /dev/null +++ b/packages/dev/core/src/Shaders/meshUVSpaceRendererFinaliser.fragment.fx @@ -0,0 +1,7 @@ + +uniform sampler2D decalSampler; +uniform sampler2D maskSampler; + +void main() { + gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); +} \ No newline at end of file diff --git a/packages/dev/core/src/Shaders/meshUVSpaceRendererFinaliser.vertex.fx b/packages/dev/core/src/Shaders/meshUVSpaceRendererFinaliser.vertex.fx new file mode 100644 index 00000000000..88d8bd384b4 --- /dev/null +++ b/packages/dev/core/src/Shaders/meshUVSpaceRendererFinaliser.vertex.fx @@ -0,0 +1,8 @@ +attribute vec2 uv; + +varying vec2 vUV; + +void main(void) { + gl_Position = vec4(vec2(uv.x, uv.y) * 2.0 - 1.0, 0., 1.0); + vUV = uv; +} \ No newline at end of file From cc92a0a87cf67d90771a9bd946b0a12dad2ab67c Mon Sep 17 00:00:00 2001 From: machine <@baktrian> Date: Sun, 3 Dec 2023 17:14:42 +0000 Subject: [PATCH 07/21] remove unnecessary --- .../core/src/Meshes/meshUVSpaceRenderer.ts | 100 ++++++------------ 1 file changed, 34 insertions(+), 66 deletions(-) diff --git a/packages/dev/core/src/Meshes/meshUVSpaceRenderer.ts b/packages/dev/core/src/Meshes/meshUVSpaceRenderer.ts index 1cdafdcccd0..c99dc30525e 100644 --- a/packages/dev/core/src/Meshes/meshUVSpaceRenderer.ts +++ b/packages/dev/core/src/Meshes/meshUVSpaceRenderer.ts @@ -1,4 +1,3 @@ -//@ts-nocheck import type { Texture } from "core/Materials/Textures/texture"; import type { Vector3 } from "core/Maths/math.vector"; import type { Scene } from "core/scene"; @@ -10,7 +9,7 @@ import { Matrix } from "core/Maths/math.vector"; import { Constants } from "core/Engines/constants"; import { ShaderMaterial } from "core/Materials/shaderMaterial"; import { RenderTargetTexture } from "core/Materials/Textures/renderTargetTexture"; -import { Color4 } from "core/Maths/math.color"; +import { Color3, Color4 } from "core/Maths/math.color"; import "../Shaders/meshUVSpaceRenderer.vertex"; import "../Shaders/meshUVSpaceRenderer.fragment"; @@ -21,7 +20,7 @@ import "../Shaders/meshUVSpaceRendererMasker.fragment"; import "../Shaders/meshUVSpaceRendererFinaliser.fragment"; import "../Shaders/meshUVSpaceRendererFinaliser.vertex"; // import { MeshBuilder } from "./meshBuilder"; -import { PBRMaterial} from ".."; +import { Material, MeshBuilder, PBRMaterial} from ".."; // import { TextureFormat } from ".."; @@ -80,6 +79,7 @@ export class MeshUVSpaceRenderer { * */ _finalTexture: any; + decalTexture: any; private static _GetShader(scene: Scene): ShaderMaterial { if (!scene._meshUVSpaceRendererShader) { @@ -166,21 +166,6 @@ export class MeshUVSpaceRenderer { * @param size The size of the projection * @param angle The rotation angle around the direction of the projection */ - public renderTextureOLD(texture: BaseTexture, position: Vector3, normal: Vector3, size: Vector3, angle = 0): void { - if (!this.texture) { - this._createDiffuseRTT(); - } - - if (MeshUVSpaceRenderer._IsRenderTargetTexture(this.texture)) { - const matrix = this._createProjectionMatrix(position, normal, size, angle); - const shader = MeshUVSpaceRenderer._GetShader(this._scene); - - shader.setTexture("textureSampler", texture); - shader.setMatrix("projMatrix", matrix); - - this.texture.render(); - } - } // Method to use the mask texture to fix UV seams public async renderTexture(texture: BaseTexture, position: Vector3, normal: Vector3, size: Vector3, angle = 0): void { @@ -188,50 +173,24 @@ export class MeshUVSpaceRenderer { //todo flag await this._createMaskTexture(); - this._createSeamTexture(); - // Create the diffuse render target texture if it doesn't exist if (!this.decalTexture) { this._createDiffuseRTT(); } - const plane = MeshBuilder.CreatePlane("image", {size: 1}, this._scene); - const pbr = new PBRMaterial("P", this._scene); - pbr.roughness = 1; - pbr.emissiveTexture = this._maskTexture; - pbr.emissiveIntensity = 1; - pbr.emissiveColor = new Color3(1, 1, 1); - pbr.albedoTexture = this._maskTexture; - plane.material = pbr; - pbr.disableLighting = true; - - const plane2 = MeshBuilder.CreatePlane("image", {size: 1}, this._scene); - const pbr2 = new PBRMaterial("P2", this._scene); - pbr2.roughness = 1; - pbr2.emissiveTexture = this._seamTexture; - pbr2.emissiveIntensity = 1; - pbr2.emissiveColor = new Color3(1, 1, 1); - pbr2.albedoTexture = this._seamTexture; - plane2.material = pbr2; - pbr2.disableLighting = true; - plane2.position.y -= 1; - - // Prepare the shader with the decal texture, mask texture, and necessary uniforms + // const plane = MeshBuilder.CreatePlane("image", {size: 1}, this._scene); + // const pbr = new PBRMaterial("P", this._scene); + // pbr.roughness = 1; + // pbr.emissiveTexture = this._maskTexture; + // pbr.emissiveIntensity = 1; + // pbr.emissiveColor = new Color3(1, 1, 1); + // pbr.albedoTexture = this._maskTexture; + // plane.material = pbr; + // pbr.disableLighting = true; + + // // Prepare the shader with the decal texture, mask texture, and necessary uniforms const shader = MeshUVSpaceRenderer._GetShader(this._scene); shader.setTexture("textureSampler", texture); // Decal texture - shader.setTexture("maskTexture", this._maskTexture); // Mask texture for seam fixing - - - // const plane2 = MeshBuilder.CreateSphere("image", {diameter:0.2}, this._scene); - // const pbr2 = new PBRMaterial("P", this._scene); - // pbr2.roughness = 1; - // // pbr2.emissiveTexture = this._maskTexture; - // // pbr2.emissiveIntensity = 1; - // // pbr2.emissiveColor = new Color3(1, 1, 1); - // // pbr2.albedoTexture = this._maskTexture; - // plane2.material = shader; - // pbr2.disableLighting = true; - // this.finalTexture = // Calculate and set the projection matrix const projectionMatrix = this._createProjectionMatrix(position, normal, size, angle); @@ -328,9 +287,9 @@ export class MeshUVSpaceRenderer { this._options.textureType ); } - + try { - this._scene.clearColor = new Color4(0,0,0,1); + this._scene.clearColor = new Color4(0, 0, 0, 1); // Set up the mask material const maskMaterial = new ShaderMaterial( "meshUVSpaceRendererFinaliserShader", @@ -341,26 +300,35 @@ export class MeshUVSpaceRenderer { }, { attributes: ["position", "uv"], - uniforms: ["worldViewProjection"], + // uniforms: ["worldViewProjection"], samplers: ["decalTexture", "maskTexture"] } ); - this._mesh.material = this._mesh.material as PBRMaterial; - maskMaterial.setTexture("decalTexture", this.texture); + // this._mesh.material = this._mesh.material as PBRMaterial; + maskMaterial.setTexture("decalTexture", this.decalTexture); maskMaterial.setTexture("maskTexture", this._maskTexture); maskMaterial.backFaceCulling = false; - - this.texture.renderList.push(this._mesh); - this.texture.setMaterialForRendering(this._mesh, maskMaterial); + // Ensure the mask texture is updated - this._scene.customRenderTargets.push(this.texture); - this.texture.render(); + // this._scene.customRenderTargets.push(this.texture); + if (MeshUVSpaceRenderer._IsRenderTargetTexture(this.texture)) { + this.texture.render(); + } + const plane = MeshBuilder.CreatePlane("image", {size: 1}, this._scene); + const pbr = new PBRMaterial("P", this._scene); + pbr.roughness = 1; + pbr.emissiveTexture = this.texture; + pbr.emissiveIntensity = 1; + pbr.emissiveColor = new Color3(1, 1, 1); + pbr.albedoTexture = this.texture; + plane.material = pbr; + pbr.disableLighting = true; } catch (error) { console.error("Error creating mask texture:", error); } - } + } /** * Clears the texture map From 44806650decf5a4b24a874c0a9aaabc6fe8c0aac Mon Sep 17 00:00:00 2001 From: machine <@baktrian> Date: Sun, 3 Dec 2023 17:17:38 +0000 Subject: [PATCH 08/21] delete unnecessary --- .../core/src/Meshes/meshUVSpaceRenderer.ts | 4 ++ .../meshUVSpaceRendererCombine.fragment.fx | 22 --------- .../meshUVSpaceRendererCombine.vertex.fx | 17 ------- .../meshUVSpaceRendererSeam.fragment.fx | 46 ------------------- 4 files changed, 4 insertions(+), 85 deletions(-) delete mode 100644 packages/dev/core/src/Shaders/meshUVSpaceRendererCombine.fragment.fx delete mode 100644 packages/dev/core/src/Shaders/meshUVSpaceRendererCombine.vertex.fx delete mode 100644 packages/dev/core/src/Shaders/meshUVSpaceRendererSeam.fragment.fx diff --git a/packages/dev/core/src/Meshes/meshUVSpaceRenderer.ts b/packages/dev/core/src/Meshes/meshUVSpaceRenderer.ts index c99dc30525e..bbd69f5d800 100644 --- a/packages/dev/core/src/Meshes/meshUVSpaceRenderer.ts +++ b/packages/dev/core/src/Meshes/meshUVSpaceRenderer.ts @@ -79,6 +79,10 @@ export class MeshUVSpaceRenderer { * */ _finalTexture: any; + + /** + * + */ decalTexture: any; private static _GetShader(scene: Scene): ShaderMaterial { diff --git a/packages/dev/core/src/Shaders/meshUVSpaceRendererCombine.fragment.fx b/packages/dev/core/src/Shaders/meshUVSpaceRendererCombine.fragment.fx deleted file mode 100644 index 7be8bec9036..00000000000 --- a/packages/dev/core/src/Shaders/meshUVSpaceRendererCombine.fragment.fx +++ /dev/null @@ -1,22 +0,0 @@ -// Simple fragment shader to blend two textures -precision highp float; - -// Varying: received from the vertex shader -varying vec2 vUV; - -// Uniforms: the two textures and the blend factor -uniform sampler2D texture1; -uniform sampler2D texture2; -uniform float blendFactor; // Ranges from 0.0 (only texture1) to 1.0 (only texture2) - -void main(void) { - // Sample the pixel from both textures - vec4 color1 = texture2D(texture1, vUV); - vec4 color2 = texture2D(texture2, vUV); - - // Linearly interpolate between the two textures based on the blendFactor - vec4 blendedColor = mix(color1, color2, blendFactor); - - // Set the final color - gl_FragColor = blendedColor; -} diff --git a/packages/dev/core/src/Shaders/meshUVSpaceRendererCombine.vertex.fx b/packages/dev/core/src/Shaders/meshUVSpaceRendererCombine.vertex.fx deleted file mode 100644 index 74cf5a1d418..00000000000 --- a/packages/dev/core/src/Shaders/meshUVSpaceRendererCombine.vertex.fx +++ /dev/null @@ -1,17 +0,0 @@ -// Simple vertex shader -precision highp float; - -// Attributes -attribute vec3 position; -attribute vec2 uv; - -// Uniforms -uniform mat4 worldViewProjection; - -// Varying: will be passed to the fragment shader -varying vec2 vUV; - -void main(void) { - gl_Position = worldViewProjection * vec4(position, 1.0); - vUV = uv; -} \ No newline at end of file diff --git a/packages/dev/core/src/Shaders/meshUVSpaceRendererSeam.fragment.fx b/packages/dev/core/src/Shaders/meshUVSpaceRendererSeam.fragment.fx deleted file mode 100644 index f8b3e1f171a..00000000000 --- a/packages/dev/core/src/Shaders/meshUVSpaceRendererSeam.fragment.fx +++ /dev/null @@ -1,46 +0,0 @@ -precision highp float; - -varying vec2 vUV; - -uniform sampler2D maskTexture; // The mask texture for seams - -void main(void) { - - // Hard-coded texel size for a 1024x1024 texture - vec2 texelSize = vec2(1.0 / 1024.0, 1.0 / 1024.0); - - // Sample the center pixel and surrounding pixels - float centerPixel = texture2D(maskTexture, vUV).r; - float rightPixel = texture2D(maskTexture, vUV + vec2(texelSize.x, 0.0)).r; - float leftPixel = texture2D(maskTexture, vUV - vec2(texelSize.x, 0.0)).r; - float topPixel = texture2D(maskTexture, vUV + vec2(0.0, texelSize.y)).r; - float bottomPixel = texture2D(maskTexture, vUV - vec2(0.0, texelSize.y)).r; - - // Sample the corner pixels - float topLeftPixel = texture2D(maskTexture, vUV + vec2(-texelSize.x, texelSize.y)).r; - float topRightPixel = texture2D(maskTexture, vUV + vec2(texelSize.x, texelSize.y)).r; - float bottomLeftPixel = texture2D(maskTexture, vUV + vec2(-texelSize.x, -texelSize.y)).r; - float bottomRightPixel = texture2D(maskTexture, vUV + vec2(texelSize.x, -texelSize.y)).r; - - // Detect edges by checking if the center pixel is white but at least one of the neighbors is not - if (centerPixel > 0.5 && (rightPixel < 0.5 || leftPixel < 0.5 || topPixel < 0.5 || bottomPixel < 0.5 || topLeftPixel < 0.5 || topRightPixel < 0.5 || bottomLeftPixel < 0.5 || bottomRightPixel < 0.5)) { - // Current pixel is on the edge of a UV island - gl_FragColor = vec4(1.0, 1.0, 0.0, 1.0); // YELLOW - } else { - // Current pixel is not on the edge of a UV island - gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0); // GRN - } - - // Add padding to the edge of the UV island - vec2 offsets[4]; - offsets[0] = vec2(texelSize.x, 0.0); // right - offsets[1] = vec2(-texelSize.x, 0.0); // left - offsets[2] = vec2(0.0, texelSize.y); // top - offsets[3] = vec2(0.0, -texelSize.y); // bottom - - for (int i = 0; i < 4; i++) { - if (texture2D(maskTexture, vUV + offsets[i]).r < 0.1 && texture2D(maskTexture, vUV).r > 0.1) { - gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); // RED - } - } -} From 516f3c20512d530627a282ad5fec82880ae43f10 Mon Sep 17 00:00:00 2001 From: machine <@baktrian> Date: Sun, 3 Dec 2023 17:45:00 +0000 Subject: [PATCH 09/21] delete unnecessary --- packages/dev/core/src/Meshes/meshUVSpaceRenderer.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/dev/core/src/Meshes/meshUVSpaceRenderer.ts b/packages/dev/core/src/Meshes/meshUVSpaceRenderer.ts index bbd69f5d800..d3d46e4516a 100644 --- a/packages/dev/core/src/Meshes/meshUVSpaceRenderer.ts +++ b/packages/dev/core/src/Meshes/meshUVSpaceRenderer.ts @@ -314,10 +314,11 @@ export class MeshUVSpaceRenderer { maskMaterial.setTexture("maskTexture", this._maskTexture); maskMaterial.backFaceCulling = false; - + // Ensure the mask texture is updated - // this._scene.customRenderTargets.push(this.texture); if (MeshUVSpaceRenderer._IsRenderTargetTexture(this.texture)) { + this._scene.customRenderTargets.push(this.texture); + this.texture.render(); } const plane = MeshBuilder.CreatePlane("image", {size: 1}, this._scene); @@ -330,7 +331,7 @@ export class MeshUVSpaceRenderer { plane.material = pbr; pbr.disableLighting = true; } catch (error) { - console.error("Error creating mask texture:", error); + console.error("Error creating final texture:", error); } } From 7445e4cdd50bbd28597c65b85cf1accd40df2a9d Mon Sep 17 00:00:00 2001 From: machine <@baktrian> Date: Sun, 3 Dec 2023 17:45:11 +0000 Subject: [PATCH 10/21] delete unnecessary --- packages/dev/core/src/Meshes/meshUVSpaceRenderer.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/dev/core/src/Meshes/meshUVSpaceRenderer.ts b/packages/dev/core/src/Meshes/meshUVSpaceRenderer.ts index d3d46e4516a..445caf3a6a0 100644 --- a/packages/dev/core/src/Meshes/meshUVSpaceRenderer.ts +++ b/packages/dev/core/src/Meshes/meshUVSpaceRenderer.ts @@ -315,7 +315,6 @@ export class MeshUVSpaceRenderer { maskMaterial.backFaceCulling = false; - // Ensure the mask texture is updated if (MeshUVSpaceRenderer._IsRenderTargetTexture(this.texture)) { this._scene.customRenderTargets.push(this.texture); From c9cbb31cd8f91f528276544072d4cf71f3b48bcd Mon Sep 17 00:00:00 2001 From: machine <@baktrian> Date: Sun, 3 Dec 2023 17:46:46 +0000 Subject: [PATCH 11/21] update naming --- packages/dev/core/src/Meshes/meshUVSpaceRenderer.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/dev/core/src/Meshes/meshUVSpaceRenderer.ts b/packages/dev/core/src/Meshes/meshUVSpaceRenderer.ts index 445caf3a6a0..9a70dc26463 100644 --- a/packages/dev/core/src/Meshes/meshUVSpaceRenderer.ts +++ b/packages/dev/core/src/Meshes/meshUVSpaceRenderer.ts @@ -295,7 +295,7 @@ export class MeshUVSpaceRenderer { try { this._scene.clearColor = new Color4(0, 0, 0, 1); // Set up the mask material - const maskMaterial = new ShaderMaterial( + const finalMaterial = new ShaderMaterial( "meshUVSpaceRendererFinaliserShader", this._scene, { @@ -310,14 +310,14 @@ export class MeshUVSpaceRenderer { ); // this._mesh.material = this._mesh.material as PBRMaterial; - maskMaterial.setTexture("decalTexture", this.decalTexture); - maskMaterial.setTexture("maskTexture", this._maskTexture); - maskMaterial.backFaceCulling = false; + finalMaterial.setTexture("decalTexture", this.decalTexture); + finalMaterial.setTexture("maskTexture", this._maskTexture); + finalMaterial.backFaceCulling = false; if (MeshUVSpaceRenderer._IsRenderTargetTexture(this.texture)) { this._scene.customRenderTargets.push(this.texture); - + this.texture.setMaterialForRendering(this._mesh, finalMaterial); this.texture.render(); } const plane = MeshBuilder.CreatePlane("image", {size: 1}, this._scene); From 903ab2d1235bf2a3235dfb1063ac3c61ebdf0863 Mon Sep 17 00:00:00 2001 From: machine <@baktrian> Date: Sun, 3 Dec 2023 17:59:11 +0000 Subject: [PATCH 12/21] enable mesh as renderer --- packages/dev/core/src/Meshes/meshUVSpaceRenderer.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/dev/core/src/Meshes/meshUVSpaceRenderer.ts b/packages/dev/core/src/Meshes/meshUVSpaceRenderer.ts index 9a70dc26463..a2eddfb9462 100644 --- a/packages/dev/core/src/Meshes/meshUVSpaceRenderer.ts +++ b/packages/dev/core/src/Meshes/meshUVSpaceRenderer.ts @@ -260,8 +260,7 @@ export class MeshUVSpaceRenderer { } ); - this._mesh.material = this._mesh.material as PBRMaterial; - maskMaterial.setTexture("textureSampler", this._mesh.material.albedoTexture); + maskMaterial.setTexture("textureSampler", this._mesh.material?.albedoTexture); maskMaterial.backFaceCulling = false; this._mesh.material = this._mesh.material as PBRMaterial; @@ -317,6 +316,7 @@ export class MeshUVSpaceRenderer { if (MeshUVSpaceRenderer._IsRenderTargetTexture(this.texture)) { this._scene.customRenderTargets.push(this.texture); + this.texture.renderList?.push(this._mesh); this.texture.setMaterialForRendering(this._mesh, finalMaterial); this.texture.render(); } From 634e756301b2bbbed272a04b8270a4da9f109702 Mon Sep 17 00:00:00 2001 From: machine <@baktrian> Date: Sun, 3 Dec 2023 18:43:57 +0000 Subject: [PATCH 13/21] configuration --- .../core/src/Meshes/meshUVSpaceRenderer.ts | 32 +++++++++++-------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/packages/dev/core/src/Meshes/meshUVSpaceRenderer.ts b/packages/dev/core/src/Meshes/meshUVSpaceRenderer.ts index a2eddfb9462..aa2abea1f51 100644 --- a/packages/dev/core/src/Meshes/meshUVSpaceRenderer.ts +++ b/packages/dev/core/src/Meshes/meshUVSpaceRenderer.ts @@ -20,7 +20,7 @@ import "../Shaders/meshUVSpaceRendererMasker.fragment"; import "../Shaders/meshUVSpaceRendererFinaliser.fragment"; import "../Shaders/meshUVSpaceRendererFinaliser.vertex"; // import { MeshBuilder } from "./meshBuilder"; -import { Material, MeshBuilder, PBRMaterial} from ".."; +import { Material, Mesh, MeshBuilder, PBRMaterial} from ".."; // import { TextureFormat } from ".."; @@ -313,22 +313,28 @@ export class MeshUVSpaceRenderer { finalMaterial.setTexture("maskTexture", this._maskTexture); finalMaterial.backFaceCulling = false; - + // Create a full-screen quad + const fullScreenQuad = MeshBuilder.CreatePlane("image", { size: 1 }, this._scene); + // fullScreenQuad.scaling.y = -1; // Invert Y for correct UVs + // fullScreenQuad.position.z = 1; // Place it in front of the camera + fullScreenQuad.isPickable = false; // Ensure it does not interfere with scene interaction + fullScreenQuad.setEnabled(true); + // fullScreenQuad.material = finalMaterial; if (MeshUVSpaceRenderer._IsRenderTargetTexture(this.texture)) { this._scene.customRenderTargets.push(this.texture); - this.texture.renderList?.push(this._mesh); - this.texture.setMaterialForRendering(this._mesh, finalMaterial); + this.texture.renderList?.push(fullScreenQuad); + this.texture.setMaterialForRendering(fullScreenQuad, finalMaterial); this.texture.render(); } - const plane = MeshBuilder.CreatePlane("image", {size: 1}, this._scene); - const pbr = new PBRMaterial("P", this._scene); - pbr.roughness = 1; - pbr.emissiveTexture = this.texture; - pbr.emissiveIntensity = 1; - pbr.emissiveColor = new Color3(1, 1, 1); - pbr.albedoTexture = this.texture; - plane.material = pbr; - pbr.disableLighting = true; + // const plane = MeshBuilder.CreatePlane("image", {size: 1}, this._scene); + // const pbr = new PBRMaterial("P", this._scene); + // pbr.roughness = 1; + // pbr.emissiveTexture = this.texture; + // pbr.emissiveIntensity = 1; + // pbr.emissiveColor = new Color3(1, 1, 1); + // pbr.albedoTexture = this.texture; + // plane.material = pbr; + // pbr.disableLighting = true; } catch (error) { console.error("Error creating final texture:", error); } From 19d7a17f2e28360db3b1f45063d7155452d3d2e4 Mon Sep 17 00:00:00 2001 From: machine <@baktrian> Date: Sun, 3 Dec 2023 18:58:25 +0000 Subject: [PATCH 14/21] create v1 of broken shader --- .../core/src/Meshes/meshUVSpaceRenderer.ts | 6 +- .../meshUVSpaceRendererFinaliser.fragment.fx | 55 ++++++++++++++++++- .../meshUVSpaceRendererFinaliser.vertex.fx | 15 ++++- 3 files changed, 67 insertions(+), 9 deletions(-) diff --git a/packages/dev/core/src/Meshes/meshUVSpaceRenderer.ts b/packages/dev/core/src/Meshes/meshUVSpaceRenderer.ts index aa2abea1f51..97d3fa38a46 100644 --- a/packages/dev/core/src/Meshes/meshUVSpaceRenderer.ts +++ b/packages/dev/core/src/Meshes/meshUVSpaceRenderer.ts @@ -304,13 +304,13 @@ export class MeshUVSpaceRenderer { { attributes: ["position", "uv"], // uniforms: ["worldViewProjection"], - samplers: ["decalTexture", "maskTexture"] + samplers: ["decalSampler", "maskSampler"] } ); // this._mesh.material = this._mesh.material as PBRMaterial; - finalMaterial.setTexture("decalTexture", this.decalTexture); - finalMaterial.setTexture("maskTexture", this._maskTexture); + finalMaterial.setTexture("decalSampler", this.decalTexture); + finalMaterial.setTexture("maskSampler", this._maskTexture); finalMaterial.backFaceCulling = false; // Create a full-screen quad diff --git a/packages/dev/core/src/Shaders/meshUVSpaceRendererFinaliser.fragment.fx b/packages/dev/core/src/Shaders/meshUVSpaceRendererFinaliser.fragment.fx index f144431572c..e189ccb48ba 100644 --- a/packages/dev/core/src/Shaders/meshUVSpaceRendererFinaliser.fragment.fx +++ b/packages/dev/core/src/Shaders/meshUVSpaceRendererFinaliser.fragment.fx @@ -1,7 +1,56 @@ +// Fragment shader +precision highp float; -uniform sampler2D decalSampler; -uniform sampler2D maskSampler; +// Varyings +varying vec2 vUV; + +// Uniforms +uniform sampler2D decalSampler; +uniform sampler2D maskSampler; +// uniform vec2 textureSize; void main() { - gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); + vec4 mask = texture2D(maskSampler, vUV).rgba; + + if (mask.r > 0.5) { + gl_FragColor = texture2D(decalSampler, vUV); + } else { + vec2 texelSize = 1.0 / 1024.0; + + vec2 uv_p01 = vUV + vec2(-1.0, 0.0) * texelSize; + vec2 uv_p21 = vUV + vec2(1.0, 0.0) * texelSize; + vec2 uv_p10 = vUV + vec2(0.0, -1.0) * texelSize; + vec2 uv_p12 = vUV + vec2(0.0, 1.0) * texelSize; + + float mask_p01 = texture2D(maskSampler, uv_p01).r; + float mask_p21 = texture2D(maskSampler, uv_p21).r; + float mask_p10 = texture2D(maskSampler, uv_p10).r; + float mask_p12 = texture2D(maskSampler, uv_p12).r; + + vec4 col = vec4(0.0, 0.0, 0.0, 0.0); + float total_weight = 0.0; + + if (mask_p01 > 0.5) { + col += texture2D(decalSampler, uv_p01); + total_weight += 1.0; + } + if (mask_p21 > 0.5) { + col += texture2D(decalSampler, uv_p21); + total_weight += 1.0; + } + if (mask_p10 > 0.5) { + col += texture2D(decalSampler, uv_p10); + total_weight += 1.0; + } + if (mask_p12 > 0.5) { + col += texture2D(decalSampler, uv_p12); + total_weight += 1.0; + } + + if (total_weight > 0.0) { + gl_FragColor = col / total_weight; + } else { + gl_FragColor = col; + } + } } \ No newline at end of file diff --git a/packages/dev/core/src/Shaders/meshUVSpaceRendererFinaliser.vertex.fx b/packages/dev/core/src/Shaders/meshUVSpaceRendererFinaliser.vertex.fx index 88d8bd384b4..e2117c086ba 100644 --- a/packages/dev/core/src/Shaders/meshUVSpaceRendererFinaliser.vertex.fx +++ b/packages/dev/core/src/Shaders/meshUVSpaceRendererFinaliser.vertex.fx @@ -1,8 +1,17 @@ +// Vertex shader +precision highp float; + +// Attributes +attribute vec3 position; attribute vec2 uv; +// Uniforms +uniform mat4 worldViewProjection; + +// Varyings varying vec2 vUV; -void main(void) { - gl_Position = vec4(vec2(uv.x, uv.y) * 2.0 - 1.0, 0., 1.0); +void main() { + gl_Position = worldViewProjection * vec4(position, 1.0); vUV = uv; -} \ No newline at end of file +} From 72de092214bdd4ffd2392f7b0e023aeadefd990c Mon Sep 17 00:00:00 2001 From: machine <@baktrian> Date: Mon, 4 Dec 2023 07:10:56 +0000 Subject: [PATCH 15/21] final texture setup with postprocessing --- .../core/src/Meshes/meshUVSpaceRenderer.ts | 125 +++++++++--------- .../meshUVSpaceRendererFinaliser.fragment.fx | 30 ++--- 2 files changed, 74 insertions(+), 81 deletions(-) diff --git a/packages/dev/core/src/Meshes/meshUVSpaceRenderer.ts b/packages/dev/core/src/Meshes/meshUVSpaceRenderer.ts index 97d3fa38a46..a579b885dc6 100644 --- a/packages/dev/core/src/Meshes/meshUVSpaceRenderer.ts +++ b/packages/dev/core/src/Meshes/meshUVSpaceRenderer.ts @@ -1,11 +1,11 @@ -import type { Texture } from "core/Materials/Textures/texture"; +import { Texture } from "core/Materials/Textures/texture"; import type { Vector3 } from "core/Maths/math.vector"; import type { Scene } from "core/scene"; import type { AbstractMesh } from "./abstractMesh"; import type { ThinTexture } from "core/Materials/Textures/thinTexture"; import type { BaseTexture } from "core/Materials/Textures/baseTexture"; import type { Nullable } from "core/types"; -import { Matrix } from "core/Maths/math.vector"; +import { Matrix, Vector2 } from "core/Maths/math.vector"; import { Constants } from "core/Engines/constants"; import { ShaderMaterial } from "core/Materials/shaderMaterial"; import { RenderTargetTexture } from "core/Materials/Textures/renderTargetTexture"; @@ -20,7 +20,8 @@ import "../Shaders/meshUVSpaceRendererMasker.fragment"; import "../Shaders/meshUVSpaceRendererFinaliser.fragment"; import "../Shaders/meshUVSpaceRendererFinaliser.vertex"; // import { MeshBuilder } from "./meshBuilder"; -import { Material, Mesh, MeshBuilder, PBRMaterial} from ".."; +import type { PBRMaterial} from ".."; +import { Material, Mesh, MeshBuilder, PostProcess} from ".."; // import { TextureFormat } from ".."; @@ -83,7 +84,11 @@ export class MeshUVSpaceRenderer { /** * */ - decalTexture: any; + decalTexture: Texture; + /** + * + */ + finalMaterial: ShaderMaterial; private static _GetShader(scene: Scene): ShaderMaterial { if (!scene._meshUVSpaceRendererShader) { @@ -96,8 +101,8 @@ export class MeshUVSpaceRenderer { }, { attributes: ["position", "normal", "uv"], - uniforms: ["world", "projMatrix", "texelSize"], - samplers: ["textureSampler", "maskTexture"], + uniforms: ["world", "projMatrix"], + samplers: ["textureSampler"], needAlphaBlending: true, } ); @@ -155,11 +160,11 @@ export class MeshUVSpaceRenderer { * @returns true if the texture is ready to be used */ public isReady(): boolean { - if (!this.texture) { + if (!this.decalTexture) { this._createDiffuseRTT(); } - return MeshUVSpaceRenderer._IsRenderTargetTexture(this.texture) ? this.texture.isReadyForRendering() : this.texture.isReady(); + return MeshUVSpaceRenderer._IsRenderTargetTexture(this.decalTexture) ? this.decalTexture.isReadyForRendering() : this.decalTexture.isReady(); } /** @@ -172,7 +177,7 @@ export class MeshUVSpaceRenderer { */ // Method to use the mask texture to fix UV seams - public async renderTexture(texture: BaseTexture, position: Vector3, normal: Vector3, size: Vector3, angle = 0): void { + public async renderTexture(texture: BaseTexture, position: Vector3, normal: Vector3, size: Vector3, angle = 0): Promise { // Ensure the mask texture is ready for seam fixing //todo flag await this._createMaskTexture(); @@ -202,30 +207,8 @@ export class MeshUVSpaceRenderer { if (MeshUVSpaceRenderer._IsRenderTargetTexture(this.decalTexture)) { this.decalTexture.render(); + this._createFinalTexture(); } - - this._createFinalTexture(); - } - - private combineTextures(t1: RenderTargetTexture, t2: RenderTargetTexture): void { - const shaderMaterial = new ShaderMaterial("shaderMaterial", this._scene, { - vertex: "custom", // Replace with your vertex shader path or string - fragment: "custom", // Replace with your fragment shader path or string - }, { - attributes: ["position", "uv"], - uniforms: ["worldViewProjection", "texture1", "texture2", "blendFactor"] - }); - - // Assign textures - shaderMaterial.setTexture("texture1", t1); - shaderMaterial.setTexture("texture2", t2); - - // Set blend factor (0.0 to 1.0) - shaderMaterial.setFloat("blendFactor", 0.5); - - // Create a plane and apply the material - const plane = MeshBuilder.CreatePlane("plane", {size: 1}, this._scene); - plane.material = shaderMaterial; } private _createMaskTexture(): void { @@ -290,11 +273,12 @@ export class MeshUVSpaceRenderer { this._options.textureType ); } - + try { this._scene.clearColor = new Color4(0, 0, 0, 1); - // Set up the mask material - const finalMaterial = new ShaderMaterial( + + // Set up the shader material + this.finalMaterial = new ShaderMaterial( "meshUVSpaceRendererFinaliserShader", this._scene, { @@ -303,53 +287,57 @@ export class MeshUVSpaceRenderer { }, { attributes: ["position", "uv"], - // uniforms: ["worldViewProjection"], - samplers: ["decalSampler", "maskSampler"] + uniforms: ["worldViewProjection", "textureSize"], + samplers: ["textureSampler", "maskTextureSampler"] } ); - - // this._mesh.material = this._mesh.material as PBRMaterial; - finalMaterial.setTexture("decalSampler", this.decalTexture); - finalMaterial.setTexture("maskSampler", this._maskTexture); - finalMaterial.backFaceCulling = false; - - // Create a full-screen quad - const fullScreenQuad = MeshBuilder.CreatePlane("image", { size: 1 }, this._scene); - // fullScreenQuad.scaling.y = -1; // Invert Y for correct UVs - // fullScreenQuad.position.z = 1; // Place it in front of the camera - fullScreenQuad.isPickable = false; // Ensure it does not interfere with scene interaction - fullScreenQuad.setEnabled(true); - // fullScreenQuad.material = finalMaterial; + + this.finalMaterial.setTexture("textureSampler", this.decalTexture); + this.finalMaterial.setTexture("maskTextureSampler", this._maskTexture); + this.finalMaterial.setVector2("textureSize", new Vector2(this._options.width, this._options.height)); + this.finalMaterial.backFaceCulling = false; + + // Create and configure the post-process + const postProcess = new PostProcess( + "finalTexturePostProcess", + "meshUVSpaceRendererFinaliser", + ["textureSize"], + ["textureSampler", "maskTextureSampler"], + 1.0, // options: scale ratio or PostProcessOptions object + null, // camera + Texture.NEAREST_SAMPLINGMODE, // sampling mode + this._scene.getEngine(), // engine + false, // reusable + null, // defines + this._options.textureType // textureType + ); + + postProcess.onApply = (effect) => { + effect.setTexture("textureSampler", this.decalTexture); + effect.setTexture("maskTextureSampler", this._maskTexture); + effect.setVector2("textureSize", new Vector2(this._options.width, this._options.height)); + }; + if (MeshUVSpaceRenderer._IsRenderTargetTexture(this.texture)) { - this._scene.customRenderTargets.push(this.texture); - this.texture.renderList?.push(fullScreenQuad); - this.texture.setMaterialForRendering(fullScreenQuad, finalMaterial); + this.texture.addPostProcess(postProcess); this.texture.render(); } - // const plane = MeshBuilder.CreatePlane("image", {size: 1}, this._scene); - // const pbr = new PBRMaterial("P", this._scene); - // pbr.roughness = 1; - // pbr.emissiveTexture = this.texture; - // pbr.emissiveIntensity = 1; - // pbr.emissiveColor = new Color3(1, 1, 1); - // pbr.albedoTexture = this.texture; - // plane.material = pbr; - // pbr.disableLighting = true; } catch (error) { console.error("Error creating final texture:", error); } } + /** * Clears the texture map */ public clear(): void { - if (MeshUVSpaceRenderer._IsRenderTargetTexture(this.texture) && this.texture.renderTarget) { + if (MeshUVSpaceRenderer._IsRenderTargetTexture(this.decalTexture) && this.decalTexture.renderTarget) { const engine = this._scene.getEngine(); - engine.bindFramebuffer(this.texture.renderTarget); + engine.bindFramebuffer(this.decalTexture.renderTarget); engine.clear(this.clearColor, true, true, true); - engine.unBindFramebuffer(this.texture.renderTarget); + engine.unBindFramebuffer(this.decalTexture.renderTarget); } } @@ -358,7 +346,7 @@ export class MeshUVSpaceRenderer { */ public dispose() { if (this._textureCreatedInternally) { - this.texture.dispose(); + this.decalTexture.dispose(); this._textureCreatedInternally = false; } } @@ -371,6 +359,11 @@ export class MeshUVSpaceRenderer { texture.setMaterialForRendering(this._mesh, MeshUVSpaceRenderer._GetShader(this._scene)); this.decalTexture = texture; + + // Additional check after assignment + if (!this.decalTexture.isReady()) { + console.error("decalTexture is not ready after creation in _createDiffuseRTT."); + } } private _createRenderTargetTexture(width: number, height: number): RenderTargetTexture { diff --git a/packages/dev/core/src/Shaders/meshUVSpaceRendererFinaliser.fragment.fx b/packages/dev/core/src/Shaders/meshUVSpaceRendererFinaliser.fragment.fx index e189ccb48ba..10912eeac93 100644 --- a/packages/dev/core/src/Shaders/meshUVSpaceRendererFinaliser.fragment.fx +++ b/packages/dev/core/src/Shaders/meshUVSpaceRendererFinaliser.fragment.fx @@ -5,45 +5,45 @@ precision highp float; varying vec2 vUV; // Uniforms -uniform sampler2D decalSampler; -uniform sampler2D maskSampler; -// uniform vec2 textureSize; +uniform sampler2D textureSampler; +uniform sampler2D maskTextureSampler; +uniform vec2 textureSize; void main() { - vec4 mask = texture2D(maskSampler, vUV).rgba; + vec4 mask = texture2D(maskTextureSampler, vUV).rgba; if (mask.r > 0.5) { - gl_FragColor = texture2D(decalSampler, vUV); + gl_FragColor = texture2D(textureSampler, vUV); } else { - vec2 texelSize = 1.0 / 1024.0; + vec2 texelSize = 1.0 / textureSize; vec2 uv_p01 = vUV + vec2(-1.0, 0.0) * texelSize; vec2 uv_p21 = vUV + vec2(1.0, 0.0) * texelSize; vec2 uv_p10 = vUV + vec2(0.0, -1.0) * texelSize; vec2 uv_p12 = vUV + vec2(0.0, 1.0) * texelSize; - float mask_p01 = texture2D(maskSampler, uv_p01).r; - float mask_p21 = texture2D(maskSampler, uv_p21).r; - float mask_p10 = texture2D(maskSampler, uv_p10).r; - float mask_p12 = texture2D(maskSampler, uv_p12).r; + float mask_p01 = texture2D(maskTextureSampler, uv_p01).r; + float mask_p21 = texture2D(maskTextureSampler, uv_p21).r; + float mask_p10 = texture2D(maskTextureSampler, uv_p10).r; + float mask_p12 = texture2D(maskTextureSampler, uv_p12).r; vec4 col = vec4(0.0, 0.0, 0.0, 0.0); float total_weight = 0.0; if (mask_p01 > 0.5) { - col += texture2D(decalSampler, uv_p01); + col += texture2D(textureSampler, uv_p01); total_weight += 1.0; } if (mask_p21 > 0.5) { - col += texture2D(decalSampler, uv_p21); + col += texture2D(textureSampler, uv_p21); total_weight += 1.0; } if (mask_p10 > 0.5) { - col += texture2D(decalSampler, uv_p10); + col += texture2D(textureSampler, uv_p10); total_weight += 1.0; } if (mask_p12 > 0.5) { - col += texture2D(decalSampler, uv_p12); + col += texture2D(textureSampler, uv_p12); total_weight += 1.0; } @@ -53,4 +53,4 @@ void main() { gl_FragColor = col; } } -} \ No newline at end of file +} From abf516ca11b42baea0bb2e026a2319e37e5cdc53 Mon Sep 17 00:00:00 2001 From: machine <@baktrian> Date: Mon, 4 Dec 2023 07:44:41 +0000 Subject: [PATCH 16/21] adjustments --- packages/dev/core/src/Meshes/meshUVSpaceRenderer.ts | 2 +- .../core/src/Shaders/meshUVSpaceRendererFinaliser.fragment.fx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/dev/core/src/Meshes/meshUVSpaceRenderer.ts b/packages/dev/core/src/Meshes/meshUVSpaceRenderer.ts index a579b885dc6..43a01007371 100644 --- a/packages/dev/core/src/Meshes/meshUVSpaceRenderer.ts +++ b/packages/dev/core/src/Meshes/meshUVSpaceRenderer.ts @@ -88,7 +88,7 @@ export class MeshUVSpaceRenderer { /** * */ - finalMaterial: ShaderMaterial; + public finalMaterial: ShaderMaterial; private static _GetShader(scene: Scene): ShaderMaterial { if (!scene._meshUVSpaceRendererShader) { diff --git a/packages/dev/core/src/Shaders/meshUVSpaceRendererFinaliser.fragment.fx b/packages/dev/core/src/Shaders/meshUVSpaceRendererFinaliser.fragment.fx index 10912eeac93..85df921065e 100644 --- a/packages/dev/core/src/Shaders/meshUVSpaceRendererFinaliser.fragment.fx +++ b/packages/dev/core/src/Shaders/meshUVSpaceRendererFinaliser.fragment.fx @@ -15,7 +15,7 @@ void main() { if (mask.r > 0.5) { gl_FragColor = texture2D(textureSampler, vUV); } else { - vec2 texelSize = 1.0 / textureSize; + vec2 texelSize = 4.0 / textureSize; vec2 uv_p01 = vUV + vec2(-1.0, 0.0) * texelSize; vec2 uv_p21 = vUV + vec2(1.0, 0.0) * texelSize; From e6980858d6d34c50f071f1a6f033e7d2e5c39898 Mon Sep 17 00:00:00 2001 From: machine <@baktrian> Date: Mon, 4 Dec 2023 08:13:09 +0000 Subject: [PATCH 17/21] clean up for merge --- .../core/src/Meshes/meshUVSpaceRenderer.ts | 37 ++++++++++--------- 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/packages/dev/core/src/Meshes/meshUVSpaceRenderer.ts b/packages/dev/core/src/Meshes/meshUVSpaceRenderer.ts index 43a01007371..fba7f52a387 100644 --- a/packages/dev/core/src/Meshes/meshUVSpaceRenderer.ts +++ b/packages/dev/core/src/Meshes/meshUVSpaceRenderer.ts @@ -9,7 +9,10 @@ import { Matrix, Vector2 } from "core/Maths/math.vector"; import { Constants } from "core/Engines/constants"; import { ShaderMaterial } from "core/Materials/shaderMaterial"; import { RenderTargetTexture } from "core/Materials/Textures/renderTargetTexture"; -import { Color3, Color4 } from "core/Maths/math.color"; +import { Color4 } from "core/Maths/math.color"; +import { PBRMaterial} from "core/Materials/PBR/pbrMaterial"; +import { StandardMaterial } from "core/Materials/standardMaterial"; +import { PostProcess } from "core/PostProcesses/postProcess"; import "../Shaders/meshUVSpaceRenderer.vertex"; import "../Shaders/meshUVSpaceRenderer.fragment"; @@ -19,10 +22,6 @@ import "../Shaders/meshUVSpaceRendererMasker.fragment"; import "../Shaders/meshUVSpaceRendererFinaliser.fragment"; import "../Shaders/meshUVSpaceRendererFinaliser.vertex"; -// import { MeshBuilder } from "./meshBuilder"; -import type { PBRMaterial} from ".."; -import { Material, Mesh, MeshBuilder, PostProcess} from ".."; -// import { TextureFormat } from ".."; declare module "../scene" { @@ -167,7 +166,7 @@ export class MeshUVSpaceRenderer { return MeshUVSpaceRenderer._IsRenderTargetTexture(this.decalTexture) ? this.decalTexture.isReadyForRendering() : this.decalTexture.isReady(); } -/** + /** * Projects and renders a texture in the mesh UV space * @param texture The texture * @param position The position of the center of projection (world space coordinates) @@ -187,16 +186,6 @@ export class MeshUVSpaceRenderer { this._createDiffuseRTT(); } - // const plane = MeshBuilder.CreatePlane("image", {size: 1}, this._scene); - // const pbr = new PBRMaterial("P", this._scene); - // pbr.roughness = 1; - // pbr.emissiveTexture = this._maskTexture; - // pbr.emissiveIntensity = 1; - // pbr.emissiveColor = new Color3(1, 1, 1); - // pbr.albedoTexture = this._maskTexture; - // plane.material = pbr; - // pbr.disableLighting = true; - // // Prepare the shader with the decal texture, mask texture, and necessary uniforms const shader = MeshUVSpaceRenderer._GetShader(this._scene); shader.setTexture("textureSampler", texture); // Decal texture @@ -213,7 +202,7 @@ export class MeshUVSpaceRenderer { private _createMaskTexture(): void { if (this._maskTexture) { - return; // Mask texture already created + return; } try { @@ -243,7 +232,19 @@ export class MeshUVSpaceRenderer { } ); - maskMaterial.setTexture("textureSampler", this._mesh.material?.albedoTexture); + let texture = null; + if (this._mesh.material instanceof PBRMaterial) { + texture = (this._mesh.material as PBRMaterial).albedoTexture; + } else if (this._mesh.material instanceof StandardMaterial) { + texture = (this._mesh.material as StandardMaterial).diffuseTexture; + } + + if (texture) { + maskMaterial.setTexture("textureSampler", texture); + } else { + console.error("Material does not have a valid texture property."); + } + maskMaterial.backFaceCulling = false; this._mesh.material = this._mesh.material as PBRMaterial; From ecc90d64609a918d0199494eede4db5a25b97269 Mon Sep 17 00:00:00 2001 From: machine <@baktrian> Date: Mon, 4 Dec 2023 08:18:10 +0000 Subject: [PATCH 18/21] continue cleanup operation --- .../src/Shaders/meshUVSpaceRendererMasker.fragment.fx | 8 -------- 1 file changed, 8 deletions(-) diff --git a/packages/dev/core/src/Shaders/meshUVSpaceRendererMasker.fragment.fx b/packages/dev/core/src/Shaders/meshUVSpaceRendererMasker.fragment.fx index 35fcf6e926f..9c14cc9ba4d 100644 --- a/packages/dev/core/src/Shaders/meshUVSpaceRendererMasker.fragment.fx +++ b/packages/dev/core/src/Shaders/meshUVSpaceRendererMasker.fragment.fx @@ -1,11 +1,3 @@ -// varying vec2 vUV; - -// uniform sampler2D textureSampler; - -// void main(void) { -// gl_FragColor = vec4(vUV.x, vUV.y, 0.0, 1.0); -// } - varying vec2 vUV; void main(void) { From f0d3c4db40af2c6880551afa7ed9796d147dbded Mon Sep 17 00:00:00 2001 From: machine <@baktrian> Date: Mon, 4 Dec 2023 10:20:08 +0000 Subject: [PATCH 19/21] only create post processing effect once --- .../core/src/Meshes/meshUVSpaceRenderer.ts | 60 +++++++++---------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/packages/dev/core/src/Meshes/meshUVSpaceRenderer.ts b/packages/dev/core/src/Meshes/meshUVSpaceRenderer.ts index fba7f52a387..38f7d875fa9 100644 --- a/packages/dev/core/src/Meshes/meshUVSpaceRenderer.ts +++ b/packages/dev/core/src/Meshes/meshUVSpaceRenderer.ts @@ -88,6 +88,7 @@ export class MeshUVSpaceRenderer { * */ public finalMaterial: ShaderMaterial; + _finalPostProcess: any; private static _GetShader(scene: Scene): ShaderMaterial { if (!scene._meshUVSpaceRendererShader) { @@ -174,13 +175,7 @@ export class MeshUVSpaceRenderer { * @param size The size of the projection * @param angle The rotation angle around the direction of the projection */ - - // Method to use the mask texture to fix UV seams public async renderTexture(texture: BaseTexture, position: Vector3, normal: Vector3, size: Vector3, angle = 0): Promise { - // Ensure the mask texture is ready for seam fixing - //todo flag - await this._createMaskTexture(); - // Create the diffuse render target texture if it doesn't exist if (!this.decalTexture) { this._createDiffuseRTT(); @@ -196,12 +191,14 @@ export class MeshUVSpaceRenderer { if (MeshUVSpaceRenderer._IsRenderTargetTexture(this.decalTexture)) { this.decalTexture.render(); + await this._createMaskTexture(); this._createFinalTexture(); } } private _createMaskTexture(): void { if (this._maskTexture) { + Promise.resolve(); return; } try { @@ -298,29 +295,31 @@ export class MeshUVSpaceRenderer { this.finalMaterial.setVector2("textureSize", new Vector2(this._options.width, this._options.height)); this.finalMaterial.backFaceCulling = false; - // Create and configure the post-process - const postProcess = new PostProcess( - "finalTexturePostProcess", - "meshUVSpaceRendererFinaliser", - ["textureSize"], - ["textureSampler", "maskTextureSampler"], - 1.0, // options: scale ratio or PostProcessOptions object - null, // camera - Texture.NEAREST_SAMPLINGMODE, // sampling mode - this._scene.getEngine(), // engine - false, // reusable - null, // defines - this._options.textureType // textureType - ); + // Create the post-process only if it hasn't been created already + if (!this._finalPostProcess) { + this._finalPostProcess = new PostProcess( + "finalTexturePostProcess", + "meshUVSpaceRendererFinaliser", + ["textureSize"], + ["textureSampler", "maskTextureSampler"], + 1.0, + null, + Texture.NEAREST_SAMPLINGMODE, + this._scene.getEngine(), + false, + null, + this._options.textureType + ); - postProcess.onApply = (effect) => { - effect.setTexture("textureSampler", this.decalTexture); - effect.setTexture("maskTextureSampler", this._maskTexture); - effect.setVector2("textureSize", new Vector2(this._options.width, this._options.height)); - }; + this._finalPostProcess.onApply = (effect: { setTexture: (arg0: string, arg1: Texture) => void; setVector2: (arg0: string, arg1: Vector2) => void; }) => { + effect.setTexture("textureSampler", this.decalTexture); + effect.setTexture("maskTextureSampler", this._maskTexture); + effect.setVector2("textureSize", new Vector2(this._options.width, this._options.height)); + }; + } if (MeshUVSpaceRenderer._IsRenderTargetTexture(this.texture)) { - this.texture.addPostProcess(postProcess); + this.texture.addPostProcess(this._finalPostProcess); this.texture.render(); } } catch (error) { @@ -328,17 +327,18 @@ export class MeshUVSpaceRenderer { } } + /** * Clears the texture map */ public clear(): void { - if (MeshUVSpaceRenderer._IsRenderTargetTexture(this.decalTexture) && this.decalTexture.renderTarget) { + if (MeshUVSpaceRenderer._IsRenderTargetTexture(this.texture) && this.texture.renderTarget) { const engine = this._scene.getEngine(); - engine.bindFramebuffer(this.decalTexture.renderTarget); + engine.bindFramebuffer(this.texture.renderTarget); engine.clear(this.clearColor, true, true, true); - engine.unBindFramebuffer(this.decalTexture.renderTarget); + engine.unBindFramebuffer(this.texture.renderTarget); } } @@ -347,7 +347,7 @@ export class MeshUVSpaceRenderer { */ public dispose() { if (this._textureCreatedInternally) { - this.decalTexture.dispose(); + this.texture.dispose(); this._textureCreatedInternally = false; } } From 109023b277a21b41e378cf42a311ddb10724fa31 Mon Sep 17 00:00:00 2001 From: machine <@baktrian> Date: Mon, 4 Dec 2023 11:31:13 +0000 Subject: [PATCH 20/21] add flag in options --- .../core/src/Meshes/meshUVSpaceRenderer.ts | 27 ++++++++++++------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/packages/dev/core/src/Meshes/meshUVSpaceRenderer.ts b/packages/dev/core/src/Meshes/meshUVSpaceRenderer.ts index 38f7d875fa9..f205868b819 100644 --- a/packages/dev/core/src/Meshes/meshUVSpaceRenderer.ts +++ b/packages/dev/core/src/Meshes/meshUVSpaceRenderer.ts @@ -60,6 +60,10 @@ export interface IMeshUVSpaceRendererOptions { * If you plan to use the texture as a decal map and rotate / offset the texture, you should set this to false */ optimizeUVAllocation?: boolean; + /** + * If true, the texture will be blended with the mesh's texture to avoid seams. Default: false + */ + uvEdgeBlending?: boolean; } /** @@ -72,22 +76,25 @@ export class MeshUVSpaceRenderer { private _options: Required; private _textureCreatedInternally = false; /** - * + * Mask Texture for the UV Edge Blending */ _maskTexture: any; /** - * + * Final Texture for the UV Edge Blending */ _finalTexture: any; /** - * + * The decal texture */ decalTexture: Texture; /** - * + * The final material for the UV Edge Blending */ public finalMaterial: ShaderMaterial; + /** + * The final post process for the UV Edge Blending + */ _finalPostProcess: any; private static _GetShader(scene: Scene): ShaderMaterial { @@ -151,6 +158,7 @@ export class MeshUVSpaceRenderer { textureType: Constants.TEXTURETYPE_UNSIGNED_BYTE, generateMipMaps: true, optimizeUVAllocation: true, + uvEdgeBlending: options?.uvEdgeBlending ?? false, ...options, }; } @@ -191,8 +199,12 @@ export class MeshUVSpaceRenderer { if (MeshUVSpaceRenderer._IsRenderTargetTexture(this.decalTexture)) { this.decalTexture.render(); - await this._createMaskTexture(); - this._createFinalTexture(); + if(this._options.uvEdgeBlending) { + await this._createMaskTexture(); + this._createFinalTexture(); + } else { + this.texture = this.decalTexture; + } } } @@ -202,7 +214,6 @@ export class MeshUVSpaceRenderer { return; } try { - this._scene.clearColor = new Color4(0,0,0,1); // Create a new render target texture for the mask this._maskTexture = new RenderTargetTexture( @@ -326,8 +337,6 @@ export class MeshUVSpaceRenderer { console.error("Error creating final texture:", error); } } - - /** * Clears the texture map From 8cb60dc853a1ed7ee13d6a8ab35bf71674a16bf6 Mon Sep 17 00:00:00 2001 From: machine <@baktrian> Date: Mon, 4 Dec 2023 11:37:06 +0000 Subject: [PATCH 21/21] final improvement --- packages/dev/core/src/Meshes/meshUVSpaceRenderer.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/dev/core/src/Meshes/meshUVSpaceRenderer.ts b/packages/dev/core/src/Meshes/meshUVSpaceRenderer.ts index f205868b819..1cbd24d9f07 100644 --- a/packages/dev/core/src/Meshes/meshUVSpaceRenderer.ts +++ b/packages/dev/core/src/Meshes/meshUVSpaceRenderer.ts @@ -327,10 +327,12 @@ export class MeshUVSpaceRenderer { effect.setTexture("maskTextureSampler", this._maskTexture); effect.setVector2("textureSize", new Vector2(this._options.width, this._options.height)); }; + if (MeshUVSpaceRenderer._IsRenderTargetTexture(this.texture)) { + this.texture.addPostProcess(this._finalPostProcess); + } } if (MeshUVSpaceRenderer._IsRenderTargetTexture(this.texture)) { - this.texture.addPostProcess(this._finalPostProcess); this.texture.render(); } } catch (error) {