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;
}