diff options
Diffstat (limited to 'src/com/mbien/opencl/demos/julia3d/Renderer.java')
-rw-r--r-- | src/com/mbien/opencl/demos/julia3d/Renderer.java | 203 |
1 files changed, 203 insertions, 0 deletions
diff --git a/src/com/mbien/opencl/demos/julia3d/Renderer.java b/src/com/mbien/opencl/demos/julia3d/Renderer.java new file mode 100644 index 0000000..92ca2d7 --- /dev/null +++ b/src/com/mbien/opencl/demos/julia3d/Renderer.java @@ -0,0 +1,203 @@ +package com.mbien.opencl.demos.julia3d; + +import com.mbien.opencl.demos.julia3d.structs.RenderingConfig; +import com.sun.opengl.util.BufferUtil; +import com.sun.opengl.util.awt.TextRenderer; +import java.awt.Dimension; +import java.awt.Font; +import java.nio.FloatBuffer; +import java.util.Timer; +import java.util.TimerTask; +import javax.media.opengl.GL2; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLProfile; +import javax.media.opengl.awt.GLCanvas; +import javax.swing.JFrame; + +import static javax.media.opengl.GL2.*; +import static java.lang.String.*; + +/** + * JOGL renderer for displaying the julia set. + * @author Michael Bien + */ +public class Renderer implements GLEventListener { + + public final static int MU_RECT_SIZE = 80; + + private final Julia3d julia3d; + private final GLCanvas canvas; + private final RenderingConfig config; + private final FloatBuffer juliaSlice; + private final UserSceneController usi; + private final TextRenderer textRenderer; + + private TimerTask task; + private final Timer timer; + + public Renderer(Julia3d julia3d) { + this.julia3d = julia3d; + this.config = julia3d.config; + + timer = new Timer(); + + juliaSlice = BufferUtil.newFloatBuffer(MU_RECT_SIZE * MU_RECT_SIZE * 4); + + canvas = new GLCanvas(new GLCapabilities(GLProfile.get(GLProfile.GL2))); + canvas.addGLEventListener(this); + + usi = new UserSceneController(); + usi.init(this, canvas, config); + + JFrame frame = new JFrame("Java OpenCL - Julia3D GPU"); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + canvas.setPreferredSize(new Dimension(config.getWidth(), config.getHeight())); + frame.add(canvas); + frame.pack(); + + textRenderer = new TextRenderer(frame.getFont().deriveFont(Font.BOLD, 14), true, true, null, false); + + frame.setVisible(true); + } + + public void init(GLAutoDrawable drawable) { + drawable.getGL().getGL2().glMatrixMode(GL_PROJECTION); + } + + void update() { + julia3d.update(false); + canvas.display(); + } + + public void display(GLAutoDrawable drawable) { + + //compute + julia3d.compute(config.getActvateFastRendering() == 1); + + GL2 gl = drawable.getGL().getGL2(); + gl.glClear(GL_COLOR_BUFFER_BIT); + + // draw julia set + gl.glRasterPos2i(0, 0); + gl.glDrawPixels(config.getWidth(), config.getHeight(), GL_RGB, GL_FLOAT, julia3d.getPixelBuffer()); + + + // Draw Mu constant + int width = config.getWidth(); + int height = config.getHeight(); + float[] mu = config.getMu(); + + gl.glEnable(GL_BLEND); + gl.glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + int baseMu1 = width - MU_RECT_SIZE - 2; + int baseMu2 = 1; + drawJuliaSlice(gl, baseMu1, baseMu2, mu[0], mu[1]); + int baseMu3 = width - MU_RECT_SIZE - 2; + int baseMu4 = MU_RECT_SIZE + 2; + drawJuliaSlice(gl, baseMu3, baseMu4, mu[2], mu[3]); + gl.glDisable(GL_BLEND); + + gl.glColor3f(1, 1, 1); + int mu1 = (int) (baseMu1 + MU_RECT_SIZE * (mu[0] + 1.5f) / 3.f); + int mu2 = (int) (baseMu2 + MU_RECT_SIZE * (mu[1] + 1.5f) / 3.f); + gl.glBegin(GL_LINES); + gl.glVertex2i(mu1 - 4, mu2); + gl.glVertex2i(mu1 + 4, mu2); + gl.glVertex2i(mu1, mu2 - 4); + gl.glVertex2i(mu1, mu2 + 4); + gl.glEnd(); + + int mu3 = (int) (baseMu3 + MU_RECT_SIZE * (mu[2] + 1.5f) / 3.f); + int mu4 = (int) (baseMu4 + MU_RECT_SIZE * (mu[3] + 1.5f) / 3.f); + gl.glBegin(GL_LINES); + gl.glVertex2i(mu3 - 4, mu4); + gl.glVertex2i(mu3 + 4, mu4); + gl.glVertex2i(mu3, mu4 - 4); + gl.glVertex2i(mu3, mu4 + 4); + gl.glEnd(); + + // info text + textRenderer.beginRendering(width, height); + textRenderer.draw(format("Epsilon %.5f - Max. Iter. %d", config.getEpsilon(), config.getMaxIterations()), 8, 10); + textRenderer.draw(format("Mu = (%.3f, %.3f, %.3f, %.3f)", mu[0], mu[1], mu[2], mu[3]), 8, 25); + textRenderer.draw(format("Shadow %s - SuperSampling %dx%d - Fast rendering %s", + config.getEnableShadow() == 1 ? "on" : "off", + config.getSuperSamplingSize(), config.getSuperSamplingSize(), + config.getActvateFastRendering() == 1 ? "on" : "off"), 8, 40); + textRenderer.endRendering(); + + // timer task scheduling, delay gpu intensive high quality rendering + if(task != null) { + task.cancel(); + } + if(config.getActvateFastRendering() == 1) { + task = new TimerTask() { + @Override + public void run() { + config.setActvateFastRendering(0); + update(); + config.setActvateFastRendering(1); + } + }; + timer.schedule(task, 2000); + } + } + + private void drawJuliaSlice(GL2 gl, int origX, int origY, float cR, float cI) { + + int index = 0; + float invSize = 3.0f / MU_RECT_SIZE; + for (int i = 0; i < MU_RECT_SIZE; ++i) { + for (int j = 0; j < MU_RECT_SIZE; ++j) { + + float x = i * invSize - 1.5f; + float y = j * invSize - 1.5f; + + int iter; + for (iter = 0; iter < 64; ++iter) { + float x2 = x * x; + float y2 = y * y; + if (x2 + y2 > 4.0f) { + break; + } + + float newx = x2 - y2 + cR; + float newy = 2.f * x * y + cI; + x = newx; + y = newy; + } + + juliaSlice.put(index++, iter / 64.0f); + juliaSlice.put(index++, 0.0f); + juliaSlice.put(index++, 0.0f); + juliaSlice.put(index++, 0.5f); + } + } + + gl.glRasterPos2i(origX, origY); + gl.glDrawPixels(MU_RECT_SIZE, MU_RECT_SIZE, GL_RGBA, GL_FLOAT, juliaSlice); + } + + + public void reshape(GLAutoDrawable drawable, int x, int y, int newWidth, int newHeight) { + + config.setWidth(newWidth); + config.setHeight(newHeight); + + GL2 gl = drawable.getGL().getGL2(); + + gl.glViewport(0, 0, newWidth, newHeight); + gl.glLoadIdentity(); + gl.glOrtho(-0.5f, newWidth - 0.5f, -0.5f, newHeight - 0.5f, -1.0f, 1.0f); + + julia3d.update(true); + + } + + public void dispose(GLAutoDrawable drawable) { + } + + +} |