читать и писать в разные текстуры в одном буфере кадра - PullRequest
0 голосов
/ 28 мая 2020

Возможно ли чтение из текстуры A и запись в текстуру B, которые используют один и тот же FBO? Я не верю, что это уже было описано здесь. Кто-то задал вопрос о OpenGL , но не о WebGL. Похоже, что ответ отрицательный, основываясь на ответе на этот пост , но если бы кто-то мог сказать мне окончательно, возможно ли чтение / запись текстур в том же fbo, это действительно помогло бы мне. В моем коде я получаю следующую ошибку:

Предупреждение WebGL: drawElementsInstanced: Уровень текстуры 0 будет прочитан модулем 0 TEXTURE_2D, но записан вложенным фреймбуфером COLOR_ATTACHMENT1, что будет недопустимой обратной связью.

следующий фрагмент кода генерирует предупреждение о недопустимой обратной связи. Я знаю, что код может не выглядеть / не быть полезным, но дело в выполнении чтения / записи. Подводя итог тому, что я ожидаю, следует использовать текстуру A (или называть ее текстурой 1) для рендеринга текстуры B (также известной как текстура 2). Тогда я должен что-то увидеть на экране; скорее всего 4 квадрата жадности:

/* YOU CAN PROBABLY IGNORE THIS AS IT'S INITIALIZATION CODE */

const canvas = document.querySelector('canvas');
const gl = canvas.getContext('webgl2');
var fb;
var textures = [];

var tex_datei1 = new Array( 4*64*64 ).fill(9);

var vbo = gl.createBuffer();
gl.bindBuffer( gl.ARRAY_BUFFER , vbo );

var vertices = new Array( 4*64*64 ).fill( 0 );

gl.bindBuffer( gl.ARRAY_BUFFER , vbo );
gl.bufferData( gl.ARRAY_BUFFER , new Float32Array( vertices ) , gl.STATIC_DRAW );

var ibo = gl.createBuffer();
gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER , ibo );

var indices = [ ...Array( vertices.length/4 ).keys() ];
indices[0] = 0;
indices[1] = 1;
indices[2] = 2;
indices[3] = 2;
indices[4] = 3;
indices[5] = 1;
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array( indices ), gl.STATIC_DRAW);

var vc = `#version 300 es
 precision mediump float;

 uniform sampler2D u_image0;
 uniform sampler2D u_image1;

 in vec3 coordinates;

void main(void) {

  float x = coordinates.x;
  float y = coordinates.y;

  vec4 sample_A = texture( u_image0 , vec2( x , y ) );
  sample_A.x *= 64.0 * 4.0;
  sample_A.y *= 64.0 * 4.0;

  gl_Position = vec4( sample_A.x/10.0 , sample_A.y/10.0 , 0.0 , 1.0 );

  gl_PointSize = 30.0;

}
`;

var vs = gl.createShader( gl.VERTEX_SHADER );
gl.shaderSource( vs , vc );
gl.compileShader(vs);
if( !gl.getShaderParameter( vs , gl.COMPILE_STATUS ) ){
  console.log( gl.COMPILE_STATUS );
  console.log( gl.getShaderInfoLog(vs) );
}

var fc = `#version 300 es
precision highp float;
out vec4 color;
void main(void) {
  color = vec4( 0.5 , 0.5 , 0.0 , 1.0 );
}
`;

var fs = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fs, fc);
gl.compileShader(fs);
if( !gl.getShaderParameter( fs , gl.COMPILE_STATUS ) ){
  console.log( gl.COMPILE_STATUS );
  console.log( gl.getShaderInfoLog(fs) );
}

var program = gl.createProgram();
gl.attachShader(program, vs);
gl.attachShader(program, fs);
gl.linkProgram(program);
gl.useProgram( program);

var coordinates_u_loc = gl.getAttribLocation(program, "coordinates");
var u_image0_loc = gl.getUniformLocation( program , "u_image0");
var die_berechnung_u_image1Location = gl.getUniformLocation( program , "u_image1");

gl.bindBuffer( gl.ARRAY_BUFFER , vbo );
gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER , ibo );
gl.enableVertexAttribArray( coordinates_u_loc );
gl.vertexAttribPointer( coordinates_u_loc , 4 , gl.FLOAT , false , 0 , 0 );
 
 
 
 
 
 
 
 
/* HERE IS WHERE I GET INTO FRAMEBUFFER SETUP */

fb = gl.createFramebuffer();
gl.bindFramebuffer( gl.FRAMEBUFFER , fb );


gl.uniform1i( u_image0_loc , 0);
//gl.uniform1i( u_image1_loc , 1);


var internal_formats = [ gl.RGBA , gl.RGBA ];
var formats = [ gl.RGBA , gl.RGBA ];
var types = [ gl.UNSIGNED_BYTE , gl.UNSIGNED_BYTE ];

var datas = [ new Uint8Array( tex_datei1.slice() ) , new Uint8Array( tex_datei1.slice() ) ];

for( var i = 0 ; i < datas.length ; i++ ){

  var texture = gl.createTexture();
  gl.bindTexture( gl.TEXTURE_2D , texture );

  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);

  gl.texImage2D( gl.TEXTURE_2D ,
    0 ,
    internal_formats[i] ,
    64 ,
    64 ,
    0 ,
    formats[ i ] ,
    types[ i ] ,
    datas[ i ]
  );

  textures.push( texture );

 }

/* HERE MAY LIE MY ISSUE AS I HAVE NO IDEA HOW TO SPECIFY THAT THE SECOND TEXTURE SHOULD BE WRITTEN TO. I'VE TRIED MESSING AROUND WITH THE LAYERS PARAMETER BUT THAT JUST CREATES MIPS ISSUES. */

gl.bindTexture( gl.TEXTURE_2D , textures[ 0 ] );
var attachmentPoint = gl.COLOR_ATTACHMENT0;
gl.framebufferTexture2D( gl.FRAMEBUFFER , attachmentPoint , gl.TEXTURE_2D , textures[ 0 ] , 0 );

gl.bindTexture( gl.TEXTURE_2D , textures[ 1 ] );
var attachmentPoint = gl.COLOR_ATTACHMENT1;
gl.framebufferTexture2D( gl.FRAMEBUFFER , attachmentPoint , gl.TEXTURE_2D , textures[ 1 ] , 0 );

var er = gl.checkFramebufferStatus( gl.FRAMEBUFFER );
if( er !== 36053 ){
  console.log( er );
}








 /* DRAW */

 gl.clearColor( 0.0 , 0.0 , 0.0 , 0.0 );
 gl.enable( gl.DEPTH_TEST );
 gl.clear( gl.COLOR_BUFFER_BIT );

 gl.viewport( 0,0, 64 , 64 );

 gl.activeTexture(gl.TEXTURE1);
 gl.bindTexture(gl.TEXTURE_2D, textures[1] );

 gl.drawElements( gl.POINTS , indices.length , gl.UNSIGNED_SHORT , 0 );
										
<!DOCTYPE html>
<html>
    <head>
        
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <body>
      <canvas width="64" heigh="64" style="width:64px; height:64px; border:thick solid #0000FF; "></canvas>

    </body>
    
</html>

1 Ответ

1 голос
/ 30 мая 2020

Возможно ли чтение из текстуры A и запись в текстуру B, которые обе используют один и тот же FBO

Нет, это невозможно. Зачем вам это нужно?

Чего вы пытаетесь достичь sh? Иногда писать А, а иногда Б? Если так, сделайте 2 фбос. fboA и fboB, прикрепите текстуру A к fboA и B к fboB. Когда вы хотите записать в А привязку fboA. Если вы хотите записать в B, привяжите fboB. Если вы иногда хотите писать в оба, сделайте fboAB и присоедините к нему A и B.

Как бы то ни было, код не настроен на запись в B, когда у вас есть обе текстуры. См .: WebGL 2.0: несколько текстур вывода из одной программы

обновление

Код прикрепляет texture[0] и texture[1] к фреймбуферу. Итак, на данный момент оба texture[0] и texture[1] настроены для записи. Также в этот момент texture[1] привязан к текстурному блоку 0 для чтения.

Шейдер ссылается только на одну текстуру, хотя он объявляет и u_image0, и u_image1, вы никогда не используете u_image1.

Затем код назначает texture[1] текстурному блоку 1, но никогда не устанавливает u_image0, поэтому u_image0 использует текстурный блок 0, так как по умолчанию для униформ установлено значение 0.

Тогда код вызывает gl.drawArrays. Поскольку буфер кадра использует для записи как texture[0], так и texture[1], а шейдер использует texture[1] в текстурном блоке 0 для чтения, это обратная связь l oop, и поэтому код получает ошибку.

Вот сценарий, который вы можете вставить в верхнюю часть фрагмента HTML

<script src="https://greggman.github.io/webgl-helpers/webgl-check-framebuffer-feedback.js"></script>

из https://greggman.github.io/webgl-helpers/

Когда я это сделаю и проверю JavaScript console Я вижу эту ошибку

Неперехваченная ошибка: обратная связь WebGL l oop: текстура на униформе: u_image0, привязанный к текстурному блоку 0, также прикрепляется к текущему фреймбуферу во вложении: COLOR_ATTACHMENT1

Если вы хотите использовать текстуру A для генерации текстуры B, тогда во время инициализации вы присоединяете B и только B к объекту фреймбуфера

// at init time
const fb = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0,
                        gl.TEXTURE_2D, textureB, 0);

Затем во время рендеринга вы привязываете этот фреймбуфер

// make gl.drawXXX write to textureB
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);

Привязать текстуру A к некоторому текстурному блоку.

const unit = 7;
gl.activeTexture(gl.TEXTURE0 + unit);
gl.bindTexture(gl.TEXTURE, textureA); 

Сообщите сэмплеру шейдера, на какой блок вы накладываете текстуру

gl.uniform1i(u_image0Location, unit);

Подробнее здесь

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...