Roi Atalla avatar Roi Atalla committed 2516669

Example 7.2 is fully functional with UBO's. Also, I made a small change in my Matrix4 class: I made the direct FloatBuffer static. This way, only 1 direct FloatBuffer is used for all upload operations.

Comments (0)

Files changed (13)

src/main/java/com/ra4king/opengl/GLProgram.java

 				
 				Display.update();
 				
-				int error;
-				while((error = glGetError()) != GL_NO_ERROR)
-					System.out.println(gluErrorString(error));
+				checkGLError();
 				
 				frames++;
 				if(System.nanoTime() - lastFPS >= 1e9) {
 		}
 	}
 	
+	public void checkGLError() {
+		int error;
+		while((error = glGetError()) != GL_NO_ERROR)
+			throw new RuntimeException("OpenGL Error: " + gluErrorString(error));
+	}
+	
 	public int getWidth() {
 		return Display.getWidth();
 	}

src/main/java/com/ra4king/opengl/arcsynthesis/gl33/chapter7/example2/Example7_2.java

+package com.ra4king.opengl.arcsynthesis.gl33.chapter7.example2;
+
+import static org.lwjgl.opengl.GL11.*;
+import static org.lwjgl.opengl.GL15.*;
+import static org.lwjgl.opengl.GL20.*;
+import static org.lwjgl.opengl.GL30.*;
+import static org.lwjgl.opengl.GL31.*;
+import static org.lwjgl.opengl.GL32.*;
+
+import org.lwjgl.input.Keyboard;
+
+import com.ra4king.opengl.GLProgram;
+import com.ra4king.opengl.util.Mesh;
+import com.ra4king.opengl.util.ShaderProgram;
+import com.ra4king.opengl.util.math.Matrix4;
+import com.ra4king.opengl.util.math.MatrixStack;
+import com.ra4king.opengl.util.math.Vector3;
+
+public class Example7_2 extends GLProgram {
+	public static void main(String[] args) {
+		new Example7_2().run();
+	}
+	
+	private final TreeData[] forest = {
+			new TreeData(-45.0f, -40.0f, 2.0f, 3.0f),
+			new TreeData(-42.0f, -35.0f, 2.0f, 3.0f),
+			new TreeData(-39.0f, -29.0f, 2.0f, 4.0f),
+			new TreeData(-44.0f, -26.0f, 3.0f, 3.0f),
+			new TreeData(-40.0f, -22.0f, 2.0f, 4.0f),
+			new TreeData(-36.0f, -15.0f, 3.0f, 3.0f),
+			new TreeData(-41.0f, -11.0f, 2.0f, 3.0f),
+			new TreeData(-37.0f, -6.0f, 3.0f, 3.0f),
+			new TreeData(-45.0f, 0.0f, 2.0f, 3.0f),
+			new TreeData(-39.0f, 4.0f, 3.0f, 4.0f),
+			new TreeData(-36.0f, 8.0f, 2.0f, 3.0f),
+			new TreeData(-44.0f, 13.0f, 3.0f, 3.0f),
+			new TreeData(-42.0f, 17.0f, 2.0f, 3.0f),
+			new TreeData(-38.0f, 23.0f, 3.0f, 4.0f),
+			new TreeData(-41.0f, 27.0f, 2.0f, 3.0f),
+			new TreeData(-39.0f, 32.0f, 3.0f, 3.0f),
+			new TreeData(-44.0f, 37.0f, 3.0f, 4.0f),
+			new TreeData(-36.0f, 42.0f, 2.0f, 3.0f),
+			
+			new TreeData(-32.0f, -45.0f, 2.0f, 3.0f),
+			new TreeData(-30.0f, -42.0f, 2.0f, 4.0f),
+			new TreeData(-34.0f, -38.0f, 3.0f, 5.0f),
+			new TreeData(-33.0f, -35.0f, 3.0f, 4.0f),
+			new TreeData(-29.0f, -28.0f, 2.0f, 3.0f),
+			new TreeData(-26.0f, -25.0f, 3.0f, 5.0f),
+			new TreeData(-35.0f, -21.0f, 3.0f, 4.0f),
+			new TreeData(-31.0f, -17.0f, 3.0f, 3.0f),
+			new TreeData(-28.0f, -12.0f, 2.0f, 4.0f),
+			new TreeData(-29.0f, -7.0f, 3.0f, 3.0f),
+			new TreeData(-26.0f, -1.0f, 2.0f, 4.0f),
+			new TreeData(-32.0f, 6.0f, 2.0f, 3.0f),
+			new TreeData(-30.0f, 10.0f, 3.0f, 5.0f),
+			new TreeData(-33.0f, 14.0f, 2.0f, 4.0f),
+			new TreeData(-35.0f, 19.0f, 3.0f, 4.0f),
+			new TreeData(-28.0f, 22.0f, 2.0f, 3.0f),
+			new TreeData(-33.0f, 26.0f, 3.0f, 3.0f),
+			new TreeData(-29.0f, 31.0f, 3.0f, 4.0f),
+			new TreeData(-32.0f, 38.0f, 2.0f, 3.0f),
+			new TreeData(-27.0f, 41.0f, 3.0f, 4.0f),
+			new TreeData(-31.0f, 45.0f, 2.0f, 4.0f),
+			new TreeData(-28.0f, 48.0f, 3.0f, 5.0f),
+			
+			new TreeData(-25.0f, -48.0f, 2.0f, 3.0f),
+			new TreeData(-20.0f, -42.0f, 3.0f, 4.0f),
+			new TreeData(-22.0f, -39.0f, 2.0f, 3.0f),
+			new TreeData(-19.0f, -34.0f, 2.0f, 3.0f),
+			new TreeData(-23.0f, -30.0f, 3.0f, 4.0f),
+			new TreeData(-24.0f, -24.0f, 2.0f, 3.0f),
+			new TreeData(-16.0f, -21.0f, 2.0f, 3.0f),
+			new TreeData(-17.0f, -17.0f, 3.0f, 3.0f),
+			new TreeData(-25.0f, -13.0f, 2.0f, 4.0f),
+			new TreeData(-23.0f, -8.0f, 2.0f, 3.0f),
+			new TreeData(-17.0f, -2.0f, 3.0f, 3.0f),
+			new TreeData(-16.0f, 1.0f, 2.0f, 3.0f),
+			new TreeData(-19.0f, 4.0f, 3.0f, 3.0f),
+			new TreeData(-22.0f, 8.0f, 2.0f, 4.0f),
+			new TreeData(-21.0f, 14.0f, 2.0f, 3.0f),
+			new TreeData(-16.0f, 19.0f, 2.0f, 3.0f),
+			new TreeData(-23.0f, 24.0f, 3.0f, 3.0f),
+			new TreeData(-18.0f, 28.0f, 2.0f, 4.0f),
+			new TreeData(-24.0f, 31.0f, 2.0f, 3.0f),
+			new TreeData(-20.0f, 36.0f, 2.0f, 3.0f),
+			new TreeData(-22.0f, 41.0f, 3.0f, 3.0f),
+			new TreeData(-21.0f, 45.0f, 2.0f, 3.0f),
+			
+			new TreeData(-12.0f, -40.0f, 2.0f, 4.0f),
+			new TreeData(-11.0f, -35.0f, 3.0f, 3.0f),
+			new TreeData(-10.0f, -29.0f, 1.0f, 3.0f),
+			new TreeData(-9.0f, -26.0f, 2.0f, 2.0f),
+			new TreeData(-6.0f, -22.0f, 2.0f, 3.0f),
+			new TreeData(-15.0f, -15.0f, 1.0f, 3.0f),
+			new TreeData(-8.0f, -11.0f, 2.0f, 3.0f),
+			new TreeData(-14.0f, -6.0f, 2.0f, 4.0f),
+			new TreeData(-12.0f, 0.0f, 2.0f, 3.0f),
+			new TreeData(-7.0f, 4.0f, 2.0f, 2.0f),
+			new TreeData(-13.0f, 8.0f, 2.0f, 2.0f),
+			new TreeData(-9.0f, 13.0f, 1.0f, 3.0f),
+			new TreeData(-13.0f, 17.0f, 3.0f, 4.0f),
+			new TreeData(-6.0f, 23.0f, 2.0f, 3.0f),
+			new TreeData(-12.0f, 27.0f, 1.0f, 2.0f),
+			new TreeData(-8.0f, 32.0f, 2.0f, 3.0f),
+			new TreeData(-10.0f, 37.0f, 3.0f, 3.0f),
+			new TreeData(-11.0f, 42.0f, 2.0f, 2.0f),
+			
+			new TreeData(15.0f, 5.0f, 2.0f, 3.0f),
+			new TreeData(15.0f, 10.0f, 2.0f, 3.0f),
+			new TreeData(15.0f, 15.0f, 2.0f, 3.0f),
+			new TreeData(15.0f, 20.0f, 2.0f, 3.0f),
+			new TreeData(15.0f, 25.0f, 2.0f, 3.0f),
+			new TreeData(15.0f, 30.0f, 2.0f, 3.0f),
+			new TreeData(15.0f, 35.0f, 2.0f, 3.0f),
+			new TreeData(15.0f, 40.0f, 2.0f, 3.0f),
+			new TreeData(15.0f, 45.0f, 2.0f, 3.0f),
+			
+			new TreeData(25.0f, 5.0f, 2.0f, 3.0f),
+			new TreeData(25.0f, 10.0f, 2.0f, 3.0f),
+			new TreeData(25.0f, 15.0f, 2.0f, 3.0f),
+			new TreeData(25.0f, 20.0f, 2.0f, 3.0f),
+			new TreeData(25.0f, 25.0f, 2.0f, 3.0f),
+			new TreeData(25.0f, 30.0f, 2.0f, 3.0f),
+			new TreeData(25.0f, 35.0f, 2.0f, 3.0f),
+			new TreeData(25.0f, 40.0f, 2.0f, 3.0f),
+			new TreeData(25.0f, 45.0f, 2.0f, 3.0f),
+	};
+	
+	private final int globalMatricesBindingIndex = 0;
+	
+	private ProgramData uniformColor, objectColor, uniformColorTint;
+	private Matrix4 perspectiveMatrix;
+	
+	private int ubo;
+	
+	private Mesh coneMesh, cylinderMesh, cubeTintMesh, cubeColorMesh, planeMesh;
+	
+	private Vector3 camTarget = new Vector3(0,0.4f,0);
+	private Vector3 sphereCamRelPos = new Vector3(67.5f,-46,150);
+	
+	private boolean drawLookAtPoint = true;
+	
+	public Example7_2() {
+		super("Example 7.2", 500, 500, true);
+	}
+	
+	@Override
+	public void init() {
+		glClearColor(0, 0, 0, 0);
+		glClearDepth(1);
+		
+		uniformColor = loadProgram("example7.2.PosOnly.vert", "example7.2.ColorUniform.frag");
+		objectColor = loadProgram("example7.2.PosColor.vert", "example7.2.ColorPassthrough.frag");
+		uniformColorTint = loadProgram("example7.2.PosColor.vert", "example7.2.ColorMultUniform.frag");
+		
+		perspectiveMatrix = new Matrix4();
+		
+		ubo = glGenBuffers();
+		glBindBuffer(GL_UNIFORM_BUFFER, ubo);
+		glBufferData(GL_UNIFORM_BUFFER, 16 * 4 * 2, GL_STREAM_DRAW);
+		glBindBuffer(GL_UNIFORM_BUFFER, 0);
+		
+		glBindBufferRange(GL_UNIFORM_BUFFER, globalMatricesBindingIndex, ubo, 0, 16 * 4 * 2);
+		
+		try {
+			coneMesh = new Mesh(getClass().getResource("example7.2.UnitConeTint.xml"));
+			cylinderMesh = new Mesh(getClass().getResource("example7.2.UnitCylinderTint.xml"));
+			cubeTintMesh = new Mesh(getClass().getResource("example7.2.UnitCubeTint.xml"));
+			cubeColorMesh = new Mesh(getClass().getResource("example7.2.UnitCubeColor.xml"));
+			planeMesh = new Mesh(getClass().getResource("example7.2.UnitPlane.xml"));
+		}
+		catch(Exception exc) {
+			exc.printStackTrace();
+			destroy();
+		}
+		
+		glEnable(GL_CULL_FACE);
+		glCullFace(GL_BACK);
+		glFrontFace(GL_CW);
+		
+		glEnable(GL_DEPTH_TEST);
+		glDepthMask(true);
+		glDepthFunc(GL_LEQUAL);
+		glDepthRange(0,1);
+		glEnable(GL_DEPTH_CLAMP);
+	}
+	
+	private ProgramData loadProgram(String vs, String fs) {
+		ProgramData data = new ProgramData(new ShaderProgram(readFromFile(vs), readFromFile(fs)));
+		data.modelToWorldMatrixUniform = glGetUniformLocation(data.program.getProgram(),"modelToWorldMatrix");
+		data.globalUniformBlockIndex = glGetUniformBlockIndex(data.program.getProgram(), "GlobalMatrices");
+		data.baseColorUniform = glGetUniformLocation(data.program.getProgram(), "baseColor");
+		
+		glUniformBlockBinding(data.program.getProgram(), data.globalUniformBlockIndex, globalMatricesBindingIndex);
+		
+		return data;
+	}
+	
+	@Override
+	public void resized() {
+		super.resized();
+		
+		perspectiveMatrix.clearToPerspective(45*(float)Math.PI/180, getWidth(), getHeight(), 1, 1000);
+		
+		glBindBuffer(GL_UNIFORM_BUFFER, ubo);
+		glBufferSubData(GL_UNIFORM_BUFFER, 0, perspectiveMatrix.getBuffer());
+		glBindBuffer(GL_UNIFORM_BUFFER, 0);
+	}
+	
+	@Override
+	public void update(long deltaTime) {
+		float delta = deltaTime / (float)1e9;
+		
+		float speed1 = (Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) ? 4f : 16) * delta;
+		float speed2 = (Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) ? 11.25f : 45f) * delta;
+		float speed3 = (Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) ? 5f : 20) * delta;
+		
+		if(Keyboard.isKeyDown(Keyboard.KEY_W))
+			camTarget.sub(0,0,speed1);
+		if(Keyboard.isKeyDown(Keyboard.KEY_S))
+			camTarget.add(0,0,speed1);
+		
+		if(Keyboard.isKeyDown(Keyboard.KEY_D))
+			camTarget.add(speed1,0,0);
+		if(Keyboard.isKeyDown(Keyboard.KEY_A))
+			camTarget.sub(speed1,0,0);
+		
+		if(Keyboard.isKeyDown(Keyboard.KEY_E))
+			camTarget.sub(speed1,0,0);
+		if(Keyboard.isKeyDown(Keyboard.KEY_Q))
+			camTarget.add(speed1,0,0);
+		
+		if(Keyboard.isKeyDown(Keyboard.KEY_I))
+			sphereCamRelPos.sub(0,speed2,0);
+		if(Keyboard.isKeyDown(Keyboard.KEY_K))
+			sphereCamRelPos.add(0,speed2,0);
+		
+		if(Keyboard.isKeyDown(Keyboard.KEY_J))
+			sphereCamRelPos.sub(speed2,0,0);
+		if(Keyboard.isKeyDown(Keyboard.KEY_L))
+			sphereCamRelPos.add(speed2,0,0);
+		
+		if(Keyboard.isKeyDown(Keyboard.KEY_O))
+			sphereCamRelPos.sub(0,0,speed3);
+		if(Keyboard.isKeyDown(Keyboard.KEY_U))
+			sphereCamRelPos.add(0,0,speed3);
+		
+		sphereCamRelPos.y(clamp(sphereCamRelPos.y(), -78.75f, -1));
+		camTarget.y(camTarget.y() > 0 ? camTarget.y() : 0);
+		sphereCamRelPos.z(sphereCamRelPos.z() > 5 ? sphereCamRelPos.z() : 5);
+	}
+	
+	private float clamp(float value, float low, float high) {
+		return Math.min(Math.max(value, low), high);
+	}
+	
+	@Override
+	public void keyPressed(int key, char c, long nanos) {
+		switch(key) {
+			case Keyboard.KEY_SPACE:
+				drawLookAtPoint = !drawLookAtPoint;
+				System.out.printf("Target: %f, %f, %f\n", camTarget.x(), camTarget.y(), camTarget.z());
+				System.out.printf("Position: %f,  %f, %f\n", sphereCamRelPos.x(), sphereCamRelPos.y(), sphereCamRelPos.z());
+				break;
+		}
+	}
+	
+	private Matrix4 calcLookAtMatrix(Vector3 cameraPoint, Vector3 lookPoint, Vector3 upPoint) {
+		Vector3 lookDir = new Vector3(lookPoint).sub(cameraPoint).normalize();
+		Vector3 upDir = new Vector3(upPoint).normalize();
+		
+		Vector3 rightDir = lookDir.cross(upDir).normalize();
+		Vector3 perpUpDir = rightDir.cross(lookDir);
+		
+		Matrix4 rotMat = new Matrix4().clearToIdentity();
+		rotMat.put(0,rightDir,0);
+		rotMat.put(1,perpUpDir,0);
+		rotMat.put(2,lookDir.mul(-1),0);
+		
+		return rotMat.transpose().translate(new Vector3(cameraPoint).mul(-1));
+	}
+	
+	private Vector3 resolveCamPosition() {
+		double phi = sphereCamRelPos.x() * Math.PI / 180;
+		double theta = (sphereCamRelPos.y() + 90) * Math.PI / 180;
+		
+		float sinTheta = (float)Math.sin(theta);
+		float cosTheta = (float)Math.cos(theta);
+		float cosPhi = (float)Math.cos(phi);
+		float sinPhi = (float)Math.sin(phi);
+		
+		return new Vector3(sinTheta * cosPhi, cosTheta, sinTheta * sinPhi).mul(sphereCamRelPos.z()).add(camTarget);
+	}
+	
+	@Override
+	public void render() {
+		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+		
+		Vector3 camPos = resolveCamPosition();
+		
+		MatrixStack camMatrix = new MatrixStack();
+		camMatrix.setTop(calcLookAtMatrix(camPos, camTarget, new Vector3(0,1,0)));
+		
+		glBindBuffer(GL_UNIFORM_BUFFER, ubo);
+		glBufferSubData(GL_UNIFORM_BUFFER, 16 * 4, camMatrix.getTop().getBuffer());
+		glBindBuffer(GL_UNIFORM_BUFFER, 0);
+		
+		MatrixStack modelMatrix = new MatrixStack();
+		
+		{
+			modelMatrix.pushMatrix();
+			
+			modelMatrix.getTop().scale(100, 1, 100);
+			
+			uniformColor.program.begin();
+			glUniformMatrix4(uniformColor.modelToWorldMatrixUniform,false,modelMatrix.getTop().getBuffer());
+			glUniform4f(uniformColor.baseColorUniform,0.302f,0.416f,0.0589f,1.0f);
+			planeMesh.render();
+			uniformColor.program.end();
+			
+			modelMatrix.popMatrix();
+		}
+		
+		drawForest(modelMatrix);
+		
+		{
+			modelMatrix.pushMatrix();
+			
+			modelMatrix.getTop().translate(20,0,-10);
+			
+			drawParthenon(modelMatrix);
+			
+			modelMatrix.popMatrix();
+		}
+		
+		if(drawLookAtPoint) {
+			glDisable(GL_DEPTH_TEST);
+			
+			modelMatrix.pushMatrix();
+			
+			modelMatrix.getTop().translate(camTarget).scale(1,1,1);
+			
+			objectColor.program.begin();
+			glUniformMatrix4(objectColor.modelToWorldMatrixUniform, false, modelMatrix.getTop().getBuffer());
+			cubeColorMesh.render();
+			objectColor.program.end();
+			
+			modelMatrix.popMatrix();
+			
+			glEnable(GL_DEPTH_TEST);
+		}
+	}
+	
+	private void drawForest(MatrixStack modelMatrix) {
+		for(TreeData tree : forest) {
+			modelMatrix.pushMatrix();
+			modelMatrix.getTop().translate(tree.x,0,tree.z);
+			drawTree(modelMatrix, tree.trunkHeight, tree.coneHeight);
+			modelMatrix.popMatrix();
+		}
+	}
+	
+	private void drawTree(MatrixStack modelMatrix, float trunkHeight, float coneHeight) {
+		modelMatrix.pushMatrix();
+		
+		modelMatrix.getTop().scale(1,trunkHeight,1).translate(0,0.5f,0);
+		
+		uniformColorTint.program.begin();
+		glUniformMatrix4(uniformColorTint.modelToWorldMatrixUniform, false, modelMatrix.getTop().getBuffer());
+		glUniform4f(uniformColorTint.baseColorUniform, 0.694f, 0.4f, 0.106f, 1);
+		cylinderMesh.render();
+		uniformColorTint.program.end();
+		
+		modelMatrix.popMatrix();
+		
+		
+		modelMatrix.pushMatrix();
+		
+		modelMatrix.getTop().translate(0,trunkHeight,0).scale(3,coneHeight,3);
+		
+		uniformColorTint.program.begin();
+		glUniformMatrix4(uniformColorTint.modelToWorldMatrixUniform, false, modelMatrix.getTop().getBuffer());
+		glUniform4f(uniformColorTint.baseColorUniform, 0, 1, 0, 1);
+		coneMesh.render();
+		uniformColorTint.program.end();
+		
+		modelMatrix.popMatrix();
+	}
+	
+	private final float parthenonWidth = 14;
+	private final float parthenonLength = 20;
+	private final float parthenonColumnHeight = 5;
+	private final float parthenonBaseHeight = 1;
+	private final float parthenonTopHeight = 2;
+	
+	private final float frontZVal = parthenonLength/2 - 1;
+	private final float rightXVal = parthenonWidth/2 - 1;
+	
+	private void drawParthenon(MatrixStack modelMatrix) {
+		{
+			modelMatrix.pushMatrix();
+			
+			modelMatrix.getTop().scale(parthenonWidth,parthenonBaseHeight,parthenonLength).translate(0,0.5f,0);
+			
+			uniformColorTint.program.begin();
+			glUniformMatrix4(uniformColorTint.modelToWorldMatrixUniform, false, modelMatrix.getTop().getBuffer());
+			glUniform4f(uniformColorTint.baseColorUniform, 0.9f, 0.9f, 0.9f, 0.9f);
+			cubeTintMesh.render();
+			uniformColorTint.program.end();
+			
+			modelMatrix.popMatrix();
+		}
+		
+		{
+			modelMatrix.pushMatrix();
+			
+			modelMatrix.getTop().translate(0,parthenonColumnHeight+parthenonBaseHeight,0)
+								.scale(parthenonWidth,parthenonTopHeight,parthenonLength)
+								.translate(0,0.5f,0);
+			
+			uniformColorTint.program.begin();
+			glUniformMatrix4(uniformColorTint.modelToWorldMatrixUniform, false, modelMatrix.getTop().getBuffer());
+			glUniform4f(uniformColorTint.baseColorUniform, 0.9f, 0.9f, 0.9f, 0.9f);
+			cubeTintMesh.render();
+			uniformColorTint.program.end();
+			
+			modelMatrix.popMatrix();
+		}
+		
+		for(int a = 0; a < parthenonWidth/2; a++) {
+			{
+				modelMatrix.pushMatrix();
+				modelMatrix.getTop().translate(2*a - parthenonWidth/2 + 1, parthenonBaseHeight, frontZVal);
+				drawColumn(modelMatrix);
+				modelMatrix.popMatrix();
+			}
+			
+			{
+				modelMatrix.pushMatrix();
+				modelMatrix.getTop().translate(2*a - parthenonWidth/2 + 1, parthenonBaseHeight, -frontZVal);
+				drawColumn(modelMatrix);
+				modelMatrix.popMatrix();
+			}
+		}
+		
+		for(int a = 1; a < (parthenonLength-2)/2; a++) {
+			{
+				modelMatrix.pushMatrix();
+				modelMatrix.getTop().translate(rightXVal,parthenonBaseHeight,2*a - parthenonLength/2 + 1);
+				drawColumn(modelMatrix);
+				modelMatrix.popMatrix();
+			}
+			
+			{
+				modelMatrix.pushMatrix();
+				modelMatrix.getTop().translate(-rightXVal,parthenonBaseHeight,2*a - parthenonLength/2 + 1);
+				drawColumn(modelMatrix);
+				modelMatrix.popMatrix();
+			}
+		}
+		
+		{
+			modelMatrix.pushMatrix();
+			
+			modelMatrix.getTop().translate(0,1,0).scale(parthenonWidth-6, parthenonColumnHeight, parthenonLength-6).translate(0,0.5f,0);
+			
+			objectColor.program.begin();
+			glUniformMatrix4(objectColor.modelToWorldMatrixUniform, false, modelMatrix.getTop().getBuffer());
+			cubeColorMesh.render();
+			objectColor.program.end();
+			
+			modelMatrix.popMatrix();
+		}
+		
+		{
+			modelMatrix.pushMatrix();
+			
+			modelMatrix.getTop().translate(0,parthenonColumnHeight + parthenonBaseHeight + parthenonTopHeight/2,parthenonLength/2)
+								.rotate(-135*(float)Math.PI/180,1,0,0)
+								.rotate(45*(float)Math.PI/180, 0, 1, 0);
+			
+			objectColor.program.begin();
+			glUniformMatrix4(objectColor.modelToWorldMatrixUniform, false, modelMatrix.getTop().getBuffer());
+			cubeColorMesh.render();
+			objectColor.program.end();
+
+			modelMatrix.popMatrix();
+		}
+	}
+	
+	private final float columnBaseHeight = 0.25f;
+	
+	private void drawColumn(MatrixStack modelMatrix) {
+		{
+			modelMatrix.pushMatrix();
+			
+			modelMatrix.getTop().scale(1, columnBaseHeight, 1).translate(0,0.5f,0);
+			
+			uniformColorTint.program.begin();
+			glUniformMatrix4(uniformColorTint.modelToWorldMatrixUniform, false, modelMatrix.getTop().getBuffer());
+			glUniform4f(uniformColorTint.baseColorUniform, 1, 1, 1, 1);
+			cubeTintMesh.render();
+			uniformColorTint.program.end();
+
+			modelMatrix.popMatrix();
+		}
+		
+		{
+			modelMatrix.pushMatrix();
+			
+			modelMatrix.getTop().translate(0, parthenonColumnHeight - columnBaseHeight, 0).scale(1,columnBaseHeight,1).translate(0,0.5f,0);
+			
+			uniformColorTint.program.begin();
+			glUniformMatrix4(uniformColorTint.modelToWorldMatrixUniform, false, modelMatrix.getTop().getBuffer());
+			glUniform4f(uniformColorTint.baseColorUniform, 0.9f, 0.9f, 0.9f, 0.9f);
+			cubeTintMesh.render();
+			uniformColorTint.program.end();
+
+			modelMatrix.popMatrix();
+		}
+		
+		{
+			modelMatrix.pushMatrix();
+			
+			modelMatrix.getTop().translate(0, columnBaseHeight, 0).scale(0.8f,  parthenonColumnHeight - columnBaseHeight*2,  0.8f).translate(0,0.5f,0);
+			
+			uniformColorTint.program.begin();
+			glUniformMatrix4(uniformColorTint.modelToWorldMatrixUniform, false, modelMatrix.getTop().getBuffer());
+			glUniform4f(uniformColorTint.baseColorUniform, 0.9f, 0.9f, 0.9f, 0.9f);
+			cylinderMesh.render();
+			uniformColorTint.program.end();
+
+			modelMatrix.popMatrix();
+		}
+	}
+	
+	private static class ProgramData {
+		private ShaderProgram program;
+		private int globalUniformBlockIndex;
+		private int modelToWorldMatrixUniform;
+		private int baseColorUniform;
+		
+		public ProgramData(ShaderProgram program) {
+			this.program = program;
+		}
+	}
+	
+	private static class TreeData {
+		private float x, z, trunkHeight, coneHeight;
+		
+		public TreeData(float x, float z, float trunkHeight, float coneHeight) {
+			this.x = x;
+			this.z = z;
+			this.trunkHeight = trunkHeight;
+			this.coneHeight = coneHeight;
+		}
+	}
+}

src/main/java/com/ra4king/opengl/arcsynthesis/gl33/chapter7/example2/example7.2.ColorMultUniform.frag

+#version 330
+
+smooth in vec4 interpColor;
+uniform vec4 baseColor;
+
+out vec4 outputColor;
+
+void main()
+{
+	outputColor = interpColor * baseColor;
+}

src/main/java/com/ra4king/opengl/arcsynthesis/gl33/chapter7/example2/example7.2.ColorPassthrough.frag

+#version 330
+
+smooth in vec4 interpColor;
+
+out vec4 outputColor;
+
+void main()
+{
+	outputColor = interpColor;
+}

src/main/java/com/ra4king/opengl/arcsynthesis/gl33/chapter7/example2/example7.2.ColorUniform.frag

+#version 330
+
+uniform vec4 baseColor;
+
+out vec4 outputColor;
+
+void main()
+{
+	outputColor = baseColor;
+}

src/main/java/com/ra4king/opengl/arcsynthesis/gl33/chapter7/example2/example7.2.PosColor.vert

+#version 330
+
+layout(location = 0) in vec4 position;
+layout(location = 1) in vec4 color;
+
+smooth out vec4 interpColor;
+
+layout(std140) uniform GlobalMatrices
+{
+	mat4 cameraToClipMatrix;
+	mat4 worldToCameraMatrix;
+};
+
+uniform mat4 modelToWorldMatrix;
+
+void main()
+{
+	gl_Position = cameraToClipMatrix * worldToCameraMatrix * modelToWorldMatrix * position;
+	interpColor = color;
+}

src/main/java/com/ra4king/opengl/arcsynthesis/gl33/chapter7/example2/example7.2.PosOnly.vert

+#version 330
+
+layout(location = 0) in vec4 position;
+
+layout(std140) uniform GlobalMatrices
+{
+	mat4 cameraToClipMatrix;
+	mat4 worldToCameraMatrix;
+};
+
+uniform mat4 modelToWorldMatrix;
+
+void main()
+{
+	gl_Position = cameraToClipMatrix * worldToCameraMatrix * modelToWorldMatrix * position;
+}

src/main/java/com/ra4king/opengl/arcsynthesis/gl33/chapter7/example2/example7.2.UnitConeTint.xml

+<?xml version="1.0" encoding="UTF-8"?>
+<?oxygen RNGSchema="../../Documents/meshFormat.rnc" type="compact"?>
+
+<mesh xmlns="http://www.arcsynthesis.com/gltut/mesh" >
+	<attribute index="0" type="float" size="3" > 
+		0 0.866 0
+		0.5 0 0
+		0.48907381875731 0 0.1039557588888
+		0.45677280077542 0 0.20336815992623
+		0.40450865316151 0 0.29389241146627
+		0.33456556611288 0 0.37157217599218
+		0.2500003830126 0 0.43301248075957
+		0.15450900193016 0 0.47552809414644
+		0.052264847412855 0 0.49726088296277
+		-0.052263527886268 0 0.49726102165048
+		-0.15450774007312 0 0.47552850414828
+		-0.24999923397422 0 0.43301314415651
+		-0.33456458011157 0 0.37157306379065
+		-0.40450787329018 0 0.29389348486527
+		-0.45677226111814 0 0.20336937201315
+		-0.48907354289964 0 0.10395705668972
+		-0.49999999999824 0 1.3267948966764e-006
+		-0.48907409461153 0 -0.10395446108714
+		-0.45677334042948 0 -0.20336694783787
+		-0.40450943302999 0 -0.2938913380652
+		-0.33456655211184 0 -0.3715712881911
+		-0.25000153204922 0 -0.43301181735958
+		-0.15451026378611 0 -0.47552768414126
+		-0.052266166939075 0 -0.49726074427155
+		0.052262208359312 0 -0.4972611603347
+		0.15450647821499 0 -0.47552891414676
+		0.24999808493408 0 -0.4330138075504
+		0.3345635941079 0 -0.37157395158649
+		0.40450709341601 0 -0.2938945582622
+		0.45677172145764 0 -0.20337058409865
+		0.48907326703854 0 -0.10395835448992
+		0 0 0
+	</attribute>
+	<attribute index="1" type="float" size="4" > 
+		1 1 1 1
+		0.9 0.9 0.9 1
+		0.82 0.82 0.82 1
+		0.74 0.74 0.74 1
+		0.66 0.66 0.66 1
+		0.58 0.58 0.58 1
+		0.5 0.5 0.5 1
+		0.58 0.58 0.58 1
+		0.66 0.66 0.66 1
+		0.74 0.74 0.74 1
+		0.82 0.82 0.82 1
+		0.9 0.9 0.9 1
+		0.82 0.82 0.82 1
+		0.74 0.74 0.74 1
+		0.66 0.66 0.66 1
+		0.58 0.58 0.58 1
+		0.5 0.5 0.5 1
+		0.58 0.58 0.58 1
+		0.66 0.66 0.66 1
+		0.74 0.74 0.74 1
+		0.82 0.82 0.82 1
+		0.9 0.9 0.9 1
+		0.82 0.82 0.82 1
+		0.74 0.74 0.74 1
+		0.66 0.66 0.66 1
+		0.58 0.58 0.58 1
+		0.5 0.5 0.5 1
+		0.58 0.58 0.58 1
+		0.66 0.66 0.66 1
+		0.74 0.74 0.74 1
+		0.82 0.82 0.82 1
+		0.9 0.9 0.9 1
+	</attribute>
+	<indices cmd="tri-fan" type="ushort" >0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 1</indices>
+	<indices cmd="tri-fan" type="ushort" >31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 30</indices>
+</mesh>

src/main/java/com/ra4king/opengl/arcsynthesis/gl33/chapter7/example2/example7.2.UnitCubeColor.xml

+<?xml version="1.0" encoding="UTF-8"?>
+<?oxygen RNGSchema="../../Documents/meshFormat.rnc" type="compact"?>
+
+<mesh xmlns="http://www.arcsynthesis.com/gltut/mesh" >
+	<attribute index="0" type="float" size="3" > 
+		0.5 0.5 0.5
+		0.5 -0.5 0.5
+		-0.5 -0.5 0.5
+		-0.5 0.5 0.5
+		0.5 0.5 0.5
+		-0.5 0.5 0.5
+		-0.5 0.5 -0.5
+		0.5 0.5 -0.5
+		0.5 0.5 0.5
+		0.5 0.5 -0.5
+		0.5 -0.5 -0.5
+		0.5 -0.5 0.5
+		0.5 0.5 -0.5
+		-0.5 0.5 -0.5
+		-0.5 -0.5 -0.5
+		0.5 -0.5 -0.5
+		0.5 -0.5 0.5
+		0.5 -0.5 -0.5
+		-0.5 -0.5 -0.5
+		-0.5 -0.5 0.5
+		-0.5 0.5 0.5
+		-0.5 -0.5 0.5
+		-0.5 -0.5 -0.5
+		-0.5 0.5 -0.5
+	</attribute>
+	<attribute index="1" type="float" size="4" > 
+		0 1 0 1
+		0 1 0 1
+		0 1 0 1
+		0 1 0 1
+		0 0 1 1
+		0 0 1 1
+		0 0 1 1
+		0 0 1 1
+		1 0 0 1
+		1 0 0 1
+		1 0 0 1
+		1 0 0 1
+		1 1 0 1
+		1 1 0 1
+		1 1 0 1
+		1 1 0 1
+		0 1 1 1
+		0 1 1 1
+		0 1 1 1
+		0 1 1 1
+		1 0 1 1
+		1 0 1 1
+		1 0 1 1
+		1 0 1 1
+	</attribute>
+	<indices cmd="triangles" type="ushort" > 
+		0 1 2
+		2 3 0
+		4 5 6
+		6 7 4
+		8 9 10
+		10 11 8
+		12 13 14
+		14 15 12
+		16 17 18
+		18 19 16
+		20 21 22
+		22 23 20
+	</indices>
+</mesh>

src/main/java/com/ra4king/opengl/arcsynthesis/gl33/chapter7/example2/example7.2.UnitCubeTint.xml

+<?xml version="1.0" encoding="UTF-8"?>
+<?oxygen RNGSchema="../../Documents/meshFormat.rnc" type="compact"?>
+
+<mesh xmlns="http://www.arcsynthesis.com/gltut/mesh" >
+	<attribute index="0" type="float" size="3" > 
+		0.5 0.5 0.5
+		0.5 -0.5 0.5
+		-0.5 -0.5 0.5
+		-0.5 0.5 0.5
+		0.5 0.5 0.5
+		-0.5 0.5 0.5
+		-0.5 0.5 -0.5
+		0.5 0.5 -0.5
+		0.5 0.5 0.5
+		0.5 0.5 -0.5
+		0.5 -0.5 -0.5
+		0.5 -0.5 0.5
+		0.5 0.5 -0.5
+		-0.5 0.5 -0.5
+		-0.5 -0.5 -0.5
+		0.5 -0.5 -0.5
+		0.5 -0.5 0.5
+		0.5 -0.5 -0.5
+		-0.5 -0.5 -0.5
+		-0.5 -0.5 0.5
+		-0.5 0.5 0.5
+		-0.5 -0.5 0.5
+		-0.5 -0.5 -0.5
+		-0.5 0.5 -0.5
+	</attribute>
+	<attribute index="1" type="float" size="4" > 
+		1 1 1 1
+		1 1 1 1
+		1 1 1 1
+		1 1 1 1
+		0.75 0.75 0.75 1
+		0.75 0.75 0.75 1
+		0.75 0.75 0.75 1
+		0.75 0.75 0.75 1
+		0.5 0.5 0.5 1
+		0.5 0.5 0.5 1
+		0.5 0.5 0.5 1
+		0.5 0.5 0.5 1
+		1 1 1 1
+		1 1 1 1
+		1 1 1 1
+		1 1 1 1
+		0.75 0.75 0.75 1
+		0.75 0.75 0.75 1
+		0.75 0.75 0.75 1
+		0.75 0.75 0.75 1
+		0.5 0.5 0.5 1
+		0.5 0.5 0.5 1
+		0.5 0.5 0.5 1
+		0.5 0.5 0.5 1
+	</attribute>
+	<indices cmd="triangles" type="ushort" > 
+		0 1 2
+		2 3 0
+		4 5 6
+		6 7 4
+		8 9 10
+		10 11 8
+		12 13 14
+		14 15 12
+		16 17 18
+		18 19 16
+		20 21 22
+		22 23 20
+	</indices>
+</mesh>

src/main/java/com/ra4king/opengl/arcsynthesis/gl33/chapter7/example2/example7.2.UnitCylinderTint.xml

+<?xml version="1.0" encoding="UTF-8"?>
+<?oxygen RNGSchema="../../Documents/meshFormat.rnc" type="compact"?>
+
+<mesh xmlns="http://www.arcsynthesis.com/gltut/mesh" >
+	<attribute index="0" type="float" size="3" > 
+		0 0.5 0
+		0.5 0.5 0
+		0.5 -0.5 0
+		0.48907381875731 0.5 0.1039557588888
+		0.48907381875731 -0.5 0.1039557588888
+		0.45677280077542 0.5 0.20336815992623
+		0.45677280077542 -0.5 0.20336815992623
+		0.40450865316151 0.5 0.29389241146627
+		0.40450865316151 -0.5 0.29389241146627
+		0.33456556611288 0.5 0.37157217599218
+		0.33456556611288 -0.5 0.37157217599218
+		0.2500003830126 0.5 0.43301248075957
+		0.2500003830126 -0.5 0.43301248075957
+		0.15450900193016 0.5 0.47552809414644
+		0.15450900193016 -0.5 0.47552809414644
+		0.052264847412855 0.5 0.49726088296277
+		0.052264847412855 -0.5 0.49726088296277
+		-0.052263527886268 0.5 0.49726102165048
+		-0.052263527886268 -0.5 0.49726102165048
+		-0.15450774007312 0.5 0.47552850414828
+		-0.15450774007312 -0.5 0.47552850414828
+		-0.24999923397422 0.5 0.43301314415651
+		-0.24999923397422 -0.5 0.43301314415651
+		-0.33456458011157 0.5 0.37157306379065
+		-0.33456458011157 -0.5 0.37157306379065
+		-0.40450787329018 0.5 0.29389348486527
+		-0.40450787329018 -0.5 0.29389348486527
+		-0.45677226111814 0.5 0.20336937201315
+		-0.45677226111814 -0.5 0.20336937201315
+		-0.48907354289964 0.5 0.10395705668972
+		-0.48907354289964 -0.5 0.10395705668972
+		-0.49999999999824 0.5 1.3267948966764e-006
+		-0.49999999999824 -0.5 1.3267948966764e-006
+		-0.48907409461153 0.5 -0.10395446108714
+		-0.48907409461153 -0.5 -0.10395446108714
+		-0.45677334042948 0.5 -0.20336694783787
+		-0.45677334042948 -0.5 -0.20336694783787
+		-0.40450943302999 0.5 -0.2938913380652
+		-0.40450943302999 -0.5 -0.2938913380652
+		-0.33456655211184 0.5 -0.3715712881911
+		-0.33456655211184 -0.5 -0.3715712881911
+		-0.25000153204922 0.5 -0.43301181735958
+		-0.25000153204922 -0.5 -0.43301181735958
+		-0.15451026378611 0.5 -0.47552768414126
+		-0.15451026378611 -0.5 -0.47552768414126
+		-0.052266166939075 0.5 -0.49726074427155
+		-0.052266166939075 -0.5 -0.49726074427155
+		0.052262208359312 0.5 -0.4972611603347
+		0.052262208359312 -0.5 -0.4972611603347
+		0.15450647821499 0.5 -0.47552891414676
+		0.15450647821499 -0.5 -0.47552891414676
+		0.24999808493408 0.5 -0.4330138075504
+		0.24999808493408 -0.5 -0.4330138075504
+		0.3345635941079 0.5 -0.37157395158649
+		0.3345635941079 -0.5 -0.37157395158649
+		0.40450709341601 0.5 -0.2938945582622
+		0.40450709341601 -0.5 -0.2938945582622
+		0.45677172145764 0.5 -0.20337058409865
+		0.45677172145764 -0.5 -0.20337058409865
+		0.48907326703854 0.5 -0.10395835448992
+		0.48907326703854 -0.5 -0.10395835448992
+		0 -0.5 0</attribute>
+	<attribute index="1" type="float" size="4" > 
+		1 1 1 1
+		0.9 0.9 0.9 1
+		0.9 0.9 0.9 1
+		0.82 0.82 0.82 1
+		0.82 0.82 0.82 1
+		0.74 0.74 0.74 1
+		0.74 0.74 0.74 1
+		0.66 0.66 0.66 1
+		0.66 0.66 0.66 1
+		0.58 0.58 0.58 1
+		0.58 0.58 0.58 1
+		0.5 0.5 0.5 1
+		0.5 0.5 0.5 1
+		0.58 0.58 0.58 1
+		0.58 0.58 0.58 1
+		0.66 0.66 0.66 1
+		0.66 0.66 0.66 1
+		0.74 0.74 0.74 1
+		0.74 0.74 0.74 1
+		0.82 0.82 0.82 1
+		0.82 0.82 0.82 1
+		0.9 0.9 0.9 1
+		0.9 0.9 0.9 1
+		0.82 0.82 0.82 1
+		0.82 0.82 0.82 1
+		0.74 0.74 0.74 1
+		0.74 0.74 0.74 1
+		0.66 0.66 0.66 1
+		0.66 0.66 0.66 1
+		0.58 0.58 0.58 1
+		0.58 0.58 0.58 1
+		0.5 0.5 0.5 1
+		0.5 0.5 0.5 1
+		0.58 0.58 0.58 1
+		0.58 0.58 0.58 1
+		0.66 0.66 0.66 1
+		0.66 0.66 0.66 1
+		0.74 0.74 0.74 1
+		0.74 0.74 0.74 1
+		0.82 0.82 0.82 1
+		0.82 0.82 0.82 1
+		0.9 0.9 0.9 1
+		0.9 0.9 0.9 1
+		0.82 0.82 0.82 1
+		0.82 0.82 0.82 1
+		0.74 0.74 0.74 1
+		0.74 0.74 0.74 1
+		0.66 0.66 0.66 1
+		0.66 0.66 0.66 1
+		0.58 0.58 0.58 1
+		0.58 0.58 0.58 1
+		0.5 0.5 0.5 1
+		0.5 0.5 0.5 1
+		0.58 0.58 0.58 1
+		0.58 0.58 0.58 1
+		0.66 0.66 0.66 1
+		0.66 0.66 0.66 1
+		0.74 0.74 0.74 1
+		0.74 0.74 0.74 1
+		0.82 0.82 0.82 1
+		0.82 0.82 0.82 1
+		1 1 1 1
+	</attribute>
+	<indices cmd="tri-fan" type="ushort" >0 1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31 33 35 37 39 41 43 45 47 49 51 53 55 57 59 1</indices>
+	<indices cmd="tri-fan" type="ushort" >61 60 58 56 54 52 50 48 46 44 42 40 38 36 34 32 30 28 26 24 22 20 18 16 14 12 10 8 6 4 2 60</indices>
+	<indices cmd="tri-strip" type="ushort" >1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 1 2</indices>
+</mesh>

src/main/java/com/ra4king/opengl/arcsynthesis/gl33/chapter7/example2/example7.2.UnitPlane.xml

+<?xml version="1.0" encoding="UTF-8"?>
+<?oxygen RNGSchema="../../Documents/meshFormat.rnc" type="compact"?>
+
+<mesh xmlns="http://www.arcsynthesis.com/gltut/mesh" >
+	<attribute index="0" type="float" size="3" > 
+		0.5 0 -0.5
+		0.5 0 0.5
+		-0.5 0 0.5
+		-0.5 0 -0.5
+	</attribute>
+	<indices cmd="triangles" type="ushort" > 
+		0 1 2
+		0 2 1
+		2 3 0
+		2 0 3
+	</indices>
+</mesh>

src/main/java/com/ra4king/opengl/util/math/Matrix4.java

 		return rotate(angle, vec.x(), vec.y(), vec.z());
 	}
 	
-	private FloatBuffer direct;
+	private final static FloatBuffer direct = BufferUtils.createFloatBuffer(16);
 	
 	public FloatBuffer getBuffer() {
-		if(direct == null)
-			direct = BufferUtils.createFloatBuffer(16);
 		direct.clear();
 		direct.put((FloatBuffer)matrix.position(16).flip());
 		direct.flip();
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.