diff --git a/manual/en/indexed-textures.html b/manual/en/indexed-textures.html index 502710d26fbcfd..83d3533e6e1787 100644 --- a/manual/en/indexed-textures.html +++ b/manual/en/indexed-textures.html @@ -40,10 +40,10 @@

Indexed Textures for Picking and Color

the user select a country and show their selection?

The first idea that comes to mind is to generate geometry for each country. We could use a picking solution like we covered before. -We'd build 3D geometry for each country. If the user clicks on the mesh for +We'd build 3D geometry for each country. If the user clicks on the mesh for that country we'd know what country was clicked.

So, just to check that solution I tried generating 3D meshes of all the countries -using the same data I used to generate the outlines +using the same data I used to generate the outlines in the previous article. The result was a 15.5meg binary GLTF (.glb) file. Making the user download 15.5meg sounds like too much to me.

@@ -53,11 +53,11 @@

Indexed Textures for Picking and Color

win. For a borders of Canada probably much less.

Another solution would be to use just actual data compression. For example gzipping the file brought it down to 11meg. That's 30% less but arguably not enough.

-

We could store all the data as 16bit ranged values instead of 32bit float values. +

We could store all the data as 16bit ranged values instead of 32bit float values. Or we could use something like draco compression -and maybe that would be enough. I didn't check and I would encourage you to check +and maybe that would be enough. I didn't check and I would encourage you to check yourself and tell me how it goes as I'd love to know. ๐Ÿ˜…

-

In my case I thought about the GPU picking solution +

In my case I thought about the GPU picking solution we covered at the end of the article on picking. In that solution we drew every mesh with a unique color that represented that mesh's id. We then drew all the meshes and looked at the color that was clicked @@ -65,13 +65,13 @@

Indexed Textures for Picking and Color

Taking inspiration from that we could pre-generate a map of countries where each country's color is its index number in our array of countries. We could then use a similar GPU picking technique. We'd draw the globe off screen using -this index texture. Looking at the color of the pixel the user clicks would +this index texture. Looking at the color of the pixel the user clicks would tell us the country id.

-

So, I wrote some code +

So, I wrote some code to generate such a texture. Here it is.

-

Note: The data used to generate this texture comes from this website +

Note: The data used to generate this texture comes from this website and is therefore licensed as CC-BY-SA.

It's only 217k, much better than the 14meg for the country meshes. In fact we could probably even lower the resolution but 217k seems good enough for now.

@@ -244,14 +244,14 @@

Indexed Textures for Picking and Color

The code stills shows countries based on their area but if you click one just that one will have a label.

-

So that seems like a reasonable solution for picking countries +

So that seems like a reasonable solution for picking countries but what about highlighting the selected countries?

For that we can take inspiration from paletted graphics.

Paletted graphics -or Indexed Color is -what older systems like the Atari 800, Amiga, NES, +or Indexed Color is +what older systems like the Atari 800, Amiga, NES, Super Nintendo, and even older IBM PCs used. Instead of storing bitmaps -as RGB colors 8bits per color, 24 bytes per pixel or more, they stored +as RGBA colors 8bits per color, 32 bytes per pixel or more, they stored bitmaps as 8bit values or less. The value for each pixel was an index into a palette. So for example a value of 3 in the image means "display color 3". What color color#3 is is @@ -259,7 +259,7 @@

Indexed Textures for Picking and Color

In JavaScript you can think of it like this

const face7x7PixelImageData = [
   0, 1, 1, 1, 1, 1, 0,
-  1, 0, 0, 0, 0, 0, 1, 
+  1, 0, 0, 0, 0, 0, 1,
   1, 0, 2, 0, 2, 0, 1,
   1, 0, 0, 0, 0, 0, 1,
   1, 0, 3, 3, 3, 0, 1,
@@ -284,8 +284,8 @@ 

Indexed Textures for Picking and Color

texture we can color each individual country. For example by setting the entire palette texture to black and then for one country's entry in the palette a different color, we can highlight just that country.

-

To do paletted index graphics requires some custom shader code. -Let's modify the default shaders in three.js. +

To do paletted index graphics requires some custom shader code. +Let's modify the default shaders in three.js. That way we can use lighting and other features if we want.

Like we covered in the article on animating lots of objects we can modify the default shaders by adding a function to a material's @@ -331,14 +331,14 @@

Indexed Textures for Picking and Color

}

Digging through all those snippets -we find that three.js uses a variable called diffuseColor to manage the +we find that three.js uses a variable called diffuseColor to manage the base material color. It sets this in the <color_fragment> snippet so we should be able to modify it after that point.

-

diffuseColor at that point in the shader should already be the color from -our outline texture so we can look up the color from a palette texture +

diffuseColor at that point in the shader should already be the color from +our outline texture so we can look up the color from a palette texture and mix them for the final result.

Like we did before we'll make an array -of search and replacement strings and apply them to the shader in +of search and replacement strings and apply them to the shader in Material.onBeforeCompile.

{
   const loader = new THREE.TextureLoader();
@@ -389,7 +389,7 @@ 

Indexed Textures for Picking and Color

Above can see above we add 3 uniforms, indexTexture, paletteTexture, and paletteTextureWidth. We get a color from the indexTexture -and convert it to an index. vUv is the texture coordinates provided by +and convert it to an index. vUv is the texture coordinates provided by three.js. We then use that index to get a color out of the palette texture. We then mix the result with the current diffuseColor. The diffuseColor at this point is our black and white outline texture so if we add the 2 colors @@ -407,21 +407,21 @@

Indexed Textures for Picking and Color

const maxNumCountries = 512;
 const paletteTextureWidth = maxNumCountries;
 const paletteTextureHeight = 1;
-const palette = new Uint8Array(paletteTextureWidth * 3);
+const palette = new Uint8Array(paletteTextureWidth * 4);
 const paletteTexture = new THREE.DataTexture(
-    palette, paletteTextureWidth, paletteTextureHeight, THREE.RGBFormat);
+    palette, paletteTextureWidth, paletteTextureHeight);
 paletteTexture.minFilter = THREE.NearestFilter;
 paletteTexture.magFilter = THREE.NearestFilter;
 

A DataTexture let's us give a texture raw data. In this case -we're giving it 512 RGB colors, 3 bytes each where each byte is +we're giving it 512 RGBA colors, 4 bytes each where each byte is red, green, and blue respectively using values that go from 0 to 255.

Let's fill it with random colors just to see it work

for (let i = 1; i < palette.length; ++i) {
   palette[i] = Math.random() * 256;
 }
 // set the ocean color (index #0)
-palette.set([100, 200, 255], 0);
+palette.set([100, 200, 255, 255], 0);
 paletteTexture.needsUpdate = true;
 

Anytime we want three.js to update the palette texture with @@ -454,11 +454,13 @@

Indexed Textures for Picking and Color

const tempColor = new THREE.Color();
 function get255BasedColor(color) {
   tempColor.set(color);
-  return tempColor.toArray().map(v => v * 255);
+  const base = tempColor.toArray().map(v => v * 255);
+  base.push(255); // alpha
+  return base;
 }
 

Calling it like this color = get255BasedColor('red') will -return an array like [255, 0, 0].

+return an array like [255, 0, 0, 255].

Next let's use it to make a few colors and fill out the palette.

const selectedColor = get255BasedColor('red');
@@ -467,7 +469,7 @@ 

Indexed Textures for Picking and Color

resetPalette(); function setPaletteColor(index, color) { - palette.set(color, index * 3); + palette.set(color, index * 4); } function resetPalette() { @@ -628,11 +630,11 @@

Indexed Textures for Picking and Color

- + - \ No newline at end of file + diff --git a/manual/examples/indexed-textures-picking-and-highlighting.html b/manual/examples/indexed-textures-picking-and-highlighting.html index 5896fa045c6be2..0505a238360c29 100644 --- a/manual/examples/indexed-textures-picking-and-highlighting.html +++ b/manual/examples/indexed-textures-picking-and-highlighting.html @@ -99,17 +99,19 @@ pickingScene.background = new THREE.Color(0); const tempColor = new THREE.Color(); - function get255BasedColor(color) { + function get255BasedColor(color) { tempColor.set(color); - return tempColor.toArray().map(v => v * 255); + const base = tempColor.toArray().map(v => v * 255); + base.push(255); // alpha + return base; } const maxNumCountries = 512; const paletteTextureWidth = maxNumCountries; const paletteTextureHeight = 1; - const palette = new Uint8Array(paletteTextureWidth * 3); + const palette = new Uint8Array(paletteTextureWidth * 4); const paletteTexture = new THREE.DataTexture( - palette, paletteTextureWidth, paletteTextureHeight, THREE.RGBFormat); + palette, paletteTextureWidth, paletteTextureHeight); paletteTexture.minFilter = THREE.NearestFilter; paletteTexture.magFilter = THREE.NearestFilter; @@ -119,7 +121,7 @@ resetPalette(); function setPaletteColor(index, color) { - palette.set(color, index * 3); + palette.set(color, index * 4); } function resetPalette() { @@ -441,4 +443,3 @@ main(); - diff --git a/manual/examples/indexed-textures-picking-debounced.html b/manual/examples/indexed-textures-picking-debounced.html index b0cf11d74533ba..a7839b2fa34484 100644 --- a/manual/examples/indexed-textures-picking-debounced.html +++ b/manual/examples/indexed-textures-picking-debounced.html @@ -102,15 +102,16 @@ const tempColor = new THREE.Color(); function get255BasedColor(color) { tempColor.set(color); - return tempColor.toArray().map(v => v * 255); + const base = tempColor.toArray().map(v => v * 255); + base.push(255); // alpha + return base; } const maxNumCountries = 512; const paletteTextureWidth = maxNumCountries; const paletteTextureHeight = 1; - const palette = new Uint8Array(paletteTextureWidth * 3); - const paletteTexture = new THREE.DataTexture( - palette, paletteTextureWidth, paletteTextureHeight, THREE.RGBFormat); + const palette = new Uint8Array(paletteTextureWidth * 4); + const paletteTexture = new THREE.DataTexture(palette, paletteTextureWidth, paletteTextureHeight); paletteTexture.minFilter = THREE.NearestFilter; paletteTexture.magFilter = THREE.NearestFilter; @@ -120,7 +121,7 @@ resetPalette(); function setPaletteColor(index, color) { - palette.set(color, index * 3); + palette.set(color, index * 4); } function resetPalette() { @@ -469,4 +470,3 @@ main(); - diff --git a/manual/examples/indexed-textures-random-colors.html b/manual/examples/indexed-textures-random-colors.html index 5dc7ae3a3b1293..d24717857685f6 100644 --- a/manual/examples/indexed-textures-random-colors.html +++ b/manual/examples/indexed-textures-random-colors.html @@ -101,16 +101,15 @@ const maxNumCountries = 512; const paletteTextureWidth = maxNumCountries; const paletteTextureHeight = 1; - const palette = new Uint8Array(paletteTextureWidth * 3); - const paletteTexture = new THREE.DataTexture( - palette, paletteTextureWidth, paletteTextureHeight, THREE.RGBFormat); + const palette = new Uint8Array(paletteTextureWidth * 4); + const paletteTexture = new THREE.DataTexture(palette, paletteTextureWidth, paletteTextureHeight); paletteTexture.minFilter = THREE.NearestFilter; paletteTexture.magFilter = THREE.NearestFilter; for (let i = 1; i < palette.length; ++i) { palette[i] = Math.random() * 256; } // set the ocean color (index #0) - palette.set([100, 200, 255], 0); + palette.set([100, 200, 255, 255], 0); paletteTexture.needsUpdate = true; { @@ -418,4 +417,3 @@ main(); - diff --git a/manual/ja/indexed-textures.html b/manual/ja/indexed-textures.html index 4bb8b9688ac1e4..616cbd73b18574 100644 --- a/manual/ja/indexed-textures.html +++ b/manual/ja/indexed-textures.html @@ -235,14 +235,14 @@

ๅœง็ธฎใƒ†ใ‚ฏใ‚นใƒใƒฃใฎใƒ”ใƒƒใ‚ญใƒณใ‚ฐใจใ‚ซใƒฉใƒผ

ๅ›ฝใ‚’้ธๆŠžใ™ใ‚‹ๅˆ็†็š„ใช่งฃๆฑบ็ญ–ใฎใ‚ˆใ†ใซๆ€ใˆใพใ™ใŒใ€้ธๆŠžใ•ใ‚ŒใŸๅ›ฝใ‚’ๅผท่ชฟ่กจ็คบใ™ใ‚‹ใซใฏใฉใ†ใงใ—ใ‚‡ใ†ใ‹๏ผŸ

ใƒ‘ใƒฌใƒƒใƒˆใ‚ฐใƒฉใƒ•ใ‚ฃใƒƒใ‚ฏใ‚น ใ‹ใ‚‰ใ‚คใƒณใ‚นใƒ”ใƒฌใƒผใ‚ทใƒงใƒณใ‚’ๅพ—ใ‚‹ไบ‹ใŒใงใใพใ™ใ€‚

ใƒ‘ใƒฌใƒƒใƒˆใ‚ฐใƒฉใƒ•ใ‚ฃใƒƒใ‚ฏใ‚นใ‚„ใ‚คใƒณใƒ‡ใƒƒใ‚ฏใ‚นใ‚ซใƒฉใƒผใฏAtari 800ใ€Amigaใ€ใƒ•ใ‚กใƒŸใ‚ณใƒณใ€ใ‚นใƒผใƒ‘ใƒผใƒ•ใ‚กใƒŸใ‚ณใƒณใ€IBMใฎๅคใ„PCใชใฉใฎๅคใ„ใ‚ทใ‚นใƒ†ใƒ ใงไฝฟใ‚ใ‚Œใฆใ„ใพใ—ใŸใ€‚ -ใƒ“ใƒƒใƒˆใƒžใƒƒใƒ—ใ‚’RGBใ‚ซใƒฉใƒผ8ใƒ“ใƒƒใƒˆใ€1ใƒ”ใ‚ฏใ‚ปใƒซ24ใƒใ‚คใƒˆไปฅไธŠใงๆ ผ็ดใ™ใ‚‹ใฎใงใฏใชใใ€ใƒ“ใƒƒใƒˆใƒžใƒƒใƒ—ใ‚’8ใƒ“ใƒƒใƒˆไปฅไธ‹ใฎๅ€คใงๆ ผ็ดใ—ใฆใ„ใพใ—ใŸใ€‚ +ใƒ“ใƒƒใƒˆใƒžใƒƒใƒ—ใ‚’RGBAใ‚ซใƒฉใƒผ8ใƒ“ใƒƒใƒˆใ€1ใƒ”ใ‚ฏใ‚ปใƒซ32ใƒใ‚คใƒˆไปฅไธŠใงๆ ผ็ดใ™ใ‚‹ใฎใงใฏใชใใ€ใƒ“ใƒƒใƒˆใƒžใƒƒใƒ—ใ‚’8ใƒ“ใƒƒใƒˆไปฅไธ‹ใฎๅ€คใงๆ ผ็ดใ—ใฆใ„ใพใ—ใŸใ€‚ ๅ„ใƒ”ใ‚ฏใ‚ปใƒซใฎๅ€คใฏใƒ‘ใƒฌใƒƒใƒˆใธใฎใ‚คใƒณใƒ‡ใƒƒใ‚ฏใ‚นใงใ™ใ€‚ ใใฎใŸใ‚ไพ‹ใˆใฐ็”ปๅƒๅ†…ใฎๅ€คใŒ3ใงใ‚ใ‚Œใฐ "color 3ใ‚’่กจ็คบใ™ใ‚‹" ใจใ„ใ†ไบ‹ใซใชใ‚Šใพใ™ใ€‚ color 3ใŒไฝ•่‰ฒใ‹ใฏ "ใƒ‘ใƒฌใƒƒใƒˆ" ใจๅ‘ผใฐใ‚Œใ‚‹ๅˆฅใฎๅ ดๆ‰€ใงๅฎš็พฉใ•ใ‚Œใฆใ„ใพใ™ใ€‚

JavaScriptใงใฏๆฌกใฎใ‚ˆใ†ใชใ‚ณใƒผใƒ‰ใซใงใใพใ™ใ€‚

const face7x7PixelImageData = [
   0, 1, 1, 1, 1, 1, 0,
-  1, 0, 0, 0, 0, 0, 1, 
+  1, 0, 0, 0, 0, 0, 1,
   1, 0, 2, 0, 2, 0, 1,
   1, 0, 0, 0, 0, 0, 1,
   1, 0, 3, 3, 3, 0, 1,
@@ -377,20 +377,20 @@ 

ๅœง็ธฎใƒ†ใ‚ฏใ‚นใƒใƒฃใฎใƒ”ใƒƒใ‚ญใƒณใ‚ฐใจใ‚ซใƒฉใƒผ

const maxNumCountries = 512;
 const paletteTextureWidth = maxNumCountries;
 const paletteTextureHeight = 1;
-const palette = new Uint8Array(paletteTextureWidth * 3);
+const palette = new Uint8Array(paletteTextureWidth * 4);
 const paletteTexture = new THREE.DataTexture(
-    palette, paletteTextureWidth, paletteTextureHeight, THREE.RGBFormat);
+    palette, paletteTextureWidth, paletteTextureHeight);
 paletteTexture.minFilter = THREE.NearestFilter;
 paletteTexture.magFilter = THREE.NearestFilter;
 

DataTexture ใฏใƒ†ใ‚ฏใ‚นใƒใƒฃใฎ็”Ÿใƒ‡ใƒผใ‚ฟใ‚’ไธŽใˆใ‚‹ไบ‹ใŒใงใใพใ™ใ€‚ -ไปŠๅ›žใฏใฏ512ใฎRGBใ‚ซใƒฉใƒผใ‚’3ใƒใ‚คใƒˆใšใคไธŽใˆใ€ใใ‚Œใžใ‚Œใฎใƒใ‚คใƒˆใŒ่ตคใ€็ท‘ใ€้’ใง0ใ€œ255ใฎๅ€คใ‚’ไฝฟ็”จใ—ใพใ™ใ€‚

+ไปŠๅ›žใฏใฏ512ใฎRGBAใ‚ซใƒฉใƒผใ‚’4ใƒใ‚คใƒˆใšใคไธŽใˆใ€ใใ‚Œใžใ‚Œใฎใƒใ‚คใƒˆใŒ่ตคใ€็ท‘ใ€้’ใง0ใ€œ255ใฎๅ€คใ‚’ไฝฟ็”จใ—ใพใ™ใ€‚

ใƒฉใƒณใƒ€ใƒ ใชใ‚ซใƒฉใƒผใงๅก—ใ‚Šใคใถใ—ใพใ—ใ‚‡ใ†๏ผ

for (let i = 1; i < palette.length; ++i) {
   palette[i] = Math.random() * 256;
 }
 // set the ocean color (index #0)
-palette.set([100, 200, 255], 0);
+palette.set([100, 200, 255, 255], 0);
 paletteTexture.needsUpdate = true;
 

ใƒ‘ใƒฌใƒƒใƒˆใƒ†ใ‚ฏใ‚นใƒใƒฃใ‚’ palette ้…ๅˆ—ใฎๅ†…ๅฎนใงๆ›ดๆ–ฐใ—ใŸใ„ๆ™‚ใฏใ€ๅธธใซ paletteTexture.needsUpdate ใ‚’ true ใซใ™ใ‚‹ๅฟ…่ฆใŒใ‚ใ‚Šใพใ™ใ€‚

@@ -419,7 +419,9 @@

ๅœง็ธฎใƒ†ใ‚ฏใ‚นใƒใƒฃใฎใƒ”ใƒƒใ‚ญใƒณใ‚ฐใจใ‚ซใƒฉใƒผ

const tempColor = new THREE.Color();
 function get255BasedColor(color) {
   tempColor.set(color);
-  return tempColor.toArray().map(v => v * 255);
+  const base = tempColor.toArray().map(v => v * 255);
+  base.push(255); // alpha
+  return base;
 }
 

ใ“ใฎใ‚ˆใ†ใซ color = get255BasedColor('red') ใ‚’ๅ‘ผใณๅ‡บใ™ใจ [255, 0, 0] ใฎใ‚ˆใ†ใช้…ๅˆ—ใŒ่ฟ”ใ•ใ‚Œใพใ™ใ€‚

@@ -430,7 +432,7 @@

ๅœง็ธฎใƒ†ใ‚ฏใ‚นใƒใƒฃใฎใƒ”ใƒƒใ‚ญใƒณใ‚ฐใจใ‚ซใƒฉใƒผ

resetPalette(); function setPaletteColor(index, color) { - palette.set(color, index * 3); + palette.set(color, index * 4); } function resetPalette() { @@ -586,11 +588,11 @@

ๅœง็ธฎใƒ†ใ‚ฏใ‚นใƒใƒฃใฎใƒ”ใƒƒใ‚ญใƒณใ‚ฐใจใ‚ซใƒฉใƒผ

- + - \ No newline at end of file + diff --git a/manual/ko/indexed-textures.html b/manual/ko/indexed-textures.html index 5cb63ab426d6cc..1c28030210f04a 100644 --- a/manual/ko/indexed-textures.html +++ b/manual/ko/indexed-textures.html @@ -212,11 +212,11 @@

ํ”ผํ‚น๊ณผ ์ƒ‰์ƒ์— ์ธ๋ฑ์Šค ํ…์Šค์ฒ˜ ์‚ฌ์šฉํ•˜๊ธฐ

์œ„ ์˜ˆ์ œ๋Š” ์—ฌ์ „ํžˆ ์˜์—ญ ํฌ๊ธฐ์— ๋”ฐ๋ผ ๋‚˜๋ผ ์ด๋ฆ„์„ ๋ณด์—ฌ์ฃผ๊ธด ํ•˜๋‚˜, ํŠน์ • ๋‚˜๋ผ๋ฅผ ํด๋ฆญํ•˜๋ฉด ํ•ด๋‹น ๋‚˜๋ผ์˜ ์ด๋ฆ„๋งŒ ๋ณด์—ฌ์ค„ ๊ฒ๋‹ˆ๋‹ค.

์ด๋งŒํ•˜๋ฉด ๊ฐ ๋‚˜๋ผ๋ฅผ ํ”ผํ‚นํ•˜๋Š” ์˜ˆ์ œ๋กœ ์ถฉ๋ถ„ํ•ด ๋ณด์ด์ง€๋งŒ... ์„ ํƒํ•œ ๋‚˜๋ผ์˜ ์ƒ‰์„ ๋ฐ”๊พธ๋ ค๋ฉด ์–ด๋–ป๊ฒŒ ํ•ด์•ผ ํ• ๊นŒ์š”?

์ปฌ๋Ÿฌ ํŒ”๋ ˆํŠธ(color palette)๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

-

์ปฌ๋Ÿฌ ํŒ”๋ ˆํŠธ) ํ˜น์€ ์ธ๋ฑ์Šค ํŒ”๋ ˆํŠธ๋Š” ์•„ํƒ€๋ฆฌ 800, Amiga, NES, ์Šˆํผ ๋‹Œํ…๋„, ๊ตฌํ˜• IBM PC ๋“ฑ ๊ตฌํ˜• ์‹œ์Šคํ…œ์—์„œ ์‚ฌ์šฉํ•˜๋˜ ๊ธฐ๋ฒ•์ž…๋‹ˆ๋‹ค. ๋น„ํŠธ๋งต์„ ์ƒ‰์ƒ๋‹น 8๋น„ํŠธ ํ˜น์€ 24๋ฐ”์ดํŠธ ์ด์ƒ์˜ RGB ์ƒ‰์ƒ์œผ๋กœ ์ ์šฉํ•˜๋Š” ๋Œ€์‹  ๋น„ํŠธ๋งต์„ 8๋น„ํŠธ ์ดํ•˜์˜ ๊ฐ’์œผ๋กœ ์ €์žฅํ•˜๋Š” ๊ธฐ๋ฒ•์ด์ฃ . ๊ฐ ํ”ฝ์…€์˜ ์ƒ‰์ƒ๊ฐ’์€ ํŒ”๋ ˆํŠธ์˜ ์ธ๋ฑ์Šค ๊ฐ’์œผ๋กœ, ํ”ฝ์…€์˜ ์ƒ‰์ƒ๊ฐ’์ด 3์ด๋ผ๋ฉด ํŠน์ • "ํŒ”๋ ˆํŠธ"์˜ 3๋ฒˆ ์ƒ‰์ƒ์„ ์‚ฌ์šฉํ•œ๋‹ค๋Š” ์˜๋ฏธ์ž…๋‹ˆ๋‹ค.

+

์ปฌ๋Ÿฌ ํŒ”๋ ˆํŠธ) ํ˜น์€ ์ธ๋ฑ์Šค ํŒ”๋ ˆํŠธ๋Š” ์•„ํƒ€๋ฆฌ 800, Amiga, NES, ์Šˆํผ ๋‹Œํ…๋„, ๊ตฌํ˜• IBM PC ๋“ฑ ๊ตฌํ˜• ์‹œ์Šคํ…œ์—์„œ ์‚ฌ์šฉํ•˜๋˜ ๊ธฐ๋ฒ•์ž…๋‹ˆ๋‹ค. ๋น„ํŠธ๋งต์„ ์ƒ‰์ƒ๋‹น 8๋น„ํŠธ ํ˜น์€ 32๋ฐ”์ดํŠธ ์ด์ƒ์˜ RGBA ์ƒ‰์ƒ์œผ๋กœ ์ ์šฉํ•˜๋Š” ๋Œ€์‹  ๋น„ํŠธ๋งต์„ 8๋น„ํŠธ ์ดํ•˜์˜ ๊ฐ’์œผ๋กœ ์ €์žฅํ•˜๋Š” ๊ธฐ๋ฒ•์ด์ฃ . ๊ฐ ํ”ฝ์…€์˜ ์ƒ‰์ƒ๊ฐ’์€ ํŒ”๋ ˆํŠธ์˜ ์ธ๋ฑ์Šค ๊ฐ’์œผ๋กœ, ํ”ฝ์…€์˜ ์ƒ‰์ƒ๊ฐ’์ด 3์ด๋ผ๋ฉด ํŠน์ • "ํŒ”๋ ˆํŠธ"์˜ 3๋ฒˆ ์ƒ‰์ƒ์„ ์‚ฌ์šฉํ•œ๋‹ค๋Š” ์˜๋ฏธ์ž…๋‹ˆ๋‹ค.

์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋กœ ์„ค๋ช…ํ•˜์ž๋ฉด ์•„๋ž˜์™€ ๊ฐ™์€ ํ˜•์‹์„ ์ƒ๊ฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

const face7x7PixelImageData = [
   0, 1, 1, 1, 1, 1, 0,
-  1, 0, 0, 0, 0, 0, 1, 
+  1, 0, 0, 0, 0, 0, 1,
   1, 0, 2, 0, 2, 0, 1,
   1, 0, 0, 0, 0, 0, 1,
   1, 0, 3, 3, 3, 0, 1,
@@ -334,19 +334,19 @@ 

ํ”ผํ‚น๊ณผ ์ƒ‰์ƒ์— ์ธ๋ฑ์Šค ํ…์Šค์ฒ˜ ์‚ฌ์šฉํ•˜๊ธฐ

const maxNumCountries = 512;
 const paletteTextureWidth = maxNumCountries;
 const paletteTextureHeight = 1;
-const palette = new Uint8Array(paletteTextureWidth * 3);
+const palette = new Uint8Array(paletteTextureWidth * 4);
 const paletteTexture = new THREE.DataTexture(
-    palette, paletteTextureWidth, paletteTextureHeight, THREE.RGBFormat);
+    palette, paletteTextureWidth, paletteTextureHeight);
 paletteTexture.minFilter = THREE.NearestFilter;
 paletteTexture.magFilter = THREE.NearestFilter;
 
-

DataTexture๋ฅผ ์“ฐ๋ฉด ํ…์Šค์ฒ˜๋ฅผ ๋กœ์šฐ-๋ฐ์ดํ„ฐ(raw data) ํ˜•์‹์œผ๋กœ ๋„˜๊ธธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ์ œ์˜ ๊ฒฝ์šฐ์—๋Š” 512 RGB ์ƒ‰์ƒ์„ ๋„˜๊ฒจ์ฃผ๋ฉด ๋˜๊ฒ ์ฃ . ๊ฐ ๊ฐ’์€ 3๋ฐ”์ดํŠธ๋กœ, ์ด ๋ฐ”์ดํŠธ๋Š” ๊ฐ๊ฐ red, green, blue์„ 0๋ถ€ํ„ฐ 255๊นŒ์ง€์˜ ์ˆซ์ž๋กœ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.

+

DataTexture๋ฅผ ์“ฐ๋ฉด ํ…์Šค์ฒ˜๋ฅผ ๋กœ์šฐ-๋ฐ์ดํ„ฐ(raw data) ํ˜•์‹์œผ๋กœ ๋„˜๊ธธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ์ œ์˜ ๊ฒฝ์šฐ์—๋Š” 512 RGBA ์ƒ‰์ƒ์„ ๋„˜๊ฒจ์ฃผ๋ฉด ๋˜๊ฒ ์ฃ . ๊ฐ ๊ฐ’์€ 3๋ฐ”์ดํŠธ๋กœ, ์ด ๋ฐ”์ดํŠธ๋Š” ๊ฐ๊ฐ red, green, blue์„ 0๋ถ€ํ„ฐ 255๊นŒ์ง€์˜ ์ˆซ์ž๋กœ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.

์ผ๋‹จ์€ ๋ฌด์ž‘์œ„๋กœ ์ƒ‰์„ ์ง€์ •ํ•ด ์ž˜ ์ž‘๋™ํ•˜๋Š”์ง€ ํ…Œ์ŠคํŠธํ•ด๋ด…์‹œ๋‹ค.

for (let i = 1; i < palette.length; ++i) {
   palette[i] = Math.random() * 256;
 }
 // ๋ฐ”๋‹ค์˜ ์ƒ‰์„ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค. (index #0)
-palette.set([100, 200, 255], 0);
+palette.set([100, 200, 255, 255], 0);
 paletteTexture.needsUpdate = true;
 

palette ๋ฐฐ์—ด๋กœ ํŒ”๋ ˆํŠธ ํ…์Šค์ฒ˜๋ฅผ ์—…๋ฐ์ดํŠธํ•  ๋•Œ๋งˆ๋‹ค ์žฅ๋ฉด์„ ์—…๋ฐ์ดํŠธํ•ด์•ผ ํ•˜๋‹ˆ paletteTexture.needsUpdate๋ฅผ true๋กœ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.

@@ -375,7 +375,9 @@

ํ”ผํ‚น๊ณผ ์ƒ‰์ƒ์— ์ธ๋ฑ์Šค ํ…์Šค์ฒ˜ ์‚ฌ์šฉํ•˜๊ธฐ

const tempColor = new THREE.Color();
 function get255BasedColor(color) {
   tempColor.set(color);
-  return tempColor.toArray().map(v => v * 255);
+  const base = tempColor.toArray().map(v => v * 255);
+  base.push(255); // alpha
+  return base;
 }
 

์œ„ ํ•จ์ˆ˜๋ฅผ color = get255BasedColor('red')์™€ ๊ฐ™์€ ์‹์œผ๋กœ ํ˜ธ์ถœํ•˜๋ฉด [255, 0, 0] ์ด๋Ÿฐ ์‹์˜ ๋ฐฐ์—ด์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

@@ -386,7 +388,7 @@

ํ”ผํ‚น๊ณผ ์ƒ‰์ƒ์— ์ธ๋ฑ์Šค ํ…์Šค์ฒ˜ ์‚ฌ์šฉํ•˜๊ธฐ

resetPalette(); function setPaletteColor(index, color) { - palette.set(color, index * 3); + palette.set(color, index * 4); } function resetPalette() { @@ -534,11 +536,11 @@

ํ”ผํ‚น๊ณผ ์ƒ‰์ƒ์— ์ธ๋ฑ์Šค ํ…์Šค์ฒ˜ ์‚ฌ์šฉํ•˜๊ธฐ

- + - \ No newline at end of file +