Commits

Alex Szpakowski committed cf5867c

The current transformation matrices will now be sent as uniforms to the active shader when rendering in ES2

  • Participants
  • Parent commits 8468f17
  • Branches GLES2-compatibility

Comments (0)

Files changed (7)

File src/modules/graphics/opengl/Context.cpp

 	if (extensionsInitialized)
 		return;
 
+	glewExperimental = GL_TRUE;
 	glewInit();
 
 	// The functionality of the core and ARB VBOs are identical, so we can
 	}
 	else
 	{
-		// and use the old glEnableClientState etc. otherwise
+		// and use the fixed-function glEnableClientState etc. otherwise
 		state.vertexAttribMap[ATTRIB_VERTEX] = GL_VERTEX_ARRAY;
 		state.vertexAttribMap[ATTRIB_COLOR] = GL_COLOR_ARRAY;
 		state.vertexAttribMap[ATTRIB_TEXCOORD] = GL_TEXTURE_COORD_ARRAY;
 
 	// get the current color
 	GLfloat color[4];
-	glGetFloatv(GL_CURRENT_COLOR, color);
+
+	if (shadersSupported)
+		glGetVertexAttribfv(state.vertexAttribMap[ATTRIB_COLOR], GL_CURRENT_VERTEX_ATTRIB, color);
+	else
+		glGetFloatv(GL_CURRENT_COLOR, color);
+
 	state.color = Color(color[0] * 255, color[1] * 255, color[2] * 255, color[3] * 255);
 
 	// get the current clear color
 		glGetFloatv(GL_POINT_SIZE_RANGE, pointsizerange);
 
 	state.maxPointSize = pointsizerange[1];
+
+	state.lastUsedShader = NULL;
 }
 
 void Context::setupRender()
 	const Matrix &projectionMatrix = projectionStack.back();
 	const Matrix &modelViewMatrix = modelViewStack.back();
 
-	if (Shader::currentShader)
+	Shader *shader = Shader::currentShader;
+
+	bool mvmatrixchanged = shader != state.lastUsedShader || modelViewMatrix != state.modelViewMatrix;
+	bool pmatrixchanged = shader != state.lastUsedShader || projectionMatrix != state.projectionMatrix;
+
+	if (GLEW_ES_VERSION_2_0 && shader != NULL)
 	{
-		// TODO: send uniforms to active shader if applicable:
-		// modelview/projection/normal matrices, point size, etc.
+		// send transformation matrices to the active shader for use when rendering
+
+		if (mvmatrixchanged && shader->hasUniform("ModelViewMatrix"))
+			shader->sendMatrix("ModelViewMatrix", 4, modelViewMatrix.getElements(), 1);
+
+		if (pmatrixchanged && shader->hasUniform("ProjectionMatrix"))
+			shader->sendMatrix("ProjectionMatrix", 4, projectionMatrix.getElements(), 1);
+
+		if ((mvmatrixchanged || pmatrixchanged) && shader->hasUniform("ModelViewProjectionMatrix"))
+		{
+			Matrix mvpMatrix = projectionMatrix * modelViewMatrix;
+			shader->sendMatrix("ModelViewProjectionMatrix", 4, mvpMatrix.getElements(), 1);
+		}
+
+		// TODO: NormalMatrix
+		// 'transpose of the inverse of the upper leftmost 3x3 of the Model-View Matrix'
+	}
+	else if (!GLEW_ES_VERSION_2_0)
+	{
+		// send transformation matrices to fixed-function OpenGL
+		// if a shader is active, OpenGL will send the relevant matrices automatically
+
+		if (pmatrixchanged)
+		{
+			glMatrixMode(GL_PROJECTION);
+			glLoadMatrixf(projectionMatrix.getElements());
+			state.projectionMatrix = projectionMatrix;
+			glMatrixMode(GL_MODELVIEW);
+		}
+
+		if (mvmatrixchanged)
+			glLoadMatrixf(modelViewMatrix.getElements());
 	}
 
-	// Send modelview and projection matrices to OpenGL for use when rendering.
+	if (mvmatrixchanged)
+		state.modelViewMatrix = modelViewMatrix;
 
-	if (projectionMatrix != state.projectionMatrix)
-	{
-		glMatrixMode(GL_PROJECTION);
-		glLoadMatrixf(projectionMatrix.getElements());
+	if (pmatrixchanged)
 		state.projectionMatrix = projectionMatrix;
-		glMatrixMode(GL_MODELVIEW);
-	}
 
-	if (modelViewMatrix != state.modelViewMatrix)
-	{
-		glLoadMatrixf(modelViewMatrix.getElements());
-		state.modelViewMatrix = modelViewMatrix;
-	}
+	state.lastUsedShader = shader;
 }
 
 void Context::setCapability(GLenum capability, bool enable)

File src/modules/graphics/opengl/Context.h

 namespace opengl
 {
 
+class Shader;
+
 /**
  * Thin layer between OpenGL and the rest of the program.
  * Shadows OpenGL context state internally for better efficiency, and
 	// Standard vertex attributes.
 	enum VertexAttribType
 	{
-		ATTRIB_NONE = 0x100000,
+		ATTRIB_NONE = 0x00,
 		ATTRIB_VERTEX = 0x01,
 		ATTRIB_COLOR = 0x02,
 		ATTRIB_TEXCOORD = 0x04,
 		std::vector<GLuint> textureUnits;
 		int curTextureUnit;
 
+		// The last active shader used when rendering.
+		Shader *lastUsedShader;
+
 	} state;
 
 	bool shadersSupported;

File src/modules/graphics/opengl/Graphics.cpp

 void Graphics::clear()
 {
 	glClear(GL_COLOR_BUFFER_BIT);
-	getContext()->modelViewStack.back() = Matrix();
+	getContext()->modelViewStack.back().setIdentity();
 }
 
 void Graphics::present()

File src/modules/graphics/opengl/Shader.cpp

 
 		~TemporaryAttacher()
 		{
-			if (prevShader != NULL)
+			if (prevShader)
 				prevShader->attach();
 			else
 				Shader::detach();
 	Context *ctx = getContext();
 
 	// bind generic vertex attribute locations to names in the shader
-	// does nothing if we only have built-in (deprecated) attributes
 
 	std::map<Context::VertexAttribType, std::string>::const_iterator it;
 	for (it = vertexAttribNames.begin(); it != vertexAttribNames.end(); ++it)
 
 void Shader::detach()
 {
-	if (defaultShader != NULL)
+	if (defaultShader)
 		defaultShader->attach();
 	else
 	{
 	}
 }
 
+GLint Shader::getUniformLocation(const std::string &name, bool unsafe)
+{
+	std::map<std::string, GLint>::const_iterator it = uniforms.find(name);
+	if (it != uniforms.end() && (it->second != -1 || unsafe))
+		return it->second;
+
+	GLint location = glGetUniformLocation(program, name.c_str());
+	if (location == -1 && !unsafe)
+	{
+		throw love::Exception("Cannot get location of shader variable `%s'.\n"
+							  "A common error is to define but not use the variable.", name.c_str());
+	}
+
+	uniforms[name] = location;
+	return location;
+}
+
 void Shader::sendFloat(const std::string &name, int size, const GLfloat *vec, int count)
 {
 	TemporaryAttacher attacher(this);
 	sendTexture(name, canvas.getTextureName());
 }
 
-GLint Shader::getUniformLocation(const std::string &name, bool unsafe)
-{
-	std::map<std::string, GLint>::const_iterator it = uniforms.find(name);
-	if (it != uniforms.end() && (it->second != -1 || unsafe))
-		return it->second;
-
-	GLint location = glGetUniformLocation(program, name.c_str());
-	if (location == -1 && !unsafe)
-	{
-		throw love::Exception(
-			"Cannot get location of shader variable `%s'.\n"
-			"A common error is to define but not use the variable.", name.c_str());
-	}
-
-	uniforms[name] = location;
-	return location;
-}
-
 int Shader::getTextureUnit(const std::string &name)
 {
 	std::map<std::string, GLint>::const_iterator it = textureUnitPool.find(name);
 	return textureunit;
 }
 
+bool Shader::hasUniform(const std::string &name)
+{
+	return getUniformLocation(name, true) >= 0;
+}
+
 void Shader::checkSetUniformError()
 {
-	GLenum error_code = glGetError();
-	if (GL_INVALID_OPERATION == error_code)
+	if (glGetError() == GL_INVALID_OPERATION)
 	{
 		throw love::Exception(
 			"Invalid operation:\n"

File src/modules/graphics/opengl/Shader.h

 	 * Send at least one matrix to this Shader as a uniform.
 	 *
 	 * @param name The name of the uniform variable in the source code.
-	 * @param size Number of rows/columns in the matrix.
+	 * @param size Number of rows / columns in the matrix.
 	 * @param m Pointer to the first element of the first matrix.
 	 * @param count Number of matrices to send.
 	 * @param unsafe See above.
 	 **/
 	void sendCanvas(const std::string &name, const Canvas &canvas);
 
+	/**
+	 * Determines whether this Shader has a particular active uniform variable.
+	 *
+	 * @param name The name of the uniform variable in the source code.
+	 **/
+	bool hasUniform(const std::string &name);
+
 	static std::string getGLSLVersion();
 	static bool isSupported();
 

File src/scripts/graphics.lua

 
 attribute vec4 VertexPosition;
 attribute vec4 VertexColor;
-attribute vec4 VertexTexCoord;
+attribute vec2 VertexTexCoord;
 
 varying vec4 VaryingColor;
 varying vec2 VaryingTexCoord;]],
 
 		FOOTER = [[
 void main() {
-	VaryingTexCoord = VertexTexCoord.st;
+	VaryingTexCoord = VertexTexCoord;
 	VaryingColor = VertexColor;
 	gl_Position = position(ModelViewProjectionMatrix, VertexPosition);
 }]],
 	function love.graphics.setMode(...)
 		local success = _setMode(...)
 
-		-- make sure we always have a default shader, if they're supported
+		-- make sure we always have a default shader active, if possible
 		if success then
 			if love.graphics.isSupported("shader") and not love.graphics.getDefaultShader() then
 				local defaultshader = love.graphics.newShader(defaultcode.vert, defaultcode.frag)

File src/scripts/graphics.lua.h

 	0x74, 0x65, 0x78, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x3b, 0x0a,
 	0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x20, 0x76, 0x65, 0x63, 0x34, 0x20, 0x56, 0x65, 0x72, 
 	0x74, 0x65, 0x78, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x3b, 0x0a,
-	0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x20, 0x76, 0x65, 0x63, 0x34, 0x20, 0x56, 0x65, 0x72, 
+	0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x20, 0x76, 0x65, 0x63, 0x32, 0x20, 0x56, 0x65, 0x72, 
 	0x74, 0x65, 0x78, 0x54, 0x65, 0x78, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x3b, 0x0a,
 	0x76, 0x61, 0x72, 0x79, 0x69, 0x6e, 0x67, 0x20, 0x76, 0x65, 0x63, 0x34, 0x20, 0x56, 0x61, 0x72, 0x79, 0x69, 
 	0x6e, 0x67, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x3b, 0x0a,
 	0x09, 0x09, 0x46, 0x4f, 0x4f, 0x54, 0x45, 0x52, 0x20, 0x3d, 0x20, 0x5b, 0x5b, 0x0a,
 	0x76, 0x6f, 0x69, 0x64, 0x20, 0x6d, 0x61, 0x69, 0x6e, 0x28, 0x29, 0x20, 0x7b, 0x0a,
 	0x09, 0x56, 0x61, 0x72, 0x79, 0x69, 0x6e, 0x67, 0x54, 0x65, 0x78, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x20, 0x3d, 
-	0x20, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x54, 0x65, 0x78, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x2e, 0x73, 0x74, 
-	0x3b, 0x0a,
+	0x20, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x54, 0x65, 0x78, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x3b, 0x0a,
 	0x09, 0x56, 0x61, 0x72, 0x79, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x3d, 0x20, 0x56, 0x65, 
 	0x72, 0x74, 0x65, 0x78, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x3b, 0x0a,
 	0x09, 0x67, 0x6c, 0x5f, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x3d, 0x20, 0x70, 0x6f, 0x73, 
 	0x5f, 0x73, 0x65, 0x74, 0x4d, 0x6f, 0x64, 0x65, 0x28, 0x2e, 0x2e, 0x2e, 0x29, 0x0a,
 	0x09, 0x09, 0x2d, 0x2d, 0x20, 0x6d, 0x61, 0x6b, 0x65, 0x20, 0x73, 0x75, 0x72, 0x65, 0x20, 0x77, 0x65, 0x20, 
 	0x61, 0x6c, 0x77, 0x61, 0x79, 0x73, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x61, 0x20, 0x64, 0x65, 0x66, 0x61, 
-	0x75, 0x6c, 0x74, 0x20, 0x73, 0x68, 0x61, 0x64, 0x65, 0x72, 0x2c, 0x20, 0x69, 0x66, 0x20, 0x74, 0x68, 0x65, 
-	0x79, 0x27, 0x72, 0x65, 0x20, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x0a,
+	0x75, 0x6c, 0x74, 0x20, 0x73, 0x68, 0x61, 0x64, 0x65, 0x72, 0x20, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x2c, 
+	0x20, 0x69, 0x66, 0x20, 0x70, 0x6f, 0x73, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x0a,
 	0x09, 0x09, 0x69, 0x66, 0x20, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
 	0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 
 	0x73, 0x2e, 0x69, 0x73, 0x53, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x28, 0x22, 0x73, 0x68, 0x61,