Index: Source/Plugins/Plugin_VideoOGL/Src/GLUtil.h
===================================================================
--- Source/Plugins/Plugin_VideoOGL/Src/GLUtil.h	(revision 6929)
+++ Source/Plugins/Plugin_VideoOGL/Src/GLUtil.h	(working copy)
@@ -123,6 +123,10 @@
 extern CGprofile g_cgvProf, g_cgfProf;
 #endif
 
+// Uncomment to use GLSL instead of CG
+// Experimental, doesn't work, and still requires CG for fragment shader
+#define USE_GLSL
+
 // XXX: Dual-source blending in OpenGL does not work correctly yet. To make it
 // work, we may need to use glBindFragDataLocation. To use that, we need to
 // use GLSL shaders across the whole pipeline. Yikes!
Index: Source/Plugins/Plugin_VideoOGL/Src/main.cpp
===================================================================
--- Source/Plugins/Plugin_VideoOGL/Src/main.cpp	(revision 6929)
+++ Source/Plugins/Plugin_VideoOGL/Src/main.cpp	(working copy)
@@ -95,6 +95,12 @@
 
 #include "VideoState.h"
 
+#ifdef USE_GLSL
+	#define PLUGIN_NAME "Dolphin OpenGL GLSL"
+#else
+	#define PLUGIN_NAME "Dolphin OpenGL"
+#endif
+
 // Logging
 int GLScissorX, GLScissorY, GLScissorW, GLScissorH;
 
@@ -173,12 +179,13 @@
 {
 	_PluginInfo->Version = 0x0100;
 	_PluginInfo->Type = PLUGIN_TYPE_VIDEO;
+
 #ifdef DEBUGFAST
-	sprintf(_PluginInfo->Name, "Dolphin OpenGL (DebugFast)");
+	sprintf(_PluginInfo->Name, PLUGIN_NAME " (DebugFast)");
 #elif defined _DEBUG
-	sprintf(_PluginInfo->Name, "Dolphin OpenGL (Debug)");
+	sprintf(_PluginInfo->Name, PLUGIN_NAME " (Debug)");
 #else
-	sprintf(_PluginInfo->Name, _trans("Dolphin OpenGL"));
+	sprintf(_PluginInfo->Name, _trans(PLUGIN_NAME));
 #endif
 }
 
@@ -281,7 +288,7 @@
 	// Now the window handle is written
 	_pVideoInitialize->pWindowHandle = g_VideoInitialize.pWindowHandle;
 
-	OSD::AddMessage("Dolphin OpenGL Video Plugin.", 5000);
+	OSD::AddMessage(PLUGIN_NAME " Video Plugin.", 5000);
 	s_PluginInitialized = true;
 }
 
Index: Source/Plugins/Plugin_VideoOGL/Src/VertexShaderCache.cpp
===================================================================
--- Source/Plugins/Plugin_VideoOGL/Src/VertexShaderCache.cpp	(revision 6929)
+++ Source/Plugins/Plugin_VideoOGL/Src/VertexShaderCache.cpp	(working copy)
@@ -38,6 +38,7 @@
 VertexShaderCache::VSCache VertexShaderCache::vshaders;
 bool VertexShaderCache::s_displayCompileAlert;
 GLuint VertexShaderCache::CurrentShader;
+GLuint VertexShaderCache::program = 0;
 bool VertexShaderCache::ShaderEnabled;
 
 static VERTEXSHADER *pShaderLast = NULL;
@@ -53,6 +54,27 @@
 	glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, const_number, f);
 }
 
+void SetVSConstant4fvByName(const char * name, const float *f)
+{
+	GLint varLocation = glGetUniformLocation(VertexShaderCache::program, name);
+	if (varLocation > -1)
+		glUniform4fv(varLocation, 1, f);
+}
+
+void SetVSConstant3fvByName(const char * name, const float * f)
+{
+	float buf[4];
+	buf[0] = *f++;
+	buf[1] = *f++;
+	buf[2] = *f++;
+	buf[3] = 0.0f;
+
+	GLint varLocation = glGetUniformLocation(VertexShaderCache::program, name);
+	if (varLocation > -1)
+		glUniform4fv(varLocation, 1, buf);
+}
+
+
 void SetMultiVSConstant4fv(unsigned int const_number, unsigned int count, const float *f)
 {
     if(GLEW_EXT_gpu_program_parameters)
@@ -97,6 +119,8 @@
 
 void VertexShaderCache::Init()
 {
+	program = glCreateProgram();
+	
 	glEnable(GL_VERTEX_PROGRAM_ARB);
 	ShaderEnabled = true;
 	CurrentShader = 0;
@@ -104,7 +128,7 @@
 
 	s_displayCompileAlert = true;
 
-	glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, (GLint *)&s_nMaxVertexInstructions);		
+	glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, (GLint *)&s_nMaxVertexInstructions);
 	if (strstr((const char*)glGetString(GL_VENDOR), "Humper") != NULL) s_nMaxVertexInstructions = 4096;
 #if CG_VERSION_NUM == 2100
 	if (strstr((const char*)glGetString(GL_VENDOR), "ATI") != NULL)
@@ -152,7 +176,18 @@
 	VSCacheEntry& entry = vshaders[uid];
 	entry.frameCount = frameCount;
 	pShaderLast = &entry.shader;
-	const char *code = GenerateVertexShaderCode(components, API_OPENGL);
+	
+	const char * code;
+#ifdef USE_GLSL
+		code = GenerateVertexShaderCode(components, API_OPENGL_GLSL);
+#else
+		code = GenerateVertexShaderCode(components, API_OPENGL);
+#endif
+	
+/*	code = GenerateVertexShaderCode(components, API_OPENGL);
+//	printf("%s\n----------\n", code);
+	code = GenerateVertexShaderCode(components, API_OPENGL_GLSL);
+	printf("%s\n\n", code); */
 
 #if defined(_DEBUG) || defined(DEBUGFAST)
 	if (g_ActiveConfig.iLog & CONF_SAVESHADERS && code) {
@@ -164,7 +199,16 @@
 	}
 #endif
 
-	if (!code || !VertexShaderCache::CompileVertexShader(entry.shader, code)) {
+	bool ret = false;
+	if (code) {
+#ifdef USE_GLSL
+			ret = VertexShaderCache::CompileVertexShaderGLSL(entry.shader, code);
+#else
+			ret = VertexShaderCache::CompileVertexShader(entry.shader, code);
+#endif
+	}
+
+	if (!ret) {
 		ERROR_LOG(VIDEO, "failed to create vertex shader");
 		GFX_DEBUGGER_PAUSE_AT(NEXT_ERROR, true);
 		return NULL;
@@ -173,6 +217,7 @@
 	INCSTAT(stats.numVertexShadersCreated);
 	SETSTAT(stats.numVertexShadersAlive, vshaders.size());
 	GFX_DEBUGGER_PAUSE_AT(NEXT_VERTEX_SHADER_CHANGE, true);
+
 	return pShaderLast;
 }
 
@@ -236,11 +281,140 @@
 	return true;
 }
 
+static GLenum checkForGLError(const char * situation)
+{
+	GLenum error = GL_REPORT_ERROR();
+	if (error != GL_NO_ERROR)
+		fprintf(stderr, "Error: %d -- %s\n", error, situation);
+	return error;
+}
+
+static void printProgramInfoLog(GLuint obj)
+{
+	int infologLength = 0;
+	int charsWritten  = 0;
+	char *infoLog;
+
+	glGetProgramiv(obj, GL_INFO_LOG_LENGTH,&infologLength);
+
+	if (infologLength > 0)
+	{
+		infoLog = (char *)malloc(infologLength);
+		glGetProgramInfoLog(obj, infologLength, &charsWritten, infoLog);
+		fprintf(stderr, "%s", infoLog);
+		free(infoLog);
+	}
+}
+
+bool VertexShaderCache::CompileVertexShaderGLSL(VERTEXSHADER& vs, const char* pstrprogram)
+{
+	// Reset GL error before compiling shaders. Yeah, we need to investigate the causes of these.
+	checkForGLError("before VS!");
+			
+// Create program with options -- cgCreateProgram -- I think this compiles it
+// Make sure program is valid, and destroy it if it is not.
+// Ugly hack on compiled program (maybe not necessary for GLSL)
+// glGenProgramsARB
+// SetCurrentShader -- glBindProgramARB
+// glProgramStringARB
+// CGDestroyProgram and return true
+
+// Usually with CG:
+// cgCreateContext
+// ...
+// cgCreateProgram -- we start here in this function
+// cgGLLoadProgram
+// cgGLBindProgram
+// cgGLEnableProfile -- maybe this is done later
+// ...
+
+// Usually with GLSL:
+// glCreateProgram
+// glCreateShader *
+// glShaderSource
+// glCompileShader
+// glAttachShader
+// glLinkProgram
+// glUseProgram *
+// glDetachShader
+// glDeleteShader
+// glDeleteProgram
+
+// In CG, a program is a shader, in GLSL, a program is a container for shaders
+
+	GLuint shader = glCreateShader(GL_VERTEX_SHADER);
+	checkForGLError("creating vertex shader");
+	glShaderSource(shader, 1, &pstrprogram, NULL);
+	checkForGLError("submitting vertex shader source");
+	glCompileShader(shader);
+	checkForGLError("compiling vertex shader");
+
+	int x;
+	glGetShaderiv(shader, GL_COMPILE_STATUS, &x);
+	fprintf(stderr, "shader compile status: %d\n", x);
+
+	printProgramInfoLog(program);
+
+	fprintf(stderr, "shader: %u -- Current Shader: %u\n", shader, CurrentShader);
+
+	glGetProgramiv(program, GL_ATTACHED_SHADERS, &x);
+	fprintf(stderr, "%d %d %d\n", glIsProgram(program), glIsShader(shader), x);
+
+	if (CurrentShader && x) {
+		glDetachShader(program, CurrentShader);
+	}
+
+	glGetProgramiv(program, GL_ATTACHED_SHADERS, &x);
+	fprintf(stderr, "%d %d %d\n", glIsProgram(program), glIsShader(shader), x);
+	glGetProgramiv(program, GL_LINK_STATUS, &x);
+	fprintf(stderr, "program link status: %d\n", x);
+
+	checkForGLError("before attaching shader");
+	glAttachShader(program, shader);
+	x = checkForGLError("attaching shader");
+
+	glLinkProgram(program);
+	checkForGLError("linking program");
+	glUseProgram(program);
+	checkForGLError("using program");
+
+	printProgramInfoLog(program);
+
+	glGetProgramiv(program, GL_LINK_STATUS, &x);
+	fprintf(stderr, "program link status: %d\n", x);
+
+/*	glDeleteShader(shader); -- make sure it still works OK before enabling this
+	glDeleteProgram(program); */
+
+/*	float f[4] = { 1.0f, 0.5f, 0.0f, 1.0f };
+	SetVSConstant4fvByName("myColor", f); */
+
+#if defined(_DEBUG) || defined(DEBUGFAST)
+	vs.strprog = pstrprogram;
+#endif
+
+	ShaderEnabled = true;
+	CurrentShader = shader;
+	vs.glprogid = shader;
+
+	fprintf(stderr, "\n");
+
+	if (shader)
+		return true;
+	else
+		return false;
+}
+
 void VertexShaderCache::DisableShader()
 {
 	if (ShaderEnabled)
 	{
+#ifdef USE_GLSL
+//		fprintf(stderr, "Detaching CurrentShader\n");
+		glDetachShader(program, CurrentShader);
+#else
 		glDisable(GL_VERTEX_PROGRAM_ARB);
+#endif
 		ShaderEnabled = false;
 	}
 }
@@ -248,6 +422,7 @@
 
 void VertexShaderCache::SetCurrentShader(GLuint Shader)
 {
+#ifndef USE_GLSL
 	if (!ShaderEnabled)
 	{
 		glEnable(GL_VERTEX_PROGRAM_ARB);
@@ -259,4 +434,40 @@
 			CurrentShader = Shader;
 		glBindProgramARB(GL_VERTEX_PROGRAM_ARB, CurrentShader);
 	}
+#else
+	int num_shaders_attached, x;
+	glGetProgramiv(program, GL_ATTACHED_SHADERS, &num_shaders_attached);
+
+	ShaderEnabled = true;
+	if (CurrentShader != Shader) {
+
+		if (Shader) {
+			if (num_shaders_attached)
+				glDetachShader(program, CurrentShader);
+			CurrentShader = Shader;
+		}
+
+		// If Shader is 0 and CurrentShader is already attached, we don't want to
+		// attach it again
+		glGetProgramiv(program, GL_ATTACHED_SHADERS, &num_shaders_attached);
+		if (!num_shaders_attached) {
+			glAttachShader(program, CurrentShader);
+
+/*
+			checkForGLError("attaching shader");
+		
+			glLinkProgram(program);
+			checkForGLError("linking program");
+			glUseProgram(program);
+			checkForGLError("using program");
+		
+			printProgramInfoLog(program);
+		
+			glGetProgramiv(program, GL_LINK_STATUS, &x);
+			fprintf(stderr, "program link status: %d\n", x); */
+		}
+	}
+	// TODO: I think that after I attach the shader I have to link and use it again.
+	// I want to test on a simpler program to be sure
+#endif
 }
Index: Source/Plugins/Plugin_VideoOGL/Src/VertexShaderCache.h
===================================================================
--- Source/Plugins/Plugin_VideoOGL/Src/VertexShaderCache.h	(revision 6929)
+++ Source/Plugins/Plugin_VideoOGL/Src/VertexShaderCache.h	(working copy)
@@ -43,7 +43,11 @@
 		VSCacheEntry() : frameCount(0) {}
 		void Destroy() {
 			// printf("Destroying vs %i\n", shader.glprogid);
+#ifdef USE_GLSL
+			glDeleteShader(shader.glprogid);
+#else
 			glDeleteProgramsARB(1, &shader.glprogid);
+#endif
 			shader.glprogid = 0;
 		}
 	};
@@ -52,7 +56,7 @@
 
 	static VSCache vshaders;
 
-    static bool s_displayCompileAlert;
+	static bool s_displayCompileAlert;
 	
 	static GLuint CurrentShader;
 	static bool ShaderEnabled;
@@ -63,10 +67,12 @@
 
 	static VERTEXSHADER* SetShader(u32 components);
 	static bool CompileVertexShader(VERTEXSHADER& ps, const char* pstrprogram);
-
+	static bool CompileVertexShaderGLSL(VERTEXSHADER& ps, const char* pstrprogram);
+	
 	static void SetCurrentShader(GLuint Shader);
 	static void DisableShader();
-	
+
+	static GLuint program;
 };
 
 #endif // _VERTEXSHADERCACHE_H_
Index: Source/Core/VideoCommon/Src/VertexShaderManager.cpp
===================================================================
--- Source/Core/VideoCommon/Src/VertexShaderManager.cpp	(revision 6929)
+++ Source/Core/VideoCommon/Src/VertexShaderManager.cpp	(working copy)
@@ -162,14 +162,24 @@
 
 // Syncs the shader constant buffers with xfmem
 // TODO: A cleaner way to control the matricies without making a mess in the parameters field
-void VertexShaderManager::SetConstants()
+void VertexShaderManager::SetConstants(bool glsl)
 {
+	int i, j;
+	char tmpstr[128];
+
 	if (nTransformMatricesChanged[0] >= 0)
 	{
 		int startn = nTransformMatricesChanged[0] / 4;
 		int endn = (nTransformMatricesChanged[1] + 3) / 4;
 		const float* pstart = (const float*)&xfmem[startn * 4];
-		SetMultiVSConstant4fv(C_TRANSFORMMATRICES + startn, endn - startn, pstart);
+		if (!glsl)
+			SetMultiVSConstant4fv(C_TRANSFORMMATRICES + startn, endn - startn, pstart);
+		else {
+			for (i = startn; i < endn; i++) {
+				sprintf(tmpstr, "ctrmtx.T[%d].t", i);
+				SetVSConstant4fvByName(tmpstr, pstart + i * 4);
+			}
+		}
 		nTransformMatricesChanged[0] = nTransformMatricesChanged[1] = -1;
 	}
 	if (nNormalMatricesChanged[0] >= 0)
@@ -177,7 +187,14 @@
 		int startn = nNormalMatricesChanged[0] / 3;
 		int endn = (nNormalMatricesChanged[1] + 2) / 3;
 		const float *pnstart = (const float*)&xfmem[XFMEM_NORMALMATRICES+3*startn];
-		SetMultiVSConstant3fv(C_NORMALMATRICES + startn, endn - startn, pnstart);
+		if (!glsl)
+			SetMultiVSConstant3fv(C_NORMALMATRICES + startn, endn - startn, pnstart);
+		else {
+			for (i = startn; i < endn; i++) {
+				sprintf(tmpstr, "cnmtx.T[%d].t", i);
+				SetVSConstant3fvByName(tmpstr, pnstart + i * 3);
+			}
+		}
 		nNormalMatricesChanged[0] = nNormalMatricesChanged[1] = -1;
 	}
 
@@ -186,7 +203,14 @@
 		int startn = nPostTransformMatricesChanged[0] / 4;
 		int endn = (nPostTransformMatricesChanged[1] + 3 ) / 4;
 		const float* pstart = (const float*)&xfmem[XFMEM_POSTMATRICES + startn * 4];
-		SetMultiVSConstant4fv(C_POSTTRANSFORMMATRICES + startn, endn - startn, pstart);
+		if (!glsl)
+			SetMultiVSConstant4fv(C_POSTTRANSFORMMATRICES + startn, endn - startn, pstart);
+		else {
+			for (i = startn; i < endn; i++) {
+				sprintf(tmpstr, "cpostmtx.T[%d].t", i);
+				SetVSConstant4fvByName(tmpstr, pstart + i * 4);
+			}
+		}
 	}
 
 	if (nLightsChanged[0] >= 0)
@@ -215,10 +239,16 @@
 					fabs(xfmemptr[2]) < 0.00001f)
 				{
 					// dist attenuation, make sure not equal to 0!!!
-					SetVSConstant4f(C_LIGHTS+5*i+j+1, 0.00001f, xfmemptr[1], xfmemptr[2], 0);
+					if (!glsl)
+						SetVSConstant4f(C_LIGHTS+5*i+j+1, 0.00001f, xfmemptr[1], xfmemptr[2], 0);
+					else
+						; // TODO: lights
 				}
 				else
-					SetVSConstant4fv(C_LIGHTS+5*i+j+1, xfmemptr);
+					if (!glsl)
+						SetVSConstant4fv(C_LIGHTS+5*i+j+1, xfmemptr);
+					else
+						; // TODO: lights
 			}
 		}
 
@@ -229,8 +259,14 @@
 	{
 		for (int i = 0; i < 4; ++i)
 			if (nMaterialsChanged & (1 << i))
-				SetVSConstant4fv(C_MATERIALS + i, &s_fMaterials[4 * i]);
-
+			{
+				if (!glsl)
+					SetVSConstant4fv(C_MATERIALS + i, &s_fMaterials[4 * i]);
+				else {
+					sprintf(tmpstr, I_MATERIALS".C%d", i);
+					SetVSConstant4fvByName(tmpstr, s_fMaterials + i * 4);
+				}
+			}
 		nMaterialsChanged = 0;
 	}
 
@@ -241,8 +277,18 @@
 		const float *pos = (const float *)xfmem + MatrixIndexA.PosNormalMtxIdx * 4;
 		const float *norm = (const float *)xfmem + XFMEM_NORMALMATRICES + 3 * (MatrixIndexA.PosNormalMtxIdx & 31);
 
-		SetMultiVSConstant4fv(C_POSNORMALMATRIX, 3, pos);
-		SetMultiVSConstant3fv(C_POSNORMALMATRIX + 3, 3, norm);
+		if (!glsl) {
+			SetMultiVSConstant4fv(C_POSNORMALMATRIX, 3, pos);
+			SetMultiVSConstant3fv(C_POSNORMALMATRIX + 3, 3, norm);
+		}
+		else {
+			for (i = 0; i < 3; i++) {
+				sprintf(tmpstr, I_POSNORMALMATRIX".T%d", i);
+				SetVSConstant4fvByName(tmpstr, pos + i * 4);
+				sprintf(tmpstr, I_POSNORMALMATRIX".N%d", i);
+				SetVSConstant3fvByName(tmpstr, norm + i * 3);
+			}
+		}
 	}
 
 	if (bTexMatricesChanged[0])
@@ -256,7 +302,14 @@
 
 		for (int i = 0; i < 4; ++i)
 		{
-			SetMultiVSConstant4fv(C_TEXMATRICES + 3 * i, 3, fptrs[i]);
+			if (!glsl)
+				SetMultiVSConstant4fv(C_TEXMATRICES + 3 * i, 3, fptrs[i]);
+			else {
+				for (j = 0; j < 3; j++) {
+					sprintf(tmpstr, I_TEXMATRICES".T[%d].t", i * 3 + j);
+					SetVSConstant4fvByName(tmpstr, fptrs[i] + j * 4);
+				}
+			}
 		}
 	}
 
@@ -270,14 +323,27 @@
 
 		for (int i = 0; i < 4; ++i)
 		{
-			SetMultiVSConstant4fv(C_TEXMATRICES+3 * i + 12, 3, fptrs[i]);
+			if (!glsl)
+				SetMultiVSConstant4fv(C_TEXMATRICES+3 * i + 12, 3, fptrs[i]);
+			else {
+				for (j = 0; j < 3; j++) {
+					sprintf(tmpstr, I_TEXMATRICES".T[%d].t", i * 3 + j + 12);
+					SetVSConstant4fvByName(tmpstr, fptrs[i] + j * 4);
+				}
+			}
 		}
 	}
 
 	if (bViewportChanged)
 	{
 		bViewportChanged = false;
-		SetVSConstant4f(C_DEPTHPARAMS,xfregs.rawViewport[5]/ 16777216.0f,xfregs.rawViewport[2]/ 16777216.0f,0.0f,0.0f);
+		if (!glsl)
+			SetVSConstant4f(C_DEPTHPARAMS,xfregs.rawViewport[5]/ 16777216.0f,xfregs.rawViewport[2]/ 16777216.0f,0.0f,0.0f);
+		else {
+			float depth_params[4] = { xfregs.rawViewport[5] / 16777216.0f, xfregs.rawViewport[2] / 16777216.0f, 0.0f, 0.0f };
+			SetVSConstant4fvByName(I_DEPTHPARAMS, depth_params);
+		}
+
 		// This is so implementation-dependent that we can't have it here.
 		UpdateViewport();
 	}
@@ -400,11 +466,25 @@
 			Matrix44::Set(mtxB, g_fProjectionMatrix);
 			Matrix44::Multiply(mtxB, viewMtx, mtxA); // mtxA = projection x view
 
-			SetMultiVSConstant4fv(C_PROJECTION, 4, &mtxA.data[0]);
+			if (!glsl)
+				SetMultiVSConstant4fv(C_PROJECTION, 4, &mtxA.data[0]);
+			else {
+				for (i = 0; i < 4; i++) {
+					sprintf(tmpstr, "cproj.T%d", i);
+					SetVSConstant4fvByName(tmpstr, &mtxA.data[i * 4]);
+				}
+			}
 		}
 		else
 		{
-			SetMultiVSConstant4fv(C_PROJECTION, 4, &g_fProjectionMatrix[0]);
+			if (!glsl)
+				SetMultiVSConstant4fv(C_PROJECTION, 4, &g_fProjectionMatrix[0]);
+			else {
+				for (i = 0; i < 4; i++) {
+					sprintf(tmpstr, "cproj.T%d", i);
+					SetVSConstant4fvByName(tmpstr, &g_fProjectionMatrix[i * 4]);
+				}
+			}
 		}
 	}
 }
Index: Source/Core/VideoCommon/Src/VertexShaderGen.cpp
===================================================================
--- Source/Core/VideoCommon/Src/VertexShaderGen.cpp	(revision 6929)
+++ Source/Core/VideoCommon/Src/VertexShaderGen.cpp	(working copy)
@@ -75,6 +75,38 @@
 
 #define LIGHTS_POS ""
 
+// This isn't the right place for this. For efficiency and clarity of code, we need to compile this
+// source file twice when using GLSL, once for DirectX without GLSL, and once for OpenGL with GLSL
+// To compile DirectX or OpenGL without GLSL, comment out this line.
+#define USE_GLSL
+
+#ifndef USE_GLSL
+	#define FLOAT4 "float4"
+	#define FLOAT3 "float3"
+	#define RAWPOS "rawpos"
+	#define RAWNORM0 "rawnorm0"
+	#define COLOR0 "color0"
+	#define COLOR1 "color1"
+	#define TEX "tex"
+	#define OPOS "o.pos"
+	#define OCOLORS0 "o.colors_0"
+	#define OCOLORS1 "o.colors_1"
+	#define OTEX_D "o.tex%d"
+	// output vars clipPos and Normal are defined where they are used
+#else
+	#define FLOAT4 "vec4"
+	#define FLOAT3 "vec3"
+	#define RAWPOS "gl_Vertex"
+	#define RAWNORM0 "gl_Normal"
+	#define COLOR0 "gl_Color"
+	#define COLOR1 "gl_SecondaryColor"
+	#define TEX "gl_MultiTexCoord"
+	#define OPOS "gl_Position"
+	#define OCOLORS0 "gl_FrontColor"
+	#define OCOLORS1 "gl_FrontSecondaryColor"
+	#define OTEX_D "gl_TexCoord[%d]"
+#endif
+
 char *GenerateLightShader(char *p, int index, const LitChannel& chan, const char *dest, int coloralpha);
 
 const char *GenerateVertexShaderCode(u32 components, API_TYPE api_type)
@@ -95,18 +127,19 @@
 
 	char *p = text;
 	WRITE(p, "//Vertex Shader: comp:%x, \n", components);
-	WRITE(p, "typedef struct { float4 T0, T1, T2; float4 N0, N1, N2; } s_"I_POSNORMALMATRIX";\n"
-		"typedef struct { float4 t; } FLT4;\n"
-		"typedef struct { FLT4 T[24]; } s_"I_TEXMATRICES";\n"
-		"typedef struct { FLT4 T[64]; } s_"I_TRANSFORMMATRICES";\n"
-		"typedef struct { FLT4 T[32]; } s_"I_NORMALMATRICES";\n"
-		"typedef struct { FLT4 T[64]; } s_"I_POSTTRANSFORMMATRICES";\n"
-		"typedef struct { float4 col; float4 cosatt; float4 distatt; float4 pos; float4 dir; } Light;\n"
-		"typedef struct { Light lights[8]; } s_"I_LIGHTS";\n"
-		"typedef struct { float4 C0, C1, C2, C3; } s_"I_MATERIALS";\n"
-		"typedef struct { float4 T0, T1, T2, T3; } s_"I_PROJECTION";\n"
+	WRITE(p, "struct s_"I_POSNORMALMATRIX" { "FLOAT4" T0, T1, T2; "FLOAT4" N0, N1, N2; };\n"
+		"struct FLT4 { "FLOAT4" t; };\n"
+		"struct s_"I_TEXMATRICES" { FLT4 T[24]; };\n"
+		"struct s_"I_TRANSFORMMATRICES" { FLT4 T[64]; };\n"
+		"struct s_"I_NORMALMATRICES" { FLT4 T[32]; };\n"
+		"struct s_"I_POSTTRANSFORMMATRICES" { FLT4 T[64]; };\n"
+		"struct Light { "FLOAT4" col; "FLOAT4" cosatt; "FLOAT4" distatt; "FLOAT4" pos; "FLOAT4" dir; };\n"
+		"struct s_"I_LIGHTS" { Light lights[8]; };\n"
+		"struct s_"I_MATERIALS" { "FLOAT4" C0, C1, C2, C3; };\n"
+		"struct s_"I_PROJECTION" { "FLOAT4" T0, T1, T2, T3; };\n"
 		);
 
+#ifndef USE_GLSL
 	WRITE(p, "struct VS_OUTPUT {\n");
 	WRITE(p, "  float4 pos : POSITION;\n");
 	WRITE(p, "  float4 colors_0 : COLOR0;\n");
@@ -132,20 +165,29 @@
 		}
 	}	
 	WRITE(p, "};\n");
+#endif
 
 	// uniforms
 
-	WRITE(p, "uniform s_"I_TRANSFORMMATRICES" "I_TRANSFORMMATRICES" : register(c%d);\n", C_TRANSFORMMATRICES);
-	WRITE(p, "uniform s_"I_TEXMATRICES" "I_TEXMATRICES" : register(c%d);\n", C_TEXMATRICES); // also using tex matrices
-	WRITE(p, "uniform s_"I_NORMALMATRICES" "I_NORMALMATRICES" : register(c%d);\n", C_NORMALMATRICES);
-	WRITE(p, "uniform s_"I_POSNORMALMATRIX" "I_POSNORMALMATRIX" : register(c%d);\n", C_POSNORMALMATRIX);
-	WRITE(p, "uniform s_"I_POSTTRANSFORMMATRICES" "I_POSTTRANSFORMMATRICES" : register(c%d);\n", C_POSTTRANSFORMMATRICES);
-	WRITE(p, "uniform s_"I_LIGHTS" "I_LIGHTS" : register(c%d);\n", C_LIGHTS);
-	WRITE(p, "uniform s_"I_MATERIALS" "I_MATERIALS" : register(c%d);\n", C_MATERIALS);
-	WRITE(p, "uniform s_"I_PROJECTION" "I_PROJECTION" : register(c%d);\n", C_PROJECTION);
-	WRITE(p, "uniform float4 "I_DEPTHPARAMS" : register(c%d);\n", C_DEPTHPARAMS);
+#ifndef USE_GLSL
+	#define REGISTER_NUM(num) " : register(c%d);\n", num
+#else
+	// Note that GLSL doesn't allow manually assigning register numbers
+	#define REGISTER_NUM(num) ";\n"
+#endif
 
-	WRITE(p, "VS_OUTPUT main(\n");	
+	WRITE(p, "uniform s_"I_TRANSFORMMATRICES" "I_TRANSFORMMATRICES REGISTER_NUM(C_TRANSFORMMATRICES));
+	WRITE(p, "uniform s_"I_TEXMATRICES" "I_TEXMATRICES REGISTER_NUM(C_TEXMATRICES)); // also using tex matrices
+	WRITE(p, "uniform s_"I_NORMALMATRICES" "I_NORMALMATRICES REGISTER_NUM(C_NORMALMATRICES));
+	WRITE(p, "uniform s_"I_POSNORMALMATRIX" "I_POSNORMALMATRIX REGISTER_NUM(C_POSNORMALMATRIX));
+	WRITE(p, "uniform s_"I_POSTTRANSFORMMATRICES" "I_POSTTRANSFORMMATRICES REGISTER_NUM(C_POSTTRANSFORMMATRICES));
+	WRITE(p, "uniform s_"I_LIGHTS" "I_LIGHTS REGISTER_NUM(C_LIGHTS));
+	WRITE(p, "uniform s_"I_MATERIALS" "I_MATERIALS REGISTER_NUM(C_MATERIALS));
+	WRITE(p, "uniform s_"I_PROJECTION" "I_PROJECTION REGISTER_NUM(C_PROJECTION));
+	WRITE(p, "uniform "FLOAT4" "I_DEPTHPARAMS REGISTER_NUM(C_DEPTHPARAMS));
+
+#ifndef USE_GLSL
+	WRITE(p, "VS_OUTPUT main(\n");
 	
 	// inputs
 	if (components & VB_HAS_NRM0)
@@ -180,7 +222,18 @@
 			WRITE(p, "  float fposmtx : ATTR%d,\n", SHADER_POSMTX_ATTRIB);
 	}
 	WRITE(p, "  float4 rawpos : POSITION) {\n");
-	WRITE(p, "VS_OUTPUT o;\n");	
+	WRITE(p, "VS_OUTPUT o;\n");
+#else
+	if (components & VB_HAS_NRM1)
+		WRITE(p, "attribute vec3 rawnorm1;\n");
+	if (components & VB_HAS_NRM2)
+		WRITE(p, "attribute vec3 rawnorm2;\n");
+	if (components & VB_HAS_POSMTXIDX)
+		WRITE(p, "attribute float fposmtx;\n");
+
+	WRITE(p, "void main() {\n");
+#endif
+
 	// transforms
 	if (components & VB_HAS_POSMTXIDX) {
 		if (api_type == API_D3D9)
@@ -190,55 +243,55 @@
 		}
 		else if (api_type == API_D3D11)
 		{
-			WRITE(p, "int posmtx = blend_indices.x * 255.0f;\n");
+			WRITE(p, "int posmtx = blend_indices.x * 255.0;\n");
 		}
 		else
 		{
-			WRITE(p, "int posmtx = fposmtx;\n");
+			WRITE(p, "int posmtx = int(fposmtx);\n");
 		}
 
-		WRITE(p, "float4 pos = float4(dot("I_TRANSFORMMATRICES".T[posmtx].t, rawpos), dot("I_TRANSFORMMATRICES".T[posmtx+1].t, rawpos), dot("I_TRANSFORMMATRICES".T[posmtx+2].t, rawpos), 1);\n");		
+		WRITE(p, FLOAT4" pos = "FLOAT4"(dot("I_TRANSFORMMATRICES".T[posmtx].t, "RAWPOS"), dot("I_TRANSFORMMATRICES".T[posmtx+1].t, "RAWPOS"), dot("I_TRANSFORMMATRICES".T[posmtx+2].t, "RAWPOS"), 1);\n");
 
 		if (components & VB_HAS_NRMALL) {
 			WRITE(p, "int normidx = posmtx >= 32 ? (posmtx-32) : posmtx;\n");
-			WRITE(p, "float3 N0 = "I_NORMALMATRICES".T[normidx].t.xyz, N1 = "I_NORMALMATRICES".T[normidx+1].t.xyz, N2 = "I_NORMALMATRICES".T[normidx+2].t.xyz;\n");
+			WRITE(p, FLOAT3" N0 = "I_NORMALMATRICES".T[normidx].t.xyz, N1 = "I_NORMALMATRICES".T[normidx+1].t.xyz, N2 = "I_NORMALMATRICES".T[normidx+2].t.xyz;\n");
 		}
 
 		if (components & VB_HAS_NRM0)
-			WRITE(p, "float3 _norm0 = normalize(float3(dot(N0, rawnorm0), dot(N1, rawnorm0), dot(N2, rawnorm0)));\n");
+			WRITE(p, FLOAT3" _norm0 = normalize("FLOAT3"(dot(N0, "RAWNORM0"), dot(N1, "RAWNORM0"), dot(N2, "RAWNORM0")));\n");
 		if (components & VB_HAS_NRM1)
-			WRITE(p, "float3 _norm1 = float3(dot(N0, rawnorm1), dot(N1, rawnorm1), dot(N2, rawnorm1));\n");
+			WRITE(p, FLOAT3" _norm1 = "FLOAT3"(dot(N0, rawnorm1), dot(N1, rawnorm1), dot(N2, rawnorm1));\n");
 		if (components & VB_HAS_NRM2)
-			WRITE(p, "float3 _norm2 = float3(dot(N0, rawnorm2), dot(N1, rawnorm2), dot(N2, rawnorm2));\n");
+			WRITE(p, FLOAT3" _norm2 = "FLOAT3"(dot(N0, rawnorm2), dot(N1, rawnorm2), dot(N2, rawnorm2));\n");
 	}
 	else
 	{
-		WRITE(p, "float4 pos = float4(dot("I_POSNORMALMATRIX".T0, rawpos), dot("I_POSNORMALMATRIX".T1, rawpos), dot("I_POSNORMALMATRIX".T2, rawpos), 1.0f);\n");
+		WRITE(p, FLOAT4" pos = "FLOAT4"(dot("I_POSNORMALMATRIX".T0, "RAWPOS"), dot("I_POSNORMALMATRIX".T1, "RAWPOS"), dot("I_POSNORMALMATRIX".T2, "RAWPOS"), 1.0);\n");
 		if (components & VB_HAS_NRM0)
-			WRITE(p, "float3 _norm0 = normalize(float3(dot("I_POSNORMALMATRIX".N0.xyz, rawnorm0), dot("I_POSNORMALMATRIX".N1.xyz, rawnorm0), dot("I_POSNORMALMATRIX".N2.xyz, rawnorm0)));\n");
+			WRITE(p, FLOAT3" _norm0 = normalize("FLOAT3"(dot("I_POSNORMALMATRIX".N0.xyz, "RAWNORM0"), dot("I_POSNORMALMATRIX".N1.xyz, "RAWNORM0"), dot("I_POSNORMALMATRIX".N2.xyz, "RAWNORM0")));\n");
 		if (components & VB_HAS_NRM1)
-			WRITE(p, "float3 _norm1 = float3(dot("I_POSNORMALMATRIX".N0.xyz, rawnorm1), dot("I_POSNORMALMATRIX".N1.xyz, rawnorm1), dot("I_POSNORMALMATRIX".N2.xyz, rawnorm1));\n");
+			WRITE(p, FLOAT3" _norm1 = "FLOAT3"(dot("I_POSNORMALMATRIX".N0.xyz, rawnorm1), dot("I_POSNORMALMATRIX".N1.xyz, rawnorm1), dot("I_POSNORMALMATRIX".N2.xyz, rawnorm1));\n");
 		if (components & VB_HAS_NRM2)
-			WRITE(p, "float3 _norm2 = float3(dot("I_POSNORMALMATRIX".N0.xyz, rawnorm2), dot("I_POSNORMALMATRIX".N1.xyz, rawnorm2), dot("I_POSNORMALMATRIX".N2.xyz, rawnorm2));\n");
+			WRITE(p, FLOAT3" _norm2 = "FLOAT3"(dot("I_POSNORMALMATRIX".N0.xyz, rawnorm2), dot("I_POSNORMALMATRIX".N1.xyz, rawnorm2), dot("I_POSNORMALMATRIX".N2.xyz, rawnorm2));\n");
 	}
 
 	if (!(components & VB_HAS_NRM0))
-		WRITE(p, "float3 _norm0 = float3(0.0f, 0.0f, 0.0f);\n");
+		WRITE(p, FLOAT3" _norm0 = "FLOAT3"(0.0, 0.0, 0.0);\n");
 
 	
 
-	WRITE(p, "o.pos = float4(dot("I_PROJECTION".T0, pos), dot("I_PROJECTION".T1, pos), dot("I_PROJECTION".T2, pos), dot("I_PROJECTION".T3, pos));\n");
+	WRITE(p, OPOS" = "FLOAT4"(dot("I_PROJECTION".T0, pos), dot("I_PROJECTION".T1, pos), dot("I_PROJECTION".T2, pos), dot("I_PROJECTION".T3, pos));\n");
 
-	WRITE(p, "float4 mat, lacc;\n"
-	"float3 ldir, h;\n"
+	WRITE(p, FLOAT4" mat, lacc;\n"
+	FLOAT3" ldir, h;\n"
 	"float dist, dist2, attn;\n");
 
 	if(xfregs.nNumChans == 0)
 	{
 		if (components & VB_HAS_COL0)
-			WRITE(p, "o.colors_0 = color0;\n");
+			WRITE(p, OCOLORS0" = "COLOR0";\n");
 		else
-			WRITE(p, "o.colors_0 = float4(1.0f, 1.0f, 1.0f, 1.0f);\n");		
+			WRITE(p, OCOLORS0" = "FLOAT4"(1.0, 1.0, 1.0, 1.0);\n");		
 	}
 	// lights/colors
 	for (int j = 0; j < xfregs.nNumChans; j++)
@@ -246,15 +299,21 @@
 		const LitChannel& color = xfregs.colChans[j].color;
 		const LitChannel& alpha = xfregs.colChans[j].alpha;
 
+		const char * color_j;
+		if (j == 0)
+			color_j = COLOR0;
+		else if (j == 1)
+			color_j = COLOR1;
+		
 		WRITE(p, "{\n");
 		
 		if (color.matsource) {// from vertex
 			if (components & (VB_HAS_COL0 << j))
-				WRITE(p, "mat = color%d;\n", j);
+				WRITE(p, "mat = %s;\n", color_j);
 			else if (components & VB_HAS_COL0)
-				WRITE(p, "mat = color0;\n");
+				WRITE(p, "mat = "COLOR0";\n");
 			else
-				WRITE(p, "mat = float4(1.0f, 1.0f, 1.0f, 1.0f);\n");
+				WRITE(p, "mat = "FLOAT4"(1.0, 1.0, 1.0, 1.0);\n");
 		}
 		else // from color
 			WRITE(p, "mat = "I_MATERIALS".C%d;\n", j+2);
@@ -262,28 +321,28 @@
 		if (color.enablelighting) {
 			if (color.ambsource) { // from vertex
 				if (components & (VB_HAS_COL0<<j) )
-					WRITE(p, "lacc = color%d;\n", j);
+					WRITE(p, "lacc = %s;\n", color_j);
 				else if (components & VB_HAS_COL0 )
-					WRITE(p, "lacc = color0;\n");
+					WRITE(p, "lacc = "COLOR0";\n");
 				else
-					WRITE(p, "lacc = float4(0.0f, 0.0f, 0.0f, 0.0f);\n");
+					WRITE(p, "lacc = "FLOAT4"(0.0, 0.0, 0.0, 0.0);\n");
 			}
 			else // from color
 				WRITE(p, "lacc = "I_MATERIALS".C%d;\n", j);
 		}
 		else
 		{
-			WRITE(p, "lacc = float4(1.0f, 1.0f, 1.0f, 1.0f);\n");
+			WRITE(p, "lacc = "FLOAT4"(1.0, 1.0, 1.0, 1.0);\n");
 		}
 
 		// check if alpha is different
 		if (alpha.matsource != color.matsource) {
 			if (alpha.matsource) {// from vertex
 				if (components & (VB_HAS_COL0<<j))
-					WRITE(p, "mat.w = color%d.w;\n", j);
+					WRITE(p, "mat.w = %s.w;\n", color_j);
 				else if (components & VB_HAS_COL0)
-					WRITE(p, "mat.w = color0.w;\n");
-				else WRITE(p, "mat.w = 1.0f;\n");
+					WRITE(p, "mat.w = "COLOR0".w;\n");
+				else WRITE(p, "mat.w = 1.0;\n");
 			}
 			else // from color
 				WRITE(p, "mat.w = "I_MATERIALS".C%d.w;\n", j+2);
@@ -293,20 +352,22 @@
 		{
 			if (alpha.ambsource) {// from vertex
 				if (components & (VB_HAS_COL0<<j) )
-					WRITE(p, "lacc.w = color%d.w;\n", j);
+					WRITE(p, "lacc.w = %s.w;\n", color_j);
 				else if (components & VB_HAS_COL0 )
-					WRITE(p, "lacc.w = color0.w;\n");
+					WRITE(p, "lacc.w = "COLOR0".w;\n");
 				else
-					WRITE(p, "lacc.w = 0.0f;\n");
+					WRITE(p, "lacc.w = 0.0;\n");
 			}
 			else // from color
 				WRITE(p, "lacc.w = "I_MATERIALS".C%d.w;\n", j);
 		}
 		else
 		{
-			WRITE(p, "lacc.w = 1.0f;\n");
+			WRITE(p, "lacc.w = 1.0;\n");
 		}	
 		
+// TODO: Finish Lighting for GLSL
+#ifndef USE_GLSL
 		if(color.enablelighting && alpha.enablelighting)
 		{
 			// both have lighting, test if they use the same lights
@@ -344,15 +405,25 @@
 					p = GenerateLightShader(p, i, workingchannel, "lacc", coloralpha);
 			}
 		}
+#endif
+
+#ifndef USE_GLSL
 		WRITE(p, "o.colors_%d = mat * saturate(lacc);\n", j);
+#else
+		if (j == 0)
+			WRITE(p, OCOLORS0" = mat * clamp(lacc, 0.0, 1.0);\n");
+		else if (j == 1)
+			WRITE(p, OCOLORS1" = mat * clamp(lacc, 0.0, 1.0);\n");
+#endif
 		WRITE(p, "}\n");
 	}	
+
 	if(xfregs.nNumChans < 2)
 	{
 		if (components & VB_HAS_COL1)
-			WRITE(p, "o.colors_1 = color1;\n");
+			WRITE(p, OCOLORS1" = "COLOR1";\n");
 		else
-			WRITE(p, "o.colors_1 = o.colors_0;\n");		
+			WRITE(p, OCOLORS1" = "OCOLORS0";\n");
 	}
 	// special case if only pos and tex coord 0 and tex coord input is AB11
 	// donko - this has caused problems in some games. removed for now.
@@ -364,21 +435,21 @@
 		*/
 
 	// transform texcoords
-	WRITE(p, "float4 coord = float4(0.0f, 0.0f, 1.0f, 1.0f);\n");
+	WRITE(p, FLOAT4" coord = "FLOAT4"(0.0, 0.0, 1.0, 1.0);\n");
 	for (int i = 0; i < xfregs.numTexGens; ++i) {
 		TexMtxInfo& texinfo = xfregs.texcoords[i].texmtxinfo;
 
 		WRITE(p, "{\n");
-		WRITE(p, "coord = float4(0.0f, 0.0f, 1.0f, 1.0f);\n");
+		WRITE(p, "coord = "FLOAT4"(0.0, 0.0, 1.0, 1.0);\n");
 		switch (texinfo.sourcerow) {
 		case XF_SRCGEOM_INROW:
 			_assert_( texinfo.inputform == XF_TEXINPUT_ABC1 );
-			WRITE(p, "coord = rawpos;\n"); // pos.w is 1
+			WRITE(p, "coord = "RAWPOS";\n"); // pos.w is 1
 			break;
 		case XF_SRCNORMAL_INROW:
 			if (components & VB_HAS_NRM0) {
 				_assert_( texinfo.inputform == XF_TEXINPUT_ABC1 );
-				WRITE(p, "coord = float4(rawnorm0.xyz, 1.0f);\n");
+				WRITE(p, "coord = "FLOAT4"("RAWNORM0".xyz, 1.0);\n");
 			}
 			break;
 		case XF_SRCCOLORS_INROW:
@@ -387,19 +458,19 @@
 		case XF_SRCBINORMAL_T_INROW:
 			if (components & VB_HAS_NRM1) {
 				_assert_( texinfo.inputform == XF_TEXINPUT_ABC1 );
-				WRITE(p, "coord = float4(rawnorm1.xyz, 1.0f);\n");
+				WRITE(p, "coord = "FLOAT4"(rawnorm1.xyz, 1.0);\n");
 			}
 			break;
 		case XF_SRCBINORMAL_B_INROW:
 			if (components & VB_HAS_NRM2) {
 				_assert_( texinfo.inputform == XF_TEXINPUT_ABC1 );
-				WRITE(p, "coord = float4(rawnorm2.xyz, 1.0f);\n");
+				WRITE(p, "coord = "FLOAT4"(rawnorm2.xyz, 1.0);\n");
 			}
 			break;
 		default:
 			_assert_(texinfo.sourcerow <= XF_SRCTEX7_INROW);
 			if (components & (VB_HAS_UV0<<(texinfo.sourcerow - XF_SRCTEX0_INROW)) )
-				WRITE(p, "coord = float4(tex%d.x, tex%d.y, 1.0f, 1.0f);\n", texinfo.sourcerow - XF_SRCTEX0_INROW, texinfo.sourcerow - XF_SRCTEX0_INROW);
+				WRITE(p, "coord = "FLOAT4"("TEX"%d.x, "TEX"%d.y, 1.0, 1.0);\n", texinfo.sourcerow - XF_SRCTEX0_INROW, texinfo.sourcerow - XF_SRCTEX0_INROW);
 			break;
 		}
 
@@ -410,42 +481,42 @@
 				if (components & (VB_HAS_NRM1|VB_HAS_NRM2)) {
 					// transform the light dir into tangent space
 					WRITE(p, "ldir = normalize("I_LIGHTS".lights[%d].pos.xyz - pos.xyz);\n", texinfo.embosslightshift);
-					WRITE(p, "o.tex%d.xyz = o.tex%d.xyz + float3(dot(ldir, _norm1), dot(ldir, _norm2), 0.0f);\n", i, texinfo.embosssourceshift);
+					WRITE(p, OTEX_D".xyz = "OTEX_D".xyz + "FLOAT3"(dot(ldir, _norm1), dot(ldir, _norm2), 0.0);\n", i, texinfo.embosssourceshift);
 				}
 				else _assert_(0); // should have normals
 
 				break;
 			case XF_TEXGEN_COLOR_STRGBC0:
 				_assert_(texinfo.sourcerow == XF_SRCCOLORS_INROW);
-				WRITE(p, "o.tex%d.xyz = float3(o.colors_0.x, o.colors_0.y, 1);\n", i);
+				WRITE(p, OTEX_D".xyz = "FLOAT3"("OCOLORS0".x, "OCOLORS0".y, 1);\n", i);
 				break;
 			case XF_TEXGEN_COLOR_STRGBC1:
 				_assert_(texinfo.sourcerow == XF_SRCCOLORS_INROW);
-				WRITE(p, "o.tex%d.xyz = float3(o.colors_1.x, o.colors_1.y, 1);\n", i);
+				WRITE(p, OTEX_D".xyz = "FLOAT3"("OCOLORS1".x, "OCOLORS1".y, 1);\n", i);
 				break;
 			case XF_TEXGEN_REGULAR:
 			default:
 				if (components & (VB_HAS_TEXMTXIDX0<<i)) {
 					if (texinfo.projection == XF_TEXPROJ_STQ)
-						WRITE(p, "o.tex%d.xyz = float3(dot(coord, "I_TRANSFORMMATRICES".T[tex%d.z].t), dot(coord, "I_TRANSFORMMATRICES".T[tex%d.z+1].t), dot(coord, "I_TRANSFORMMATRICES".T[tex%d.z+2].t));\n", i, i, i, i);
+						WRITE(p, OTEX_D".xyz = "FLOAT3"(dot(coord, "I_TRANSFORMMATRICES".T["TEX"%d.z].t), dot(coord, "I_TRANSFORMMATRICES".T["TEX"%d.z+1].t), dot(coord, "I_TRANSFORMMATRICES".T["TEX"%d.z+2].t));\n", i, i, i, i);
 					else {
-						WRITE(p, "o.tex%d.xyz = float3(dot(coord, "I_TRANSFORMMATRICES".T[tex%d.z].t), dot(coord, "I_TRANSFORMMATRICES".T[tex%d.z+1].t), 1);\n", i, i, i);
+						WRITE(p, OTEX_D".xyz = "FLOAT3"(dot(coord, "I_TRANSFORMMATRICES".T["TEX"%d.z].t), dot(coord, "I_TRANSFORMMATRICES".T["TEX"%d.z+1].t), 1);\n", i, i, i);
 					}
 				}
 				else {
 					if (texinfo.projection == XF_TEXPROJ_STQ)
-						WRITE(p, "o.tex%d.xyz = float3(dot(coord, "I_TEXMATRICES".T[%d].t), dot(coord, "I_TEXMATRICES".T[%d].t), dot(coord, "I_TEXMATRICES".T[%d].t));\n", i, 3*i, 3*i+1, 3*i+2);
+						WRITE(p, OTEX_D".xyz = "FLOAT3"(dot(coord, "I_TEXMATRICES".T[%d].t), dot(coord, "I_TEXMATRICES".T[%d].t), dot(coord, "I_TEXMATRICES".T[%d].t));\n", i, 3*i, 3*i+1, 3*i+2);
 					else
-						WRITE(p, "o.tex%d.xyz = float3(dot(coord, "I_TEXMATRICES".T[%d].t), dot(coord, "I_TEXMATRICES".T[%d].t), 1);\n", i, 3*i, 3*i+1);
+						WRITE(p, OTEX_D".xyz = "FLOAT3"(dot(coord, "I_TEXMATRICES".T[%d].t), dot(coord, "I_TEXMATRICES".T[%d].t), 1);\n", i, 3*i, 3*i+1);
 				}
 				break;
 		}
 
 		if (xfregs.bEnableDualTexTransform && texinfo.texgentype == XF_TEXGEN_REGULAR) { // only works for regular tex gen types?
 			int postidx = xfregs.texcoords[i].postmtxinfo.index;
-			WRITE(p, "float4 P0 = "I_POSTTRANSFORMMATRICES".T[%d].t;\n"
-				"float4 P1 = "I_POSTTRANSFORMMATRICES".T[%d].t;\n"
-				"float4 P2 = "I_POSTTRANSFORMMATRICES".T[%d].t;\n",
+			WRITE(p, FLOAT4" P0 = "I_POSTTRANSFORMMATRICES".T[%d].t;\n"
+				FLOAT4" P1 = "I_POSTTRANSFORMMATRICES".T[%d].t;\n"
+				FLOAT4" P2 = "I_POSTTRANSFORMMATRICES".T[%d].t;\n",
 				postidx&0x3f, (postidx+1)&0x3f, (postidx+2)&0x3f);
 
 			if (texGenSpecialCase) {
@@ -454,15 +525,15 @@
 				// q of output is unknown
 
 				// multiply by postmatrix
-				WRITE(p, "o.tex%d.xyz = float3(dot(P0.xy, o.tex%d.xy) + P0.z + P0.w, dot(P1.xy, o.tex%d.xy) + P1.z + P1.w, 0.0f);\n", i, i, i);
+				WRITE(p, OTEX_D".xyz = "FLOAT3"(dot(P0.xy, "OTEX_D".xy) + P0.z + P0.w, dot(P1.xy, "OTEX_D".xy) + P1.z + P1.w, 0.0);\n", i, i, i);
 			}
 			else
 			{
 				if (xfregs.texcoords[i].postmtxinfo.normalize)
-					WRITE(p, "o.tex%d.xyz = normalize(o.tex%d.xyz);\n", i, i);
+					WRITE(p, OTEX_D".xyz = normalize("OTEX_D".xyz);\n", i, i);
 
 				// multiply by postmatrix
-				WRITE(p, "o.tex%d.xyz = float3(dot(P0.xyz, o.tex%d.xyz) + P0.w, dot(P1.xyz, o.tex%d.xyz) + P1.w, dot(P2.xyz, o.tex%d.xyz) + P2.w);\n", i, i, i, i);
+				WRITE(p, OTEX_D".xyz = "FLOAT3"(dot(P0.xyz, "OTEX_D".xyz) + P0.w, dot(P1.xyz, "OTEX_D".xyz) + P1.w, dot(P2.xyz, "OTEX_D".xyz) + P2.w);\n", i, i, i, i);
 			}
 		}
 
@@ -471,32 +542,41 @@
 
 	// clipPos/w needs to be done in pixel shader, not here
 	if (xfregs.numTexGens < 7) {
-		WRITE(p, "o.clipPos = float4(pos.x,pos.y,o.pos.z,o.pos.w);\n");
+#ifndef USE_GLSL
+		WRITE(p, "o.clipPos = "FLOAT4"(pos.x,pos.y,"OPOS".z,"OPOS".w);\n");
+#else
+		WRITE(p, "gl_TexCoord[%d] = "FLOAT4"(pos.x,pos.y,"OPOS".z,"OPOS".w);\n", xfregs.numTexGens);
+#endif
+
 	} else {
-		WRITE(p, "o.tex0.w = pos.x;\n");
-		WRITE(p, "o.tex1.w = pos.y;\n");
-		WRITE(p, "o.tex2.w = o.pos.z;\n");
-		WRITE(p, "o.tex3.w = o.pos.w;\n");
+		WRITE(p, OTEX_D".w = pos.x;\n", 0);
+		WRITE(p, OTEX_D".w = pos.y;\n", 1);
+		WRITE(p, OTEX_D".w = o.pos.z;\n", 2);
+		WRITE(p, OTEX_D".w = o.pos.w;\n", 3);
 	}
 
 	if(g_ActiveConfig.bEnablePixelLigting && g_ActiveConfig.backend_info.bSupportsPixelLighting)
 	{
 		if (xfregs.numTexGens < 7) {
-			WRITE(p, "o.Normal = float4(_norm0.x,_norm0.y,_norm0.z,pos.z);\n");
+#ifndef USE_GLSL
+			WRITE(p, "o.Normal = "FLOAT4"(_norm0.x,_norm0.y,_norm0.z,pos.z);\n");
+#else
+			WRITE(p, "gl_TexCoord[%d] = "FLOAT4"(_norm0.x,_norm0.y,_norm0.z,pos.z);\n", xfregs.numTexGens + 1);
+#endif
 		} else {
-			WRITE(p, "o.tex4.w = _norm0.x;\n");
-			WRITE(p, "o.tex5.w = _norm0.y;\n");
-			WRITE(p, "o.tex6.w = _norm0.z;\n");
+			WRITE(p, OTEX_D".w = _norm0.x;\n", 4);
+			WRITE(p, OTEX_D".w = _norm0.y;\n", 5);
+			WRITE(p, OTEX_D".w = _norm0.z;\n", 6);
 			if (xfregs.numTexGens < 8)
-				WRITE(p, "o.tex7 = pos.xyzz;\n");
+				WRITE(p, OTEX_D" = pos.xyzz;\n", 7);
 			else
-				WRITE(p, "o.tex7.w = pos.z;\n");
+				WRITE(p, OTEX_D".w = pos.z;\n", 7);
 		}		
 		if (components & VB_HAS_COL0)
-			WRITE(p, "o.colors_0 = color0;\n");		
+			WRITE(p, OCOLORS0" = "COLOR0";\n");		
 
 		if (components & VB_HAS_COL1)
-			WRITE(p, "o.colors_1 = color1;\n");
+			WRITE(p, OCOLORS1" = "COLOR1";\n");
 	}
 
 	//write the true depth value, if the game uses depth textures pixel shaders will override with the correct values
@@ -506,14 +586,14 @@
 	} else {
 	    // this results in a scale from -1..0 to -1..1 after perspective
 	    // divide
-	    WRITE(p, "o.pos.z = o.pos.w + o.pos.z * 2.0f;\n");
+	    WRITE(p, OPOS".z = "OPOS".w + "OPOS".z * 2.0;\n");
 
 	    // Sonic Unleashed puts its final rendering at the near or
 	    // far plane of the viewing frustrum(actually box, they use
 	    // orthogonal projection for that), and we end up putting it
 	    // just beyond, and the rendering gets clipped away. (The
 	    // primitive gets dropped)
-	    WRITE(p, "o.pos.z = o.pos.z * 1048575.0f/1048576.0f;\n");
+	    WRITE(p, OPOS".z = "OPOS".z * 1048575.0/1048576.0;\n");
 
 	    // the next steps of the OGL pipeline are:
 	    // (x_c,y_c,z_c,w_c) = o.pos  //switch to OGL spec terminology
@@ -526,7 +606,11 @@
 	    //seems to get rather complicated
 	}
 
+#ifndef USE_GLSL
 	WRITE(p, "return o;\n}\n");
+#else
+	WRITE(p, "}\n");
+#endif
 
 
 	if (text[sizeof(text) - 1] != 0x7C)
@@ -552,7 +636,7 @@
 			case LIGHTDIF_CLAMP:
 				WRITE(p, "ldir = normalize("I_LIGHTS".lights[%d].pos.xyz - pos.xyz);\n", index);
 				WRITE(p, "%s.%s += %sdot(ldir, _norm0)) * "I_LIGHTS".lights[%d].col.%s;\n",
-					dest, swizzle, chan.diffusefunc != LIGHTDIF_SIGN ? "max(0.0f," :"(", index, swizzle);
+					dest, swizzle, chan.diffusefunc != LIGHTDIF_SIGN ? "max(0.0," :"(", index, swizzle);
 				break;
 			default: _assert_(0);
 		}
@@ -565,14 +649,14 @@
 			WRITE(p, "dist2 = dot(ldir, ldir);\n"
 				"dist = sqrt(dist2);\n"
 				"ldir = ldir / dist;\n"
-				"attn = max(0.0f, dot(ldir, "I_LIGHTS".lights[%d].dir.xyz));\n",index);
-			WRITE(p, "attn = max(0.0f, dot("I_LIGHTS".lights[%d].cosatt.xyz, float3(1.0f, attn, attn*attn))) / dot("I_LIGHTS".lights[%d].distatt.xyz, float3(1.0f,dist,dist2));\n", index, index);
+				"attn = max(0.0, dot(ldir, "I_LIGHTS".lights[%d].dir.xyz));\n",index);
+			WRITE(p, "attn = max(0.0, dot("I_LIGHTS".lights[%d].cosatt.xyz, float3(1.0, attn, attn*attn))) / dot("I_LIGHTS".lights[%d].distatt.xyz, float3(1.0,dist,dist2));\n", index, index);
 		}
 		else if (chan.attnfunc == 1) 
 		{ // specular
 			WRITE(p, "ldir = normalize("I_LIGHTS".lights[%d].pos.xyz);\n",index);
-			WRITE(p, "attn = (dot(_norm0,ldir) >= 0.0f) ? max(0.0f, dot(_norm0, "I_LIGHTS".lights[%d].dir.xyz)) : 0.0f;\n", index);
-			WRITE(p, "attn = max(0.0f, dot("I_LIGHTS".lights[%d].cosatt.xyz, float3(1,attn,attn*attn))) / dot("I_LIGHTS".lights[%d].distatt.xyz, float3(1,attn,attn*attn));\n", index, index);
+			WRITE(p, "attn = (dot(_norm0,ldir) >= 0.0) ? max(0.0, dot(_norm0, "I_LIGHTS".lights[%d].dir.xyz)) : 0.0;\n", index);
+			WRITE(p, "attn = max(0.0, dot("I_LIGHTS".lights[%d].cosatt.xyz, float3(1,attn,attn*attn))) / dot("I_LIGHTS".lights[%d].distatt.xyz, float3(1,attn,attn*attn));\n", index, index);
 		}
 
 		switch (chan.diffusefunc)
@@ -585,7 +669,7 @@
 				WRITE(p, "%s.%s += attn * %sdot(ldir, _norm0)) * "I_LIGHTS".lights[%d].col.%s;\n",
 					dest, 
 					swizzle, 
-					chan.diffusefunc != LIGHTDIF_SIGN ? "max(0.0f," :"(", 
+					chan.diffusefunc != LIGHTDIF_SIGN ? "max(0.0," :"(", 
 					index, 
 					swizzle);
 				break;
Index: Source/Core/VideoCommon/Src/VertexShaderGen.h
===================================================================
--- Source/Core/VideoCommon/Src/VertexShaderGen.h	(revision 6929)
+++ Source/Core/VideoCommon/Src/VertexShaderGen.h	(working copy)
@@ -104,6 +104,7 @@
 
 // components is included in the uid.
 const char *GenerateVertexShaderCode(u32 components, API_TYPE api_type);
+const char *GenerateVertexShaderCodeGLSL(u32 components, char * text);
 void GetVertexShaderId(VERTEXSHADERUID *uid, u32 components);
 
 extern VERTEXSHADERUID  last_vertex_shader_uid;
Index: Source/Core/VideoCommon/Src/VideoCommon.h
===================================================================
--- Source/Core/VideoCommon/Src/VideoCommon.h	(revision 6929)
+++ Source/Core/VideoCommon/Src/VideoCommon.h	(working copy)
@@ -152,6 +152,7 @@
 	API_D3D9,
 	API_D3D11,
 	API_GLSL,
+	API_OPENGL_GLSL,
 	API_NONE
 } API_TYPE;
 
Index: Source/Core/VideoCommon/Src/VertexShaderManager.h
===================================================================
--- Source/Core/VideoCommon/Src/VertexShaderManager.h	(revision 6929)
+++ Source/Core/VideoCommon/Src/VertexShaderManager.h	(working copy)
@@ -50,7 +50,7 @@
 	static void Shutdown();
 
 	// constant management
-	static void SetConstants();
+	static void SetConstants(bool glsl = false);
 
 	static void SetViewport(float* _Viewport, int constantIndex = -1);
 	static void SetViewportChanged();
@@ -67,8 +67,9 @@
 
 void SetVSConstant4f(unsigned int const_number, float f1, float f2, float f3, float f4);
 void SetVSConstant4fv(unsigned int const_number, const float *f);
+void SetVSConstant4fvByName(const char * name, const float *f);
+void SetVSConstant3fvByName(const char * name, const float *f);
 void SetMultiVSConstant3fv(unsigned int const_number, unsigned int count, const float *f);
 void SetMultiVSConstant4fv(unsigned int const_number, unsigned int count, const float *f);
 
-
 #endif // _VERTEXSHADERMANAGER_H
Index: CMakeLists.txt
===================================================================
--- CMakeLists.txt	(revision 6929)
+++ CMakeLists.txt	(working copy)
@@ -96,7 +96,7 @@
 endif(NOT CMAKE_BUILD_TYPE)
 
 if(CMAKE_BUILD_TYPE STREQUAL Debug)
-	add_definitions(-D_DEBUG -ggdb)
+	add_definitions(-D_DEBUG -ggdb -O0)
 	set(wxWidgets_USE_DEBUG ON CACHE BOOL "Use wxWidgets Debugging")
 endif(CMAKE_BUILD_TYPE STREQUAL Debug)
 
