El recuperación de datos de píxeles del sombreador de fragmento resulta en un comportamiento inesperado -- javascript campo con glsl campo con processing campo con shader campo con p5.js camp Relacionados El problema

Recuperating pixel data from fragment shader results in unexpected behavior


3
vote

problema

Español

Actualmente estoy tratando de usar un sombreador de fragmento para transportar algunos datos de posición de partículas (y en el futuro, modificarla). No tengo ningún problema en enviar los datos al sombreador con una textura Sampler2D, pero cuando intento recuperar los datos, mis 20 partículas de repente tienen las posiciones incorrectas. He imprimido tantas salidas como sea posible y he minimizado el código tanto como puedo todavía no puedo entender dónde estoy equivocado.

Una versión minimizada reproducible está disponible en el sitio web de P5JS aquí

Aquí está mi Sketch.js:

  let theShader; let shaderTexture;  let NUM_PARTICLES = 20; let particleTexture; let particles = [];  function preload(){     theShader = loadShader('basic.vert', 'basic.frag'); }  function setup() {   createCanvas(400, 400, WEBGL);      // Initiate Particles   for(let i = 0; i < NUM_PARTICLES;i++){     particles.push(createVector(i*20,i*20,0));   }      // Initialize Shader   shaderTexture = createGraphics(NUM_PARTICLES, 1, WEBGL);   shaderTexture.noStroke();      // Create Particle Texture   particleTexture = createImage(NUM_PARTICLES, 1);      // Fill Particle Texture   particleTexture.loadPixels();   for (let i = 0; i < NUM_PARTICLES; i++) {        particleTexture.pixels[i*4+0] = map(particles[i].x,0,width,0,255); // R     particleTexture.pixels[i*4+1] = map(particles[i].y,0,height,0,255); // G     particleTexture.pixels[i*4+2] = 0; // B     particleTexture.pixels[i*4+3] = 255; // A   }   particleTexture.updatePixels(); }  function draw() {     translate(-width/2, -height/2);   background(255);      // Display Particles Before Modification   for(let i = 0; i < NUM_PARTICLES;i++){     circle(particles[i].x,particles[i].y,10); // draw circle at particle location   }    // Apply Texture   shaderTexture.shader(theShader); // set shader   theShader.setUniform('text', particleTexture); // send particleTexture to shader   shaderTexture.rect(0,0,NUM_PARTICLES,1); // set rect to recieve shader out      // Print Shader Output   for(let i = 0; i < NUM_PARTICLES;i++){     let newPos = shaderTexture.get(i, 0);     print(newPos);   }      // Update and Display Particles   for(let i = 0; i < NUM_PARTICLES;i++){     let newPos = shaderTexture.get(i, 0);     particles[i].x = map(newPos[0],0,255,0,width);     particles[i].y = map(newPos[1],0,255,0,height);     fill(255,0,0);     circle(particles[i].x,particles[i].y,10);   }    noLoop(); }   

y aquí está mi shader fragmento que no debe modificarse nada:

  #ifdef GL_ES precision highp float; #endif  uniform sampler2D text;  void main() {   vec2 particle = texture2D(text, vec2(gl_FragCoord.x, gl_FragCoord.y)).xy;    gl_FragColor = vec4(particle.x,particle.y,0.0,1.0); // R,G,B,A }   

también mi shader de vértice que es predeterminado:

  #ifdef GL_ES precision highp float; #endif  attribute vec3 aPosition;  void main() {   vec4 positionVec4 = vec4(aPosition, 1.0);    positionVec4.xy = positionVec4.xy * 2.0 - 1.0;     gl_Position = positionVec4; }   
Original en ingles

I'm currently trying to use a fragment shader to transport some particle position data (and in the future, modify it). I have no problem sending the data to the shader using a sampler2D texture, but when I try to recuperate the data, My 20 particles suddenly have the wrong positions. I've printed as many outputs as possible and have minimized the code as much as I can yet still fail to understand where I'm wrong.

a reproducible minimized version is available on the p5js website here

Here is my sketch.js :

let theShader; let shaderTexture;  let NUM_PARTICLES = 20; let particleTexture; let particles = [];  function preload(){     theShader = loadShader('basic.vert', 'basic.frag'); }  function setup() {   createCanvas(400, 400, WEBGL);      // Initiate Particles   for(let i = 0; i < NUM_PARTICLES;i++){     particles.push(createVector(i*20,i*20,0));   }      // Initialize Shader   shaderTexture = createGraphics(NUM_PARTICLES, 1, WEBGL);   shaderTexture.noStroke();      // Create Particle Texture   particleTexture = createImage(NUM_PARTICLES, 1);      // Fill Particle Texture   particleTexture.loadPixels();   for (let i = 0; i < NUM_PARTICLES; i++) {        particleTexture.pixels[i*4+0] = map(particles[i].x,0,width,0,255); // R     particleTexture.pixels[i*4+1] = map(particles[i].y,0,height,0,255); // G     particleTexture.pixels[i*4+2] = 0; // B     particleTexture.pixels[i*4+3] = 255; // A   }   particleTexture.updatePixels(); }  function draw() {     translate(-width/2, -height/2);   background(255);      // Display Particles Before Modification   for(let i = 0; i < NUM_PARTICLES;i++){     circle(particles[i].x,particles[i].y,10); // draw circle at particle location   }    // Apply Texture   shaderTexture.shader(theShader); // set shader   theShader.setUniform('text', particleTexture); // send particleTexture to shader   shaderTexture.rect(0,0,NUM_PARTICLES,1); // set rect to recieve shader out      // Print Shader Output   for(let i = 0; i < NUM_PARTICLES;i++){     let newPos = shaderTexture.get(i, 0);     print(newPos);   }      // Update and Display Particles   for(let i = 0; i < NUM_PARTICLES;i++){     let newPos = shaderTexture.get(i, 0);     particles[i].x = map(newPos[0],0,255,0,width);     particles[i].y = map(newPos[1],0,255,0,height);     fill(255,0,0);     circle(particles[i].x,particles[i].y,10);   }    noLoop(); } 

and here is my fragment shader which should not be modifying anything :

#ifdef GL_ES precision highp float; #endif  uniform sampler2D text;  void main() {   vec2 particle = texture2D(text, vec2(gl_FragCoord.x, gl_FragCoord.y)).xy;    gl_FragColor = vec4(particle.x,particle.y,0.0,1.0); // R,G,B,A } 

also my vertex shader which is default :

#ifdef GL_ES precision highp float; #endif  attribute vec3 aPosition;  void main() {   vec4 positionVec4 = vec4(aPosition, 1.0);    positionVec4.xy = positionVec4.xy * 2.0 - 1.0;     gl_Position = positionVec4; } 
              

Lista de respuestas

4
 
vote
vote
La mejor respuesta
 

Al buscar una textura con texture2D Las coordenadas de la textura deben especificarse en el rango [0.0, 1.0]. (0, 0) es la parte inferior izquierda y (1, 1) es la parte superior derecha. Sin embargo, gl_FragCoord.xy Contiene las coordenadas de la ventana, con la parte superior izquierda (0.5, 0.5) y la parte superior derecha (ancho-0.5, altura-0.5).
Por lo tanto, debe dividir gl_FragCoord por el tamaño de la ventana. Desde que se basa en un rectángulo con el tamaño num_Particlesx1 (ancho == num_plarticles, altura = 1), debe dividir gl_FragCoord.x por num_particles : < / p>

vec2 particle = texture2D(text, vec2(gl_FragCoord.x, gl_FragCoord.y)).xy;

  vec2 particle = texture2D(text, vec2(gl_FragCoord.x/20.0, 0.0)).xy;   

Alternativamente, puede agregar un 99887776610 uniforme al sombreador de fragmento y dividir %macro test_me(param=); %if %sysevalf(%superq(param)=,boolean) %then %put Empty; %else %put Not Empty;; %mend test_me; %test_me(param=); %test_me(param=MyParam); %test_me(param=param=5); 1111 por %macro test_me(param=); %if %sysevalf(%superq(param)=,boolean) %then %put Empty; %else %put Not Empty;; %mend test_me; %test_me(param=); %test_me(param=MyParam); %test_me(param=param=5); 2 :

  %macro test_me(param=);    %if %sysevalf(%superq(param)=,boolean) %then %put Empty;   %else %put Not Empty;; %mend test_me;  %test_me(param=); %test_me(param=MyParam); %test_me(param=param=5); 3  

Establecer el valor del %macro test_me(param=); %if %sysevalf(%superq(param)=,boolean) %then %put Empty; %else %put Not Empty;; %mend test_me; %test_me(param=); %test_me(param=MyParam); %test_me(param=param=5); 4 uniforme por %macro test_me(param=); %if %sysevalf(%superq(param)=,boolean) %then %put Empty; %else %put Not Empty;; %mend test_me; %test_me(param=); %test_me(param=MyParam); %test_me(param=param=5); 5 :

  %macro test_me(param=);    %if %sysevalf(%superq(param)=,boolean) %then %put Empty;   %else %put Not Empty;; %mend test_me;  %test_me(param=); %test_me(param=MyParam); %test_me(param=param=5); 6  


Si está utilizando OpenGL ES Idioma de sombreado 3.00 Tiene la opción de usarla %macro test_me(param=); %if %sysevalf(%superq(param)=,boolean) %then %put Empty; %else %put Not Empty;; %mend test_me; %test_me(param=); %test_me(param=MyParam); %test_me(param=param=5); 7 para buscar la textura con coordenadas de píxeles integrales u obtener el tamaño de la textura usando %macro test_me(param=); %if %sysevalf(%superq(param)=,boolean) %then %put Empty; %else %put Not Empty;; %mend test_me; %test_me(param=); %test_me(param=MyParam); %test_me(param=param=5); 8 .
Lamentablemente p5.js ( %macro test_me(param=); %if %sysevalf(%superq(param)=,boolean) %then %put Empty; %else %put Not Empty;; %mend test_me; %test_me(param=); %test_me(param=MyParam); %test_me(param=param=5); 9 ) no parece proporcionar un contexto de WebGl 2.0 , así que esta no es una opción.

 

When looking up a texture with texture2D the texture coordinates must be specified in range [0.0, 1.0]. (0, 0) is the bottom left and (1, 1) is the top right. However gl_FragCoord.xy contains window coordinates, with top left (0.5, 0.5) and top right (width-0.5, height-0.5).
Hence you need to divide gl_FragCoord by the size of the viewport. Since you draw on a rectangle with the size NUM_PARTICLESx1 (width == NUM_PARTICLES, height = 1), you must divide gl_FragCoord.x by NUM_PARTICLES:

vec2 particle = texture2D(text, vec2(gl_FragCoord.x, gl_FragCoord.y)).xy;

vec2 particle = texture2D(text, vec2(gl_FragCoord.x/20.0, 0.0)).xy; 

Alternatively you can add a size uniform to the fragment shader and divide gl_FragCoord.xy by size:

#ifdef GL_ES precision highp float; #endif  uniform sampler2D text; uniform vec2 size;  void main() {      vec2 particle = texture2D(text, gl_FragCoord.xy / size).xy;    gl_FragColor = vec4(particle.x,particle.y,0.0,1.0); // R,G,B,A } 

Set the value of the size uniform by [NUM_PARTICLES, 1]:

// Apply Texture shaderTexture.shader(theShader); // set shader theShader.setUniform('text', particleTexture); // send particleTexture to shader theShader.setUniform('size', [NUM_PARTICLES, 1]); shaderTexture.rect(0,0,NUM_PARTICLES,1); // set rect to recieve shader out 


If you are using OpenGL ES Shading Language 3.00 you have the option to use texelFetch to lookup the texture with integral pixel coordinates or get the size of the texture using textureSize.
Unfortunately p5.js (createCanvas()) doesn't seem to provide a WebGL 2.0 context, so this is not an option.

 
 

Relacionados problema

0  ERROR DE TENSORFLOW: Construir el tensor de la forma (120800) debe coincidir con la longitud de los valores (121881)  ( Tensorflow error constructing tensor of shape 120800 should match the length ) 
Soy nuevo en la máquina y nuevo en TensorFlow. Como método de aprendizaje, he estado siguiendo con Dan Shiffman del tren de codificación, ya que muestra cómo ...

1  Dos matrices de prueba de igualdad [duplicar]  ( Two arrays equality test ) 
Esta pregunta ya tiene respuestas aquí : ¿Cómo comparar matrices en JavaScript? ...

0  El texto que estoy dibujando a HTML está parpadeando P5JS  ( Text i am drawing to html is blinking p5js ) 
Estoy asumiendo que esto se debe a que el bucle de dibujo está dibujando cada X cantidad de segundos. ¿Cómo puedo reducir la velocidad o evitar que se actua...

0  LoadJson con Lat y Lon y obtén las variables  ( Loadjson with lat and lon and get the variables ) 
Estoy cargando el archivo JSON y quiero tomar las variables de latitud y longitud del archivo. Lo estoy haciendo con deja que lat = row.get ('lat'); pero no...

1  ¿Cuál es la mejor manera de cambiar el lienzo P5.JS dinámicamente en la misma página web?  ( What is the best way to change p5 js canvas dynamically in the same webpage ) 
Estoy tratando de desarrollar una página web que me permita cambiar el lienzo P5.JS y también la disposición del deslizador con solo seleccionar una opción d...

1  Problemas, utilizando métodos de ancho y altura p5.js dentro de un objeto  ( Problems using p5 js width and height methods inside an object ) 
Hola, tengo problemas para entender dónde y dónde no puedo usar los métodos P5.js. En este codepen , camelot2 Si reemplace los valores X e Y dentro de ...

1  ¿Cómo puedo mantener una imagen diferente en cada lado de la caja () en p5.js?  ( How do i is it posssible to keep different picture in each side of box in p5 ) 
Como principiante en p5.js, estoy tratando de hacer dados interactivos, donde el único problema ahora está guardando caras diferentes en cada lado en el cubo....

1  Sistema de partículas dentro de un dibujo en p5.js  ( Particle system within a drawing in p5 js ) 
Estoy tratando de crear un sistema de partículas dentro de un dibujo de forma básica. Las partículas deben emitir desde la parte superior de la estructura más...

0  p5.js no está cargando mi elipse  ( P5 js is not loading my ellipse ) 
Estoy tratando de dibujar una elipse para simular un pájaro en un pájaro de flappy. El elipse que estoy dibujo no está cargando en mi pantalla, he comprobado ...

1  La función p5.js clara () no funciona correctamente en dispositivos móviles y algunos navegadores  ( P5 js clear function is not working properly in mobile and some browsers ) 
El HTML que he usado es muy simple que se da a continuación: <!doctype html> <html> <head> <meta charset="UTF-8"> <meta name="viewport" c...




© 2022 respuesta.top Reservados todos los derechos. Centro de preguntas y respuestas reservados todos los derechos