Как вы визуализируете R8UI, RedIntegerFormat, тип без подписи WebGLRenderTarget?

#javascript #three.js #webgl #webgl2

Вопрос:

Я пытаюсь выполнить рендеринг для одного компонента 8-битной цели рендеринга в three.js но я получаю ряд ошибок, которые я не знаю, как решить, и поиск, похоже, не дает много других совпадений. WebGLRenderTarget создается со следующими параметрами:

 format: THREE.RedIntegerFormat,
type: THREE.UnsignedByteType,
internalFormat: 'R8UI',
minFilter: THREE.NearestFilter,
magFilter: THREE.NearestFilter,
 

При рендеринге в целевой объект рендеринга, а затем при попытке скопировать его на экран я получаю следующие ошибки WebGL:

 GL_INVALID_OPERATION: No defined conversion between clear value and attachment format.
GL_INVALID_OPERATION: Fragment shader output type does not match the bound framebuffer attachment type.
GL_INVALID_OPERATION: Mismatch between texture format and sampler type (signed/unsigned/float/shadow).
 

Вот пример повторения проблемы, которую я вижу:

 <script type="module">
import * as THREE from 'https://cdn.skypack.dev/three'
import { FullScreenQuad } from 'https://cdn.skypack.dev/three/examples/jsm/postprocessing/Pass.js'

let camera, scene, renderer;
let geometry, material, mesh;
let renderTarget, fsQuad;

class FinalMaterial extends THREE.ShaderMaterial {

  constructor() {
  
    super( {

      uniforms: {

        map: { value: null }

      },

      vertexShader: /* glsl */`

        varying vec2 vUv;

        void main() {

          vUv = uv;
          gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );

        }`,

      fragmentShader: /* glsl */`

        uniform sampler2D map;

        varying vec2 vUv;

        void main() {

          vec4 texel = texture2D( map, vUv );
          gl_FragColor = texel;

        }`

    } );

  }

}

init();

function init() {

    camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 0.01, 10 );
    camera.position.z = 1;

    scene = new THREE.Scene();

    geometry = new THREE.BoxGeometry( 0.2, 0.2, 0.2 );
    material = new THREE.MeshNormalMaterial();

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

    renderer = new THREE.WebGLRenderer( { antialias: true } );
    renderer.setSize( window.innerWidth, window.innerHeight );
    renderer.setAnimationLoop( animation );
    document.body.appendChild( renderer.domElement );
    
    renderTarget = new THREE.WebGLRenderTarget(
        window.innerWidth,
      window.innerHeight,
      {
        format: THREE.RedIntegerFormat,
        type: THREE.UnsignedByteType,
        internalFormat: 'R8UI',
        minFilter: THREE.NearestFilter,
        magFilter: THREE.NearestFilter,
        }
    );
    
    renderTarget.texture.internalFormat = 'R8UI';
    
    fsQuad = new FullScreenQuad( new FinalMaterial() );
    fsQuad.material.uniforms.map.value = renderTarget.texture;

}

function animation( time ) {

    mesh.rotation.x = time / 2000;
    mesh.rotation.y = time / 1000;

    renderer.setRenderTarget( renderTarget );
    renderer.render( scene, camera );
    
    renderer.setRenderTarget( null );
    fsQuad.render( renderer );

}
</script> 

Комментарии:

1. Если это вам поможет, я запустил ваш фрагмент в Firefox и получил больше описательных ошибок . Похоже, что источником является UINT, а пунктом назначения является FLOAT, и наоборот.

2. @Marquizzo Спасибо! Я думаю, что понимаю немного больше о том, что происходит сейчас, но суть в том, что в основном three.js не поддерживает очистку или рендеринг для целочисленных целей рендеринга. Он не использует правильные четкие функции, и система шейдеров не настроена для записи целочисленных значений. Я сделал пару пиаров, чтобы улучшить three.js-тем не менее, поддерживаю это, так что в какой-то момент это может оказаться возможным.