Commits

Jason McKesson committed 8ce4133

Tut13: Finished regular shader impostors.

Comments (0)

Files changed (10)

Tut 13 Imposters/BasicImposter.cpp

 float g_fzNear = 1.0f;
 float g_fzFar = 1000.0f;
 
+enum Impostors
+{
+	IMP_BASIC,
+ 	IMP_PERSPECTIVE,
+ 	IMP_DEPTH,
+
+	IMP_NUM_IMPOSTORS,
+};
+
 ProgramMeshData g_litMeshProg;
-ProgramImposData g_litImposterProg;
+ProgramImposData g_litImpProgs[IMP_NUM_IMPOSTORS];
 UnlitProgData g_Unlit;
 
 const int g_materialBlockIndex = 0;
 	return data;
 }
 
+const char *g_impShaderNames[IMP_NUM_IMPOSTORS * 2] =
+{
+	"BasicImposter.vert", "BasicImposter.frag",
+ 	"PerspImpostor.vert", "PerspImpostor.frag",
+ 	"DepthImpostor.vert", "DepthImpostor.frag",
+};
+
 void InitializePrograms()
 {
 	g_litMeshProg = LoadLitMeshProgram("PN.vert", "Lighting.frag");
-	g_litImposterProg = LoadLitImposProgram("BasicImposter.vert", "BasicImposter.frag");
+
+	for(int iLoop = 0; iLoop < IMP_NUM_IMPOSTORS; iLoop++)
+	{
+		g_litImpProgs[iLoop] = LoadLitImposProgram(
+			g_impShaderNames[iLoop * 2], g_impShaderNames[iLoop * 2 + 1]);
+	}
 
 	g_Unlit = LoadUnlitProgram("Unlit.vert", "Unlit.frag");
 }
 	CreateMaterials();
 }
 
+int g_currImpostor = IMP_BASIC;
+
 void DrawSphere(Framework::MatrixStack &modelMatrix,
 				const glm::vec3 &position, float radius, MaterialNames material,
 				bool bDrawImposter = false)
 {
+	glBindBufferRange(GL_UNIFORM_BUFFER, g_materialBlockIndex, g_materialUniformBuffer,
+		material * g_materialBlockOffset, sizeof(MaterialBlock));
+
 	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);
+		glUseProgram(g_litImpProgs[g_currImpostor].theProgram);
+		glUniform3fv(g_litImpProgs[g_currImpostor].cameraSpherePosUnif, 1, glm::value_ptr(cameraSpherePos));
+		glUniform1f(g_litImpProgs[g_currImpostor].sphereRadiusUnif, radius);
 
 		glBindVertexArray(g_imposterVAO);
 
 		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);
 	}
+
+	glBindBufferRange(GL_UNIFORM_BUFFER, g_materialBlockIndex, 0, 0, 0);
 }
 
 void DrawSphereOrbit(Framework::MatrixStack &modelMatrix,
 const float g_fHalfLightDistance = 25.0f;
 const float g_fLightAttenuation = 1.0f / (g_fHalfLightDistance * g_fHalfLightDistance);
 
+bool g_drawImposter[4] = { false, false, false, false };
+
 //Called to update the display.
 //You should call glutSwapBuffers after all of your rendering to display what you rendered.
 //If you need continuous updates of the screen, call glutPostRedisplay() at the end of the function.
 			glBindBufferRange(GL_UNIFORM_BUFFER, g_materialBlockIndex, 0, 0, 0);
 		}
 
-		DrawSphere(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,
+			g_drawImposter[0]);
 		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);
+			20.0f, g_sphereTimer.GetAlpha(), 2.0f, MTL_DULL_GREY, g_drawImposter[1]);
 		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, true);
+			10.0f, g_sphereTimer.GetAlpha(), 1.0f, MTL_BLACK_SHINY, g_drawImposter[2]);
 		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);
+			10.0f, g_sphereTimer.GetAlpha() * 2.0f, 1.0f, MTL_GOLD_METAL, g_drawImposter[3]);
 
 		if(g_bDrawLights)
 		{
 	case 't': g_bDrawCameraPos = !g_bDrawCameraPos; break;
 	case 'g': g_bDrawLights = !g_bDrawLights; break;
 
+	case '1': g_drawImposter[0] = !g_drawImposter[0]; break;
+	case '2': g_drawImposter[1] = !g_drawImposter[1]; break;
+	case '3': g_drawImposter[2] = !g_drawImposter[2]; break;
+	case '4': g_drawImposter[3] = !g_drawImposter[3]; break;
+
+	case 'l':
+		{
+			g_currImpostor += 1;
+			g_currImpostor %= IMP_NUM_IMPOSTORS;
+			const char *impostorNames[IMP_NUM_IMPOSTORS] =
+			{
+				"basic",
+ 				"perspective-correct",
+ 				"depth-accurate",
+			};
+
+			printf("Now using %s impostor.\n", impostorNames[g_currImpostor]);
+		}
+		break;
+
+	case 32: InitializePrograms(); break;
+
 	}
 
 	g_mousePole.GLUTKeyOffset(key, 5.0f, 1.0f);

Tut 13 Imposters/data/BasicImposter.frag

 
 out vec4 outputColor;
 
+uniform float sphereRadius;
+uniform vec3 cameraSpherePos;
+
+layout(std140) uniform;
+
+uniform Material
+{
+	vec4 diffuseColor;
+	vec4 specularColor;
+	float specularShininess;
+} Mtl;
+
+struct PerLight
+{
+	vec4 cameraSpaceLightPos;
+	vec4 lightIntensity;
+};
+
+const int numberOfLights = 2;
+
+uniform Light
+{
+	vec4 ambientIntensity;
+	float lightAttenuation;
+	PerLight lights[numberOfLights];
+} Lgt;
+
+
+float CalcAttenuation(in vec3 cameraSpacePosition,
+	in vec3 cameraSpaceLightPos,
+	out vec3 lightDirection)
+{
+	vec3 lightDifference =  cameraSpaceLightPos - cameraSpacePosition;
+	float lightDistanceSqr = dot(lightDifference, lightDifference);
+	lightDirection = lightDifference * inversesqrt(lightDistanceSqr);
+	
+	return (1 / ( 1.0 + Lgt.lightAttenuation * lightDistanceSqr));
+}
+
+uniform Projection
+{
+	mat4 cameraToClipMatrix;
+};
+
+vec4 ComputeLighting(in PerLight lightData, in vec3 cameraSpacePosition,
+	in vec3 cameraSpaceNormal)
+{
+	vec3 lightDir;
+	vec4 lightIntensity;
+	if(lightData.cameraSpaceLightPos.w == 0.0)
+	{
+		lightDir = vec3(lightData.cameraSpaceLightPos);
+		lightIntensity = lightData.lightIntensity;
+	}
+	else
+	{
+		float atten = CalcAttenuation(cameraSpacePosition,
+			lightData.cameraSpaceLightPos.xyz, lightDir);
+		lightIntensity = atten * lightData.lightIntensity;
+	}
+	
+	vec3 surfaceNormal = normalize(cameraSpaceNormal);
+	float cosAngIncidence = dot(surfaceNormal, lightDir);
+	cosAngIncidence = cosAngIncidence < 0.0001 ? 0.0 : cosAngIncidence;
+	
+	vec3 viewDirection = normalize(-cameraSpacePosition);
+	
+	vec3 halfAngle = normalize(lightDir + viewDirection);
+	float angleNormalHalf = acos(dot(halfAngle, surfaceNormal));
+	float exponent = angleNormalHalf / Mtl.specularShininess;
+	exponent = -(exponent * exponent);
+	float gaussianTerm = exp(exponent);
+
+	gaussianTerm = cosAngIncidence != 0.0 ? gaussianTerm : 0.0;
+	
+	vec4 lighting = Mtl.diffuseColor * lightIntensity * cosAngIncidence;
+	lighting += Mtl.specularColor * lightIntensity * gaussianTerm;
+	
+	return lighting;
+}
+
+void Impostor(out vec3 cameraPos, out vec3 cameraNormal)
+{
+	float lensqr = dot(mapping, mapping);
+	if(lensqr > 1.0)
+		discard;
+		
+	cameraNormal = vec3(mapping, sqrt(1.0 - lensqr));
+	cameraPos = (cameraNormal * sphereRadius) + cameraSpherePos;
+}
+
 void main()
 {
-	outputColor = vec4(1.0);
+	vec3 cameraPos;
+	vec3 cameraNormal;
+	
+	Impostor(cameraPos, cameraNormal);
+	
+	vec4 accumLighting = Mtl.diffuseColor * Lgt.ambientIntensity;
+	for(int light = 0; light < numberOfLights; light++)
+	{
+		accumLighting += ComputeLighting(Lgt.lights[light],
+			cameraPos, cameraNormal);
+	}
+	
+	outputColor = sqrt(accumLighting); //2.0 gamma correction
 }

Tut 13 Imposters/data/BasicImposter.vert

 	{
 	case 0:
 		//Bottom-left
-		mapping = vec2(0.0, 0.0);
+		mapping = vec2(-1.0, -1.0);
 		offset = vec2(-sphereRadius, -sphereRadius);
 		break;
 	case 1:
 		//Top-left
-		mapping = vec2(0.0, 1.0);
+		mapping = vec2(-1.0, 1.0);
 		offset = vec2(-sphereRadius, sphereRadius);
 		break;
 	case 2:
 		//Bottom-right
-		mapping = vec2(1.0, 0.0);
+		mapping = vec2(1.0, -1.0);
 		offset = vec2(sphereRadius, -sphereRadius);
 		break;
 	case 3:

Tut 13 Imposters/data/DepthImpostor.frag

+#version 330
+
+in vec2 mapping;
+
+out vec4 outputColor;
+
+uniform float sphereRadius;
+uniform vec3 cameraSpherePos;
+
+layout(std140) uniform;
+
+uniform Material
+{
+	vec4 diffuseColor;
+	vec4 specularColor;
+	float specularShininess;
+} Mtl;
+
+struct PerLight
+{
+	vec4 cameraSpaceLightPos;
+	vec4 lightIntensity;
+};
+
+const int numberOfLights = 2;
+
+uniform Light
+{
+	vec4 ambientIntensity;
+	float lightAttenuation;
+	PerLight lights[numberOfLights];
+} Lgt;
+
+
+float CalcAttenuation(in vec3 cameraSpacePosition,
+	in vec3 cameraSpaceLightPos,
+	out vec3 lightDirection)
+{
+	vec3 lightDifference =  cameraSpaceLightPos - cameraSpacePosition;
+	float lightDistanceSqr = dot(lightDifference, lightDifference);
+	lightDirection = lightDifference * inversesqrt(lightDistanceSqr);
+	
+	return (1 / ( 1.0 + Lgt.lightAttenuation * lightDistanceSqr));
+}
+
+uniform Projection
+{
+	mat4 cameraToClipMatrix;
+};
+
+vec4 ComputeLighting(in PerLight lightData, in vec3 cameraSpacePosition,
+	in vec3 cameraSpaceNormal)
+{
+	vec3 lightDir;
+	vec4 lightIntensity;
+	if(lightData.cameraSpaceLightPos.w == 0.0)
+	{
+		lightDir = vec3(lightData.cameraSpaceLightPos);
+		lightIntensity = lightData.lightIntensity;
+	}
+	else
+	{
+		float atten = CalcAttenuation(cameraSpacePosition,
+			lightData.cameraSpaceLightPos.xyz, lightDir);
+		lightIntensity = atten * lightData.lightIntensity;
+	}
+	
+	vec3 surfaceNormal = normalize(cameraSpaceNormal);
+	float cosAngIncidence = dot(surfaceNormal, lightDir);
+	cosAngIncidence = cosAngIncidence < 0.0001 ? 0.0 : cosAngIncidence;
+	
+	vec3 viewDirection = normalize(-cameraSpacePosition);
+	
+	vec3 halfAngle = normalize(lightDir + viewDirection);
+	float angleNormalHalf = acos(dot(halfAngle, surfaceNormal));
+	float exponent = angleNormalHalf / Mtl.specularShininess;
+	exponent = -(exponent * exponent);
+	float gaussianTerm = exp(exponent);
+
+	gaussianTerm = cosAngIncidence != 0.0 ? gaussianTerm : 0.0;
+	
+	vec4 lighting = Mtl.diffuseColor * lightIntensity * cosAngIncidence;
+	lighting += Mtl.specularColor * lightIntensity * gaussianTerm;
+	
+	return lighting;
+}
+
+void Impostor(out vec3 cameraPos, out vec3 cameraNormal)
+{
+	vec3 cameraPlanePos = vec3(mapping * sphereRadius, 0.0) + cameraSpherePos;
+	vec3 rayDirection = normalize(cameraPlanePos);
+	
+	float B = 2.0 * dot(rayDirection, -cameraSpherePos);
+	float C = dot(cameraSpherePos, cameraSpherePos) - (sphereRadius * sphereRadius);
+	
+	float det = (B * B) - (4 * C);
+	if(det < 0.0)
+		discard;
+		
+	float sqrtDet = sqrt(det);
+	float posT = (-B + sqrtDet)/2;
+	float negT = (-B - sqrtDet)/2;
+	
+	float intersectT = min(posT, negT);
+	cameraPos = rayDirection * intersectT;
+	cameraNormal = normalize(cameraPos - cameraSpherePos);
+}
+
+void main()
+{
+	vec3 cameraPos;
+	vec3 cameraNormal;
+	
+	Impostor(cameraPos, cameraNormal);
+	
+	//Set the depth based on the new cameraPos.
+	vec4 clipPos = cameraToClipMatrix * vec4(cameraPos, 1.0);
+	float ndcDepth = clipPos.z / clipPos.w;
+	gl_FragDepth = ((gl_DepthRange.diff * ndcDepth) + gl_DepthRange.near + gl_DepthRange.far) / 2.0;
+	
+	vec4 accumLighting = Mtl.diffuseColor * Lgt.ambientIntensity;
+	for(int light = 0; light < numberOfLights; light++)
+	{
+		accumLighting += ComputeLighting(Lgt.lights[light],
+			cameraPos, cameraNormal);
+	}
+	
+	outputColor = sqrt(accumLighting); //2.0 gamma correction
+}

Tut 13 Imposters/data/DepthImpostor.vert

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

Tut 13 Imposters/data/Lighting.frag

 	return (1 / ( 1.0 + Lgt.lightAttenuation * lightDistanceSqr));
 }
 
-vec4 ComputeLighting(in PerLight lightData)
+vec4 ComputeLighting(in PerLight lightData, in vec3 cameraSpacePosition,
+	in vec3 cameraSpaceNormal)
 {
 	vec3 lightDir;
 	vec4 lightIntensity;
 		lightIntensity = atten * lightData.lightIntensity;
 	}
 	
-	vec3 surfaceNormal = normalize(vertexNormal);
+	vec3 surfaceNormal = normalize(cameraSpaceNormal);
 	float cosAngIncidence = dot(surfaceNormal, lightDir);
 	cosAngIncidence = cosAngIncidence < 0.0001 ? 0.0 : cosAngIncidence;
 	
 	vec4 accumLighting = Mtl.diffuseColor * Lgt.ambientIntensity;
 	for(int light = 0; light < numberOfLights; light++)
 	{
-		accumLighting += ComputeLighting(Lgt.lights[light]);
+		accumLighting += ComputeLighting(Lgt.lights[light],
+			cameraSpacePosition, vertexNormal);
 	}
 	
 	outputColor = sqrt(accumLighting); //2.0 gamma correction

Tut 13 Imposters/data/PerspImpostor.frag

+#version 330
+
+in vec2 mapping;
+
+out vec4 outputColor;
+
+uniform float sphereRadius;
+uniform vec3 cameraSpherePos;
+
+layout(std140) uniform;
+
+uniform Material
+{
+	vec4 diffuseColor;
+	vec4 specularColor;
+	float specularShininess;
+} Mtl;
+
+struct PerLight
+{
+	vec4 cameraSpaceLightPos;
+	vec4 lightIntensity;
+};
+
+const int numberOfLights = 2;
+
+uniform Light
+{
+	vec4 ambientIntensity;
+	float lightAttenuation;
+	PerLight lights[numberOfLights];
+} Lgt;
+
+
+float CalcAttenuation(in vec3 cameraSpacePosition,
+	in vec3 cameraSpaceLightPos,
+	out vec3 lightDirection)
+{
+	vec3 lightDifference =  cameraSpaceLightPos - cameraSpacePosition;
+	float lightDistanceSqr = dot(lightDifference, lightDifference);
+	lightDirection = lightDifference * inversesqrt(lightDistanceSqr);
+	
+	return (1 / ( 1.0 + Lgt.lightAttenuation * lightDistanceSqr));
+}
+
+uniform Projection
+{
+	mat4 cameraToClipMatrix;
+};
+
+vec4 ComputeLighting(in PerLight lightData, in vec3 cameraSpacePosition,
+	in vec3 cameraSpaceNormal)
+{
+	vec3 lightDir;
+	vec4 lightIntensity;
+	if(lightData.cameraSpaceLightPos.w == 0.0)
+	{
+		lightDir = vec3(lightData.cameraSpaceLightPos);
+		lightIntensity = lightData.lightIntensity;
+	}
+	else
+	{
+		float atten = CalcAttenuation(cameraSpacePosition,
+			lightData.cameraSpaceLightPos.xyz, lightDir);
+		lightIntensity = atten * lightData.lightIntensity;
+	}
+	
+	vec3 surfaceNormal = normalize(cameraSpaceNormal);
+	float cosAngIncidence = dot(surfaceNormal, lightDir);
+	cosAngIncidence = cosAngIncidence < 0.0001 ? 0.0 : cosAngIncidence;
+	
+	vec3 viewDirection = normalize(-cameraSpacePosition);
+	
+	vec3 halfAngle = normalize(lightDir + viewDirection);
+	float angleNormalHalf = acos(dot(halfAngle, surfaceNormal));
+	float exponent = angleNormalHalf / Mtl.specularShininess;
+	exponent = -(exponent * exponent);
+	float gaussianTerm = exp(exponent);
+
+	gaussianTerm = cosAngIncidence != 0.0 ? gaussianTerm : 0.0;
+	
+	vec4 lighting = Mtl.diffuseColor * lightIntensity * cosAngIncidence;
+	lighting += Mtl.specularColor * lightIntensity * gaussianTerm;
+	
+	return lighting;
+}
+
+void Impostor(out vec3 cameraPos, out vec3 cameraNormal)
+{
+	vec3 cameraPlanePos = vec3(mapping * sphereRadius, 0.0) + cameraSpherePos;
+	vec3 rayDirection = normalize(cameraPlanePos);
+	
+	float B = 2.0 * dot(rayDirection, -cameraSpherePos);
+	float C = dot(cameraSpherePos, cameraSpherePos) - (sphereRadius * sphereRadius);
+	
+	float det = (B * B) - (4 * C);
+	if(det < 0.0)
+		discard;
+		
+	float sqrtDet = sqrt(det);
+	float posT = (-B + sqrtDet)/2;
+	float negT = (-B - sqrtDet)/2;
+	
+	float intersectT = min(posT, negT);
+	cameraPos = rayDirection * intersectT;
+	cameraNormal = normalize(cameraPos - cameraSpherePos);
+}
+
+void main()
+{
+	vec3 cameraPos;
+	vec3 cameraNormal;
+	
+	Impostor(cameraPos, cameraNormal);
+	
+	vec4 accumLighting = Mtl.diffuseColor * Lgt.ambientIntensity;
+	for(int light = 0; light < numberOfLights; light++)
+	{
+		accumLighting += ComputeLighting(Lgt.lights[light],
+			cameraPos, cameraNormal);
+	}
+	
+	outputColor = sqrt(accumLighting); //2.0 gamma correction
+}

Tut 13 Imposters/data/PerspImpostor.vert

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

Tut 13 Imposters/tutorials.lua

 SetupProject("Tut 13 Basic Imposter", "BasicImposter.cpp",
 	"data/BasicImposter.vert",
 	"data/BasicImposter.frag",
+	"data/DepthImposter.vert",
+	"data/DepthImposter.frag",
+	"data/PerspImposter.vert",
+	"data/PerspImposter.frag",
 	"data/PN.vert",
 	"data/Lighting.frag")
 

framework/framework.cpp

 
 namespace Framework
 {
+	namespace
+	{
+		const char *GetShaderName(GLenum eShaderType)
+		{
+			switch(eShaderType)
+			{
+			case GL_VERTEX_SHADER: return "vertex"; break;
+			case GL_GEOMETRY_SHADER: return "geometry"; break;
+			case GL_FRAGMENT_SHADER: return "fragment"; break;
+			}
+
+			return NULL;
+		}
+	}
+
 	GLuint CreateShader(GLenum eShaderType,
 		const std::string &strShaderFile, const std::string &strShaderName)
 	{
 			GLchar *strInfoLog = new GLchar[infoLogLength + 1];
 			glGetShaderInfoLog(shader, infoLogLength, NULL, strInfoLog);
 
-			const char *strShaderType = NULL;
-			switch(eShaderType)
-			{
-			case GL_VERTEX_SHADER: strShaderType = "vertex"; break;
-			case GL_GEOMETRY_SHADER: strShaderType = "geometry"; break;
-			case GL_FRAGMENT_SHADER: strShaderType = "fragment"; break;
-			}
-
 			fprintf(stderr, "Compile failure in %s shader named \"%s\". Error:\n%s\n",
-				strShaderType, strShaderName.c_str(), strInfoLog);
+				GetShaderName(eShaderType), strShaderName.c_str(), strInfoLog);
 			delete[] strInfoLog;
 		}
 
 	{
 		std::string strFilename = "data\\" + strShaderFilename;
 		std::ifstream shaderFile(strFilename.c_str());
+		if(!shaderFile.is_open())
+		{
+			fprintf(stderr, "Cannot load the shader file \"%s\" for the %s shader.\n",
+				strFilename.c_str(), GetShaderName(eShaderType));
+			return 0;
+		}
 		std::stringstream shaderData;
 		shaderData << shaderFile.rdbuf();
 		shaderFile.close();