#version 430 core //Uniform block containing positions and masses of the attractors layout (std140, binding = 0) uniform attractor_block { vec4 attractor[8]; //xyz = position, w = strength }; //Process particles in blocks of 128 layout (local_size_x = 1024) in; //buffers containing the positions and velocities of the particles layout (rgba32f, binding = 0) uniform imageBuffer velocity_buffer; layout (rgba32f, binding = 1) uniform imageBuffer start_position_buffer; layout (rgba32f, binding = 2) uniform imageBuffer end_position_buffer; //Delta time uniform float dt; uniform vec3 nearTopLeft; uniform vec3 nearBottomRight; uniform vec3 farTopLeft; uniform vec3 farBottomRight; bool insideFrustrum(vec4 point) { //float zRelative = ((point.z - nearBottomRight.z) / (nearBottomRight.z - farBottomRight.z)); //bool moreLeft = (point.x >= (nearTopLeft.x + (nearTopLeft.x - farTopLeft.x) * zRelative)); // left plane //bool lessRight = (point.x <= (nearBottomRight.x + (nearBottomRight.x - farBottomRight.x) * zRelative)); // left plane //bool moreBottom = (point.y >= (nearBottomRight.y + (nearBottomRight.y - farBottomRight.y) * zRelative)); //top plane //bool lessTop = (point.y <= (nearTopLeft.y + (nearTopLeft.y - farTopLeft.y) * zRelative)); //bottom plane //return ( (zRelative >= -1.0f) && moreLeft && lessRight && lessTop && moreBottom); return ((point.x < farBottomRight.x) && (point.x > farTopLeft.x) && (point.y < farTopLeft.y) && (point.y > farBottomRight.y) && (point.z > -1.0)); } vec4 scaleToZZero(vec4 v){ vec4 newV = v / (1 + v.z); return newV; } void main(void) { //read the current position and velocity from the buffers vec4 vel = imageLoad(velocity_buffer, int(gl_GlobalInvocationID.x)); vec4 pos = imageLoad(start_position_buffer, int(gl_GlobalInvocationID.x)); int i; bool inFrustrum = true; float dt2 = dt * dt; while( inFrustrum && pos.z < 0.0f){ //update position using current velocity * time pos.xyz += vel.xyz * dt; //for each attractor... BOTTLENECK for(i = 0; i < 8; i++) { if(attractor[i].w > 0){ //calculate force and update velocity accordingly vec3 dir = (attractor[i].xyz - pos.xyz); float dist = dot(dir, dir); vel.xyz += (dt2 * attractor[i].w * cross(dir, vel.xyz) / (pow(dist, 2))); } } inFrustrum = insideFrustrum(pos); } pos = scaleToZZero(pos); //store the new position back into the buffers imageStore(end_position_buffer, int(gl_GlobalInvocationID.x), pos); }