Skip to content

Commit 0bad60e

Browse files
committed
add reaction_diffusion
1 parent ba764c3 commit 0bad60e

4 files changed

Lines changed: 162 additions & 1 deletion

File tree

external_library/java/PixelFlow/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,4 +38,4 @@ end
3838
@skylight = DwSkyLight.new(context, scene_display, mat_scene_bounds)
3939
```
4040

41-
In __antialiasing.rb__ if just use the overloaded `color` method jruby complains of overloaded method, but guesses right and chooses the correct java signature (float, float, float). Mainly to show how we can do it, we provide an alias method `color_float` that avoids the look up cost in detecting the correct signature, this is not generally important if you can put up with the warning.
41+
In __antialiasing.rb__ if we just use the overloaded `color` method, jruby complains of overloaded method but guesses right and chooses the correct java signature (float, float, float). Mainly to show how we can do it, we provide an alias method `color_float` that avoids the look up cost in detecting the correct signature, this is not generally important if you can put up with the warning.
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// file: grayscott.frag
2+
// author: diewald
3+
4+
#version 150
5+
6+
out vec2 fragColor;
7+
8+
uniform vec2 wh_rcp;
9+
uniform sampler2D tex;
10+
11+
uniform float dA = 1.0;
12+
uniform float dB = 0.5;
13+
uniform float feed = 0.055;
14+
uniform float kill = 0.062;
15+
uniform float dt = 1.0;
16+
17+
void main () {
18+
19+
vec2 posn = gl_FragCoord.xy * wh_rcp;
20+
21+
vec4 val = texture(tex, posn);
22+
23+
vec4 laplace = -val;
24+
laplace += textureOffset(tex, posn, ivec2(-1, 0)) * + 0.20;
25+
laplace += textureOffset(tex, posn, ivec2(+1, 0)) * + 0.20;
26+
laplace += textureOffset(tex, posn, ivec2( 0,-1)) * + 0.20;
27+
laplace += textureOffset(tex, posn, ivec2( 0,+1)) * + 0.20;
28+
laplace += textureOffset(tex, posn, ivec2(-1,-1)) * + 0.05;
29+
laplace += textureOffset(tex, posn, ivec2(+1,-1)) * + 0.05;
30+
laplace += textureOffset(tex, posn, ivec2(-1,+1)) * + 0.05;
31+
laplace += textureOffset(tex, posn, ivec2(+1,+1)) * + 0.05;
32+
33+
float nA = val.r + (dA * laplace.r - val.r * val.g * val.g + (feed * (1.0 - val.r))) * dt;
34+
float nB = val.g + (dB * laplace.g + val.r * val.g * val.g - ((kill + feed) * val.g)) * dt;
35+
36+
fragColor = clamp(vec2(nA, nB), vec2(0), vec2(1));
37+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// file: render.frag
2+
// author: diewald
3+
4+
#version 150
5+
6+
out vec4 fragColor;
7+
8+
uniform vec2 wh_rcp;
9+
uniform sampler2D tex;
10+
11+
void main () {
12+
vec2 val = texture(tex, gl_FragCoord.xy * wh_rcp).rg;
13+
fragColor = vec4(vec3(1.0 - val.g), 1);
14+
}
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
load_library :PixelFlow
2+
3+
# PixelFlow | Copyright (C) 2016 Thomas Diewald - http://thomasdiewald.com
4+
# translated to JRubyArt by MArtihn Prout
5+
# A Processing/Java library for high performance GPU-Computing (GLSL).
6+
# MIT License: https://opensource.org/licenses/MIT
7+
module Reaction
8+
java_import 'com.thomasdiewald.pixelflow.java.DwPixelFlow'
9+
java_import 'com.thomasdiewald.pixelflow.java.dwgl.DwGLSLProgram'
10+
java_import 'com.thomasdiewald.pixelflow.java.dwgl.DwGLTexture'
11+
java_import 'com.thomasdiewald.pixelflow.java.imageprocessing.filter.DwFilter'
12+
java_import 'com.jogamp.opengl.GL2'
13+
end
14+
15+
include Reaction
16+
# reaction-diffusion, grayscott
17+
#
18+
# using custom shaders/textures for fast multipass rendering.
19+
attr_reader :context, :tex_grayscott, :shader_grayscott, :shader_render
20+
attr_reader :pass, :tex_render
21+
22+
def settings
23+
size(800, 800, P2D)
24+
smooth(0)
25+
end
26+
27+
def setup
28+
# multipass rendering texture
29+
@tex_grayscott = DwGLTexture::TexturePingPong.new
30+
# pixelflow context
31+
@context = DwPixelFlow.new(self)
32+
@pass = 0
33+
# 1) 32 bit per channel
34+
tex_grayscott.resize(
35+
context,
36+
GL2::GL_RG32F, # NB we need :: not . here to access constant
37+
width,
38+
height,
39+
GL2::GL_RG,
40+
GL2::GL_FLOAT,
41+
GL2::GL_NEAREST,
42+
2,
43+
4
44+
)
45+
46+
# 2) 16 bit per channel, lack of precision is obvious in the result, its fast though
47+
# tex_grayscott.resize(context, GL2::GL_RG16F, width, height, GL2::GL_RG, GL2::GL_FLOAT, GL2::GL_NEAREST, 2, 2)
48+
49+
# 3) 16 bit per channel, better than 2)
50+
# tex_grayscott.resize(context, GL2::GL_RG16_SNORM, width, height, GL2::GL_RG, GL2::GL_FLOAT, GL2::GL_NEAREST, 2, 2)
51+
52+
# glsl shader
53+
@shader_grayscott = context.createShader(data_path('grayscott.frag'))
54+
@shader_render = context.createShader(data_path('render.frag'))
55+
# init
56+
@tex_render = create_graphics(width, height, P2D)
57+
tex_render.smooth(0)
58+
tex_render.beginDraw
59+
tex_render.textureSampling(2)
60+
tex_render.blendMode(REPLACE)
61+
tex_render.clear
62+
tex_render.noStroke
63+
tex_render.background(0x00FF0000) # NB: we can use hexadecimal in ruby
64+
tex_render.fill(0x0000FF00)
65+
tex_render.noStroke
66+
tex_render.rectMode(CENTER)
67+
tex_render.rect(width / 2, height / 2, 20, 20)
68+
tex_render.endDraw
69+
# copy initial data to source texture
70+
DwFilter.get(context).copy.apply(tex_render, tex_grayscott.src)
71+
frame_rate(1_000)
72+
end
73+
74+
def reaction_diffusion_pass
75+
context.beginDraw(tex_grayscott.dst)
76+
shader_grayscott.begin
77+
shader_grayscott.uniform1f('dA', 1.0)
78+
shader_grayscott.uniform1f('dB', 0.5)
79+
shader_grayscott.uniform1f('feed', 0.055)
80+
shader_grayscott.uniform1f('kill', 0.062)
81+
shader_grayscott.uniform1f('dt', 1)
82+
shader_grayscott.uniform2f('wh_rcp', 1.0 / width, 1.0 / height)
83+
shader_grayscott.uniformTexture('tex', tex_grayscott.src)
84+
shader_grayscott.drawFullScreenQuad
85+
shader_grayscott.end
86+
context.endDraw('reaction_diffusion_pass')
87+
tex_grayscott.swap
88+
@pass += 1
89+
end
90+
91+
def draw
92+
# multipass rendering, ping-pong
93+
context.begin
94+
100.times { reaction_diffusion_pass }
95+
# create display texture
96+
context.beginDraw(tex_render)
97+
shader_render.begin
98+
shader_render.uniform2f('wh_rcp', 1.0 / width, 1.0 / height)
99+
shader_render.uniformTexture('tex', tex_grayscott.src)
100+
shader_render.drawFullScreenQuad
101+
shader_render.end
102+
context.endDraw('render')
103+
context.end
104+
# put it on the screen
105+
blendMode(REPLACE)
106+
image(tex_render, 0, 0)
107+
save_frame(data_path('grayscott1.jpg')) if frame_count == 1_000
108+
format_string = 'Reaction Diffusion [size %d/%d] [frame %d] [fps: (%6.2f)]'
109+
surface.set_title(format(format_string, width, height, pass, frame_rate))
110+
end

0 commit comments

Comments
 (0)