What is relation between type and format of texture

懵懂的女人 提交于 2021-01-28 13:43:42

问题


I am working on volumetric rendering raw data in three.js. I have a hard time understanding the relationship between the type and format of the texture (in my case it is texture3d) in three.js.

Available type of texture type are :

and available format are:

I tried to put type as THREE.UnsignedIntType for u8int datatype of raw data but it gives invalid internalformat of texture error but everything works fine with type of THREE.UnsignedByteType.

this is my code of texture,

    var texture = new THREE.DataTexture3D(data, dims[0], dims[1], dims[2]);
    texture.format = THREE.RedFormat;
    texture.type = THREE.UnsignedByteType;

Could anyone please say how both are related. I cannot make static since the raw data type can be of any bit (8/16/32) and type(int/float).


回答1:


The three.js texture format and types are aliases for the WebGL formats and types. Only certain combinations are allowed.

The list of valid combinations for WebGL1 is

| format          | type
+-----------------+------
| RGBA            | UNSIGNED_BYTE
| RGB             | UNSIGNED_BYTE
| RGBA            | UNSIGNED_SHORT_4_4_4_4
| RGBA            | UNSIGNED_SHORT_5_5_5_1
| RGB             | UNSIGNED_SHORT_5_6_5
| LUMINANCE_ALPHA | UNSIGNED_BYTE
| LUMINANCE       | UNSIGNED_BYTE
| ALPHA           | UNSIGNED_BYTE

So translating that to three.js is

| format               | type
+----------------------+------
| RGBAFormat           | UnsignedByteType
| RGBFormat            | UnsignedByteType
| RGBAFormat           | UnsignedShort4444
| RGBAFormat           | UnsignedShort5551
| RGBFormat            | UnsignedShort565
| LuminanceAlphaFormat | UnsignedByteType
| LuminanceFormat      | UnsignedByteType
| AlphaFormat          | UnsignedByteType

Note: WebGL1 does not support 3D textures directly although you can implement them yourself via creative shaders

WebGL2 allows a much larger list of combinations

Note that the format/type combination is the format and type of the data you are supplying to three.js, not the format of the texture that data will be stored in.

To specify the internal format you set texture.internalFormat. To specify format and type you can set texture.format and texture.type

Only certain combinations of format/type can be used as input for a given internal format. See the link above for the list.

If you want 1 channel unsigned int texture you need to set

texture.internalFormat = 'R32UI';
texture.format = THREE.RedIntegerFormat;
texture.type = THREE.UnsignedIntType;

You'll also need to make sure you set texture.minFilter and texture.magFilter to THREE.NearestFilter and you'll need to make sure your shaders use uniform usampler3D someSamplerName;

<canvas id="c"></canvas>
<script type="module">
import * as THREE from 'https://threejsfundamentals.org/threejs/resources/threejs/r115/build/three.module.js';

function main() {
  const canvas = document.querySelector('#c');
  const context = canvas.getContext('webgl2');
  const renderer = new THREE.WebGLRenderer({canvas, context});

  const fov = 75;
  const aspect = 2;  // the canvas default
  const near = 0.1;
  const far = 5;
  const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
  camera.position.z = 2;

  const scene = new THREE.Scene();

  const data = new Uint32Array([1234]);
  const texture = new THREE.DataTexture3D(data, 1, 1, 1);
  texture.internalFormat = 'R32UI';
  texture.format = THREE.RedIntegerFormat;
  texture.type = THREE.UnsignedIntType;

  const boxWidth = 1;
  const boxHeight = 1;
  const boxDepth = 1;
  const geometry = new THREE.BoxGeometry(boxWidth, boxHeight, boxDepth);

  const shader = {
    uniforms: {
      threeD: { value: texture },
    },
    vertexShader: `#version 300 es
      void main() {
        gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
      }
    `,
    fragmentShader: `#version 300 es
      #include <common>

      uniform highp usampler3D threeD;
      out vec4 c;
      
      void main() {
        uvec4 color = texture(threeD, vec3(0));
        // this also works
        // uvec4 color = texelFetch(threeD, ivec3(0), 0);
        c = vec4(float(color.r) / 2468.0, 0, 0, 1);
      }
    `,
  };


  const material = new THREE.ShaderMaterial(shader);

  const cube = new THREE.Mesh(geometry, material);
  scene.add(cube);

  renderer.render(scene, camera);
}

main();
</script>

With RGIntegerFormat and UnsignedByteType you need to use internal format RG8UI and pass your data in as Uint8Array

<canvas id="c"></canvas>
<script type="module">
import * as THREE from 'https://threejsfundamentals.org/threejs/resources/threejs/r115/build/three.module.js';

function main() {
  const canvas = document.querySelector('#c');
  const context = canvas.getContext('webgl2');
  const renderer = new THREE.WebGLRenderer({canvas, context});

  const fov = 75;
  const aspect = 2;  // the canvas default
  const near = 0.1;
  const far = 5;
  const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
  camera.position.z = 2;

  const scene = new THREE.Scene();

// THREE.RGIntegerFormat as format and THREE.UnsignedByteType

  const data = new Uint8Array([11, 22]);
  const texture = new THREE.DataTexture3D(data, 1, 1, 1);
  texture.internalFormat = 'RG8UI';
  texture.format = THREE.RGIntegerFormat;
  texture.type = THREE.UnsignedByteType;
window.t = THREE;
  const boxWidth = 1;
  const boxHeight = 1;
  const boxDepth = 1;
  const geometry = new THREE.BoxGeometry(boxWidth, boxHeight, boxDepth);

  const shader = {
    uniforms: {
      threeD: { value: texture },
    },
    vertexShader: `#version 300 es
      void main() {
        gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
      }
    `,
    fragmentShader: `#version 300 es
      #include <common>

      uniform highp usampler3D threeD;
      out vec4 c;
      
      void main() {
        uvec4 color = texture(threeD, vec3(0));
        // this also works
        // uvec4 color = texelFetch(threeD, ivec3(0), 0);
        c = vec4(vec2(color.rg) / vec2(22), 0, 1);
      }
    `,
  };


  const material = new THREE.ShaderMaterial(shader);

  const cube = new THREE.Mesh(geometry, material);
  scene.add(cube);

  renderer.render(scene, camera);
}

main();
</script>


来源:https://stackoverflow.com/questions/62003464/what-is-relation-between-type-and-format-of-texture

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!