Jason McKesson avatar Jason McKesson committed 7f296c7

Projective texture works.

Comments (0)

Files changed (13)

Tut 17 Spotlight on Textures/Double Projection.cpp

 
 GLuint g_projectionUniformBuffer = 0;
 GLuint g_lightUniformBuffer = 0;
-GLuint g_stoneTex;
-
-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("seamless_rock1_small.dds"));
-
-		std::auto_ptr<glimg::ImageSet> pImageSet(glimg::loaders::dds::LoadFromFile(filename.c_str()));
-		g_stoneTex = glimg::CreateTexture(pImageSet.get(), 0);
-	}
-	catch(std::exception &e)
-	{
-		printf("%s\n", e.what());
-		throw;
-	}
-}
 
 ////////////////////////////////
 //View setup.
 std::vector<Framework::NodeRef> g_nodes;
 Framework::Timer g_timer(Framework::Timer::TT_LOOP, 10.0f);
 
-Framework::UniformVec4Binder g_blueBinder;
-Framework::UniformVec4Binder g_redBinder;
 Framework::UniformIntBinder g_lightNumBinder;
 Framework::TextureBinder g_stoneTexBinder;
 
 
 void LoadAndSetupScene()
 {
-	g_nodes.clear();
-
 	std::auto_ptr<Framework::Scene> pScene(new Framework::Scene("dp_scene.xml"));
 
 	std::vector<Framework::NodeRef> nodes;
 	nodes.push_back(pScene->FindNode("rightBar"));
 	nodes.push_back(pScene->FindNode("leaningBar"));
 	nodes.push_back(pScene->FindNode("spinBar"));
-//	nodes.push_back(pScene->FindNode("diorama"));
-//	nodes.push_back(pScene->FindNode("floor"));
 
 	AssociateUniformWithNodes(nodes, g_lightNumBinder, "numberOfLights");
 	SetStateBinderWithNodes(nodes, g_lightNumBinder);
 	//Setup our Uniform Buffers
 	glGenBuffers(1, &g_projectionUniformBuffer);
 	glBindBuffer(GL_UNIFORM_BUFFER, g_projectionUniformBuffer);
-	glBufferData(GL_UNIFORM_BUFFER, sizeof(ProjectionBlock), NULL, GL_DYNAMIC_DRAW);
+	glBufferData(GL_UNIFORM_BUFFER, sizeof(ProjectionBlock), NULL, GL_STREAM_DRAW);
 
 	glBindBufferRange(GL_UNIFORM_BUFFER, g_projectionBlockIndex, g_projectionUniformBuffer,
 		0, sizeof(ProjectionBlock));
 
-	CreateSamplers();
-//	LoadTextures();
-
 	try
 	{
 		LoadAndSetupScene();
 		projData.cameraToClipMatrix = persMatrix.Top();
 
 		glBindBuffer(GL_UNIFORM_BUFFER, g_projectionUniformBuffer);
-		glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(ProjectionBlock), &projData);
+		glBufferData(GL_UNIFORM_BUFFER, sizeof(ProjectionBlock), &projData, GL_STREAM_DRAW);
 		glBindBuffer(GL_UNIFORM_BUFFER, 0);
 	}
 
 		glutil::PushStack stackPush(modelMatrix);
 		//Draw lookat point.
 		modelMatrix.SetIdentity();
+		modelMatrix.Translate(glm::vec3(0.0f, 0.0f, -g_viewPole.GetView().radius));
 		modelMatrix.Scale(0.5f);
-		modelMatrix.Translate(glm::vec3(0.0f, 0.0f, -g_viewPole.GetView().radius));
 
 		glDisable(GL_DEPTH_TEST);
 		glDepthMask(GL_FALSE);
 		projData.cameraToClipMatrix = persMatrix.Top();
 
 		glBindBuffer(GL_UNIFORM_BUFFER, g_projectionUniformBuffer);
-		glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(ProjectionBlock), &projData);
+		glBufferData(GL_UNIFORM_BUFFER, sizeof(ProjectionBlock), &projData, GL_STREAM_DRAW);
 		glBindBuffer(GL_UNIFORM_BUFFER, 0);
 	}
 

Tut 17 Spotlight on Textures/Projected Light.cpp

+#include <string>
+#include <vector>
+#include <exception>
+#include <memory>
+#include <stdio.h>
+#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 "../framework/framework.h"
+#include "../framework/Mesh.h"
+#include "../framework/Timer.h"
+#include "../framework/UniformBlockArray.h"
+#include "../framework/directories.h"
+#include "../framework/MousePole.h"
+#include "../framework/Interpolators.h"
+#include "../framework/Scene.h"
+#include "../framework/SceneBinders.h"
+#include <glm/glm.hpp>
+#include <glm/gtc/type_ptr.hpp>
+#include <glm/gtc/quaternion.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*))))
+
+const float g_fzNear = 1.0f;
+const float g_fzFar = 1000.0f;
+
+const int g_projectionBlockIndex = 0;
+const int g_lightBlockIndex = 1;
+const int g_lightProjTexUnit = 3;
+
+struct ProjectionBlock
+{
+	glm::mat4 cameraToClipMatrix;
+};
+
+GLuint g_projectionUniformBuffer = 0;
+GLuint g_lightUniformBuffer = 0;
+GLuint g_lightProjTex;
+
+const int NUM_SAMPLERS = 1;
+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_CLAMP_TO_BORDER);
+		glSamplerParameteri(g_samplers[samplerIx], GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
+	}
+
+	glSamplerParameteri(g_samplers[0], GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+	glSamplerParameteri(g_samplers[0], GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+
+	float color[4] = {0.0f, 0.0f, 0.0f, 1.0f};
+	glSamplerParameterfv(g_samplers[0], GL_TEXTURE_BORDER_COLOR, color);
+}
+
+void LoadTextures()
+{
+	try
+	{
+		std::string filename(Framework::FindFileOrThrow("testLightImg.dds"));
+
+		std::auto_ptr<glimg::ImageSet> pImageSet(glimg::loaders::dds::LoadFromFile(filename.c_str()));
+		g_lightProjTex = glimg::CreateTexture(pImageSet.get(), 0);
+	}
+	catch(std::exception &e)
+	{
+		printf("%s\n", e.what());
+		throw;
+	}
+}
+
+////////////////////////////////
+//View setup.
+glutil::ViewData g_initialView =
+{
+	glm::vec3(0.0f, 0.0f, 10.0f),
+ 	glm::fquat(0.909845f, 0.16043f, -0.376867f, -0.0664516f),
+	25.0f,
+	0.0f
+};
+
+glutil::ViewScale g_initialViewScale =
+{
+	5.0f, 70.0f,
+	2.0f, 0.5f,
+	2.0f, 0.5f,
+	90.0f/250.0f
+};
+
+
+glutil::ViewData g_initLightView =
+{
+	glm::vec3(0.0f, 0.0f, 20.0f),
+	glm::fquat(1.0f, 0.0f, 0.0f, 0.0f),
+	5.0f,
+	0.0f
+};
+
+glutil::ViewScale g_initLightViewScale =
+{
+	0.05f, 10.0f,
+	0.1f, 0.05f,
+	4.0f, 1.0f,
+	90.0f/250.0f
+};
+
+glutil::ViewPole g_viewPole(g_initialView, g_initialViewScale, glutil::MB_LEFT_BTN);
+glutil::ViewPole g_lightViewPole(g_initLightView, g_initLightViewScale, glutil::MB_RIGHT_BTN);
+
+namespace
+{
+	void MouseMotion(int x, int y)
+	{
+		Framework::ForwardMouseMotion(g_viewPole, x, y);
+		Framework::ForwardMouseMotion(g_lightViewPole, x, y);
+	}
+
+	void MouseButton(int button, int state, int x, int y)
+	{
+		Framework::ForwardMouseButton(g_viewPole, button, state, x, y);
+		Framework::ForwardMouseButton(g_lightViewPole, button, state, x, y);
+	}
+
+	void MouseWheel(int wheel, int direction, int x, int y)
+	{
+		Framework::ForwardMouseWheel(g_viewPole, wheel, direction, x, y);
+	}
+}
+
+Framework::Scene *g_pScene = NULL;
+std::vector<Framework::NodeRef> g_nodes;
+Framework::Timer g_timer(Framework::Timer::TT_LOOP, 10.0f);
+
+Framework::UniformIntBinder g_lightNumBinder;
+Framework::TextureBinder g_stoneTexBinder;
+Framework::UniformMat4Binder g_lightProjMatBinder;
+Framework::UniformVec3Binder g_camLightPosBinder;
+
+glm::fquat g_spinBarOrient;
+
+GLint g_unlitModelToCameraMatrixUnif;
+GLint g_unlitObjectColorUnif;
+GLuint g_unlitProg;
+Framework::Mesh *g_pSphereMesh = NULL;
+
+GLint g_coloredModelToCameraMatrixUnif;
+GLuint g_colroedProg;
+Framework::Mesh *g_pAxesMesh = NULL;
+
+void LoadAndSetupScene()
+{
+	std::auto_ptr<Framework::Scene> pScene(new Framework::Scene("proj2d_scene.xml"));
+
+	std::vector<Framework::NodeRef> nodes;
+	nodes.push_back(pScene->FindNode("cube"));
+	nodes.push_back(pScene->FindNode("rightBar"));
+	nodes.push_back(pScene->FindNode("leaningBar"));
+	nodes.push_back(pScene->FindNode("spinBar"));
+	nodes.push_back(pScene->FindNode("diorama"));
+	nodes.push_back(pScene->FindNode("floor"));
+
+	AssociateUniformWithNodes(nodes, g_lightNumBinder, "numberOfLights");
+	SetStateBinderWithNodes(nodes, g_lightNumBinder);
+	AssociateUniformWithNodes(nodes, g_lightProjMatBinder, "cameraToLightProjMatrix");
+	SetStateBinderWithNodes(nodes, g_lightProjMatBinder);
+	AssociateUniformWithNodes(nodes, g_camLightPosBinder, "cameraSpaceProjLightPos");
+	SetStateBinderWithNodes(nodes, g_camLightPosBinder);
+	
+	GLuint unlit = pScene->FindProgram("p_unlit");
+	Framework::Mesh *pSphereMesh = pScene->FindMesh("m_sphere");
+
+	GLuint colored = pScene->FindProgram("p_colored");
+	Framework::Mesh *pAxesMesh = pScene->FindMesh("m_axes");
+
+	//No more things that can throw.
+	g_spinBarOrient = nodes[3].NodeGetOrient();
+	g_unlitProg = unlit;
+	g_unlitModelToCameraMatrixUnif = glGetUniformLocation(unlit, "modelToCameraMatrix");
+	g_unlitObjectColorUnif = glGetUniformLocation(unlit, "objectColor");
+
+	g_colroedProg = colored;
+	g_coloredModelToCameraMatrixUnif = glGetUniformLocation(colored, "modelToCameraMatrix");
+
+	std::swap(nodes, g_nodes);
+	nodes.clear();	//If something was there already, delete it.
+
+	std::swap(pSphereMesh, g_pSphereMesh);
+	std::swap(pAxesMesh, g_pAxesMesh);
+
+	Framework::Scene *pOldScene = g_pScene;
+	g_pScene = pScene.release();
+	pScene.reset(pOldScene);	//If something was there already, delete it.
+}
+
+struct PerLight
+{
+	glm::vec4 cameraSpaceLightPos;
+	glm::vec4 lightIntensity;
+};
+
+const int MAX_NUMBER_OF_LIGHTS = 4;
+
+struct LightBlock
+{
+	glm::vec4 ambientIntensity;
+	float lightAttenuation;
+	float maxIntensity;
+	float padding[2];
+	PerLight lights[MAX_NUMBER_OF_LIGHTS];
+};
+
+
+//Called after the window and OpenGL are initialized. Called exactly once, before the main loop.
+void init()
+{
+	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);
+	glEnable(GL_FRAMEBUFFER_SRGB);
+
+	//Setup our Uniform Buffers
+	glGenBuffers(1, &g_projectionUniformBuffer);
+	glBindBuffer(GL_UNIFORM_BUFFER, g_projectionUniformBuffer);
+	glBufferData(GL_UNIFORM_BUFFER, sizeof(ProjectionBlock), NULL, GL_STREAM_DRAW);
+
+	glBindBufferRange(GL_UNIFORM_BUFFER, g_projectionBlockIndex, g_projectionUniformBuffer,
+		0, sizeof(ProjectionBlock));
+
+	CreateSamplers();
+	LoadTextures();
+
+	try
+	{
+		LoadAndSetupScene();
+	}
+	catch(std::exception &except)
+	{
+		printf("%s\n", except.what());
+		throw;
+	}
+
+	glGenBuffers(1, &g_lightUniformBuffer);
+	glBindBuffer(GL_UNIFORM_BUFFER, g_lightUniformBuffer);
+	glBufferData(GL_UNIFORM_BUFFER, sizeof(LightBlock), NULL, GL_STREAM_DRAW);
+
+	glBindBufferRange(GL_UNIFORM_BUFFER, g_lightBlockIndex, g_lightUniformBuffer,
+		0, sizeof(LightBlock));
+
+	glBindBuffer(GL_UNIFORM_BUFFER, 0);
+}
+
+using Framework::Timer;
+
+int g_currSampler = 0;
+
+bool g_bDrawCameraPos = false;
+bool g_bDepthClampProj = true;
+
+int g_displayWidth = 500;
+int g_displayHeight = 500;
+
+void BuildLights( const glm::mat4 &camMatrix )
+{
+	LightBlock lightData;
+	lightData.ambientIntensity = glm::vec4(0.2f, 0.2f, 0.2f, 1.0f);
+	lightData.lightAttenuation = 1.0f / (20.0f * 20.0f);
+	lightData.maxIntensity = 3.0f;
+	lightData.lights[0].lightIntensity = glm::vec4(2.0f, 2.0f, 2.5f, 1.0f);
+	lightData.lights[0].cameraSpaceLightPos = camMatrix *
+		glm::normalize(glm::vec4(-0.2f, 0.5f, 0.5f, 0.0f));
+	lightData.lights[1].lightIntensity = glm::vec4(3.5f, 6.5f, 3.0f, 1.0f) * 1.5f;
+	lightData.lights[1].cameraSpaceLightPos = camMatrix *
+		glm::vec4(5.0f, 6.0f, 0.5f, 1.0f);
+
+	g_lightNumBinder.SetValue(2);
+
+	glBindBuffer(GL_UNIFORM_BUFFER, g_lightUniformBuffer);
+	glBufferData(GL_UNIFORM_BUFFER, sizeof(LightBlock), &lightData, GL_STREAM_DRAW);
+}
+
+//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()
+{
+	if(!g_pScene)
+		return;
+
+	g_timer.Update();
+
+	glClearColor(0.8f, 0.8f, 0.8f, 1.0f);
+	glClearDepth(1.0f);
+	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+	const glm::mat4 &cameraMatrix = g_viewPole.CalcMatrix();
+	const glm::mat4 &lightView = g_lightViewPole.CalcMatrix();
+
+	glutil::MatrixStack modelMatrix;
+	modelMatrix *= cameraMatrix;
+
+	BuildLights(cameraMatrix);
+
+	g_nodes[0].NodeSetOrient(glm::rotate(glm::fquat(),
+		360.0f * g_timer.GetAlpha(), glm::vec3(0.0f, 1.0f, 0.0f)));
+
+	g_nodes[3].NodeSetOrient(g_spinBarOrient * glm::rotate(glm::fquat(),
+		360.0f * g_timer.GetAlpha(), glm::vec3(0.0f, 0.0f, 1.0f)));
+
+	{
+		glutil::MatrixStack persMatrix;
+		persMatrix.Perspective(60.0f, (g_displayWidth / (float)g_displayHeight), g_fzNear, g_fzFar);
+
+		ProjectionBlock projData;
+		projData.cameraToClipMatrix = persMatrix.Top();
+
+		glBindBuffer(GL_UNIFORM_BUFFER, g_projectionUniformBuffer);
+		glBufferData(GL_UNIFORM_BUFFER, sizeof(ProjectionBlock), &projData, GL_STREAM_DRAW);
+		glBindBuffer(GL_UNIFORM_BUFFER, 0);
+	}
+
+	glActiveTexture(GL_TEXTURE0 + g_lightProjTexUnit);
+	glBindTexture(GL_TEXTURE_2D, g_lightProjTex);
+	glBindSampler(g_lightProjTexUnit, g_samplers[0]);
+
+	{
+		glutil::MatrixStack lightProjStack;
+		//Texture-space transform
+		lightProjStack.Translate(0.5f, 0.5f, 0.0f);
+		lightProjStack.Scale(0.5f);
+		//Project. Z-range is irrelevant.
+		lightProjStack.Perspective(45.0f, 1.0f, 1.0f, 100.0f);
+		//Transform from main camera space to light camera space.
+		lightProjStack.ApplyMatrix(lightView);
+		lightProjStack.ApplyMatrix(glm::inverse(cameraMatrix));
+
+		g_lightProjMatBinder.SetValue(lightProjStack.Top());
+
+		glm::vec4 worldLightPos = glm::inverse(lightView)[3];
+		glm::vec3 lightPos = glm::vec3(cameraMatrix * worldLightPos);
+
+		g_camLightPosBinder.SetValue(lightPos);
+	}
+
+	glViewport(0, 0, (GLsizei)g_displayWidth, (GLsizei)g_displayHeight);
+	g_pScene->Render(modelMatrix.Top());
+
+	{
+		//Draw axes
+		glutil::PushStack stackPush(modelMatrix);
+		modelMatrix.ApplyMatrix(glm::inverse(lightView));
+		modelMatrix.Scale(15.0f);
+		modelMatrix.Scale(1.0f, 1.0f, -1.0f); //Invert the Z-axis so that it points in the right direction.
+
+		glUseProgram(g_colroedProg);
+		glUniformMatrix4fv(g_coloredModelToCameraMatrixUnif, 1, GL_FALSE,
+			glm::value_ptr(modelMatrix.Top()));
+		g_pAxesMesh->Render();
+	}
+
+	if(g_bDrawCameraPos)
+	{
+		//Draw lookat point.
+		glutil::PushStack stackPush(modelMatrix);
+		modelMatrix.SetIdentity();
+		modelMatrix.Translate(glm::vec3(0.0f, 0.0f, -g_viewPole.GetView().radius));
+		modelMatrix.Scale(0.5f);
+
+		glDisable(GL_DEPTH_TEST);
+		glDepthMask(GL_FALSE);
+		glUseProgram(g_unlitProg);
+		glUniformMatrix4fv(g_unlitModelToCameraMatrixUnif, 1, GL_FALSE,
+			glm::value_ptr(modelMatrix.Top()));
+		glUniform4f(g_unlitObjectColorUnif, 0.25f, 0.25f, 0.25f, 1.0f);
+		g_pSphereMesh->Render("flat");
+		glDepthMask(GL_TRUE);
+		glEnable(GL_DEPTH_TEST);
+		glUniform4f(g_unlitObjectColorUnif, 1.0f, 1.0f, 1.0f, 1.0f);
+		g_pSphereMesh->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)
+{
+	g_displayWidth = w;
+	g_displayHeight = 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_pScene;
+		g_pScene = NULL;
+		glutLeaveMainLoop();
+		return;
+	case 32:
+		g_lightViewPole.Reset();
+		break;
+	case 't':
+		g_bDrawCameraPos = !g_bDrawCameraPos;
+		break;
+	case 'y':
+		g_bDepthClampProj = !g_bDepthClampProj;
+		break;
+	case 'p':
+		g_timer.TogglePause();
+		break;
+	case '\r': //Enter key.
+		{
+			try
+			{
+				LoadAndSetupScene();
+			}
+			catch(std::exception &except)
+			{
+				printf("Failed to reload, due to: %s\n", except.what());
+				return;
+			}
+		}
+		break;
+	}
+
+	g_viewPole.CharPress(key);
+}
+
+unsigned int defaults(unsigned int displayMode, int &width, int &height)
+{
+	g_displayWidth = width;
+	g_displayHeight = height;
+	return displayMode | GLUT_SRGB;
+}
+

Tut 17 Spotlight on Textures/data/litTexture.frag

 {
 	vec4 diffuseColor = texture(diffuseColorTex, colorCoord);
 
-	PerLight currLight;
-	currLight.cameraSpaceLightPos = normalize(vec4(0.0, 0.5, 0.5, 0.0));
-	currLight.lightIntensity = vec4(2.0, 2.0, 2.5, 1.0);
-	
 	vec4 accumLighting = diffuseColor * Lgt.ambientIntensity;
 	for(int light = 0; light < numberOfLights; light++)
 	{

Tut 17 Spotlight on Textures/data/proj2d_scene.xml

+<?xml version="1.0" encoding="UTF-8"?>
+<?oxygen RNGSchema="../../Documents/sceneFormat.rnc" type="compact"?>
+<scene xmlns="http://www.arcsynthesis.com/gltut/scene">
+    <mesh xml:id="m_sphere" file="UnitSphere.xml"/>
+    <mesh xml:id="m_cube" file="UnitCube.xml"/>
+	<mesh xml:id="m_shortBar" file="ShortBar.xml"/>
+	<mesh xml:id="m_longBar" file="LongBar.xml"/>
+	<mesh xml:id="m_diorama" file="UnitDiorama.xml"/>
+	<mesh xml:id="m_floor" file="UnitPlane.xml"/>
+    <mesh xml:id="m_axes" file="UnitAxes.xml"/>
+    <texture xml:id="t_stone" file="seamless_rock1_small.dds" srgb="true"/>
+    <texture xml:id="t_concrete_wall" file="concrete649_small.dds" srgb="true"/>
+    <texture xml:id="t_sandy_ground" file="dsc_1621_small.dds" srgb="true"/>
+    <texture xml:id="t_stone_pillar" file="rough645_small.dds" srgb="true"/>
+    <texture xml:id="t_wood_pillar" file="wood4_rotate.dds" srgb="true"/>
+    <prog
+        xml:id="p_unlit"
+        vert="Unlit.vert"
+        frag="Unlit.frag"
+        model-to-camera="modelToCameraMatrix">
+        <block name="Projection" binding="0"/>
+    </prog>
+    <prog
+        xml:id="p_colored"
+        vert="Colored.vert"
+        frag="Colored.frag"
+        model-to-camera="modelToCameraMatrix">
+        <block name="Projection" binding="0"/>
+    </prog>
+    <prog
+        xml:id="p_proj"
+        vert="projLight.vert"
+        frag="projLight.frag"
+        model-to-camera="modelToCameraMatrix"
+        normal-model-to-camera="normalModelToCameraMatrix">
+        <block name="Projection" binding="0"/>
+		<block name="Light" binding="1"/>
+        <sampler name="diffuseColorTex" unit="0"/>
+        <sampler name="lightProjTex" unit="3"/>
+    </prog>
+    <node
+        name="cube"
+        mesh="m_cube"
+        prog="p_proj"
+        pos="0 1 0"
+        orient="0.0 0.0 0.0 1.0"
+        scale="3">
+        <texture name="t_stone" unit="0" sampler="anisotropic"/>
+    </node>
+    <node
+        name="rightBar"
+        mesh="m_shortBar"
+        prog="p_proj"
+        pos="13 -2 0"
+        orient="0.0 0.0 0.0 1.0"
+        scale="3">
+        <texture name="t_stone" unit="0" sampler="anisotropic"/>
+    </node>
+    <node
+        name="leaningBar"
+        mesh="m_longBar"
+        prog="p_proj"
+        pos="3 -7 -10"
+        orient="0.64278 0 0 0.76604"
+        scale="5">
+        <texture name="t_wood_pillar" unit="0" sampler="anisotropic"/>
+    </node>
+    <node
+        name="spinBar"
+        mesh="m_longBar"
+        prog="p_proj"
+        pos="-7 0 8"
+        orient="-0.148446 0.554035 0.212003 0.791242"
+        scale="4">
+        <texture name="t_stone_pillar" unit="0" sampler="anisotropic"/>
+    </node>
+	<node
+		name="diorama"
+        mesh="m_diorama"
+        prog="p_proj"
+        pos="0 -10 0"
+        scale="47">
+        <texture name="t_concrete_wall" unit="0" sampler="anisotropic"/>
+	</node>
+	<node
+		name="floor"
+        mesh="m_floor"
+        prog="p_proj"
+        pos="0 -33.5 0"
+        scale="47">
+        <texture name="t_sandy_ground" unit="0" sampler="anisotropic"/>
+	</node>
+</scene>

Tut 17 Spotlight on Textures/data/projLight.frag

+#version 330
+
+in vec2 colorCoord;
+in vec3 cameraSpacePosition;
+in vec3 cameraSpaceNormal;
+in vec4 lightProjPosition;
+
+out vec4 outputColor;
+
+layout(std140) uniform;
+
+struct PerLight
+{
+	vec4 cameraSpaceLightPos;
+	vec4 lightIntensity;
+};
+
+uniform Light
+{
+	vec4 ambientIntensity;
+	float lightAttenuation;
+	float maxIntensity;
+	PerLight lights[4];
+} Lgt;
+
+uniform int numberOfLights;
+
+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;
+uniform sampler2D lightProjTex;
+
+uniform vec3 cameraSpaceProjLightPos;
+
+void main()
+{
+	vec4 diffuseColor = texture(diffuseColorTex, colorCoord);
+
+	PerLight currLight;
+	currLight.cameraSpaceLightPos = vec4(cameraSpaceProjLightPos, 1.0);
+	currLight.lightIntensity =
+		textureProj(lightProjTex, lightProjPosition.xyw) * 2.0;
+		
+	currLight.lightIntensity = lightProjPosition.z > 0 ?
+		currLight.lightIntensity : vec4(0.0);
+	
+	vec4 accumLighting = diffuseColor * Lgt.ambientIntensity;
+	for(int light = 0; light < numberOfLights; light++)
+	{
+		accumLighting += ComputeLighting(diffuseColor, Lgt.lights[light]);
+	}
+
+	
+	accumLighting += ComputeLighting(diffuseColor, currLight);
+
+	outputColor = accumLighting / Lgt.maxIntensity;
+	
+//	outputColor = diffuseColor;
+}

Tut 17 Spotlight on Textures/data/projLight.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;
+out vec4 lightProjPosition;
+
+uniform Projection
+{
+	mat4 cameraToClipMatrix;
+};
+
+uniform mat4 modelToCameraMatrix;
+uniform mat3 normalModelToCameraMatrix;
+uniform mat4 cameraToLightProjMatrix;
+
+void main()
+{
+	cameraSpacePosition = (modelToCameraMatrix * vec4(position, 1.0)).xyz;
+	gl_Position = cameraToClipMatrix * vec4(cameraSpacePosition, 1.0);
+	cameraSpaceNormal = normalize(normalModelToCameraMatrix * normal);
+	lightProjPosition = cameraToLightProjMatrix * vec4(cameraSpacePosition, 1.0);
+
+	colorCoord = texCoord;
+}

Tut 17 Spotlight on Textures/tutorials.lua

 
-SetupProject("Tut 17 Double Projection", "Double Projection.cpp"
-	)
+SetupProject("Tut 17 Double Projection", "Double Projection.cpp",
+    "data/litTexture.vert", "data/litTexture.frag")
 
+SetupProject("Tut 17 Projected Light", "Projected Light.cpp",
+    "data/projLight.vert", "data/projLight.frag",
+	"data/litTexture.vert", "data/litTexture.frag")
+

data/Colored.frag

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

data/Colored.vert

+#version 330
+
+layout(std140) uniform;
+
+layout(location = 0) in vec3 position;
+layout(location = 1) in vec4 color;
+
+smooth out vec4 objectColor;
+
+uniform Projection
+{
+	mat4 cameraToClipMatrix;
+};
+
+uniform mat4 modelToCameraMatrix;
+
+void main()
+{
+	gl_Position = cameraToClipMatrix * (modelToCameraMatrix * vec4(position, 1.0));
+	objectColor = color;
+}
+require "XmlWriter"
+require "vmath"
+
+local function GenStringFromArray(theArray, bAsInt)
+	local array = {" "}
+	for i, vector in ipairs(theArray) do
+		local elements = vector;
+		if(bAsInt) then
+			elements = {};
+			for i, value in ipairs(vector) do
+				elements[#elements + 1] = string.format("%i", value);
+			end
+		end
+		
+		array[#array + 1] = "        " .. table.concat(vector, " ");
+	end
+	
+	return table.concat(array, "\n");
+end
+
+local positions =
+{
+	vmath.vec3(0.0, 0.0, 0.0),
+	vmath.vec3(0.5, 0.0, 0.0),
+
+	vmath.vec3(0.0, 0.0, 0.0),
+	vmath.vec3(0.0, 0.5, 0.0),
+
+	vmath.vec3(0.0, 0.0, 0.0),
+	vmath.vec3(0.0, 0.0, 0.5),
+};
+
+local colors = 
+{
+	vmath.vec4(1.0, 0.0, 0.0, 1.0),
+	vmath.vec4(1.0, 0.0, 0.0, 1.0),
+	
+	vmath.vec4(0.0, 1.0, 0.0, 1.0),
+	vmath.vec4(0.0, 1.0, 0.0, 1.0),
+	
+	vmath.vec4(0.0, 0.0, 1.0, 1.0),
+	vmath.vec4(0.0, 0.0, 1.0, 1.0),
+};
+
+do
+	local writer = XmlWriter.XmlWriter("UnitAxes.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("arrays");
+			writer:AddAttribute("cmd", "lines");
+			writer:AddAttribute("start", "0");
+			writer:AddAttribute("count", "6");
+		writer:PopElement();
+	writer:PopElement();
+	writer:Close();
+end
+

data/UnitAxes.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 0
+        0.5 0 0
+        0 0 0
+        0 0.5 0
+        0 0 0
+        0 0 0.5</attribute>
+	<attribute index="1" type="float" size="4" > 
+        1 0 0 1
+        1 0 0 1
+        0 1 0 1
+        0 1 0 1
+        0 0 1 1
+        0 0 1 1</attribute>
+	<arrays cmd="lines" start="0" count="6" />
+</mesh>

framework/Scene.cpp

 
 					GLuint blockIx = glGetUniformBlockIndex(program, name.c_str());
 					if(blockIx == GL_INVALID_INDEX)
-						throw std::runtime_error("The uniform block " + name + " could not be found.");
+					{
+						std::cout << "Warning: the uniform block " << name << " could not be found." << std::endl;
+						continue;
+					}
 
 					int bindPoint = rapidxml::attrib_to_int(*pBindingNode, ThrowAttrib);
 					glUniformBlockBinding(program, blockIx, bindPoint);
 
 					GLint samplerLoc = glGetUniformLocation(program, name.c_str());
 					if(samplerLoc == -1)
-						throw std::runtime_error("The sampler " + name + " could not be found.");
+					{
+						std::cout << "Warning: the sampler " << name << " could not be found." << std::endl;
+						continue;
+					}
 
 					GLint textureUnit = rapidxml::attrib_to_int(*pTexunitNode, ThrowAttrib);
 					glUseProgram(program);

framework/SceneBinders.h

 		int m_val;
 	};
 
+	class UniformMat4Binder : public UniformBinderBase
+	{
+	public:
+		UniformMat4Binder()
+			: m_val(1.0f)	{}
+
+		void SetValue(const glm::mat4 &val)	{ m_val = val; }
+
+		virtual void BindState(GLuint prog) const
+		{
+			glUniformMatrix4fv(GetUniformLoc(prog), 1, GL_FALSE, glm::value_ptr(m_val));
+		}
+
+		virtual void UnbindState(GLuint prog) const {}
+
+	private:
+		glm::mat4 m_val;
+	};
+
 	class TextureBinder : public StateBinder
 	{
 	public:
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.