Commits

Jason McKesson committed ffea870

Tut13: Flatcard imposters work.

  • Participants
  • Parent commits ad14d09

Comments (0)

Files changed (3)

File Tut 13 Imposters/BasicImposter.cpp

 
 #define ARRAY_COUNT( array ) (sizeof( array ) / (sizeof( array[0] ) * (sizeof( array ) != sizeof(void*) || sizeof( array[0] ) <= sizeof(void*))))
 
-struct ProgramData
+struct ProgramMeshData
 {
 	GLuint theProgram;
 
 	GLuint normalModelToCameraMatrixUnif;
 };
 
+struct ProgramImposData
+{
+	GLuint theProgram;
+
+	GLuint sphereRadiusUnif;
+	GLuint cameraSpherePosUnif;
+};
+
 struct UnlitProgData
 {
 	GLuint theProgram;
 float g_fzNear = 1.0f;
 float g_fzFar = 1000.0f;
 
-ProgramData g_litMeshProg;
-ProgramData g_litImposterProg;
+ProgramMeshData g_litMeshProg;
+ProgramImposData g_litImposterProg;
 UnlitProgData g_Unlit;
 
 const int g_materialBlockIndex = 0;
 	return data;
 }
 
-ProgramData LoadLitProgram(const std::string &strVertexShader, const std::string &strFragmentShader)
+ProgramMeshData LoadLitMeshProgram(const std::string &strVertexShader, const std::string &strFragmentShader)
 {
 	std::vector<GLuint> shaderList;
 
 	shaderList.push_back(Framework::LoadShader(GL_VERTEX_SHADER, strVertexShader));
 	shaderList.push_back(Framework::LoadShader(GL_FRAGMENT_SHADER, strFragmentShader));
 
-	ProgramData data;
+	ProgramMeshData data;
 	data.theProgram = Framework::CreateProgram(shaderList);
 	data.modelToCameraMatrixUnif = glGetUniformLocation(data.theProgram, "modelToCameraMatrix");
 
 	return data;
 }
 
+ProgramImposData LoadLitImposProgram(const std::string &strVertexShader, const std::string &strFragmentShader)
+{
+	std::vector<GLuint> shaderList;
+
+	shaderList.push_back(Framework::LoadShader(GL_VERTEX_SHADER, strVertexShader));
+	shaderList.push_back(Framework::LoadShader(GL_FRAGMENT_SHADER, strFragmentShader));
+
+	ProgramImposData data;
+	data.theProgram = Framework::CreateProgram(shaderList);
+	data.sphereRadiusUnif = glGetUniformLocation(data.theProgram, "sphereRadius");
+	data.cameraSpherePosUnif = glGetUniformLocation(data.theProgram, "cameraSpherePos");
+
+	GLuint materialBlock = glGetUniformBlockIndex(data.theProgram, "Material");
+	GLuint lightBlock = glGetUniformBlockIndex(data.theProgram, "Light");
+	GLuint projectionBlock = glGetUniformBlockIndex(data.theProgram, "Projection");
+
+	glUniformBlockBinding(data.theProgram, materialBlock, g_materialBlockIndex);
+	glUniformBlockBinding(data.theProgram, lightBlock, g_lightBlockIndex);
+	glUniformBlockBinding(data.theProgram, projectionBlock, g_projectionBlockIndex);
+
+	return data;
+}
+
 void InitializePrograms()
 {
-	g_litMeshProg = LoadLitProgram("PN.vert", "Lighting.frag");
+	g_litMeshProg = LoadLitMeshProgram("PN.vert", "Lighting.frag");
+	g_litImposterProg = LoadLitImposProgram("BasicImposter.vert", "BasicImposter.frag");
 
 	g_Unlit = LoadUnlitProgram("Unlit.vert", "Unlit.frag");
 }
 	g_materialUniformBuffer = ubArray.CreateBufferObject();
 }
 
+GLuint g_imposterVAO;
+GLuint g_imposterVBO;
+
 //Called after the window and OpenGL are initialized. Called exactly once, before the main loop.
 void init()
 {
 
 	glBindBuffer(GL_UNIFORM_BUFFER, 0);
 
+	glGenBuffers(1, &g_imposterVBO);
+	glBindBuffer(GL_ARRAY_BUFFER, g_imposterVBO);
+	glBufferData(GL_ARRAY_BUFFER, 4 * sizeof(float), NULL, GL_STATIC_DRAW);
+
+	glGenVertexArrays(1, &g_imposterVAO);
+	glBindVertexArray(g_imposterVAO);
+	glEnableVertexAttribArray(0);
+	glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, (void*)(0));
+
+	glBindVertexArray(0);
+	glBindBuffer(GL_ARRAY_BUFFER, 0);
+
 	CreateMaterials();
 }
 
-void DrawMeshSphere(Framework::MatrixStack &modelMatrix,
-					const glm::vec3 &position, float radius, MaterialNames material)
+void DrawSphere(Framework::MatrixStack &modelMatrix,
+				const glm::vec3 &position, float radius, MaterialNames material,
+				bool bDrawImposter = false)
 {
-	Framework::MatrixStackPusher push(modelMatrix);
-	modelMatrix.Translate(position);
-	modelMatrix.Scale(radius * 2.0f); //The unit sphere has a radius 0.5f.
+	if(bDrawImposter)
+	{
+		glm::vec4 cameraSpherePos = modelMatrix.Top() * glm::vec4(position, 1.0f);
+		glUseProgram(g_litImposterProg.theProgram);
+		glUniform3fv(g_litImposterProg.cameraSpherePosUnif, 1, glm::value_ptr(cameraSpherePos));
+		glUniform1f(g_litImposterProg.sphereRadiusUnif, radius);
 
-	glm::mat3 normMatrix(modelMatrix.Top());
-	normMatrix = glm::transpose(glm::inverse(normMatrix));
+		glBindVertexArray(g_imposterVAO);
 
-	glUseProgram(g_litMeshProg.theProgram);
-	glUniformMatrix4fv(g_litMeshProg.modelToCameraMatrixUnif, 1, GL_FALSE,
-		glm::value_ptr(modelMatrix.Top()));
-	glUniformMatrix3fv(g_litMeshProg.normalModelToCameraMatrixUnif, 1, GL_FALSE,
-		glm::value_ptr(normMatrix));
+		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
 
-	glBindBufferRange(GL_UNIFORM_BUFFER, g_materialBlockIndex, g_materialUniformBuffer,
-		material * g_materialBlockOffset, sizeof(MaterialBlock));
+		glBindVertexArray(0);
+		glUseProgram(0);
+	}
+	else
+	{
+		Framework::MatrixStackPusher push(modelMatrix);
+		modelMatrix.Translate(position);
+		modelMatrix.Scale(radius * 2.0f); //The unit sphere has a radius 0.5f.
 
-	g_pSphereMesh->Render("lit");
+		glm::mat3 normMatrix(modelMatrix.Top());
+		normMatrix = glm::transpose(glm::inverse(normMatrix));
 
-	glUseProgram(0);
-	glBindBufferRange(GL_UNIFORM_BUFFER, g_materialBlockIndex, 0, 0, 0);
+		glUseProgram(g_litMeshProg.theProgram);
+		glUniformMatrix4fv(g_litMeshProg.modelToCameraMatrixUnif, 1, GL_FALSE,
+			glm::value_ptr(modelMatrix.Top()));
+		glUniformMatrix3fv(g_litMeshProg.normalModelToCameraMatrixUnif, 1, GL_FALSE,
+			glm::value_ptr(normMatrix));
+
+		glBindBufferRange(GL_UNIFORM_BUFFER, g_materialBlockIndex, g_materialUniformBuffer,
+			material * g_materialBlockOffset, sizeof(MaterialBlock));
+
+		g_pSphereMesh->Render("lit");
+
+		glUseProgram(0);
+		glBindBufferRange(GL_UNIFORM_BUFFER, g_materialBlockIndex, 0, 0, 0);
+	}
 }
 
 void DrawSphereOrbit(Framework::MatrixStack &modelMatrix,
 					 const glm::vec3 &orbitCenter, const glm::vec3 &orbitAxis,
-					 float orbitRadius, float orbitAlpha, float sphereRadius, MaterialNames material)
+					 float orbitRadius, float orbitAlpha, float sphereRadius, MaterialNames material,
+					 bool drawImposter = false)
 {
 	Framework::MatrixStackPusher push(modelMatrix);
 
 
 	modelMatrix.Translate(offsetDir * orbitRadius);
 
-	DrawMeshSphere(modelMatrix, glm::vec3(0.0f), sphereRadius, material);
+	DrawSphere(modelMatrix, glm::vec3(0.0f), sphereRadius, material, drawImposter);
 }
 
 bool g_bDrawCameraPos = false;
 	glClearDepth(1.0f);
 	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
-	if(g_pPlaneMesh && g_pSphereMesh)
+	if(g_pPlaneMesh && g_pSphereMesh && g_pCubeMesh)
 	{
 		Framework::MatrixStack modelMatrix;
 		modelMatrix.SetMatrix(g_mousePole.CalcMatrix());
 		glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(lightData), &lightData);
 		glBindBuffer(GL_UNIFORM_BUFFER, 0);
 
-
 		{
 			glBindBufferRange(GL_UNIFORM_BUFFER, g_materialBlockIndex, g_materialUniformBuffer,
 				MTL_TERRAIN * g_materialBlockOffset, sizeof(MaterialBlock));
 			glBindBufferRange(GL_UNIFORM_BUFFER, g_materialBlockIndex, 0, 0, 0);
 		}
 
-		DrawMeshSphere(modelMatrix, glm::vec3(0.0f, 10.0f, 0.0f), 4.0f, MTL_BLUE_SHINY);
+		DrawSphere(modelMatrix, glm::vec3(0.0f, 10.0f, 0.0f), 4.0f, MTL_BLUE_SHINY);
 		DrawSphereOrbit(modelMatrix, glm::vec3(0.0f, 10.0f, 0.0f), glm::vec3(0.6f, 0.8f, 0.0f),
 			20.0f, g_sphereTimer.GetAlpha(), 2.0f, MTL_DULL_GREY);
 		DrawSphereOrbit(modelMatrix, glm::vec3(-10.0f, 1.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f),
-			10.0f, g_sphereTimer.GetAlpha(), 1.0f, MTL_BLACK_SHINY);
+			10.0f, g_sphereTimer.GetAlpha(), 1.0f, MTL_BLACK_SHINY, true);
 		DrawSphereOrbit(modelMatrix, glm::vec3(10.0f, 1.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f),
 			10.0f, g_sphereTimer.GetAlpha() * 2.0f, 1.0f, MTL_GOLD_METAL);
 

File Tut 13 Imposters/data/BasicImposter.frag

+#version 330
+
+in vec2 mapping;
+
+out vec4 outputColor;
+
+void main()
+{
+	outputColor = vec4(1.0);
+}

File Tut 13 Imposters/data/BasicImposter.vert

+#version 330
+
+layout(std140) uniform;
+
+out vec2 mapping;
+
+uniform Projection
+{
+	mat4 cameraToClipMatrix;
+};
+
+uniform float sphereRadius;
+uniform vec3 cameraSpherePos;
+
+void main()
+{
+	vec2 offset;
+	switch(gl_VertexID)
+	{
+	case 0:
+		//Bottom-left
+		mapping = vec2(0.0, 0.0);
+		offset = vec2(-sphereRadius, -sphereRadius);
+		break;
+	case 1:
+		//Top-left
+		mapping = vec2(0.0, 1.0);
+		offset = vec2(-sphereRadius, sphereRadius);
+		break;
+	case 2:
+		//Bottom-right
+		mapping = vec2(1.0, 0.0);
+		offset = vec2(sphereRadius, -sphereRadius);
+		break;
+	case 3:
+		//Top-right
+		mapping = vec2(1.0, 1.0);
+		offset = vec2(sphereRadius, sphereRadius);
+		break;
+	}
+
+	vec4 cameraCornerPos = vec4(cameraSpherePos, 1.0);
+	cameraCornerPos.xy += offset;
+
+	gl_Position = cameraToClipMatrix * cameraCornerPos;
+}