From 7887b4bb59cfcb56aa38af33c1bc2c0d98cc7956 Mon Sep 17 00:00:00 2001 From: Minkyu Lee Date: Tue, 16 Jul 2024 02:02:06 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=ED=85=8C=EB=91=90=EB=A6=AC=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=20=EC=9C=A0=ED=8B=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- projects/find-waffle/src/utils/three.ts | 41 +++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/projects/find-waffle/src/utils/three.ts b/projects/find-waffle/src/utils/three.ts index 774fc21f..6f908dfa 100644 --- a/projects/find-waffle/src/utils/three.ts +++ b/projects/find-waffle/src/utils/three.ts @@ -25,3 +25,44 @@ export function resize( camera.updateProjectionMatrix(); } } + +/** + * Material 에 테두리를 추가합니다. + * @param material 테두리를 추가할 Material + * @param color 테두리 색상 + * @param width 테두리 두께 + * @returns 테두리가 추가된 Material + */ +export function addBorderToMaterial( + material: THREE.Material, + color: THREE.ColorRepresentation, + width: number, +): THREE.Material { + if (material.defines === undefined) material.defines = {}; + material.defines.USE_UV = ''; + material.onBeforeCompile = (shader) => { + shader.uniforms.size = { value: new THREE.Vector2(1, 1) }; + shader.uniforms.borderWidth = { value: width }; + shader.uniforms.borderColor = { value: new THREE.Color(color) }; + shader.fragmentShader = ` + uniform vec2 size; + uniform float borderWidth; + uniform vec3 borderColor; + ${shader.fragmentShader} + `.replace( + '#include ', + ` + #include + vec3 col = diffuseColor.rgb; + vec2 s = (size * 0.5) - borderWidth; + + vec2 ruv = abs((vUv - 0.5) * size); + vec2 fe = fwidth(ruv); + float e = min(fe.x, fe.y) * 0.5; + float border = smoothstep(s.x + e, s.x - e, ruv.x) * smoothstep(s.y + e, s.y - e, ruv.y); + diffuseColor.rgb = mix(borderColor, col, clamp(border, 0., 1.)); + `, + ); + }; + return material; +}