undefined

6๊ฐ• ์‚ฌ์šฉ์ž ์ •์˜ ์ง€์˜ค๋ฉ”ํŠธ๋ฆฌ

three.js๊ฐ€ ์ œ๊ณตํ•˜๋Š” ์ง€์˜ค๋ฉ”ํŠธ๋ฆฌ ์™ธ์—๋„ ์ง์ ‘ ์ •์˜ํ•˜๋Š” ์ง€์˜ค๋ฉ”ํŠธ๋ฆฌ๋ฅผ ๋งŒ๋“ค์–ด๋ณด์ž

geometry๋Š” three.js์—์„œ BufferGeometry ํด๋ž˜์Šค๋ฅผ ํ†ตํ•ด ์ •์˜ํ•œ๋‹ค.


BufferGeometry์— ์ •์˜ํ•  ์ˆ˜ ์žˆ๋Š” ์†์„ฑ

  • position: geometry๋ฅผ ๊ตฌ์„ฑํ•˜๋Š” 3์ฐจ์› ์ขŒํ‘œ์— ๋Œ€ํ•œ ์ •์ (Vertex)
  • normal: ๊ฐ ์ •์ ์— ๋Œ€ํ•œ ์ˆ˜์ง ๋ฒกํ„ฐ
  • color: ๊ฐ ์ •์ ์— ๋Œ€ํ•œ ์ƒ‰์ƒ
  • uv: ๊ฐ ์ •์ ์— ๋Œ€ํ•œ ํ…์Šค์ณ ๋งตํ•‘ ์ขŒํ‘œ
  • Vertex index: position ์†์„ฑ์œผ๋กœ ์ง€์ •๋œ ์ •์ ์— ๋Œ€ํ•œ ์ธ๋ฑ์Šค ๋ฐฐ์—ด
    • mesh๋ฅผ ๊ตฌ์„ฑํ•˜๋Š” ๋ฉด์˜ ์ตœ์†Œ ๋‹จ์œ„๋Š” ์‚ผ๊ฐํ˜•์ด๊ณ  ์ด ์‚ผ๊ฐํ˜•์€ 3๊ฐœ์˜ ์ •์ ์œผ๋กœ ๊ตฌ์„ฑ๋œ๋‹ค.
    • ์ด ์‚ผ๊ฐํ˜•์„ ๊ตฌ์„ฑํ•˜๋Š” 3๊ฐœ์˜ ์ •์ ์— ๋Œ€ํ•œ position ์†์„ฑ์—์„œ์˜ ์ •์  ์ธ๋ฑ์Šค ๋ฒˆํ˜ธ๊ฐ€ Vertex index

 

๊ฐ„๋‹จํ•œ ์‚ฌ์šฉ์ž ์ง€์˜ค๋ฉ”ํŠธ๋ฆฌ๋ฅผ ๊ตฌํ˜„ํ•ด ๋ณด์ž

1. ์ •์  ๋ฐ์ดํ„ฐ ์ •์˜

const rawPositions = [
  -1, -1, 0, 
  1, -1, 0, 
  -1, 1, 0, 
  1, 1, 0
];
const positions = new Float32Array(rawPositions);

2. ์ง€์˜ค๋ฉ”ํŠธ๋ฆฌ์˜ position ์†์„ฑ ์ง€์ •

const geometry = new THREE.BufferGeometry();
geometry.setAttribute(
    "poisition", 
    new THREE.BufferAttribute(positions, 3)
); // ํ•˜๋‚˜์˜ ์ •์ ์ด (x, y, z) 3๊ฐœ์˜ ํ•ญ๋ชฉ์œผ๋กœ ๊ตฌ์„ฑ๋จ์„ ์˜๋ฏธ

3. Vertex index ์ง€์ •

Vertex index๋Š” ์‚ผ๊ฐํ˜• ๋ฉด์„ ์ •์˜ํ•œ๋‹ค.

geometry.setIndex([
  0, 1, 2,
  2, 1, 3
])
  • ์‚ผ๊ฐํ˜•์„ ๊ตฌ์„ฑํ•˜๋Š” ์ •์ ์˜ ๋ฐฐ์น˜ ์ˆœ์„œ๋Š” ๋ฐ˜์‹œ๊ณ„ ๋ฐฉํ–ฅ์ด๋‹ค.
  • ๋ฐ˜์‹œ๊ณ„ ๋ฐฉํ–ฅ์ธ ๋ฉด์ด ์•ž๋ฉด์ด๋‹ค.

4. ๋ชจ๋“  ์ •์ ์— ๋Œ€ํ•ด ๋ฒ•์„  ๋ฒกํ„ฐ ์ง€์ •

๋ฒ•์„  ๋ฒกํ„ฐ๋Š” ๊ด‘์›์ด ๋ฉ”์‰ฌ์˜ ํ‘œ๋ฉด์— ๋น„์ถ”๋Š” ์ž…์‚ฌ๊ฐ๊ณผ ๋ฐ˜์‚ฌ๊ฐ์„ ๊ณ„์‚ฐํ•˜์—ฌ ์žฌ์งˆ๊ณผ ํ•จ๊ป˜ ํ‘œ๋ฉด์˜ ์ƒ‰์ƒ์„ ๊ฒฐ์ •ํ•œ๋‹ค.

๋ชจ๋“  ์ •์ ์— ๋Œ€ํ•ด ๋ฒ•์„  ๋ฒกํ„ฐ๋ฅผ ์ž๋™์œผ๋กœ ์ง€์ •ํ•˜๋Š” ๋ฐฉ๋ฒ•

geometry.computeVertexNormals()

๋ฒ•์„  ๋ฒกํ„ฐ๋ฅผ ์ง์ ‘ ์ง€์ •ํ•˜๋Š” ๋ฐฉ๋ฒ•

const rawNormals = [
  0,0,1,
  0,0,1,
  0,0,1,
  0,0,1,
];
const normals = new Float32Array(rawNormals);
geometry.setAttribute("normal", new THREE.BufferAttribute(normals, 3));

5. ๊ฐ ์ •์ ์˜ ์ƒ‰์ƒ ๊ฐ’ ์ง€์ •

const rawColors = [
      1,0,0,
      0,1,0,
      0,0,1,
      1,1,0,
    ];
const colors = new Float32Array(rawColors);
geometry.setAttribute("color", new THREE.BufferAttribute(colors, 3));

** ์ •์  ์ƒ‰์„ ์ ์šฉํ•˜๋ ค๋ฉด Material์„ vertexColors: true๋กœ ์ง€์ •ํ•ด์•ผ ํ•œ๋‹ค.

const material = new THREE.MeshPhongMaterial({ color: 0xffffff, vertexColors: true });

6. uv ์†์„ฑ์œผ๋กœ ํ…์Šค์ณ ๋งตํ•‘

// uv ์ขŒํ‘œ๋ฅผ ๋‹ด๊ณ  ์žˆ๋Š” ๋ฐฐ์—ด
const rawUvs = [
  0, 0,
  1, 0,
  0, 1,
  1, 1,
];
const uvs = new Float32Array(rawUvs);
geometry.setAttribute("uv", new THREE.BufferAttribute(uvs, 2));
// ํ…์Šค์ณ ๋งตํ•‘
const textureLoader = new THREE.TextureLoader();
const map = textureLoader.load("/assets/uv_grid_opengl.jpg");

const material = new THREE.MeshPhongMaterial({ color: 0xffffff, map });

 

const rawPositions = [
  -1, -1, 0,
  1, -1, 0,
  -1, 1, 0,
  1, 1, 0
];
const rawUvs = [
  0, 0,
  1, 0,
  0, 1,
  1, 1,
];

์ง€์˜ค๋ฉ”ํŠธ๋ฆฌ ์ •์  ์ขŒํ‘œ์™€ uv ์ขŒํ‘œ๋Š” ๋‹ค์Œ ํ‘œ์™€ ๊ฐ™์ด ๋งตํ•‘๋œ๋‹ค.

์ง€์˜ค๋ฉ”ํŠธ๋ฆฌ ์ •์  ์ขŒํ‘œ uv ์ขŒํ‘œ
(-1, -1, 0) (0, 0)
(1, -1, 0) (1,0)
(-1, 1, 0) (0, 1)
(1, 1, 0) (1, 1)

๋งˆ๋ฌด๋ฆฌ

์ง์ ‘ ์ขŒํ‘œ๋ฅผ ๋งŒ๋“ค์–ด์„œ ์›ํ•˜๋Š” ํ˜•ํƒœ์˜ ์ง€์˜ค๋ฉ”ํŠธ๋ฆฌ๋ฅผ ๊ตฌ์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.

์ง€์˜ค๋ฉ”ํŠธ๋ฆฌ๋ฅผ ์ง์ ‘ ๋งŒ๋“ค์–ด๋ณด๋ฉด์„œ ์ง€์˜ค๋ฉ”ํŠธ๋ฆฌ๊ฐ€ ์–ด๋–ค ๋ฐฉ์‹์œผ๋กœ ํ˜•ํƒœ๋ฅผ ์ •์˜ํ•˜๋Š”์ง€ ์ดํ•ดํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค.

ํ•˜์ง€๋งŒ ์ด๋Ÿฐ ์ž‘์—…์€ ๋„ˆ๋ฌด ๋ฒˆ๊ฑฐ๋กญ๊ธฐ ๋•Œ๋ฌธ์— ์‹ค๋ฌด์—์„œ ์‚ฌ์šฉํ•˜๊ธฐ๋Š” ํž˜๋“ค ๊ฒƒ ๊ฐ™๋‹ค.