{"id":16328,"date":"2025-10-19T11:01:21","date_gmt":"2025-10-19T02:01:21","guid":{"rendered":"http:\/\/www.gisdeveloper.co.kr\/?p=16328"},"modified":"2026-01-28T12:09:27","modified_gmt":"2026-01-28T03:09:27","slug":"tsl-tip","status":"publish","type":"post","link":"http:\/\/www.gisdeveloper.co.kr\/?p=16328","title":{"rendered":"TSL Tips"},"content":{"rendered":"<h3>normalNode\uc5d0 \ub300\ud55c \uc801\uc6a9\uc744 \uc704\ud574 bumpMap \ub178\ub4dc\ub97c \uc0ac\uc6a9<\/h3>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"js\">\r\nconst diffuseTex = loader.load('.\/brick_diffuse.jpg');\r\ndiffuseTex.colorSpace = THREE.SRGBColorSpace;\r\n\r\nconst bumpTex = loader.load('.\/brick_bump.jpg');\r\n\r\nconst wallMat = new THREE.MeshStandardNodeMaterial();\r\n\r\nwallMat.colorNode = texture(diffuseTex);\r\nwallMat.normalNode = bumpMap(texture(bumpTex), float(5));\r\n<\/pre>\n<h3>\uac01\ub3c4\uc640 \uac70\ub9ac\uc5d0 \ub300\ud55c \uac00\ud558\ud559\uc801 \uacc4\uc0b0\uc2dd<\/h3>\n<p><img decoding=\"async\" src=\"http:\/\/www.gisdeveloper.co.kr\/wp-content\/uploads\/2025\/10\/20251020_095605.jpg\" alt=\"\" width=\"500\" class=\"aligncenter size-full wp-image-16334\" \/><\/p>\n<h3>GPU\ub97c \ud1b5\ud574 \uc4f0\uace0 \uc77d\uc744 \uc218 \uc788\ub294 \ud14d\uc2a4\uccd0<\/h3>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"js\">\r\n\/* \ud544\uc694\ud55c API \uc784\ud3ec\ud2b8 *\/\r\nimport { texture, textureStore, Fn, instanceIndex, float, uvec2, vec4, time } from 'three\/tsl';\r\n\r\n\/* \uc2a4\ud1a0\ub9ac\uc9c0 \ud14d\uc2a4\uccd0 \uc0dd\uc131 *\/\r\nconst width = 512, height = 512;\r\nconst storageTexture = new THREE.StorageTexture(width, height);\r\n\r\n\/* \ud14d\uc2a4\uccd0 \ub0b4\uc6a9 \uc0dd\uc131 \ud568\uc218 \uc815\uc758 *\/\r\nconst computeTexture = Fn(({ storageTexture }) => {\r\n  const posX = instanceIndex.mod(width);\r\n  const posY = instanceIndex.div(width);\r\n  const indexUV = uvec2(posX, posY);\r\n\r\n  const x = float(posX).div(50.0);\r\n  const y = float(posY).div(50.0);\r\n\r\n  const v1 = x.sin();\r\n  const v2 = y.sin();\r\n  const v3 = x.add(y.add(time.mul(1))).sin();\r\n  const v4 = x.mul(x).add(y.mul(y)).sqrt().add(5.0).sin();\r\n  const v = v1.add(v2, v3, v4);\r\n\r\n  const r = v.sin();\r\n  const g = v.add(Math.PI).sin();\r\n  const b = v.add(Math.PI).sub(0.5).sin();\r\n\r\n  textureStore(storageTexture, indexUV, vec4(r, g, b, 1)).toWriteOnly();\r\n});\r\n\r\n\/* \ud14d\uc2a4\uccd0 \ub0b4\uc6a9 \uc0dd\uc131 \ud568\uc218 \uc2e4\ud589 *\/\r\nconst computeNode = computeTexture({ storageTexture }).compute(width * height);\r\nthis._renderer.compute(computeNode);\r\n\r\n\/* \ud14d\uc2a4\uccd0 \ud65c\uc6a9 *\/\r\nconst material = new THREE.MeshBasicNodeMaterial({ color: 0x00ff00 });\r\nmaterial.colorNode = texture(storageTexture);\r\n<\/pre>\n<h3>\ub09c\uc218 \ub178\ub4dc \ud568\uc218<\/h3>\n<p>TSL\uc5d0\uc11c \uc81c\uacf5\ud558\ub294 \ub09c\uc218 \ub178\ub4dc \ud568\uc218\uc5d0\ub294 hash\uc640 rand\uac00 \uc788\ub2e4. hash\ub294 float\uc744 \ubc1b\uc544 0~1 \uc0ac\uc774\uc758 float\uc744 \ubc49\ub294\ub2e4. rand\ub294 vec2\ub97c \ubc1b\uc544 hash\uc640 \ub3d9\uc77c\ud55c \uacb0\uacfc\ub97c \ubc49\ub294\ub2e4.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>normalNode\uc5d0 \ub300\ud55c \uc801\uc6a9\uc744 \uc704\ud574 bumpMap \ub178\ub4dc\ub97c \uc0ac\uc6a9 const diffuseTex = loader.load(&#8216;.\/brick_diffuse.jpg&#8217;); diffuseTex.colorSpace = THREE.SRGBColorSpace; const bumpTex = loader.load(&#8216;.\/brick_bump.jpg&#8217;); const wallMat = new THREE.MeshStandardNodeMaterial(); wallMat.colorNode = texture(diffuseTex); wallMat.normalNode = bumpMap(texture(bumpTex), float(5)); \uac01\ub3c4\uc640 \uac70\ub9ac\uc5d0 \ub300\ud55c \uac00\ud558\ud559\uc801 \uacc4\uc0b0\uc2dd GPU\ub97c \ud1b5\ud574 \uc4f0\uace0 \uc77d\uc744 \uc218 \uc788\ub294 \ud14d\uc2a4\uccd0 \/* \ud544\uc694\ud55c API \uc784\ud3ec\ud2b8 *\/ import { texture, textureStore, Fn, instanceIndex, float, uvec2, &hellip; <\/p>\n<p class=\"link-more\"><a href=\"http:\/\/www.gisdeveloper.co.kr\/?p=16328\" class=\"more-link\">\ub354 \ubcf4\uae30<span class=\"screen-reader-text\"> &#8220;TSL Tips&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-16328","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"http:\/\/www.gisdeveloper.co.kr\/index.php?rest_route=\/wp\/v2\/posts\/16328","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/www.gisdeveloper.co.kr\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.gisdeveloper.co.kr\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.gisdeveloper.co.kr\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.gisdeveloper.co.kr\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=16328"}],"version-history":[{"count":10,"href":"http:\/\/www.gisdeveloper.co.kr\/index.php?rest_route=\/wp\/v2\/posts\/16328\/revisions"}],"predecessor-version":[{"id":16698,"href":"http:\/\/www.gisdeveloper.co.kr\/index.php?rest_route=\/wp\/v2\/posts\/16328\/revisions\/16698"}],"wp:attachment":[{"href":"http:\/\/www.gisdeveloper.co.kr\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=16328"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.gisdeveloper.co.kr\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=16328"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.gisdeveloper.co.kr\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=16328"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}