Browse Source

Multisampled Fbos and GUI mouse picking

Tankernn 8 years ago
parent
commit
030b48db66

+ 35 - 40
src/main/java/eu/tankernn/gameEngine/postProcessing/Fbo.java

@@ -1,4 +1,3 @@
-
 package eu.tankernn.gameEngine.postProcessing;
 
 import java.nio.ByteBuffer;
@@ -10,40 +9,37 @@ import org.lwjgl.opengl.GL14;
 import org.lwjgl.opengl.GL30;
 
 public class Fbo {
-
+	
 	public static final int NONE = 0;
 	public static final int DEPTH_TEXTURE = 1;
 	public static final int DEPTH_RENDER_BUFFER = 2;
-
-	private final int width;
-	private final int height;
-
-	private int frameBuffer;
-
+	
+	protected final int width;
+	protected final int height;
+	
+	protected int frameBuffer;
+	
 	private int colourTexture;
 	private int depthTexture;
-
-	private int depthBuffer;
-	private int colourBuffer;
-
+	
+	protected int depthBuffer;
+	protected int colorBuffer;
+	
 	/**
 	 * Creates an FBO of a specified width and height, with the desired type of
 	 * depth buffer attachment.
 	 * 
-	 * @param width
-	 *            - the width of the FBO.
-	 * @param height
-	 *            - the height of the FBO.
-	 * @param depthBufferType
-	 *            - an int indicating the type of depth buffer attachment that
-	 *            this FBO should use.
+	 * @param width - the width of the FBO.
+	 * @param height - the height of the FBO.
+	 * @param depthBufferType - an int indicating the type of depth buffer
+	 *        attachment that this FBO should use.
 	 */
 	public Fbo(int width, int height, int depthBufferType) {
 		this.width = width;
 		this.height = height;
 		initialiseFrameBuffer(depthBufferType);
 	}
-
+	
 	/**
 	 * Deletes the frame buffer and its attachments when the game closes.
 	 */
@@ -52,9 +48,9 @@ public class Fbo {
 		GL11.glDeleteTextures(colourTexture);
 		GL11.glDeleteTextures(depthTexture);
 		GL30.glDeleteRenderbuffers(depthBuffer);
-		GL30.glDeleteRenderbuffers(colourBuffer);
+		GL30.glDeleteRenderbuffers(colorBuffer);
 	}
-
+	
 	/**
 	 * Binds the frame buffer, setting it as the current render target. Anything
 	 * rendered after this will be rendered to this FBO, and not to the screen.
@@ -63,7 +59,7 @@ public class Fbo {
 		GL30.glBindFramebuffer(GL30.GL_DRAW_FRAMEBUFFER, frameBuffer);
 		GL11.glViewport(0, 0, width, height);
 	}
-
+	
 	/**
 	 * Unbinds the frame buffer, setting the default frame buffer as the current
 	 * render target. Anything rendered after this will be rendered to the
@@ -73,7 +69,7 @@ public class Fbo {
 		GL30.glBindFramebuffer(GL30.GL_FRAMEBUFFER, 0);
 		GL11.glViewport(0, 0, Display.getWidth(), Display.getHeight());
 	}
-
+	
 	/**
 	 * Binds the current FBO to be read from (not used in tutorial 43).
 	 */
@@ -82,32 +78,32 @@ public class Fbo {
 		GL30.glBindFramebuffer(GL30.GL_READ_FRAMEBUFFER, frameBuffer);
 		GL11.glReadBuffer(GL30.GL_COLOR_ATTACHMENT0);
 	}
-
+	
 	/**
 	 * @return The ID of the texture containing the colour buffer of the FBO.
 	 */
 	public int getColourTexture() {
 		return colourTexture;
 	}
-
+	
 	/**
 	 * @return The texture containing the FBOs depth buffer.
 	 */
 	public int getDepthTexture() {
 		return depthTexture;
 	}
-
+	
 	/**
 	 * Creates the FBO along with a colour buffer texture attachment, and
 	 * possibly a depth buffer.
 	 * 
-	 * @param type
-	 *            - the type of depth buffer attachment to be attached to the
-	 *            FBO.
+	 * @param type - the type of depth buffer attachment to be attached to the
+	 *        FBO.
 	 */
-	private void initialiseFrameBuffer(int type) {
+	protected void initialiseFrameBuffer(int type) {
 		createFrameBuffer();
 		createTextureAttachment();
+		createTextureAttachment();
 		if (type == DEPTH_RENDER_BUFFER) {
 			createDepthBufferAttachment();
 		} else if (type == DEPTH_TEXTURE) {
@@ -115,24 +111,23 @@ public class Fbo {
 		}
 		unbindFrameBuffer();
 	}
-
+	
 	/**
 	 * Creates a new frame buffer object and sets the buffer to which drawing
 	 * will occur - colour attachment 0. This is the attachment where the colour
 	 * buffer texture is.
-	 * 
 	 */
 	private void createFrameBuffer() {
 		frameBuffer = GL30.glGenFramebuffers();
 		GL30.glBindFramebuffer(GL30.GL_FRAMEBUFFER, frameBuffer);
 		GL11.glDrawBuffer(GL30.GL_COLOR_ATTACHMENT0);
 	}
-
+	
 	/**
 	 * Creates a texture and sets it as the colour buffer attachment for this
 	 * FBO.
 	 */
-	private void createTextureAttachment() {
+	protected void createTextureAttachment() {
 		colourTexture = GL11.glGenTextures();
 		GL11.glBindTexture(GL11.GL_TEXTURE_2D, colourTexture);
 		GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA8, width, height, 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE,
@@ -144,12 +139,12 @@ public class Fbo {
 		GL30.glFramebufferTexture2D(GL30.GL_FRAMEBUFFER, GL30.GL_COLOR_ATTACHMENT0, GL11.GL_TEXTURE_2D, colourTexture,
 				0);
 	}
-
+	
 	/**
 	 * Adds a depth buffer to the FBO in the form of a texture, which can later
 	 * be sampled.
 	 */
-	private void createDepthTextureAttachment() {
+	protected void createDepthTextureAttachment() {
 		depthTexture = GL11.glGenTextures();
 		GL11.glBindTexture(GL11.GL_TEXTURE_2D, depthTexture);
 		GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL14.GL_DEPTH_COMPONENT24, width, height, 0, GL11.GL_DEPTH_COMPONENT,
@@ -158,17 +153,17 @@ public class Fbo {
 		GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR);
 		GL30.glFramebufferTexture2D(GL30.GL_FRAMEBUFFER, GL30.GL_DEPTH_ATTACHMENT, GL11.GL_TEXTURE_2D, depthTexture, 0);
 	}
-
+	
 	/**
 	 * Adds a depth buffer to the FBO in the form of a render buffer. This can't
 	 * be used for sampling in the shaders.
 	 */
-	private void createDepthBufferAttachment() {
+	protected void createDepthBufferAttachment() {
 		depthBuffer = GL30.glGenRenderbuffers();
 		GL30.glBindRenderbuffer(GL30.GL_RENDERBUFFER, depthBuffer);
 		GL30.glRenderbufferStorage(GL30.GL_RENDERBUFFER, GL14.GL_DEPTH_COMPONENT24, width, height);
 		GL30.glFramebufferRenderbuffer(GL30.GL_FRAMEBUFFER, GL30.GL_DEPTH_ATTACHMENT, GL30.GL_RENDERBUFFER,
 				depthBuffer);
 	}
-
+	
 }

+ 53 - 0
src/main/java/eu/tankernn/gameEngine/postProcessing/MultisampleFbo.java

@@ -0,0 +1,53 @@
+package eu.tankernn.gameEngine.postProcessing;
+
+import org.lwjgl.opengl.Display;
+import org.lwjgl.opengl.GL11;
+import org.lwjgl.opengl.GL14;
+import org.lwjgl.opengl.GL30;
+
+import eu.tankernn.gameEngine.renderEngine.DisplayManager;
+
+public class MultisampleFbo extends Fbo {
+	/**
+	 * Creates a multisampled FBO of a specified width and height.
+	 * 
+	 * @param width - the width of the FBO.
+	 * @param height - the height of the FBO.
+	 */
+	public MultisampleFbo(int width, int height) {
+		super(width, height, DEPTH_RENDER_BUFFER);
+	}
+	
+	public void resolveToFbo(Fbo outputFbo) {
+		GL30.glBindFramebuffer(GL30.GL_DRAW_FRAMEBUFFER, outputFbo.frameBuffer);
+		GL30.glBindFramebuffer(GL30.GL_READ_FRAMEBUFFER, this.frameBuffer);
+		GL30.glBlitFramebuffer(0, 0, width, height, 0, 0, outputFbo.width, outputFbo.height, GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT, GL11.GL_NEAREST);
+		this.unbindFrameBuffer();
+	}
+	
+	public void resolveToScreen() {
+		GL30.glBindFramebuffer(GL30.GL_DRAW_FRAMEBUFFER, 0);
+		GL30.glBindFramebuffer(GL30.GL_READ_FRAMEBUFFER, this.frameBuffer);
+		GL11.glDrawBuffer(GL11.GL_BACK);
+		GL30.glBlitFramebuffer(0, 0, width, height, 0, 0, Display.getWidth(), Display.getHeight(), GL11.GL_COLOR_BUFFER_BIT, GL11.GL_NEAREST);
+		this.unbindFrameBuffer();
+	}
+	
+	@Override
+	protected void createTextureAttachment() {
+		colorBuffer = GL30.glGenRenderbuffers();
+		GL30.glBindRenderbuffer(GL30.GL_RENDERBUFFER, colorBuffer);
+		GL30.glRenderbufferStorageMultisample(GL30.GL_RENDERBUFFER, DisplayManager.MULTISAMPLING, GL11.GL_RGBA8, width, height);
+		GL30.glFramebufferRenderbuffer(GL30.GL_FRAMEBUFFER, GL30.GL_COLOR_ATTACHMENT0, GL30.GL_RENDERBUFFER,
+				colorBuffer);
+	}
+	
+	@Override
+	protected void createDepthBufferAttachment() {
+		depthBuffer = GL30.glGenRenderbuffers();
+		GL30.glBindRenderbuffer(GL30.GL_RENDERBUFFER, depthBuffer);
+		GL30.glRenderbufferStorageMultisample(GL30.GL_RENDERBUFFER, DisplayManager.MULTISAMPLING, GL14.GL_DEPTH_COMPONENT24, width, height);
+		GL30.glFramebufferRenderbuffer(GL30.GL_FRAMEBUFFER, GL30.GL_DEPTH_ATTACHMENT, GL30.GL_RENDERBUFFER,
+				depthBuffer);
+	}
+}

+ 1 - 1
src/main/java/eu/tankernn/gameEngine/postProcessing/PostProcessing.java

@@ -12,7 +12,7 @@ import eu.tankernn.gameEngine.renderEngine.Loader;
 
 public class PostProcessing {
 	
-	private static final int blurFactor = 1;
+	private static final int blurFactor = 0;
 	
 	private static final float[] POSITIONS = {-1, 1, -1, -1, 1, 1, 1, -1};
 	private static RawModel quad;

+ 2 - 2
src/main/java/eu/tankernn/gameEngine/renderEngine/DisplayManager.java

@@ -25,7 +25,7 @@ public class DisplayManager {
 	private static final int WIDTH = 1600;
 	private static final int HEIGHT = 900;
 	private static final int FPS_CAP = 60;
-	private static final int MULTISAMPLING = 8;
+	public static final int MULTISAMPLING = 8;
 	
 	private static long lastFrameTime;
 	private static float delta;
@@ -42,7 +42,7 @@ public class DisplayManager {
 		try {
 			setDisplayMode(WIDTH, HEIGHT, fullscreen);
 			Display.setResizable(true);
-			Display.create(new PixelFormat().withSamples(MULTISAMPLING).withDepthBits(24), attribs);
+			Display.create(new PixelFormat().withDepthBits(24), attribs);
 			GL11.glEnable(GL13.GL_MULTISAMPLE);
 		} catch (LWJGLException e) {
 			e.printStackTrace();

+ 22 - 6
src/main/java/eu/tankernn/gameEngine/tester/MainLoop.java

@@ -15,6 +15,7 @@ import java.util.jar.JarFile;
 
 import javax.swing.JOptionPane;
 
+import org.lwjgl.input.Mouse;
 import org.lwjgl.opengl.Display;
 import org.lwjgl.util.vector.Vector2f;
 import org.lwjgl.util.vector.Vector3f;
@@ -39,6 +40,7 @@ import eu.tankernn.gameEngine.particles.ParticleMaster;
 import eu.tankernn.gameEngine.particles.ParticleSystem;
 import eu.tankernn.gameEngine.particles.ParticleTexture;
 import eu.tankernn.gameEngine.postProcessing.Fbo;
+import eu.tankernn.gameEngine.postProcessing.MultisampleFbo;
 import eu.tankernn.gameEngine.postProcessing.PostProcessing;
 import eu.tankernn.gameEngine.renderEngine.DisplayManager;
 import eu.tankernn.gameEngine.renderEngine.Loader;
@@ -141,7 +143,7 @@ public class MainLoop {
 			entities.add(new Entity(grassModel, rand.nextInt(4), new Vector3f(x, terrainPack.getTerrainHeightByWorldPos(x, z), z), 0, 0, 0, 1));
 		}
 		
-		MousePicker picker = new MousePicker(camera, renderer.getProjectionMatrix(), terrainPack, entities);
+		
 		
 		// #### Water rendering ####
 		WaterMaster waterMaster = new WaterMaster(loader, renderer);
@@ -160,10 +162,13 @@ public class MainLoop {
 		ParticleTexture particleTexture = new ParticleTexture(loader.loadTexture("particles/cosmic"), 4, true);
 		ParticleSystem ps = new ParticleSystem(particleTexture, 50, 10, 0.3f, 4);
 		
-		Fbo fbo = new Fbo(Display.getWidth(), Display.getHeight(), Fbo.DEPTH_RENDER_BUFFER);
+		MultisampleFbo multisampleFbo = new MultisampleFbo(Display.getWidth(), Display.getHeight());
+		Fbo outputFbo = new Fbo(Display.getWidth(), Display.getHeight(), Fbo.DEPTH_TEXTURE);
 		
 		PostProcessing.init(loader);
 		
+		MousePicker picker = new MousePicker(camera, renderer.getProjectionMatrix(), terrainPack, entities, guis);
+		
 		while (!Display.isCloseRequested()) {
 			barrel.increaseRotation(0, 1, 0);
 			player.move(terrainPack);
@@ -177,6 +182,13 @@ public class MainLoop {
 				flashLight.getPosition().y = terrainPack.getTerrainHeightByWorldPos(currentPoint.x, currentPoint.z) + 1.0f;
 			}
 			
+			if (picker.getCurrentGui() != null) {
+				if (Mouse.isButtonDown(0)) {
+					System.out.println("Clicked gui.");
+					picker.getCurrentGui().getPosition().x += 0.1f;
+				}
+			}
+			
 			// Update debug info
 			
 			Terrain currentTerrain = terrainPack.getTerrainByWorldPos(player.getPosition().x, player.getPosition().z);
@@ -199,15 +211,16 @@ public class MainLoop {
 			
 			waterMaster.renderBuffers(renderer, scene);
 			
-			fbo.bindFrameBuffer();
+			multisampleFbo.bindFrameBuffer();
 			
 			renderer.renderScene(scene, new Vector4f(0, 1, 0, Float.MAX_VALUE));
 			waterMaster.renderWater(camera, lights);
 			ParticleMaster.renderParticles(camera);
 			
-			fbo.unbindFrameBuffer();
+			multisampleFbo.unbindFrameBuffer();
 			
-			PostProcessing.doPostProcessing(fbo.getColourTexture());
+			multisampleFbo.resolveToFbo(outputFbo);
+			PostProcessing.doPostProcessing(outputFbo.getColourTexture());
 			
 			guiRenderer.render(guis);
 			TextMaster.render();
@@ -216,7 +229,8 @@ public class MainLoop {
 		}
 		
 		PostProcessing.cleanUp();
-		fbo.cleanUp();
+		outputFbo.cleanUp();
+		multisampleFbo.cleanUp();
 		ParticleMaster.cleanUp();
 		TextMaster.cleanUp();
 		waterMaster.cleanUp();
@@ -261,6 +275,8 @@ public class MainLoop {
 				JOptionPane.showMessageDialog(null, "Could not export natives. Execute in terminal to see full error output.", "Export natives", JOptionPane.ERROR_MESSAGE);
 				e.printStackTrace();
 			}
+		} else {
+			System.setProperty("org.lwjgl.librarypath", nativeDir.getAbsolutePath());
 		}
 	}
 	

+ 31 - 1
src/main/java/eu/tankernn/gameEngine/util/MousePicker.java

@@ -11,6 +11,7 @@ import org.lwjgl.util.vector.Vector4f;
 
 import eu.tankernn.gameEngine.entities.Camera;
 import eu.tankernn.gameEngine.entities.Entity;
+import eu.tankernn.gameEngine.gui.GuiTexture;
 import eu.tankernn.gameEngine.models.AABB;
 import eu.tankernn.gameEngine.terrains.Terrain;
 import eu.tankernn.gameEngine.terrains.TerrainPack;
@@ -30,12 +31,16 @@ public class MousePicker {
 	private List<Entity> entities;
 	private Entity currentEntity;
 	
-	public MousePicker(Camera cam, Matrix4f projection, TerrainPack terrains, List<Entity> entities) {
+	private List<GuiTexture> guis;
+	private GuiTexture currentGui;
+	
+	public MousePicker(Camera cam, Matrix4f projection, TerrainPack terrains, List<Entity> entities, List<GuiTexture> guis) {
 		camera = cam;
 		projectionMatrix = projection;
 		viewMatrix = Maths.createViewMatrix(camera);
 		this.terrains = terrains;
 		this.entities = entities;
+		this.guis = guis;
 	}
 	
 	public Entity getCurrentEntity() {
@@ -50,9 +55,14 @@ public class MousePicker {
 		return currentRay;
 	}
 	
+	public GuiTexture getCurrentGui() {
+		return currentGui;
+	}
+	
 	public void update() {
 		viewMatrix = Maths.createViewMatrix(camera);
 		currentRay = calculateMouseRay();
+		currentGui = calculateGuiTexture();
 		if (intersectionInRange(0, RAY_RANGE, currentRay)) {
 			currentTerrainPoint = binarySearch(0, 0, RAY_RANGE, currentRay);
 		} else {
@@ -100,6 +110,26 @@ public class MousePicker {
 		return new Vector2f(x, y);
 	}
 	
+	// GUI Intersect
+	
+	private GuiTexture calculateGuiTexture() {
+		float mouseX = Mouse.getX();
+		float mouseY = Mouse.getY();
+		Vector2f mouseCoords = getNormalisedDeviceCoordinates(mouseX, mouseY);
+		
+		for (GuiTexture gui : guis) {
+			float posX = gui.getPosition().x;
+			float posY = gui.getPosition().y;
+			float scaleX = gui.getScale().x;
+			float scaleY = gui.getScale().y;
+			
+			if (mouseCoords.x > posX - scaleX && mouseCoords.x < posX + scaleX && mouseCoords.y > posY - scaleY && mouseCoords.y < posY + scaleY) {
+				return gui;
+			}
+		}
+		return null;
+	}
+	
 	// #### Entity intersect ####
 	
 	public boolean entityInstersect(Entity entity) {