Jason McKesson avatar Jason McKesson committed 816e89f

Tut16: Can load the terrain mesh and render it with a texture.
Still needs lighting, final texture, and gamma correct stuff.

Comments (0)

Files changed (9)

Tut 16 Gamma and Textures/Gamma Landscape.cpp

+#include <string>
+#include <vector>
+#include <stack>
+#include <math.h>
+#include <stdio.h>
+#include <sstream>
+#include <memory>
+#include <glimg/glimg.h>
+#include <glimg/TextureGenerator.h>
+#include <glload/gl_3_3.h>
+#include <GL/freeglut.h>
+#include <glutil/MatrixStack.h>
+#include <glutil/MousePoles.h>
+#include <glutil/Shader.h>
+#include "../framework/framework.h"
+#include "../framework/Mesh.h"
+#include "../framework/Timer.h"
+#include "../framework/UniformBlockArray.h"
+#include "../framework/directories.h"
+#include <glm/glm.hpp>
+#include <glm/gtc/type_ptr.hpp>
+#include <glm/gtc/matrix_transform.hpp>
+
+#define ARRAY_COUNT( array ) (sizeof( array ) / (sizeof( array[0] ) * (sizeof( array ) != sizeof(void*) || sizeof( array[0] ) <= sizeof(void*))))
+
+struct ProgramData
+{
+	GLuint theProgram;
+
+	GLuint modelToCameraMatrixUnif;
+};
+
+struct UnlitProgData
+{
+	GLuint theProgram;
+
+	GLuint modelToCameraMatrixUnif;
+	GLuint objectColorUnif;
+};
+
+float g_fzNear = 1.0f;
+float g_fzFar = 1000.0f;
+
+ProgramData g_progStandard;
+UnlitProgData g_progUnlit;
+
+const int g_projectionBlockIndex = 0;
+const int g_lightBlockIndex = 0;
+const int g_colorTexUnit = 0;
+
+ProgramData LoadProgram(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;
+	data.theProgram = Framework::CreateProgram(shaderList);
+	data.modelToCameraMatrixUnif = glGetUniformLocation(data.theProgram, "modelToCameraMatrix");
+
+	GLuint projectionBlock = glGetUniformBlockIndex(data.theProgram, "Projection");
+	glUniformBlockBinding(data.theProgram, projectionBlock, g_projectionBlockIndex);
+
+	GLuint colorTextureUnif = glGetUniformLocation(data.theProgram, "diffuseColorTex");
+	glUseProgram(data.theProgram);
+	glUniform1i(colorTextureUnif, g_colorTexUnit);
+	glUseProgram(0);
+
+	return data;
+}
+
+UnlitProgData LoadUnlitProgram(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));
+
+	UnlitProgData data;
+	data.theProgram = Framework::CreateProgram(shaderList);
+	data.modelToCameraMatrixUnif = glGetUniformLocation(data.theProgram, "modelToCameraMatrix");
+	data.objectColorUnif = glGetUniformLocation(data.theProgram, "objectColor");
+
+	GLuint projectionBlock = glGetUniformBlockIndex(data.theProgram, "Projection");
+	glUniformBlockBinding(data.theProgram, projectionBlock, g_projectionBlockIndex);
+
+	return data;
+}
+
+void InitializePrograms()
+{
+	g_progStandard = LoadProgram("PNT.vert", "litTexture.frag");
+	g_progUnlit = LoadUnlitProgram("Unlit.vert", "Unlit.frag");
+}
+
+struct ProjectionBlock
+{
+	glm::mat4 cameraToClipMatrix;
+};
+
+GLuint g_projectionUniformBuffer = 0;
+GLuint g_linearTexture = 0;
+// GLuint g_gammaTexture = 0;
+
+const int NUM_SAMPLERS = 2;
+GLuint g_samplers[NUM_SAMPLERS];
+
+void CreateSamplers()
+{
+	glGenSamplers(NUM_SAMPLERS, &g_samplers[0]);
+
+	for(int samplerIx = 0; samplerIx < NUM_SAMPLERS; samplerIx++)
+	{
+		glSamplerParameteri(g_samplers[samplerIx], GL_TEXTURE_WRAP_S, GL_REPEAT);
+		glSamplerParameteri(g_samplers[samplerIx], GL_TEXTURE_WRAP_T, GL_REPEAT);
+	}
+
+	//Linear mipmap linear
+	glSamplerParameteri(g_samplers[0], GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+	glSamplerParameteri(g_samplers[0], GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
+
+	//Max anisotropic
+	GLfloat maxAniso = 0.0f;
+	glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &maxAniso);
+
+	glSamplerParameteri(g_samplers[1], GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+	glSamplerParameteri(g_samplers[1], GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
+	glSamplerParameterf(g_samplers[1], GL_TEXTURE_MAX_ANISOTROPY_EXT, maxAniso);
+}
+
+void LoadTextures()
+{
+	try
+	{
+		std::string filename(Framework::FindFileOrThrow("STest.png"));
+
+		std::auto_ptr<glimg::ImageSet> pImageSet(glimg::loaders::stb::LoadFromFile(filename.c_str()));
+
+		glGenTextures(1, &g_linearTexture);
+		glBindTexture(GL_TEXTURE_2D, g_linearTexture);
+
+		glimg::OpenGLPixelTransferParams xfer = glimg::GetUploadFormatType(pImageSet->GetFormat(), 0);
+
+		for(int mipmapLevel = 0; mipmapLevel < pImageSet->GetMipmapCount(); mipmapLevel++)
+		{
+			glimg::SingleImage image = pImageSet->GetImage(mipmapLevel, 0, 0);
+			glimg::Dimensions dims = image.GetDimensions();
+
+			glTexImage2D(GL_TEXTURE_2D, mipmapLevel, GL_SRGB8_ALPHA8, dims.width, dims.height, 0,
+				xfer.format, xfer.type, image.GetImageData());
+		}
+
+		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
+		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, pImageSet->GetMipmapCount() - 1);
+
+		glBindTexture(GL_TEXTURE_2D, 0);
+	}
+	catch(std::exception &e)
+	{
+		printf("%s\n", e.what());
+		throw;
+	}
+}
+
+////////////////////////////////
+//View setup.
+glutil::ViewData g_initialView =
+{
+	glm::vec3(0.0f, 0.0f, 0.0f),
+	glm::fquat(0.924f, 0.384f, 0.0f, 0.0f),
+	30.0f,
+	0.0f
+};
+
+glutil::ViewScale g_initialViewScale =
+{
+	5.0f,
+	90.0f,
+	2.0f,
+	0.5f,
+	4.0f,
+	1.0f,
+	90.0f/250.0f
+};
+
+glutil::ViewPole g_viewPole(g_initialView, g_initialViewScale, glutil::MB_LEFT_BTN);
+
+
+namespace
+{
+	int calc_glut_modifiers()
+	{
+		int ret = 0;
+
+		int modifiers = glutGetModifiers();
+		if(modifiers & GLUT_ACTIVE_SHIFT)
+			ret |= glutil::MM_KEY_SHIFT;
+		if(modifiers & GLUT_ACTIVE_CTRL)
+			ret |= glutil::MM_KEY_CTRL;
+		if(modifiers & GLUT_ACTIVE_ALT)
+			ret |= glutil::MM_KEY_ALT;
+
+		return ret;
+	}
+
+	void MouseMotion(int x, int y)
+	{
+		g_viewPole.MouseMove(glm::ivec2(x, y));
+		glutPostRedisplay();
+	}
+
+
+	void MouseButton(int button, int state, int x, int y)
+	{
+		int modifiers = calc_glut_modifiers();
+
+		glm::ivec2 mouseLoc = glm::ivec2(x, y);
+
+		glutil::MouseButtons eButton;
+
+		switch(button)
+		{
+		case GLUT_LEFT_BUTTON:
+			eButton = glutil::MB_LEFT_BTN;
+			break;
+		case GLUT_MIDDLE_BUTTON:
+			eButton = glutil::MB_MIDDLE_BTN;
+			break;
+		case GLUT_RIGHT_BUTTON:
+			eButton = glutil::MB_RIGHT_BTN;
+			break;
+#ifdef LOAD_X11
+			//Linux Mouse wheel support
+		case 3:
+			{
+				g_viewPole.MouseWheel(1, modifiers, mouseLoc);
+				return;
+			}
+		case 4:
+			{
+				g_viewPole.MouseWheel(-1, modifiers, mouseLoc);
+				return;
+			}
+#endif
+		default:
+			return;
+		}
+
+		g_viewPole.MouseClick(eButton, state == GLUT_DOWN, modifiers, glm::ivec2(x, y));
+		glutPostRedisplay();
+	}
+
+	void MouseWheel(int wheel, int direction, int x, int y)
+	{
+		g_viewPole.MouseWheel(direction, calc_glut_modifiers(), glm::ivec2(x, y));
+		glutPostRedisplay();
+	}
+}
+
+Framework::Mesh *g_pTerrain = NULL;
+Framework::Mesh *g_pSphere = NULL;
+
+//Called after the window and OpenGL are initialized. Called exactly once, before the main loop.
+void init()
+{
+	try
+	{
+		InitializePrograms();
+
+		g_pTerrain = new Framework::Mesh("terrain.xml");
+		g_pSphere = new Framework::Mesh("UnitSphere.xml");
+	}
+	catch(std::exception &except)
+	{
+		printf("%s\n", except.what());
+		throw;
+	}
+
+	glutMouseFunc(MouseButton);
+	glutMotionFunc(MouseMotion);
+	glutMouseWheelFunc(MouseWheel);
+
+	glEnable(GL_CULL_FACE);
+	glCullFace(GL_BACK);
+	glFrontFace(GL_CW);
+
+	const float depthZNear = 0.0f;
+	const float depthZFar = 1.0f;
+
+	glEnable(GL_DEPTH_TEST);
+	glDepthMask(GL_TRUE);
+	glDepthFunc(GL_LEQUAL);
+	glDepthRange(depthZNear, depthZFar);
+	glEnable(GL_DEPTH_CLAMP);
+
+	//Setup our Uniform Buffers
+	glGenBuffers(1, &g_projectionUniformBuffer);
+	glBindBuffer(GL_UNIFORM_BUFFER, g_projectionUniformBuffer);
+	glBufferData(GL_UNIFORM_BUFFER, sizeof(ProjectionBlock), NULL, GL_DYNAMIC_DRAW);
+
+	glBindBufferRange(GL_UNIFORM_BUFFER, g_projectionBlockIndex, g_projectionUniformBuffer,
+		0, sizeof(ProjectionBlock));
+
+	glBindBuffer(GL_UNIFORM_BUFFER, 0);
+
+	LoadTextures();
+	CreateSamplers();
+}
+
+using Framework::Timer;
+
+int g_currSampler = 0;
+
+bool g_drawGammaProgram = false;
+bool g_bDrawCameraPos = 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.
+void display()
+{
+	glClearColor(0.75f, 0.75f, 1.0f, 1.0f);
+	glClearDepth(1.0f);
+	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+	if(g_pSphere && g_pTerrain)
+	{
+		glutil::MatrixStack modelMatrix;
+
+		modelMatrix.ApplyMatrix(g_viewPole.CalcMatrix());
+
+		glutil::PushStack push(modelMatrix);
+		modelMatrix.RotateX(-90.0f);
+
+		glUseProgram(g_progStandard.theProgram);
+		glUniformMatrix4fv(g_progStandard.modelToCameraMatrixUnif, 1, GL_FALSE,
+			glm::value_ptr(modelMatrix.Top()));
+
+		glActiveTexture(GL_TEXTURE0 + g_colorTexUnit);
+		glBindTexture(GL_TEXTURE_2D, g_linearTexture);
+		glBindSampler(g_colorTexUnit, g_samplers[g_currSampler]);
+
+		g_pTerrain->Render("lit-tex");
+
+		glBindSampler(g_colorTexUnit, 0);
+		glBindTexture(GL_TEXTURE_2D, 0);
+
+		glUseProgram(0);
+
+
+		push.ResetStack();
+
+
+		if(g_bDrawCameraPos)
+		{
+			//Draw lookat point.
+			modelMatrix.SetIdentity();
+			modelMatrix.Translate(glm::vec3(0.0f, 0.0f, -g_viewPole.GetView().radius));
+
+			glDisable(GL_DEPTH_TEST);
+			glDepthMask(GL_FALSE);
+			glUseProgram(g_progUnlit.theProgram);
+			glUniformMatrix4fv(g_progUnlit.modelToCameraMatrixUnif, 1, GL_FALSE,
+				glm::value_ptr(modelMatrix.Top()));
+			glUniform4f(g_progUnlit.objectColorUnif, 0.25f, 0.25f, 0.25f, 1.0f);
+			g_pSphere->Render("flat");
+			glDepthMask(GL_TRUE);
+			glEnable(GL_DEPTH_TEST);
+			glUniform4f(g_progUnlit.objectColorUnif, 1.0f, 1.0f, 1.0f, 1.0f);
+			g_pSphere->Render("flat");
+		}
+	}
+
+	glutPostRedisplay();
+	glutSwapBuffers();
+}
+
+//Called whenever the window is resized. The new window size is given, in pixels.
+//This is an opportunity to call glViewport or glScissor to keep up with the change in size.
+void reshape (int w, int h)
+{
+	glutil::MatrixStack persMatrix;
+	persMatrix.Perspective(60.0f, (h / (float)w), g_fzNear, g_fzFar);
+
+	ProjectionBlock projData;
+	projData.cameraToClipMatrix = persMatrix.Top();
+
+	glBindBuffer(GL_UNIFORM_BUFFER, g_projectionUniformBuffer);
+	glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(ProjectionBlock), &projData);
+	glBindBuffer(GL_UNIFORM_BUFFER, 0);
+
+	glViewport(0, 0, (GLsizei) w, (GLsizei) h);
+	glutPostRedisplay();
+}
+
+
+//Called whenever a key on the keyboard was pressed.
+//The key is given by the ''key'' parameter, which is in ASCII.
+//It's often a good idea to have the escape key (ASCII value 27) call glutLeaveMainLoop() to 
+//exit the program.
+void keyboard(unsigned char key, int x, int y)
+{
+	switch (key)
+	{
+	case 27:
+		delete g_pSphere;
+		delete g_pTerrain;
+		g_pSphere = NULL;
+		g_pTerrain = NULL;
+		glutLeaveMainLoop();
+		return;
+	case 'a':
+		g_drawGammaProgram = !g_drawGammaProgram;
+		break;
+	case 32:
+		g_drawGammaProgram = !g_drawGammaProgram;
+		break;
+	case 't': g_bDrawCameraPos = !g_bDrawCameraPos; break;
+	}
+
+	if(('1' <= key) && (key <= '9'))
+	{
+		int number = key - '1';
+		if(number < NUM_SAMPLERS)
+		{
+			g_currSampler = number;
+		}
+	}
+
+	g_viewPole.CharPress(key);
+}
+
+unsigned int defaults(unsigned int displayMode, int &width, int &height) {return displayMode;}

Tut 16 Gamma and Textures/data/GenSphere.lua

+require "XmlWriter"
+require "vmath"
+
+local function GenStringFromArray(theArray)
+	local array = {" "}
+	for i, vector in ipairs(theArray) do
+		array[#array + 1] = "        " .. table.concat(vector, " ");
+	end
+	
+	return table.concat(array, "\n");
+end
+
+local positions = {};
+local colors = {};
+local normals = {};
+local topFan = {};
+local botFan = {};
+local strips = {};
+local restartIndex = 65535;
+
+local iSegCount, iColorRepeatCount, iRingCount = ...;
+iSegCount = iSegCount or 15;
+iColorRepeatCount = iColorRepeatCount or 3;
+iRingCount = iRingCount or 8;
+
+local rhoAngle = math.pi * 2.0 / iSegCount;
+local thetaAngle = math.pi / (iRingCount + 1);
+local iColorCycleAngle = math.pi * 2.0 / iColorRepeatCount;
+local highColor = vmath.vec4(0.9, 0.5, 0.5, 1.0);
+local lowColor = vmath.vec4(0.5, 0.1, 0.1, 1.0)
+
+--Compute vertex attributes
+positions[#positions + 1] = vmath.vec3(0.0, 0.5, 0.0);
+colors[#colors + 1] = vmath.vec4(1.0, 1.0, 1.0, 1.0);
+normals[#normals + 1] = vmath.vec3(0.0, 1.0, 0.0);
+
+local firstSideIx = #positions;
+
+for iRing = 1, iRingCount do
+	local theta = (thetaAngle * iRing)
+	local sinTheta, cosTheta = math.sin(theta), math.cos(theta);
+
+	for iSeg = 0, (iSegCount - 1) do
+		local rho = rhoAngle * iSeg;
+		local sinRho, cosRho = math.sin(rho), math.cos(rho);
+		
+		local point = vmath.vec3(sinTheta * cosRho, cosTheta, sinTheta * sinRho);
+		positions[#positions + 1] = 0.5 * point;
+		normals[#normals + 1] = vmath.vec3(sinTheta * cosRho, cosTheta, sinTheta * sinRho);
+		colors[#colors + 1] = vmath.vec4(
+			vmath.vec3(sinTheta * cosRho, cosTheta, sinTheta * sinRho), 1.0);
+	end
+end
+
+positions[#positions + 1] = vmath.vec3(0.0, -0.5, 0.0);
+colors[#colors + 1] = vmath.vec4(1.0, 1.0, 1.0, 1.0);
+normals[#normals + 1] = vmath.vec3(0.0, -1.0, 0.0);
+
+--Compute cap fans.
+topFan[#topFan + 1] = 0;
+botFan[#botFan + 1] = #positions - 1;
+
+for iSeg = 1, iSegCount do
+	topFan[#topFan + 1] = iSeg;
+	botFan[#botFan + 1] = (#positions - 1) - iSeg;
+end
+
+topFan[#topFan + 1] = 1;
+botFan[#botFan + 1] = (#positions - 2);
+
+--Compute the strips.
+
+for iRing = 1, iRingCount - 1 do
+	local topRingStart = 1 + ((iRing - 1) * iSegCount);
+	local botRingStart = 1 + (iRing * iSegCount);
+	local strip = {};
+	strips[#strips + 1] = strip;
+	
+	for iSeg = 0, (iSegCount - 1) do
+		strip[#strip + 1] = topRingStart + iSeg;
+		strip[#strip + 1] = botRingStart + iSeg;
+	end
+
+	strip[#strip + 1] = topRingStart;
+	strip[#strip + 1] = botRingStart;
+end
+
+
+do
+	local writer = XmlWriter.XmlWriter("UnitSphere.xml");
+	writer:AddPI("oxygen", [[RNGSchema="../../Documents/meshFormat.rnc" type="compact"]]);
+	writer:PushElement("mesh", "http://www.arcsynthesis.com/gltut/mesh");
+		writer:PushElement("attribute");
+			writer:AddAttribute("index", "0");
+			writer:AddAttribute("type", "float");
+			writer:AddAttribute("size", "3");
+			writer:AddText(GenStringFromArray(positions));
+		writer:PopElement();
+		writer:PushElement("attribute");
+			writer:AddAttribute("index", "1");
+			writer:AddAttribute("type", "float");
+			writer:AddAttribute("size", "4");
+			writer:AddText(GenStringFromArray(colors));
+		writer:PopElement();
+		writer:PushElement("attribute");
+			writer:AddAttribute("index", "2");
+			writer:AddAttribute("type", "float");
+			writer:AddAttribute("size", "3");
+			writer:AddText(GenStringFromArray(normals));
+		writer:PopElement();
+		writer:PushElement("vao");
+			writer:AddAttribute("name", "lit-color");
+			writer:PushElement("source"); writer:AddAttribute("attrib", "0"); writer:PopElement();
+			writer:PushElement("source"); writer:AddAttribute("attrib", "1"); writer:PopElement();
+			writer:PushElement("source"); writer:AddAttribute("attrib", "2"); writer:PopElement();
+		writer:PopElement();
+		writer:PushElement("vao");
+			writer:AddAttribute("name", "lit");
+			writer:PushElement("source"); writer:AddAttribute("attrib", "0"); writer:PopElement();
+			writer:PushElement("source"); writer:AddAttribute("attrib", "2"); writer:PopElement();
+		writer:PopElement();
+		writer:PushElement("vao");
+			writer:AddAttribute("name", "color");
+			writer:PushElement("source"); writer:AddAttribute("attrib", "0"); writer:PopElement();
+			writer:PushElement("source"); writer:AddAttribute("attrib", "1"); writer:PopElement();
+		writer:PopElement();
+		writer:PushElement("vao");
+			writer:AddAttribute("name", "flat");
+			writer:PushElement("source"); writer:AddAttribute("attrib", "0"); writer:PopElement();
+		writer:PopElement();
+		writer:PushElement("indices");
+			writer:AddAttribute("cmd", "tri-fan");
+			writer:AddAttribute("type", "ushort");
+			writer:AddText(table.concat(topFan, " "));
+		writer:PopElement();
+		writer:PushElement("indices");
+			writer:AddAttribute("cmd", "tri-fan");
+			writer:AddAttribute("type", "ushort");
+			writer:AddText(table.concat(botFan, " "));
+		writer:PopElement();
+		for i, strip in ipairs(strips) do
+			writer:PushElement("indices");
+				writer:AddAttribute("cmd", "tri-strip");
+				writer:AddAttribute("type", "ushort");
+				writer:AddText(table.concat(strip, " "));
+			writer:PopElement();
+		end
+	writer:PopElement();
+	writer:Close();
+end

Tut 16 Gamma and Textures/data/PNT.vert

+#version 330
+
+layout(std140) uniform;
+
+layout(location = 0) in vec3 position;
+layout(location = 2) in vec3 normal;
+layout(location = 5) in vec2 texCoord;
+
+out vec2 colorCoord;
+out vec3 cameraSpacePosition;
+out vec3 cameraSpaceNormal;
+
+uniform Projection
+{
+	mat4 cameraToClipMatrix;
+};
+
+uniform mat4 modelToCameraMatrix;
+
+void main()
+{
+	gl_Position = cameraToClipMatrix * (modelToCameraMatrix * vec4(position, 1.0));
+	//Assume the modelToCameraMatrix contains no scaling.
+	cameraSpaceNormal = (modelToCameraMatrix * vec4(normal, 0)).xyz;
+	colorCoord = texCoord;
+}

Tut 16 Gamma and Textures/data/UnitSphere.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.17101007166283 0.46984631039295 0
+        0.15622547417872 0.46984631039295 0.069556062480293
+        0.11442807294522 0.46984631039295 0.12708524986075
+        0.052845018353093 0.46984631039295 0.16264024300704
+        -0.017875419994207 0.46984631039295 0.17007326059719
+        -0.085505035831417 0.46984631039295 0.14809906636301
+        -0.13835005418451 0.46984631039295 0.10051719811689
+        -0.16727309129832 0.46984631039295 0.035554993146286
+        -0.16727309129832 0.46984631039295 -0.035554993146286
+        -0.13835005418451 0.46984631039295 -0.10051719811689
+        -0.085505035831417 0.46984631039295 -0.14809906636301
+        -0.017875419994207 0.46984631039295 -0.17007326059719
+        0.052845018353093 0.46984631039295 -0.16264024300704
+        0.11442807294522 0.46984631039295 -0.12708524986075
+        0.15622547417872 0.46984631039295 -0.069556062480293
+        0.32139380484327 0.38302222155949 0
+        0.29360785052904 0.38302222155949 0.13072263728731
+        0.21505443151476 0.38302222155949 0.23884214300977
+        0.099316147583396 0.38302222155949 0.30566367239308
+        -0.033594800524011 0.38302222155949 0.31963317595235
+        -0.16069690242163 0.38302222155949 0.27833519961321
+        -0.26001305000503 0.38302222155949 0.18891053866504
+        -0.31437057909815 0.38302222155949 0.066821529383317
+        -0.31437057909815 0.38302222155949 -0.066821529383317
+        -0.26001305000503 0.38302222155949 -0.18891053866504
+        -0.16069690242163 0.38302222155949 -0.27833519961321
+        -0.033594800524011 0.38302222155949 -0.31963317595235
+        0.099316147583396 0.38302222155949 -0.30566367239308
+        0.21505443151476 0.38302222155949 -0.23884214300977
+        0.29360785052904 0.38302222155949 -0.13072263728731
+        0.43301270189222 0.25 0
+        0.39557678691519 0.25 0.17612213277682
+        0.28974205177823 0.25 0.32179114877719
+        0.13380828366491 0.25 0.41181955177317
+        -0.045262152304168 0.25 0.43064061300439
+        -0.21650635094611 0.25 0.375
+        -0.35031463461102 0.25 0.25451848022756
+        -0.42355033544314 0.25 0.090028402995978
+        -0.42355033544314 0.25 -0.090028402995978
+        -0.35031463461102 0.25 -0.25451848022756
+        -0.21650635094611 0.25 -0.375
+        -0.045262152304169 0.25 -0.43064061300439
+        0.13380828366491 0.25 -0.41181955177317
+        0.28974205177823 0.25 -0.32179114877719
+        0.39557678691519 0.25 -0.17612213277682
+        0.4924038765061 0.086824088833465 0
+        0.44983332470776 0.086824088833465 0.2002786997676
+        0.32948250445998 0.086824088833465 0.36592739287052
+        0.15216116593649 0.086824088833465 0.46830391540012
+        -0.051470220518218 0.086824088833465 0.48970643654954
+        -0.24620193825305 0.086824088833465 0.42643426597622
+        -0.39836310418954 0.086824088833465 0.28942773678193
+        -0.48164367039647 0.086824088833465 0.1023765225296
+        -0.48164367039647 0.086824088833465 -0.1023765225296
+        -0.39836310418954 0.086824088833465 -0.28942773678193
+        -0.24620193825305 0.086824088833465 -0.42643426597622
+        -0.051470220518219 0.086824088833465 -0.48970643654954
+        0.15216116593649 0.086824088833465 -0.46830391540012
+        0.32948250445998 0.086824088833465 -0.36592739287052
+        0.44983332470776 0.086824088833465 -0.2002786997676
+        0.4924038765061 -0.086824088833465 0
+        0.44983332470776 -0.086824088833465 0.2002786997676
+        0.32948250445998 -0.086824088833465 0.36592739287052
+        0.15216116593649 -0.086824088833465 0.46830391540012
+        -0.051470220518218 -0.086824088833465 0.48970643654954
+        -0.24620193825305 -0.086824088833465 0.42643426597622
+        -0.39836310418954 -0.086824088833465 0.28942773678193
+        -0.48164367039647 -0.086824088833465 0.1023765225296
+        -0.48164367039647 -0.086824088833465 -0.1023765225296
+        -0.39836310418954 -0.086824088833465 -0.28942773678193
+        -0.24620193825305 -0.086824088833465 -0.42643426597622
+        -0.051470220518219 -0.086824088833465 -0.48970643654954
+        0.15216116593649 -0.086824088833465 -0.46830391540012
+        0.32948250445998 -0.086824088833465 -0.36592739287052
+        0.44983332470776 -0.086824088833465 -0.2002786997676
+        0.43301270189222 -0.25 0
+        0.39557678691519 -0.25 0.17612213277682
+        0.28974205177823 -0.25 0.32179114877719
+        0.13380828366491 -0.25 0.41181955177317
+        -0.045262152304168 -0.25 0.43064061300439
+        -0.21650635094611 -0.25 0.375
+        -0.35031463461102 -0.25 0.25451848022756
+        -0.42355033544314 -0.25 0.090028402995978
+        -0.42355033544314 -0.25 -0.090028402995978
+        -0.35031463461102 -0.25 -0.25451848022756
+        -0.21650635094611 -0.25 -0.375
+        -0.045262152304169 -0.25 -0.43064061300439
+        0.13380828366491 -0.25 -0.41181955177317
+        0.28974205177823 -0.25 -0.32179114877719
+        0.39557678691519 -0.25 -0.17612213277682
+        0.32139380484327 -0.38302222155949 0
+        0.29360785052904 -0.38302222155949 0.13072263728731
+        0.21505443151476 -0.38302222155949 0.23884214300977
+        0.099316147583396 -0.38302222155949 0.30566367239308
+        -0.033594800524011 -0.38302222155949 0.31963317595235
+        -0.16069690242163 -0.38302222155949 0.27833519961321
+        -0.26001305000503 -0.38302222155949 0.18891053866504
+        -0.31437057909815 -0.38302222155949 0.066821529383317
+        -0.31437057909815 -0.38302222155949 -0.066821529383317
+        -0.26001305000503 -0.38302222155949 -0.18891053866504
+        -0.16069690242164 -0.38302222155949 -0.27833519961321
+        -0.033594800524011 -0.38302222155949 -0.31963317595235
+        0.099316147583396 -0.38302222155949 -0.30566367239308
+        0.21505443151476 -0.38302222155949 -0.23884214300977
+        0.29360785052904 -0.38302222155949 -0.13072263728731
+        0.17101007166283 -0.46984631039295 0
+        0.15622547417872 -0.46984631039295 0.069556062480293
+        0.11442807294522 -0.46984631039295 0.12708524986075
+        0.052845018353093 -0.46984631039295 0.16264024300704
+        -0.017875419994207 -0.46984631039295 0.17007326059719
+        -0.085505035831417 -0.46984631039295 0.14809906636301
+        -0.13835005418451 -0.46984631039295 0.10051719811689
+        -0.16727309129832 -0.46984631039295 0.035554993146286
+        -0.16727309129832 -0.46984631039295 -0.035554993146286
+        -0.13835005418451 -0.46984631039295 -0.10051719811689
+        -0.085505035831417 -0.46984631039295 -0.14809906636301
+        -0.017875419994208 -0.46984631039295 -0.17007326059719
+        0.052845018353093 -0.46984631039295 -0.16264024300704
+        0.11442807294522 -0.46984631039295 -0.12708524986075
+        0.15622547417872 -0.46984631039295 -0.069556062480293
+        0 -0.5 0</attribute>
+	<attribute index="1" type="float" size="4" > 
+        1 1 1 1
+        0.34202014332567 0.93969262078591 0 1
+        0.31245094835744 0.93969262078591 0.13911212496059 1
+        0.22885614589045 0.93969262078591 0.25417049972151 1
+        0.10569003670619 0.93969262078591 0.32528048601408 1
+        -0.035750839988415 0.93969262078591 0.34014652119437 1
+        -0.17101007166283 0.93969262078591 0.29619813272602 1
+        -0.27670010836902 0.93969262078591 0.20103439623379 1
+        -0.33454618259664 0.93969262078591 0.071109986292572 1
+        -0.33454618259664 0.93969262078591 -0.071109986292572 1
+        -0.27670010836902 0.93969262078591 -0.20103439623379 1
+        -0.17101007166283 0.93969262078591 -0.29619813272602 1
+        -0.035750839988415 0.93969262078591 -0.34014652119437 1
+        0.10569003670619 0.93969262078591 -0.32528048601408 1
+        0.22885614589045 0.93969262078591 -0.25417049972151 1
+        0.31245094835744 0.93969262078591 -0.13911212496059 1
+        0.64278760968654 0.76604444311898 0 1
+        0.58721570105808 0.76604444311898 0.26144527457462 1
+        0.43010886302952 0.76604444311898 0.47768428601953 1
+        0.19863229516679 0.76604444311898 0.61132734478617 1
+        -0.067189601048022 0.76604444311898 0.6392663519047 1
+        -0.32139380484327 0.76604444311898 0.55667039922642 1
+        -0.52002610001006 0.76604444311898 0.37782107733008 1
+        -0.62874115819631 0.76604444311898 0.13364305876663 1
+        -0.62874115819631 0.76604444311898 -0.13364305876663 1
+        -0.52002610001006 0.76604444311898 -0.37782107733008 1
+        -0.32139380484327 0.76604444311898 -0.55667039922642 1
+        -0.067189601048023 0.76604444311898 -0.6392663519047 1
+        0.19863229516679 0.76604444311898 -0.61132734478617 1
+        0.43010886302951 0.76604444311898 -0.47768428601953 1
+        0.58721570105808 0.76604444311898 -0.26144527457462 1
+        0.86602540378444 0.5 0 1
+        0.79115357383037 0.5 0.35224426555365 1
+        0.57948410355646 0.5 0.64358229755438 1
+        0.26761656732982 0.5 0.82363910354633 1
+        -0.090524304608336 0.5 0.86128122600877 1
+        -0.43301270189222 0.5 0.75 1
+        -0.70062926922204 0.5 0.50903696045513 1
+        -0.84710067088627 0.5 0.18005680599196 1
+        -0.84710067088627 0.5 -0.18005680599196 1
+        -0.70062926922204 0.5 -0.50903696045513 1
+        -0.43301270189222 0.5 -0.75 1
+        -0.090524304608337 0.5 -0.86128122600877 1
+        0.26761656732982 0.5 -0.82363910354633 1
+        0.57948410355646 0.5 -0.64358229755438 1
+        0.79115357383037 0.5 -0.35224426555365 1
+        0.98480775301221 0.17364817766693 0 1
+        0.89966664941552 0.17364817766693 0.40055739953521 1
+        0.65896500891996 0.17364817766693 0.73185478574104 1
+        0.30432233187298 0.17364817766693 0.93660783080025 1
+        -0.10294044103644 0.17364817766693 0.97941287309907 1
+        -0.4924038765061 0.17364817766693 0.85286853195244 1
+        -0.79672620837908 0.17364817766693 0.57885547356386 1
+        -0.96328734079294 0.17364817766693 0.20475304505921 1
+        -0.96328734079294 0.17364817766693 -0.20475304505921 1
+        -0.79672620837908 0.17364817766693 -0.57885547356386 1
+        -0.4924038765061 0.17364817766693 -0.85286853195244 1
+        -0.10294044103644 0.17364817766693 -0.97941287309907 1
+        0.30432233187298 0.17364817766693 -0.93660783080025 1
+        0.65896500891996 0.17364817766693 -0.73185478574104 1
+        0.89966664941552 0.17364817766693 -0.40055739953521 1
+        0.98480775301221 -0.17364817766693 0 1
+        0.89966664941552 -0.17364817766693 0.40055739953521 1
+        0.65896500891996 -0.17364817766693 0.73185478574104 1
+        0.30432233187298 -0.17364817766693 0.93660783080025 1
+        -0.10294044103644 -0.17364817766693 0.97941287309907 1
+        -0.4924038765061 -0.17364817766693 0.85286853195244 1
+        -0.79672620837908 -0.17364817766693 0.57885547356386 1
+        -0.96328734079294 -0.17364817766693 0.20475304505921 1
+        -0.96328734079294 -0.17364817766693 -0.20475304505921 1
+        -0.79672620837908 -0.17364817766693 -0.57885547356386 1
+        -0.4924038765061 -0.17364817766693 -0.85286853195244 1
+        -0.10294044103644 -0.17364817766693 -0.97941287309907 1
+        0.30432233187298 -0.17364817766693 -0.93660783080025 1
+        0.65896500891996 -0.17364817766693 -0.73185478574104 1
+        0.89966664941552 -0.17364817766693 -0.40055739953521 1
+        0.86602540378444 -0.5 0 1
+        0.79115357383037 -0.5 0.35224426555365 1
+        0.57948410355646 -0.5 0.64358229755438 1
+        0.26761656732982 -0.5 0.82363910354633 1
+        -0.090524304608336 -0.5 0.86128122600877 1
+        -0.43301270189222 -0.5 0.75 1
+        -0.70062926922204 -0.5 0.50903696045513 1
+        -0.84710067088627 -0.5 0.18005680599196 1
+        -0.84710067088627 -0.5 -0.18005680599196 1
+        -0.70062926922204 -0.5 -0.50903696045513 1
+        -0.43301270189222 -0.5 -0.75 1
+        -0.090524304608337 -0.5 -0.86128122600877 1
+        0.26761656732982 -0.5 -0.82363910354633 1
+        0.57948410355646 -0.5 -0.64358229755438 1
+        0.79115357383037 -0.5 -0.35224426555365 1
+        0.64278760968654 -0.76604444311898 0 1
+        0.58721570105808 -0.76604444311898 0.26144527457462 1
+        0.43010886302952 -0.76604444311898 0.47768428601953 1
+        0.19863229516679 -0.76604444311898 0.61132734478617 1
+        -0.067189601048022 -0.76604444311898 0.6392663519047 1
+        -0.32139380484327 -0.76604444311898 0.55667039922642 1
+        -0.52002610001006 -0.76604444311898 0.37782107733008 1
+        -0.62874115819631 -0.76604444311898 0.13364305876663 1
+        -0.62874115819631 -0.76604444311898 -0.13364305876663 1
+        -0.52002610001006 -0.76604444311898 -0.37782107733008 1
+        -0.32139380484327 -0.76604444311898 -0.55667039922642 1
+        -0.067189601048023 -0.76604444311898 -0.6392663519047 1
+        0.19863229516679 -0.76604444311898 -0.61132734478617 1
+        0.43010886302951 -0.76604444311898 -0.47768428601954 1
+        0.58721570105808 -0.76604444311898 -0.26144527457462 1
+        0.34202014332567 -0.93969262078591 0 1
+        0.31245094835744 -0.93969262078591 0.13911212496059 1
+        0.22885614589045 -0.93969262078591 0.25417049972151 1
+        0.10569003670619 -0.93969262078591 0.32528048601408 1
+        -0.035750839988415 -0.93969262078591 0.34014652119437 1
+        -0.17101007166283 -0.93969262078591 0.29619813272602 1
+        -0.27670010836902 -0.93969262078591 0.20103439623379 1
+        -0.33454618259664 -0.93969262078591 0.071109986292572 1
+        -0.33454618259664 -0.93969262078591 -0.071109986292572 1
+        -0.27670010836902 -0.93969262078591 -0.20103439623379 1
+        -0.17101007166283 -0.93969262078591 -0.29619813272602 1
+        -0.035750839988415 -0.93969262078591 -0.34014652119437 1
+        0.10569003670619 -0.93969262078591 -0.32528048601408 1
+        0.22885614589045 -0.93969262078591 -0.25417049972151 1
+        0.31245094835744 -0.93969262078591 -0.13911212496059 1
+        1 1 1 1</attribute>
+	<attribute index="2" type="float" size="3" > 
+        0 1 0
+        0.34202014332567 0.93969262078591 0
+        0.31245094835744 0.93969262078591 0.13911212496059
+        0.22885614589045 0.93969262078591 0.25417049972151
+        0.10569003670619 0.93969262078591 0.32528048601408
+        -0.035750839988415 0.93969262078591 0.34014652119437
+        -0.17101007166283 0.93969262078591 0.29619813272602
+        -0.27670010836902 0.93969262078591 0.20103439623379
+        -0.33454618259664 0.93969262078591 0.071109986292572
+        -0.33454618259664 0.93969262078591 -0.071109986292572
+        -0.27670010836902 0.93969262078591 -0.20103439623379
+        -0.17101007166283 0.93969262078591 -0.29619813272602
+        -0.035750839988415 0.93969262078591 -0.34014652119437
+        0.10569003670619 0.93969262078591 -0.32528048601408
+        0.22885614589045 0.93969262078591 -0.25417049972151
+        0.31245094835744 0.93969262078591 -0.13911212496059
+        0.64278760968654 0.76604444311898 0
+        0.58721570105808 0.76604444311898 0.26144527457462
+        0.43010886302952 0.76604444311898 0.47768428601953
+        0.19863229516679 0.76604444311898 0.61132734478617
+        -0.067189601048022 0.76604444311898 0.6392663519047
+        -0.32139380484327 0.76604444311898 0.55667039922642
+        -0.52002610001006 0.76604444311898 0.37782107733008
+        -0.62874115819631 0.76604444311898 0.13364305876663
+        -0.62874115819631 0.76604444311898 -0.13364305876663
+        -0.52002610001006 0.76604444311898 -0.37782107733008
+        -0.32139380484327 0.76604444311898 -0.55667039922642
+        -0.067189601048023 0.76604444311898 -0.6392663519047
+        0.19863229516679 0.76604444311898 -0.61132734478617
+        0.43010886302951 0.76604444311898 -0.47768428601953
+        0.58721570105808 0.76604444311898 -0.26144527457462
+        0.86602540378444 0.5 0
+        0.79115357383037 0.5 0.35224426555365
+        0.57948410355646 0.5 0.64358229755438
+        0.26761656732982 0.5 0.82363910354633
+        -0.090524304608336 0.5 0.86128122600877
+        -0.43301270189222 0.5 0.75
+        -0.70062926922204 0.5 0.50903696045513
+        -0.84710067088627 0.5 0.18005680599196
+        -0.84710067088627 0.5 -0.18005680599196
+        -0.70062926922204 0.5 -0.50903696045513
+        -0.43301270189222 0.5 -0.75
+        -0.090524304608337 0.5 -0.86128122600877
+        0.26761656732982 0.5 -0.82363910354633
+        0.57948410355646 0.5 -0.64358229755438
+        0.79115357383037 0.5 -0.35224426555365
+        0.98480775301221 0.17364817766693 0
+        0.89966664941552 0.17364817766693 0.40055739953521
+        0.65896500891996 0.17364817766693 0.73185478574104
+        0.30432233187298 0.17364817766693 0.93660783080025
+        -0.10294044103644 0.17364817766693 0.97941287309907
+        -0.4924038765061 0.17364817766693 0.85286853195244
+        -0.79672620837908 0.17364817766693 0.57885547356386
+        -0.96328734079294 0.17364817766693 0.20475304505921
+        -0.96328734079294 0.17364817766693 -0.20475304505921
+        -0.79672620837908 0.17364817766693 -0.57885547356386
+        -0.4924038765061 0.17364817766693 -0.85286853195244
+        -0.10294044103644 0.17364817766693 -0.97941287309907
+        0.30432233187298 0.17364817766693 -0.93660783080025
+        0.65896500891996 0.17364817766693 -0.73185478574104
+        0.89966664941552 0.17364817766693 -0.40055739953521
+        0.98480775301221 -0.17364817766693 0
+        0.89966664941552 -0.17364817766693 0.40055739953521
+        0.65896500891996 -0.17364817766693 0.73185478574104
+        0.30432233187298 -0.17364817766693 0.93660783080025
+        -0.10294044103644 -0.17364817766693 0.97941287309907
+        -0.4924038765061 -0.17364817766693 0.85286853195244
+        -0.79672620837908 -0.17364817766693 0.57885547356386
+        -0.96328734079294 -0.17364817766693 0.20475304505921
+        -0.96328734079294 -0.17364817766693 -0.20475304505921
+        -0.79672620837908 -0.17364817766693 -0.57885547356386
+        -0.4924038765061 -0.17364817766693 -0.85286853195244
+        -0.10294044103644 -0.17364817766693 -0.97941287309907
+        0.30432233187298 -0.17364817766693 -0.93660783080025
+        0.65896500891996 -0.17364817766693 -0.73185478574104
+        0.89966664941552 -0.17364817766693 -0.40055739953521
+        0.86602540378444 -0.5 0
+        0.79115357383037 -0.5 0.35224426555365
+        0.57948410355646 -0.5 0.64358229755438
+        0.26761656732982 -0.5 0.82363910354633
+        -0.090524304608336 -0.5 0.86128122600877
+        -0.43301270189222 -0.5 0.75
+        -0.70062926922204 -0.5 0.50903696045513
+        -0.84710067088627 -0.5 0.18005680599196
+        -0.84710067088627 -0.5 -0.18005680599196
+        -0.70062926922204 -0.5 -0.50903696045513
+        -0.43301270189222 -0.5 -0.75
+        -0.090524304608337 -0.5 -0.86128122600877
+        0.26761656732982 -0.5 -0.82363910354633
+        0.57948410355646 -0.5 -0.64358229755438
+        0.79115357383037 -0.5 -0.35224426555365
+        0.64278760968654 -0.76604444311898 0
+        0.58721570105808 -0.76604444311898 0.26144527457462
+        0.43010886302952 -0.76604444311898 0.47768428601953
+        0.19863229516679 -0.76604444311898 0.61132734478617
+        -0.067189601048022 -0.76604444311898 0.6392663519047
+        -0.32139380484327 -0.76604444311898 0.55667039922642
+        -0.52002610001006 -0.76604444311898 0.37782107733008
+        -0.62874115819631 -0.76604444311898 0.13364305876663
+        -0.62874115819631 -0.76604444311898 -0.13364305876663
+        -0.52002610001006 -0.76604444311898 -0.37782107733008
+        -0.32139380484327 -0.76604444311898 -0.55667039922642
+        -0.067189601048023 -0.76604444311898 -0.6392663519047
+        0.19863229516679 -0.76604444311898 -0.61132734478617
+        0.43010886302951 -0.76604444311898 -0.47768428601954
+        0.58721570105808 -0.76604444311898 -0.26144527457462
+        0.34202014332567 -0.93969262078591 0
+        0.31245094835744 -0.93969262078591 0.13911212496059
+        0.22885614589045 -0.93969262078591 0.25417049972151
+        0.10569003670619 -0.93969262078591 0.32528048601408
+        -0.035750839988415 -0.93969262078591 0.34014652119437
+        -0.17101007166283 -0.93969262078591 0.29619813272602
+        -0.27670010836902 -0.93969262078591 0.20103439623379
+        -0.33454618259664 -0.93969262078591 0.071109986292572
+        -0.33454618259664 -0.93969262078591 -0.071109986292572
+        -0.27670010836902 -0.93969262078591 -0.20103439623379
+        -0.17101007166283 -0.93969262078591 -0.29619813272602
+        -0.035750839988415 -0.93969262078591 -0.34014652119437
+        0.10569003670619 -0.93969262078591 -0.32528048601408
+        0.22885614589045 -0.93969262078591 -0.25417049972151
+        0.31245094835744 -0.93969262078591 -0.13911212496059
+        0 -1 0</attribute>
+	<vao name="lit-color" >
+		<source attrib="0" />
+		<source attrib="1" />
+		<source attrib="2" />
+	</vao>
+	<vao name="lit" >
+		<source attrib="0" />
+		<source attrib="2" />
+	</vao>
+	<vao name="color" >
+		<source attrib="0" />
+		<source attrib="1" />
+	</vao>
+	<vao name="flat" >
+		<source attrib="0" />
+	</vao>
+	<indices cmd="tri-fan" type="ushort" >0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 1</indices>
+	<indices cmd="tri-fan" type="ushort" >121 120 119 118 117 116 115 114 113 112 111 110 109 108 107 106 120</indices>
+	<indices cmd="tri-strip" type="ushort" >1 16 2 17 3 18 4 19 5 20 6 21 7 22 8 23 9 24 10 25 11 26 12 27 13 28 14 29 15 30 1 16</indices>
+	<indices cmd="tri-strip" type="ushort" >16 31 17 32 18 33 19 34 20 35 21 36 22 37 23 38 24 39 25 40 26 41 27 42 28 43 29 44 30 45 16 31</indices>
+	<indices cmd="tri-strip" type="ushort" >31 46 32 47 33 48 34 49 35 50 36 51 37 52 38 53 39 54 40 55 41 56 42 57 43 58 44 59 45 60 31 46</indices>
+	<indices cmd="tri-strip" type="ushort" >46 61 47 62 48 63 49 64 50 65 51 66 52 67 53 68 54 69 55 70 56 71 57 72 58 73 59 74 60 75 46 61</indices>
+	<indices cmd="tri-strip" type="ushort" >61 76 62 77 63 78 64 79 65 80 66 81 67 82 68 83 69 84 70 85 71 86 72 87 73 88 74 89 75 90 61 76</indices>
+	<indices cmd="tri-strip" type="ushort" >76 91 77 92 78 93 79 94 80 95 81 96 82 97 83 98 84 99 85 100 86 101 87 102 88 103 89 104 90 105 76 91</indices>
+	<indices cmd="tri-strip" type="ushort" >91 106 92 107 93 108 94 109 95 110 96 111 97 112 98 113 99 114 100 115 101 116 102 117 103 118 104 119 105 120 91 106</indices>
+</mesh>

Tut 16 Gamma and Textures/data/litTexture.frag

+#version 330
+
+in vec2 colorCoord;
+in vec3 cameraSpacePosition;
+in vec3 cameraSpaceNormal;
+
+out vec4 outputColor;
+
+layout(std140) uniform;
+
+struct PerLight
+{
+	vec4 cameraSpaceLightPos;
+	vec4 lightIntensity;
+};
+
+const int numberOfLights = 1;
+
+uniform Light
+{
+	vec4 ambientIntensity;
+	float lightAttenuation;
+	float maxIntensity;
+	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));
+}
+
+vec4 ComputeLighting(in vec4 diffuseColor, in PerLight lightData)
+{
+	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;
+	
+	vec4 lighting = diffuseColor * lightIntensity * cosAngIncidence;
+	
+	return lighting;
+}
+
+uniform sampler2D diffuseColorTex;
+
+void main()
+{
+	vec4 diffuseColor = texture(diffuseColorTex, colorCoord);
+	
+	/*
+	vec4 accumLighting = diffuseColor * Lgt.ambientIntensity;
+	for(int light = 0; light < numberOfLights; light++)
+	{
+		accumLighting += ComputeLighting(diffuseColor, Lgt.lights[light]);
+	}
+	
+	accumLighting = accumLighting / Lgt.maxIntensity;
+	*/
+
+	outputColor = diffuseColor;
+}

Tut 16 Gamma and Textures/tutorials.lua

 SetupProject("Tut 16 Gamma Checkers", "Gamma Checkers.cpp",
 	"data/PT.vert",
 	"data/textureGamma.frag", "data/textureNoGamma.frag")
+
+SetupProject("Tut 16 Gamma Landscape", "Gamma Landscape.cpp",
+	"data/PNT.vert",
+	"data/litGamma.frag", "data/litNoGamma.frag")

framework/framework.cpp

 #include <vector>
 #include <fstream>
 #include <sstream>
+#include <exception>
+#include <stdexcept>
 #include <string.h>
 #include <glload/gl_3_3.h>
 #include <glload/gll.hpp>
+#include <glutil/Shader.h>
 #include <GL/freeglut.h>
 #include "framework.h"
 #include "directories.h"
 
 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)
-	{
-		GLuint shader = glCreateShader(eShaderType);
-		const char *strFileData = strShaderFile.c_str();
-		glShaderSource(shader, 1, (const GLchar**)&strFileData, NULL);
-
-		glCompileShader(shader);
-
-		GLint status;
-		glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
-		if (status == GL_FALSE)
-		{
-			GLint infoLogLength;
-			glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogLength);
-
-			GLchar *strInfoLog = new GLchar[infoLogLength + 1];
-			glGetShaderInfoLog(shader, infoLogLength, NULL, strInfoLog);
-
-			fprintf(stderr, "Compile failure in %s shader named \"%s\". Error:\n%s\n",
-				GetShaderName(eShaderType), strShaderName.c_str(), strInfoLog);
-			delete[] strInfoLog;
-		}
-
-		return shader;
-	}
-
 	GLuint LoadShader(GLenum eShaderType, const std::string &strShaderFilename)
 	{
-		std::string strFilename = LOCAL_FILE_DIR + strShaderFilename;
+		std::string strFilename = FindFileOrThrow(strShaderFilename);
 		std::ifstream shaderFile(strFilename.c_str());
-		if(!shaderFile.is_open())
-		{
-			shaderFile.clear();
-			strFilename = GLOBAL_FILE_DIR + strShaderFilename;
-			shaderFile.open(strFilename.c_str());
-			if(!shaderFile.is_open())
-			{
-				fprintf(stderr, "Cannot load the shader file \"%s\" for the %s shader.\n",
-					strShaderFilename.c_str(), GetShaderName(eShaderType));
-				return 0;
-			}
-		}
 		std::stringstream shaderData;
 		shaderData << shaderFile.rdbuf();
 		shaderFile.close();
 
-		return CreateShader(eShaderType, shaderData.str(), strShaderFilename);
+		return glutil::CompileShader(eShaderType, shaderData.str());
 	}
 
 	GLuint CreateProgram(const std::vector<GLuint> &shaderList)
 	{
-		GLuint program = glCreateProgram();
-
-		for(size_t iLoop = 0; iLoop < shaderList.size(); iLoop++)
-			glAttachShader(program, shaderList[iLoop]);
-
-		glLinkProgram(program);
-
-		GLint status;
-		glGetProgramiv (program, GL_LINK_STATUS, &status);
-		if (status == GL_FALSE)
-		{
-			GLint infoLogLength;
-			glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLogLength);
-
-			GLchar *strInfoLog = new GLchar[infoLogLength + 1];
-			glGetProgramInfoLog(program, infoLogLength, NULL, strInfoLog);
-			fprintf(stderr, "Linker failure: %s\n", strInfoLog);
-			delete[] strInfoLog;
-		}
-
-		return program;
+		return glutil::LinkProgram(shaderList);
 	}
 
 	float DegToRad(float fAngDeg)
 		return fAngDeg * fDegToRad;
 	}
 
+	std::string FindFileOrThrow( const std::string &strBasename )
+	{
+		std::string strFilename = LOCAL_FILE_DIR + strBasename;
+		std::ifstream testFile(strFilename.c_str());
+		if(testFile.is_open())
+			return strFilename;
+
+		
+		strFilename = GLOBAL_FILE_DIR + strBasename;
+		testFile.open(strFilename.c_str());
+		if(testFile.is_open())
+			return strFilename;
+
+		throw std::runtime_error("Could not find the file " + strBasename);
+	}
 }
 
 

framework/framework.h

 	GLuint LoadShader(GLenum eShaderType, const std::string &strShaderFilename);
 	GLuint CreateProgram(const std::vector<GLuint> &shaderList);
 
+	//Will find a file with the given base filename, either in the local directory or the global one.
+	//If it doesn't, it will throw a std::runtime_error.
+	std::string FindFileOrThrow(const std::string &strBasename);
+
 
 }
 

framework/framework.lua

 dofile("../glsdk/links.lua")
 
 local myPath = os.getcwd();
+local usedLibs = {"glload", "glimage", "glm", "glutil", "glmesh", "freeglut"}
 
 function SetupSolution(slnName)
 	solution(slnName)
 
 		includedirs {"../tinyxml", "../framework"}
 		
-		UseLibs {"glload", "glimage", "glm", "freeglut"}
+		UseLibs(usedLibs)
 		
 		configuration "Debug"
 			defines {"DEBUG", "_DEBUG"}
 		
 		files {...}
 
-		UseLibs {"glload", "glimage", "glm", "freeglut"}
+		UseLibs(usedLibs)
 
 		includedirs {"../tinyxml", "../framework"}
 			
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.