|
| 1 | +#!/usr/bin/env jruby |
| 2 | + |
| 3 | +require 'propane' |
| 4 | + |
| 5 | + |
| 6 | +class Antialiasing < Propane::App |
| 7 | + load_library :pixel_flow, :peasycam |
| 8 | + |
| 9 | + # java_imports |
| 10 | + module AA |
| 11 | + java_import 'com.thomasdiewald.pixelflow.java.DwPixelFlow' |
| 12 | + java_import 'com.thomasdiewald.pixelflow.java.antialiasing.FXAA.FXAA' |
| 13 | + java_import 'com.thomasdiewald.pixelflow.java.antialiasing.GBAA.GBAA' |
| 14 | + java_import 'com.thomasdiewald.pixelflow.java.antialiasing.SMAA.SMAA' |
| 15 | + java_import 'com.thomasdiewald.pixelflow.java.dwgl.DwGLTextureUtils' |
| 16 | + java_import 'com.thomasdiewald.pixelflow.java.geometry.DwCube' |
| 17 | + java_import 'com.thomasdiewald.pixelflow.java.geometry.DwMeshUtils' |
| 18 | + java_import 'com.thomasdiewald.pixelflow.java.imageprocessing.filter.DwFilter' |
| 19 | + java_import 'com.thomasdiewald.pixelflow.java.render.skylight.DwSceneDisplay' |
| 20 | + java_import 'com.thomasdiewald.pixelflow.java.utils.DwMagnifier' |
| 21 | + java_import 'peasy.PeasyCam' |
| 22 | + java_import 'processing.core.PShape' |
| 23 | + java_import 'processing.opengl.PJOGL' |
| 24 | + end |
| 25 | + |
| 26 | + include AA |
| 27 | + |
| 28 | + VIEWPORT_W = 1280 |
| 29 | + VIEWPORT_H = 720 |
| 30 | + VIEWPORT_X = 230 |
| 31 | + VIEWPORT_Y = 0 |
| 32 | + GAMMA = 2.2 |
| 33 | + BACKGROUND_COLOR = 32.0 |
| 34 | + attr_reader :context, :fxaa, :smaa, :gbaa, :pg_render_noaa, :magnifier, :display |
| 35 | + attr_reader :pg_render_smaa, :pg_render_fxaa, :pg_render_msaa, :pg_render_gbaa |
| 36 | + attr_reader :peasycam, :aamode, :smaamode, :font12, :font48, :shp_scene |
| 37 | + # replace java enum with ruby symbol and use hash key to select via keyboard |
| 38 | + SMAA_MODE = { 'q' => :EDGES, 'w' => :BLEND, 'e' => :FINAL }.freeze |
| 39 | + AA_MODE = { '1' => :NoAA, |
| 40 | + '2' => :MSAA, |
| 41 | + '3' => :SMAA, |
| 42 | + '4' => :FXAA, |
| 43 | + '5' => :GBAA }.freeze |
| 44 | + |
| 45 | + def color_float(a, b, c) |
| 46 | + color(a, b, c) |
| 47 | + end |
| 48 | + java_alias :color_float, :color, [Java::float, Java::float, Java::float] |
| 49 | + |
| 50 | + def settings |
| 51 | + size(VIEWPORT_W, VIEWPORT_H, P3D) |
| 52 | + smooth(0) |
| 53 | + PJOGL.profile = 4 |
| 54 | + end |
| 55 | + |
| 56 | + def setup |
| 57 | + surface.set_location(VIEWPORT_X, VIEWPORT_Y) |
| 58 | + @aamode = :NoAA |
| 59 | + @smaamode = :FINAL |
| 60 | + # camera |
| 61 | + @peasycam = PeasyCam.new(self, -4.083, -6.096, 7.000, 2_000) |
| 62 | + peasycam.set_rotations(1.085, -0.477, 2.910) |
| 63 | + # projection |
| 64 | + perspective(60.radians, width / height.to_f, 2, 6_000) |
| 65 | + # processing font |
| 66 | + @font48 = create_font('SourceCodePro-Regular', 48) |
| 67 | + @font12 = create_font('SourceCodePro-Regular', 12) |
| 68 | + @context = DwPixelFlow.new(self) |
| 69 | + context.print |
| 70 | + context.printGL |
| 71 | + # MSAA - main render-target for MSAA |
| 72 | + @pg_render_msaa = create_graphics(width, height, P3D) |
| 73 | + pg_render_msaa.smooth(8) |
| 74 | + pg_render_msaa.textureSampling(5) |
| 75 | + # NOAA - main render-target for FXAA and MSAA |
| 76 | + @pg_render_noaa = create_graphics(width, height, P3D) |
| 77 | + pg_render_noaa.smooth(0) |
| 78 | + pg_render_noaa.textureSampling(5) |
| 79 | + # FXAA |
| 80 | + @pg_render_fxaa = create_graphics(width, height, P3D) |
| 81 | + pg_render_fxaa.smooth(0) |
| 82 | + pg_render_fxaa.textureSampling(5) |
| 83 | + # FXAA |
| 84 | + @pg_render_smaa = create_graphics(width, height, P3D) |
| 85 | + pg_render_smaa.smooth(0) |
| 86 | + pg_render_smaa.textureSampling(5) |
| 87 | + # GBAA |
| 88 | + @pg_render_gbaa = create_graphics(width, height, P3D) |
| 89 | + pg_render_gbaa.smooth(0) |
| 90 | + pg_render_gbaa.textureSampling(5) |
| 91 | + scene_display = lambda do |canvas| |
| 92 | + # lights |
| 93 | + canvas.directional_light(255, 255, 255, 200, 600, 400) |
| 94 | + canvas.directional_light(255, 255, 255, -200, -600, -400) |
| 95 | + canvas.ambient_light(64, 64, 64) |
| 96 | + # canvas.shape(shape) |
| 97 | + scene_shape(canvas) |
| 98 | + end |
| 99 | + # AA post-processing modes |
| 100 | + @fxaa = FXAA.new(context) |
| 101 | + @smaa = SMAA.new(context) |
| 102 | + @gbaa = GBAA.new(context, scene_display) |
| 103 | + mag_h = (height / 2.5).to_i |
| 104 | + @magnifier = DwMagnifier.new(self, 4, 0, height - mag_h, mag_h, mag_h) |
| 105 | + @shp_scene ||= nil |
| 106 | + frame_rate(1_000) |
| 107 | + end |
| 108 | + |
| 109 | + def draw |
| 110 | + case aamode |
| 111 | + when :MSAA |
| 112 | + display_scene_wrap(pg_render_msaa) |
| 113 | + # RGB gamma correction |
| 114 | + DwFilter.get(context).gamma.apply(pg_render_msaa, pg_render_msaa, GAMMA) |
| 115 | + when :NoAA, :SMAA, :FXAA |
| 116 | + display_scene_wrap(pg_render_noaa) |
| 117 | + # RGB gamma correction |
| 118 | + DwFilter.get(context).gamma.apply(pg_render_noaa, pg_render_noaa, GAMMA) |
| 119 | + fxaa.apply(pg_render_noaa, pg_render_fxaa) if aamode == :FXAA |
| 120 | + if aamode == :SMAA |
| 121 | + smaa.apply(pg_render_noaa, pg_render_smaa) |
| 122 | + # only for debugging |
| 123 | + filter = DwFilter.get(context).copy |
| 124 | + filter.apply(smaa.tex_edges, pg_render_smaa) if smaamode == :EDGES |
| 125 | + filter.apply(smaa.tex_blend, pg_render_smaa) if smaamode == :BLEND |
| 126 | + end |
| 127 | + when :GBAA |
| 128 | + display_scene_wrap(pg_render_noaa) |
| 129 | + # RGB gamma correction |
| 130 | + DwFilter.get(context).gamma.apply(pg_render_noaa, pg_render_noaa, GAMMA) |
| 131 | + gbaa.apply(pg_render_noaa, pg_render_gbaa) |
| 132 | + end |
| 133 | + @display = case aamode |
| 134 | + when :MSAA |
| 135 | + pg_render_msaa |
| 136 | + when :SMAA |
| 137 | + pg_render_smaa |
| 138 | + when :FXAA |
| 139 | + pg_render_fxaa |
| 140 | + when :GBAA |
| 141 | + pg_render_gbaa |
| 142 | + else |
| 143 | + pg_render_noaa |
| 144 | + end |
| 145 | + magnifier.apply(display, mouse_x, mouse_y) |
| 146 | + magnifier.display_tool |
| 147 | + peasycam.beginHUD |
| 148 | + # display Anti Aliased result |
| 149 | + blend_mode(REPLACE) |
| 150 | + clear |
| 151 | + image(display, 0, 0) |
| 152 | + blend_mode(BLEND) |
| 153 | + # display magnifer |
| 154 | + magnifier.display(g) |
| 155 | + # display AA name |
| 156 | + mode = aamode.to_s |
| 157 | + buffer = '' |
| 158 | + if aamode == :SMAA |
| 159 | + buffer = " [#{smaamode}]" if smaamode == :EDGES |
| 160 | + buffer = " [#{smaamode}]" if smaamode == :BLEND |
| 161 | + end |
| 162 | + no_stroke |
| 163 | + fill 0, 150 |
| 164 | + rect 0, height - 65, magnifier.w, 65 |
| 165 | + tx = 10 |
| 166 | + ty = 20 |
| 167 | + text_font font12 |
| 168 | + fill 200 |
| 169 | + text('[1] NoAA', tx, ty) |
| 170 | + text('[2] MSAA - MultiSample AA', tx, ty += 20) |
| 171 | + text('[3] SMAA - SubPixel Morphological AA', tx, ty += 20) |
| 172 | + text('[4] FXAA - Fast Approximate AA', tx, ty += 20) |
| 173 | + text('[5] GBAA - GeometryBuffer AA', tx, ty + 20) |
| 174 | + text_font font48 |
| 175 | + tx = 20 |
| 176 | + ty = height - 20 |
| 177 | + fill 0 |
| 178 | + text mode << buffer, tx + 2, ty + 2 |
| 179 | + fill(255, 200, 0) |
| 180 | + text mode, tx, ty |
| 181 | + peasycam.endHUD |
| 182 | + # some info, window title |
| 183 | + format_string = 'Anti Aliasing | fps: (%6.2f)' |
| 184 | + surface.set_title(format(format_string, frame_rate)) |
| 185 | + end |
| 186 | + |
| 187 | + def display_scene_wrap(canvas) |
| 188 | + canvas.begin_draw |
| 189 | + DwGLTextureUtils.copy_matrices(g, canvas) |
| 190 | + background_color_gamma = (BACKGROUND_COLOR / 255.0)**GAMMA * 255.0 |
| 191 | + # background |
| 192 | + canvas.blend_mode BLEND |
| 193 | + canvas.background background_color_gamma |
| 194 | + display_scene canvas |
| 195 | + canvas.end_draw |
| 196 | + end |
| 197 | + |
| 198 | + # render something |
| 199 | + def display_scene(canvas) |
| 200 | + # lights |
| 201 | + canvas.directional_light(255, 255, 255, 200, 600, 400) |
| 202 | + canvas.directional_light(255, 255, 255, -200, -600, -400) |
| 203 | + canvas.ambient_light(64, 64, 64) |
| 204 | + scene_shape canvas |
| 205 | + end |
| 206 | + |
| 207 | + def scene_shape(canvas) |
| 208 | + return canvas.shape(shp_scene) unless shp_scene.nil? |
| 209 | + @shp_scene = create_shape(GROUP) |
| 210 | + num_boxes = 50 |
| 211 | + num_spheres = 50 |
| 212 | + bb_size = 800 |
| 213 | + xmin = -bb_size |
| 214 | + xmax = +bb_size |
| 215 | + ymin = -bb_size |
| 216 | + ymax = +bb_size |
| 217 | + zmin = 0 |
| 218 | + zmax = +bb_size |
| 219 | + color_mode(HSB, 360.0, 1.0, 1.0) |
| 220 | + srand(0) |
| 221 | + (0..num_boxes).each do |
| 222 | + px = rand(xmin..xmax) |
| 223 | + py = rand(ymin..ymax) |
| 224 | + sx = rand(10..210) |
| 225 | + sy = rand(10..210) |
| 226 | + sz = rand(zmin..zmax) |
| 227 | + off = 45 |
| 228 | + base = 0 |
| 229 | + hsb_h = base + rand(-off..off) |
| 230 | + hsb_s = 1 |
| 231 | + hsb_b = rand(0.1..1.0) |
| 232 | + shading = color_float(hsb_h, hsb_s, hsb_b) |
| 233 | + shp_box = create_shape(BOX, sx, sy, sz) |
| 234 | + shp_box.set_fill(true) |
| 235 | + shp_box.set_stroke(false) |
| 236 | + shp_box.set_fill(shading) |
| 237 | + shp_box.translate(px, py, sz / 2) |
| 238 | + shp_scene.add_child(shp_box) |
| 239 | + end |
| 240 | + cube_smooth = DwCube.new(4) |
| 241 | + cube_facets = DwCube.new(2) |
| 242 | + (0..num_spheres).each do |
| 243 | + px = rand(xmin..xmax) |
| 244 | + py = rand(ymin..ymax) |
| 245 | + pz = rand(zmin..zmax) |
| 246 | + rr = rand(50..100) |
| 247 | + facets = true # (i%2 == 0) |
| 248 | + off = 20 |
| 249 | + base = 225 |
| 250 | + hsb_h = base + rand(-off..off) |
| 251 | + hsb_s = rand(0.1..1.0) |
| 252 | + hsb_b = 1 |
| 253 | + shading = color(hsb_h, hsb_s, hsb_b) |
| 254 | + shp_sphere = create_shape(PShape::GEOMETRY) |
| 255 | + if facets |
| 256 | + DwMeshUtils.create_polyhedron_shape(shp_sphere, cube_facets, 1, 4, false) |
| 257 | + else |
| 258 | + DwMeshUtils.create_polyhedron_shape(shp_sphere, cube_smooth, 1, 4, true) |
| 259 | + end |
| 260 | + shp_sphere.set_stroke(false) |
| 261 | + shp_sphere.set_stroke(color(0)) |
| 262 | + shp_sphere.set_stroke_weight(0.01 / rr) |
| 263 | + shp_sphere.set_fill(true) |
| 264 | + shp_sphere.set_fill(shading) |
| 265 | + shp_sphere.reset_matrix |
| 266 | + shp_sphere.scale(rr) |
| 267 | + shp_sphere.translate(px, py, pz) |
| 268 | + shp_scene.add_child(shp_sphere) |
| 269 | + end |
| 270 | + colorMode(RGB, 255, 255, 255) |
| 271 | + shp_rect = create_shape(RECT, -1000, -1000, 2000, 2000) |
| 272 | + shp_rect.set_stroke(false) |
| 273 | + shp_rect.set_fill(true) |
| 274 | + shp_rect.set_fill(color(255)) |
| 275 | + shp_scene.add_child(shp_rect) |
| 276 | + end |
| 277 | + |
| 278 | + def print_camera |
| 279 | + pos = peasycam.get_position |
| 280 | + rot = peasycam.get_rotations |
| 281 | + lat = peasycam.get_look_at |
| 282 | + dis = peasycam.get_distance |
| 283 | + cam_format = '%s: (%7.3f, %7.3f, %7.3f)' |
| 284 | + dist_format = 'distance: (%7.3f)' |
| 285 | + puts format(cam_format, 'position', pos[0], pos[1], pos[2]) |
| 286 | + puts format(cam_format, 'rotation', rot[0], rot[1], rot[2]) |
| 287 | + puts format(cam_format, 'look_at', lat[0], lat[1], lat[2]) |
| 288 | + puts format(dist_format, dis) |
| 289 | + end |
| 290 | + |
| 291 | + def key_released |
| 292 | + @aamode = AA_MODE[key] if AA_MODE.key? key |
| 293 | + @smaamode = SMAA_MODE[key] if SMAA_MODE.key? key |
| 294 | + print_camera if key == 'c' |
| 295 | + end |
| 296 | +end |
| 297 | + |
| 298 | +Antialiasing.new |
0 commit comments