Browse Source

Fixed per-vertex colors (e.g. spritebatch colors) improperly applying gamma correction when the default shader is used and gamma correction is requested but not supported on OpenGL ES.

Alex Szpakowski 9 years ago
parent
commit
aa88383793

+ 4 - 2
src/modules/graphics/opengl/Graphics.cpp

@@ -317,18 +317,20 @@ bool Graphics::setMode(int width, int height)
 	pixelSizeStack.reserve(5);
 	pixelSizeStack.push_back(1);
 
+	int gammacorrect = isGammaCorrect() ? 1 : 0;
+
 	// We always need a default shader.
 	if (!Shader::defaultShader)
 	{
 		Renderer renderer = GLAD_ES_VERSION_2_0 ? RENDERER_OPENGLES : RENDERER_OPENGL;
-		Shader::defaultShader = newShader(Shader::defaultCode[renderer]);
+		Shader::defaultShader = newShader(Shader::defaultCode[renderer][gammacorrect]);
 	}
 
 	// and a default video shader.
 	if (!Shader::defaultVideoShader)
 	{
 		Renderer renderer = GLAD_ES_VERSION_2_0 ? RENDERER_OPENGLES : RENDERER_OPENGL;
-		Shader::defaultVideoShader = newShader(Shader::defaultVideoCode[renderer]);
+		Shader::defaultVideoShader = newShader(Shader::defaultVideoCode[renderer][gammacorrect]);
 	}
 
 	// A shader should always be active, but the default shader shouldn't be

+ 5 - 4
src/modules/graphics/opengl/Shader.cpp

@@ -66,8 +66,8 @@ Shader *Shader::current = nullptr;
 Shader *Shader::defaultShader = nullptr;
 Shader *Shader::defaultVideoShader = nullptr;
 
-Shader::ShaderSource Shader::defaultCode[Graphics::RENDERER_MAX_ENUM];
-Shader::ShaderSource Shader::defaultVideoCode[Graphics::RENDERER_MAX_ENUM];
+Shader::ShaderSource Shader::defaultCode[Graphics::RENDERER_MAX_ENUM][2];
+Shader::ShaderSource Shader::defaultVideoCode[Graphics::RENDERER_MAX_ENUM][2];
 
 std::vector<int> Shader::textureCounters;
 
@@ -250,9 +250,10 @@ bool Shader::loadVolatile()
 
 	std::vector<GLuint> shaderids;
 
-	const ShaderSource *defaults = &defaultCode[Graphics::RENDERER_OPENGL];
+	bool gammacorrect = graphics::isGammaCorrect();
+	const ShaderSource *defaults = &defaultCode[Graphics::RENDERER_OPENGL][gammacorrect ? 1 : 0];
 	if (GLAD_ES_VERSION_2_0)
-		defaults = &defaultCode[Graphics::RENDERER_OPENGLES];
+		defaults = &defaultCode[Graphics::RENDERER_OPENGLES][gammacorrect ? 1 : 0];
 
 	// The shader program must have both vertex and pixel shader stages.
 	const std::string &vertexcode = shaderSource.vertex.empty() ? defaults->vertex : shaderSource.vertex;

+ 2 - 2
src/modules/graphics/opengl/Shader.h

@@ -95,8 +95,8 @@ public:
 	static Shader *defaultVideoShader;
 
 	// Default shader code (a shader is always required internally.)
-	static ShaderSource defaultCode[Graphics::RENDERER_MAX_ENUM];
-	static ShaderSource defaultVideoCode[Graphics::RENDERER_MAX_ENUM];
+	static ShaderSource defaultCode[Graphics::RENDERER_MAX_ENUM][2];
+	static ShaderSource defaultVideoCode[Graphics::RENDERER_MAX_ENUM][2];
 
 	/**
 	 * Creates a new Shader using a list of source codes.

+ 22 - 27
src/modules/graphics/opengl/wrap_Graphics.cpp

@@ -1346,41 +1346,36 @@ int w_getShader(lua_State *L)
 int w_setDefaultShaderCode(lua_State *L)
 {
 	luaL_checktype(L, 1, LUA_TTABLE);
+	luaL_checktype(L, 2, LUA_TTABLE);
 
-	lua_getfield(L, 1, "opengl");
-	lua_rawgeti(L, -1, 1);
-	lua_rawgeti(L, -2, 2);
-	lua_rawgeti(L, -3, 3);
-
-	Shader::ShaderSource openglcode;
-	openglcode.vertex = luax_checkstring(L, -3);
-	openglcode.pixel = luax_checkstring(L, -2);
+	for (int i = 0; i < 2; i++)
+	{
+		bool gammacorrect = i > 0;
 
-	Shader::ShaderSource openglVideocode;
-	openglVideocode.vertex = luax_checkstring(L, -3);
-	openglVideocode.pixel = luax_checkstring(L, -1);
+		for (int renderer = 0; renderer < Graphics::RENDERER_MAX_ENUM; renderer++)
+		{
+			const char *lang = renderer == Graphics::RENDERER_OPENGLES ? "glsles" : "glsl";
 
-	lua_pop(L, 4);
+			lua_getfield(L, i + 1, lang);
 
-	lua_getfield(L, 1, "opengles");
-	lua_rawgeti(L, -1, 1);
-	lua_rawgeti(L, -2, 2);
-	lua_rawgeti(L, -3, 3);
+			lua_getfield(L, -1, "vertex");
+			lua_getfield(L, -2, "pixel");
+			lua_getfield(L, -3, "videopixel");
 
-	Shader::ShaderSource openglescode;
-	openglescode.vertex = luax_checkstring(L, -3);
-	openglescode.pixel = luax_checkstring(L, -2);
+			Shader::ShaderSource code;
+			code.vertex = luax_checkstring(L, -3);
+			code.pixel = luax_checkstring(L, -2);
 
-	Shader::ShaderSource openglesVideocode;
-	openglesVideocode.vertex = luax_checkstring(L, -3);
-	openglesVideocode.pixel = luax_checkstring(L, -1);
+			Shader::ShaderSource videocode;
+			videocode.vertex = luax_checkstring(L, -3);
+			videocode.pixel = luax_checkstring(L, -1);
 
-	lua_pop(L, 4);
+			lua_pop(L, 4);
 
-	Shader::defaultCode[Graphics::RENDERER_OPENGL]   = openglcode;
-	Shader::defaultCode[Graphics::RENDERER_OPENGLES] = openglescode;
-	Shader::defaultVideoCode[Graphics::RENDERER_OPENGL]   = openglVideocode;
-	Shader::defaultVideoCode[Graphics::RENDERER_OPENGLES] = openglesVideocode;
+			Shader::defaultCode[renderer][i] = code;
+			Shader::defaultVideoCode[renderer][i] = videocode;
+		}
+	}
 
 	return 0;
 }

+ 36 - 42
src/modules/graphics/opengl/wrap_Graphics.lua

@@ -23,6 +23,7 @@ misrepresented as being the original software.
 --]]
 
 local table_concat = table.concat
+local ipairs = ipairs
 
 -- SHADERS
 
@@ -139,6 +140,8 @@ varying vec4 VaryingColor;
 uniform mediump float love_PointSize;
 #endif]],
 
+	FUNCTIONS = "",
+
 	FOOTER = [[
 void main() {
 	VaryingTexCoord = VertexTexCoord;
@@ -210,33 +213,21 @@ void main() {
 }]],
 }
 
-local function createVertexCode(vertexcode, lang)
-	local vertexcodes = {
+local function createShaderStageCode(stage, code, lang, gammacorrect, multicanvas)
+	stage = stage:upper()
+	local lines = {
 		lang == "glsles" and GLSL.VERSION_ES or GLSL.VERSION,
 		GLSL.SYNTAX,
-		love.graphics.isGammaCorrect() and "#define LOVE_GAMMA_CORRECT 1" or "",
-		GLSL.VERTEX.HEADER, GLSL.UNIFORMS,
+		gammacorrect and "#define LOVE_GAMMA_CORRECT 1" or "",
+		GLSL[stage].HEADER,
+		GLSL.UNIFORMS,
 		GLSL.FUNCTIONS,
+		GLSL[stage].FUNCTIONS,
 		lang == "glsles" and "#line 1" or "#line 0",
-		vertexcode,
-		GLSL.VERTEX.FOOTER,
+		code,
+		multicanvas and GLSL[stage].FOOTER_MULTI_CANVAS or GLSL[stage].FOOTER,
 	}
-	return table_concat(vertexcodes, "\n")
-end
-
-local function createPixelCode(pixelcode, is_multicanvas, lang)
-	local pixelcodes = {
-		lang == "glsles" and GLSL.VERSION_ES or GLSL.VERSION,
-		GLSL.SYNTAX,
-		love.graphics.isGammaCorrect() and "#define LOVE_GAMMA_CORRECT 1" or "",
-		GLSL.PIXEL.HEADER, GLSL.UNIFORMS,
-		GLSL.FUNCTIONS,
-		GLSL.PIXEL.FUNCTIONS,
-		lang == "glsles" and "#line 1" or "#line 0",
-		pixelcode,
-		is_multicanvas and GLSL.PIXEL.FOOTER_MULTI_CANVAS or GLSL.PIXEL.FOOTER,
-	}
-	return table_concat(pixelcodes, "\n")
+	return table_concat(lines, "\n")
 end
 
 local function isVertexCode(code)
@@ -258,11 +249,6 @@ function love.graphics._shaderCodeToGLSL(arg1, arg2)
 	local vertexcode, pixelcode
 	local is_multicanvas = false -- whether pixel code has "effects" function instead of "effect"
 
-	local lang = "glsl"
-	if (love.graphics.getRendererInfo()) == "OpenGL ES" then
-		lang = "glsles"
-	end
-
 	if arg1 then
 		if isVertexCode(arg1) then
 			vertexcode = arg1 -- first arg contains vertex shader code
@@ -287,11 +273,18 @@ function love.graphics._shaderCodeToGLSL(arg1, arg2)
 		end
 	end
 
+	local lang = "glsl"
+	if love.graphics.getRendererInfo() == "OpenGL ES" then
+		lang = "glsles"
+	end
+
+	local gammacorrect = love.graphics.isGammaCorrect()
+
 	if vertexcode then
-		vertexcode = createVertexCode(vertexcode, lang)
+		vertexcode = createShaderStageCode("VERTEX", vertexcode, lang, gammacorrect)
 	end
 	if pixelcode then
-		pixelcode = createPixelCode(pixelcode, is_multicanvas, lang)
+		pixelcode = createShaderStageCode("PIXEL", pixelcode, lang, gammacorrect, is_multicanvas)
 	end
 
 	return vertexcode, pixelcode
@@ -339,20 +332,21 @@ vec4 effect(mediump vec4 vcolor, Image tex, vec2 texcoord, vec2 pixcoord) {
 }]],
 }
 
-local defaults = {
-	opengl = {
-		createVertexCode(defaultcode.vertex, "glsl"),
-		createPixelCode(defaultcode.pixel, false, "glsl"),
-		createPixelCode(defaultcode.videopixel, false, "glsl"),
-	},
-	opengles = {
-		createVertexCode(defaultcode.vertex, "glsles"),
-		createPixelCode(defaultcode.pixel, false, "glsles"),
-		createPixelCode(defaultcode.videopixel, false, "glsles"),
-	},
-}
+local defaults = {}
+local defaults_gammacorrect = {}
+
+for _, lang in ipairs{"glsl", "glsles"} do
+	for _, gammacorrect in ipairs{false, true} do
+		local t = gammacorrect and defaults_gammacorrect or defaults
+		t[lang] = {
+			vertex = createShaderStageCode("VERTEX", defaultcode.vertex, lang, gammacorrect),
+			pixel = createShaderStageCode("PIXEL", defaultcode.pixel, lang, gammacorrect, false),
+			videopixel = createShaderStageCode("PIXEL", defaultcode.videopixel, lang, gammacorrect, false),
+		}
+	end
+end
 
-love.graphics._setDefaultShaderCode(defaults)
+love.graphics._setDefaultShaderCode(defaults, defaults_gammacorrect)
 
 function love.graphics.newVideo(file, loadaudio)
 	local video = love.graphics._newVideo(file)