Thomas Diewald libraries in JRubyArt and propane
Thomas Diewald is a prolific graphics programmer in Java, Javascript, OpenGL/WebGL, GLSL, OpenCL, C++, C. He has developed a number of libraries for vanilla processing, and we explore their use in JRubyArt and propane (actually we barely scratch the surface) in this and in subsequent posts, but hope that we can provide inspiration for others to follow.
PixelFlow library
A Processing/Java library for high performance GPU-Computing (GLSL). See PixelFlow library on github and the PixelFlow website.
Here an example sketch translated for JRubyArt for the sketch to run you need install both peasycam
and PixelFlow
libraries using the processing ide:-
# PixelFlow | Copyright (C) 2017 Thomas Diewald (www.thomasdiewald.com)
# Translated to JRubyArt by Martin Prout
#
# src - www.github.com/diwi/PixelFlow
#
# A Processing/Java library for high performance GPU-Computing.
# MIT License: https://opensource.org/licenses/MIT
#
load_libraries :peasycam, :PixelFlow
module Skylight # Namespace for java classes
java_import 'com.thomasdiewald.pixelflow.java.DwPixelFlow'
java_import 'com.thomasdiewald.pixelflow.java.render.skylight.DwSkyLight'
java_import 'com.thomasdiewald.pixelflow.java.utils.DwBoundingSphere'
java_import 'com.thomasdiewald.pixelflow.java.utils.DwVertexRecorder'
java_import 'peasy.PeasyCam'
end
include Skylight
# Basic setup for the Skylight renderer.
#
# Its important to compute or define a most optimal bounding-sphere for the
# scene. self can be done manually or automatically, as shown in self example.
#
# Any existing sketch utilizing the P3D renderer can be extended to use the
# Skylight renderer.
#
VIEWPORT_W = 1280
VIEWPORT_H = 720
VIEWPORT_X = 230
VIEWPORT_Y = 0
attr_reader :peasycam, :shape, :skylight, :cam_active, :cam_pos
def settings
size(VIEWPORT_W, VIEWPORT_H, P3D)
smooth(0)
end
def setup
surface.setLocation(VIEWPORT_X, VIEWPORT_Y)
# camera
@peasycam = PeasyCam.new(self, -4.083, -6.096, 7.000, 1500)
peasycam.set_rotations(1.085, -0.477, 2.910)
peasycam.set_distance(100)
@cam_pos = [0, 0, 0]
@cam_active = false
# projection
perspective(60 * DEG_TO_RAD, width / height.to_f, 2, 5000)
# load obj file into shape-object
@shape = load_shape(data_path('skylight_demo_scene.obj'))
# record list of vertices of the given shape
vertex_recorder = DwVertexRecorder.new(self, shape)
# compute scene bounding-sphere
scene_bs = DwBoundingSphere.new
scene_bs.compute(vertex_recorder.verts, vertex_recorder.verts_count)
# used for centering and re-scaling the scene
mat_scene_bounds = scene_bs.getUnitSphereMatrix
# library context
context = DwPixelFlow.new(self)
context.print
context.printGL
# callback for rendering scene, implements DwSceneDisplay interface
scene_display = lambda do |canvas|
canvas.background(32) if canvas == skylight.renderer.pg_render
canvas.shape(shape)
end
# init skylight renderer
@skylight = DwSkyLight.new(context, scene_display, mat_scene_bounds)
# parameters for sky-light
param = skylight.sky.param
param.iterations = 50
param.solar_azimuth = 0
param.solar_zenith = 0
param.sample_focus = 1 # full sphere sampling
param.intensity = 1.0
param.rgb = [1.0, 1.0, 1.0]
param.shadowmap_size = 256 # quality vs. performance
# parameters for sun-light
param = skylight.sun.param
param.iterations = 50
param.solar_azimuth = 45
param.solar_zenith = 55
param.sample_focus = 0.05
param.intensity = 1.0
param.rgb = [1.0, 1.0, 1.0]
param.shadowmap_size = 512
frame_rate(1000)
end
def draw
# when the camera moves, the renderer restarts
update_cam_active
skylight.reset if cam_active
# update renderer
skylight.update
peasycam.beginHUD
# display result
image(skylight.renderer.pg_render, 0, 0)
# image(skylight.sky.getSrc, 0, 0)
peasycam.endHUD
# some info, window title
sun_pass = skylight.sun.RENDER_PASS
sky_pass = skylight.sky.RENDER_PASS
title_format = 'Basic Skylight | sun: %d sky: %d fps: %6.2f'
surface.set_title(format(title_format, sun_pass, sky_pass, frame_rate))
end
def update_cam_active
cam_pos_curr = peasycam.getPosition
@cam_active = false
@cam_active |= cam_pos_curr[0] != cam_pos[0]
@cam_active |= cam_pos_curr[1] != cam_pos[1]
@cam_active |= cam_pos_curr[2] != cam_pos[2]
@cam_pos = cam_pos_curr
end
def print_camera
pos = peasycam.get_position
rot = peasycam.get_rotations
lat = peasycam.get_look_at
dis = peasycam.get_distance
cam_format = '%s: (%7.3f, %7.3f, %7.3f)'
dist_format = 'distance: (%7.3f)'
puts format(cam_format, 'position', pos[0], pos[1], pos[2])
puts format(cam_format, 'rotation', rot[0], rot[1], rot[2])
puts format(cam_format, 'look_at', lat[0], lat[1], lat[2])
puts format(dist_format, dis)
end
def key_released
print_camera
end
We can then load the libraries using the library_loader
, and the translation to JRubyArt is relatively straight forward, apart from dealing with the callback.
processing version
// callback for rendering the scene
DwSceneDisplay scene_display = new DwSceneDisplay(){
@Override
public void display(PGraphics3D canvas) {
displayScene(canvas);
}
};
public void displayScene(PGraphics canvas){
if(canvas == skylight.renderer.pg_render){
canvas.background(32);
}
canvas.shape(shape);
}
// init skylight renderer
skylight = new DwSkyLight(context, scene_display, mat_scene_bounds);
JRubyArt version
# callback for rendering scene, implements DwSceneDisplay interface
scene_display = lambda do |canvas|
canvas.background(32) if canvas == skylight.renderer.pg_render
canvas.shape(shape)
end
# init skylight renderer
@skylight = DwSkyLight.new(context, scene_display, mat_scene_bounds)