diff --git a/GLMakie/assets/shader/shadertoy.frag b/GLMakie/assets/shader/shadertoy.frag index 5b132fefc21..a7afe50a676 100644 --- a/GLMakie/assets/shader/shadertoy.frag +++ b/GLMakie/assets/shader/shadertoy.frag @@ -1,13 +1,15 @@ {{GLSL_VERSION}} -out vec4 fragment_color; - {{SHADERTOY_INPUTS}} {{TOY_SHADER}} in vec2 f_uv; +layout (location = 0) out vec4 fragment_color; +layout (location = 1) out uvec2 fragment_groupid; void main() { - mainImage(fragment_color, f_uv * iResolution.xy); + vec4 color = mainImage(f_uv * iResolution.xy); + if (color.a <= 0.0) discard; + fragment_color = color * 0.5; } diff --git a/GLMakie/experiments/clouds.frag b/GLMakie/experiments/clouds.frag index 14cffff0d0c..32bc3cf6f15 100644 --- a/GLMakie/experiments/clouds.frag +++ b/GLMakie/experiments/clouds.frag @@ -107,7 +107,7 @@ vec4 render(in vec3 ro, in vec3 rd) { return vec4(col, 1.0); } -void mainImage(in vec2 fragCoord) { +vec4 mainImage(in vec2 fragCoord) { vec2 p = (-iResolution.xy + 2.0 * gl_FragCoord.xy) / iResolution.y; vec2 m = iMouse.xy / iResolution.xy; @@ -118,5 +118,5 @@ void mainImage(in vec2 fragCoord) { // ray vec3 rd = ca * normalize(vec3(p.xy, 1.5)); - fragment_color = render(ro, rd); + return render(ro, rd); } diff --git a/GLMakie/experiments/gpu-examples.jl b/GLMakie/experiments/gpu-examples.jl new file mode 100644 index 00000000000..5edce7751fd --- /dev/null +++ b/GLMakie/experiments/gpu-examples.jl @@ -0,0 +1,78 @@ +using CUDA + +const N = 1024 # Number of particles +const dt = 0.01 # Time step +const G = 6.67430e-11 # Gravitational constant +const eps = 1e-3 # Softening factor to avoid singularity + + +# Struct to represent a particle +struct Particle + pos::CUDA.CuVector{Point3f} + vel::CUDA.CuVector{Vec3f} + mass::CUDA.CuVector{Float32} +end + +# Initialize particles with random positions, velocities, and masses +function init_particles(n) + pos = CUDA.fill(Point3f(0.0f0, 0.0f0, 0.0f0), n) + vel = CUDA.fill(Vec3f(0.0f0, 0.0f0, 0.0f0), n) + mass = CUDA.fill(0.0f0, n) + + for i in 1:n + pos[i] = rand(Point3f) .* 100 + vel[i] = (rand(Vec3f) .- 0.5) .* 10 + mass[i] = rand(Float32) * 10 + 1 + end + + Particle(pos, vel, mass) +end + +# GPU kernel to calculate forces and update positions and velocities +function update_particles!(pos, mass, vel, dt, G, eps, N) + i = threadIdx().x + (blockIdx().x - 1) * blockDim().x + @inbounds if i <= N + force = Vec3f(0.0f0, 0.0f0, 0.0f0) + pos_i = pos[i] + + for j in 1:N + if i != j + pos_j = pos[j] + diff = pos_j - pos_i + distSqr = sum(diff .* diff) + eps * eps + invDist = 1.0f0 / sqrt(distSqr) + invDist3 = invDist * invDist * invDist + mass_product = mass[i] * mass[j] + force += diff .* (G * mass_product * invDist3) + end + end + + accel = force ./ mass[i] + vel[i] += accel .* dt + pos[i] += vel[i] .* dt + end + return +end + +# Main simulation function +function run_simulation(particles, dt, G, eps, N) + threads = 256 + blocks = ceil(Int, N / threads) + @cuda threads = threads blocks = blocks update_particles!(particles, dt, G, eps, N) +end + +# Initialize particles +particles = init_particles(N) + +# Number of simulation steps +steps = 100 + +# Run the simulation +run_simulation(particles, dt, steps, G, eps, N) + +# Fetch the results from the GPU +positions = Array(pos) +println("Final positions of particles:") +for pos in positions + println(pos) +end diff --git a/GLMakie/experiments/monster.frag b/GLMakie/experiments/monster.frag index 4f031b12c26..6ef416c6c02 100644 --- a/GLMakie/experiments/monster.frag +++ b/GLMakie/experiments/monster.frag @@ -113,7 +113,7 @@ mat3 setCamera( in vec3 ro, in vec3 ta, float cr ) return mat3( cu, cv, cw ); } -void mainImage( out vec4 fragColor, in vec2 fragCoord ) +vec4 mainImage(in vec2 fragCoord ) { vec2 q = fragCoord.xy / iResolution.xy; vec2 p = -1.0 + 2.0 * q; @@ -213,5 +213,5 @@ void mainImage( out vec4 fragColor, in vec2 fragCoord ) // vigneting col *= 0.5 + 0.5*pow( 16.0*q.x*q.y*(1.0-q.x)*(1.0-q.y), 0.1 ); - fragColor = vec4( col, 1.0 ); + return vec4( col, 1.0 ); } diff --git a/GLMakie/experiments/raytracing.frag b/GLMakie/experiments/raytracing.frag index 9af6795f892..266d1feaf7f 100644 --- a/GLMakie/experiments/raytracing.frag +++ b/GLMakie/experiments/raytracing.frag @@ -271,7 +271,7 @@ vec3 cv = normalize(cross(cu, cw)); return mat3(cu, cv, cw); } -void mainImage(in vec2 fragCoord) { +vec4 mainImage(in vec2 fragCoord) { vec2 q = gl_FragCoord.xy / iResolution.xy; vec2 p = - 1.0 + 2.0 * q; p.x *= iResolution.x / iResolution.y; @@ -294,5 +294,5 @@ vec3 col = render(ro, rd); col = pow(col, vec3(0.4545)); -fragment_color = vec4(col, 1.0); + return vec4(col, 1.0); } diff --git a/GLMakie/experiments/shadertoy.jl b/GLMakie/experiments/shadertoy.jl index 5410d3b10a0..1f83f20d151 100644 --- a/GLMakie/experiments/shadertoy.jl +++ b/GLMakie/experiments/shadertoy.jl @@ -3,6 +3,7 @@ GLMakie.activate!(float=true, render_on_demand=false, vsync=true) frag = read(joinpath(@__DIR__, "clouds.frag"), String) img = load(joinpath(@__DIR__, "noise.png")) begin + GLMakie.closeall() s=Scene() shadertoy!(s, Rect2f(-1, -1, 2, 2), frag; @@ -14,9 +15,10 @@ begin end begin + GLMakie.closeall() s = Scene() shadertoy!(s, Rect2f(-1, -1, 2, 2), read(joinpath(@__DIR__, "raytracing.frag"), String)) - s + scren = display(s) end begin diff --git a/GLMakie/src/drawing_primitives.jl b/GLMakie/src/drawing_primitives.jl index 70a92b2e205..bee8c21df5b 100644 --- a/GLMakie/src/drawing_primitives.jl +++ b/GLMakie/src/drawing_primitives.jl @@ -336,7 +336,11 @@ function cached_robj!(robj_func, screen, scene, plot::AbstractPlot) end robj = robj_func(gl_attributes) - get!(gl_attributes, :ssao, Observable(false)) + gl_attributes[:ssao] = plot.ssao + gl_attributes[:transparency] = plot.transparency + gl_attributes[:overdraw] = plot.overdraw + gl_attributes[:visible] = plot.visible + gl_attributes[:fxaa] = plot.fxaa screen.cache2plot[robj.id] = plot return robj end @@ -1031,16 +1035,20 @@ function draw_atomic(screen::Screen, scene::Scene, plot::Makie.ShaderToy) uniforms[:vertices] = GLBuffer(decompose(Point2f, m)) uniforms[:uv] = GLBuffer(GeometryBasics.decompose_uv(m)) - templates = Dict("SHADERTOY_INPUTS" => """ - uniform vec2 iResolution; - uniform vec2 iMouse; - uniform float iGlobalTime; - uniform sampler2D iChannel0; - uniform sampler2D iChannel1; - uniform sampler2D iChannel2; - uniform sampler2D iChannel3; - """, - "TOY_SHADER" => plot.shader[]) + templates = Dict( + "SHADERTOY_INPUTS" => """ + uniform vec2 iResolution; + uniform vec2 iMouse; + uniform float iGlobalTime; + uniform sampler2D iChannel0; + uniform sampler2D iChannel1; + uniform sampler2D iChannel2; + uniform sampler2D iChannel3; + """, + "TOY_SHADER" => plot.shader[], + "buffers" => output_buffers(screen, to_value(false)), + "buffer_writes" => output_buffer_writes(screen, to_value(false)) + ) @gen_defaults! uniforms begin iResolution = scene.camera.resolution iChannel0 = nothing => Texture @@ -1050,9 +1058,10 @@ function draw_atomic(screen::Screen, scene::Scene, plot::Makie.ShaderToy) iGlobalTime = lift(x -> Float32(x.time), scene.events.tick) iMouse = lift(Vec2f, scene.events.mouseposition) iGlobalTime = 0.0f0 - shader = GLMakie.GLVisualizeShader(screen, - "shadertoy.frag", "shadertoy.vert"; - view=templates) + shader = GLVisualizeShader( + screen, + "fragment_output.frag", "shadertoy.frag", "shadertoy.vert"; + view=templates) end get!(uniforms, :ssao, Observable(false)) get!(uniforms, :transparency, Observable(true)) diff --git a/MakieCore/src/basic_plots.jl b/MakieCore/src/basic_plots.jl index 3570fa3612b..7a06ef43a49 100644 --- a/MakieCore/src/basic_plots.jl +++ b/MakieCore/src/basic_plots.jl @@ -785,4 +785,6 @@ end `GLMakie.closeall()` to be overwritten. """ uniforms = Dict{Symbol,Any}() + mixin_generic_plot_attributes()... + fxaa = false end