package org.andork.jogl;
import static com.jogamp.opengl.GL.GL_BACK;
import static com.jogamp.opengl.GL.GL_DRAW_FRAMEBUFFER;
import static com.jogamp.opengl.GL.GL_NEAREST;
import static com.jogamp.opengl.GL.GL_READ_FRAMEBUFFER;
import static org.andork.math3d.Vecmath.newMat3f;
import static org.andork.math3d.Vecmath.newMat4f;
import java.awt.Component;
import java.awt.Rectangle;
import java.awt.Window;
import javax.swing.SwingUtilities;
import com.jogamp.opengl.GL;
import com.jogamp.opengl.GL2ES2;
import com.jogamp.opengl.GL3;
import com.jogamp.opengl.GLAutoDrawable;
import com.jogamp.opengl.GLEventListener;
public class DefaultJoglRenderer implements GLEventListener {
protected JoglViewState viewState = new JoglViewState();
protected JoglViewSettings viewSettings = new JoglViewSettings();
protected JoglScene scene;
protected GL3Framebuffer framebuffer;
protected int desiredNumSamples = 1;
protected float[] m = newMat4f();
protected float[] n = newMat3f();
protected boolean useWindowBoundsForViewport = false;
protected int width;
protected int height;
public DefaultJoglRenderer(GL3Framebuffer framebuffer, int desiredNumSamples) {
super();
this.framebuffer = framebuffer;
this.desiredNumSamples = desiredNumSamples;
}
public DefaultJoglRenderer(JoglScene scene) {
super();
this.scene = scene;
}
public DefaultJoglRenderer(JoglScene scene, GL3Framebuffer framebuffer, int desiredNumSamples) {
super();
this.scene = scene;
this.framebuffer = framebuffer;
this.desiredNumSamples = desiredNumSamples;
}
@Override
public void display(GLAutoDrawable drawable) {
GL2ES2 gl = (GL2ES2) drawable.getGL();
int renderingFbo = -1;
if (framebuffer != null) {
GL3 gl3 = (GL3) gl;
renderingFbo = framebuffer.renderingFbo(gl3, drawable.getSurfaceWidth(), drawable.getSurfaceHeight(),
desiredNumSamples);
gl3.glBindFramebuffer(GL_DRAW_FRAMEBUFFER, renderingFbo);
}
viewState.update(viewSettings, width, height);
drawScene(drawable);
if (framebuffer != null) {
GL3 gl3 = (GL3) gl;
gl3.glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
gl3.glBindFramebuffer(GL_READ_FRAMEBUFFER, renderingFbo);
gl3.glDrawBuffer(GL_BACK);
gl3.glBlitFramebuffer(0, 0, drawable.getSurfaceWidth(), drawable.getSurfaceHeight(), 0, 0,
drawable.getSurfaceWidth(), drawable.getSurfaceHeight(), GL.GL_COLOR_BUFFER_BIT, GL_NEAREST);
}
}
@Override
public void dispose(GLAutoDrawable drawable) {
GL2ES2 gl = (GL2ES2) drawable.getGL();
if (framebuffer != null) {
framebuffer.dispose((GL3) gl);
}
}
protected void drawScene(GLAutoDrawable drawable) {
if (scene != null) {
scene.draw(viewState, (GL2ES2) drawable.getGL(), m, n);
}
}
public int getDesiredNumSamples() {
return desiredNumSamples;
}
public JoglScene getScene() {
return scene;
}
public JoglViewSettings getViewSettings() {
return viewSettings;
}
public JoglViewState getViewState() {
return viewState;
}
@Override
public void init(GLAutoDrawable drawable) {
GL2ES2 gl = (GL2ES2) drawable.getGL();
if (framebuffer != null) {
framebuffer.init((GL3) gl);
}
}
@Override
public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
GL2ES2 gl = (GL2ES2) drawable.getGL();
if (useWindowBoundsForViewport && drawable instanceof Component) {
Component canvas = (Component) drawable;
Window window = SwingUtilities.getWindowAncestor(canvas);
if (window != null) {
this.width = window.getWidth();
this.height = window.getHeight();
Rectangle bounds = SwingUtilities.convertRectangle(canvas, canvas.getBounds(), window);
gl.glViewport(-bounds.x / 2, bounds.y / 2 + bounds.height - window.getHeight(), this.width,
this.height);
return;
}
}
this.width = width;
this.height = height;
gl.glViewport(x, y, width, height);
}
public void setDesiredNumSamples(int desiredNumSamples) {
this.desiredNumSamples = desiredNumSamples;
}
public void setScene(JoglScene scene) {
this.scene = scene;
}
public void setViewSettings(JoglViewSettings viewSettings) {
this.viewSettings = viewSettings;
}
}