-
-
Notifications
You must be signed in to change notification settings - Fork 3.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
added compute shader #7452
base: dev-2.0
Are you sure you want to change the base?
added compute shader #7452
Conversation
Hi! Have you tried running this in a test sketch (e.g. by editing Some unit tests would also be helpful, e.g. ensuring that the struct is parsed into sizes correctly after creating a shader. |
@davepagurek , I've added tests last 2 tests, ComputeShader setParticles and getParticles and ComputeShader compute function are failing I'm just seeing this: For sketch: let computeShader;
let particleCount = 1000;
function setup() {
createCanvas(800, 600, WEBGL);
computeShader = createComputeShader({
particleCount: particleCount,
particleStruct: {
position: 'vec3',
velocity: 'vec3',
color: 'vec3',
lifetime: 'float'
},
computeFunction: `
#define PI 3.1415926535897932384626433832795
vec3 curlNoise(vec3 p) {
const float e = 0.1;
vec3 dx = vec3(e, 0.0, 0.0);
vec3 dy = vec3(0.0, e, 0.0);
vec3 dz = vec3(0.0, 0.0, e);
vec3 p_x0 = sin(p - dx);
vec3 p_x1 = sin(p + dx);
vec3 p_y0 = sin(p - dy);
vec3 p_y1 = sin(p + dy);
vec3 p_z0 = sin(p - dz);
vec3 p_z1 = sin(p + dz);
float x = p_y1.z - p_y0.z - p_z1.y + p_z0.y;
float y = p_z1.x - p_z0.x - p_x1.z + p_x0.z;
float z = p_x1.y - p_x0.y - p_y1.x + p_y0.x;
return normalize(vec3(x, y, z));
}
Particle compute(Particle p) {
// Apply curl noise to velocity
vec3 noise = curlNoise(p.position * 0.1);
p.velocity += noise * 0.01;
// Update position
p.position += p.velocity;
// Decrease lifetime
p.lifetime -= 0.01;
// Reset particle if lifetime is over
if (p.lifetime <= 0.0) {
p.position = vec3(rand(vTexCoord) * 2.0 - 1.0, rand(vTexCoord.yx) * 2.0 - 1.0, rand(vTexCoord.xy) * 2.0 - 1.0);
p.velocity = vec3(0.0);
p.color = vec3(rand(vTexCoord), rand(vTexCoord.yx), rand(vTexCoord.xy));
p.lifetime = 5.0 + rand(vTexCoord.xy) * 5.0;
}
// Wrap around boundaries
p.position = mod(p.position + vec3(1.0), vec3(2.0)) - vec3(1.0);
return p;
}
`
});
// Initialize particles
let initialParticles = [];
for (let i = 0; i < particleCount; i++) {
initialParticles.push({
position: [random(-1, 1), random(-1, 1), random(-1, 1)],
velocity: [0, 0, 0],
color: [random(), random(), random()],
lifetime: random(5, 10)
});
}
computeShader.setParticles(initialParticles);
}
function draw() {
background(0);
// Compute particle positions
computeShader.compute();
// Get updated particles
let particles = computeShader.getParticles();
// Render particles
push();
noStroke();
for (let p of particles) {
push();
translate(p.position[0] * width/2, p.position[1] * height/2, p.position[2] * 100);
fill(p.color[0] * 255, p.color[1] * 255, p.color[2] * 255, map(p.lifetime, 0, 10, 0, 255));
sphere(2);
pop();
}
pop();
} Honestly, I'm very new to shaders so dont know much about them and I'm a bit confused at this point, can you suggest me a great starting point to look into this issue, it will help me a lot! |
Hi @davepagurek , anything else I need to provide? |
_initCapabilities() { | ||
const gl = this.gl; | ||
|
||
if (gl.getExtension('OES_texture_float') && |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we're using existing p5.Framebuffer, it will get extensions for you, so I think we don't need to do these checks. The logs you're seeing are because we default to WebGL 2, but these extensions only exist in WebGL 1, so your code is currently setting the texture type back to UNSIGNED_BYTE. Do you read float numbers out of the framebuffer if you take these checks out?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes I am reading float numbers
this.inputFramebuffer.begin(); | ||
this.p5.background(0); | ||
this.inputFramebuffer.loadPixels(); | ||
this.inputFramebuffer.pixels.set(data); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another user mentioned this in the issue, but if the alpha channel is <1, currently I think it will multiply the other channels by that value because p5 uses premultiplied alpha on images (not super important that you know why, but if you're curious, the reasoning is here: #5891)
So to do this, I think we need to run gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false)
before setting the pixels, and set it back to false
after.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
got it
Resolves #7345
Changes:
I have added a class for compute shader.
Screenshots of the change:
PR Checklist
npm run lint
passes