From 7bb39209698055ae67a798a8f7b2c8485747a13b Mon Sep 17 00:00:00 2001 From: LunaTheFoxgirl Date: Sun, 23 Jan 2022 20:40:03 +0100 Subject: [PATCH] Switch Inochi2D to premultipled alpha --- shaders/basic/basic.frag | 2 +- source/inochi2d/core/dbg.d | 6 ++++++ source/inochi2d/core/nodes/part/package.d | 2 +- source/inochi2d/core/package.d | 19 +++++++++++++++---- source/inochi2d/core/texture.d | 20 +++++++++++++++++++- 5 files changed, 42 insertions(+), 7 deletions(-) diff --git a/shaders/basic/basic.frag b/shaders/basic/basic.frag index ff9765f..821e528 100644 --- a/shaders/basic/basic.frag +++ b/shaders/basic/basic.frag @@ -12,5 +12,5 @@ uniform sampler2D fbo; uniform float opacity; void main() { - outColor = texture(fbo, texUVs) * vec4(1, 1, 1, opacity); + outColor = texture(fbo, texUVs) * opacity; } \ No newline at end of file diff --git a/source/inochi2d/core/dbg.d b/source/inochi2d/core/dbg.d index 7e3093a..c654497 100644 --- a/source/inochi2d/core/dbg.d +++ b/source/inochi2d/core/dbg.d @@ -99,6 +99,8 @@ void inDbgSetBuffer(vec3[] points, ushort[] indices) { */ void inDbgDrawPoints(vec4 color, mat4 transform = mat4.identity) { glEnable(GL_POINT_SMOOTH); + glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE); + glBindVertexArray(dbgVAO); dbgShader.use(); @@ -112,6 +114,7 @@ void inDbgDrawPoints(vec4 color, mat4 transform = mat4.identity) { glDrawElements(GL_POINTS, indiceCount, GL_UNSIGNED_SHORT, null); glDisableVertexAttribArray(0); + glBlendFuncSeparate(GL_ONE, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE); glDisable(GL_POINT_SMOOTH); } @@ -120,6 +123,8 @@ void inDbgDrawPoints(vec4 color, mat4 transform = mat4.identity) { */ void inDbgDrawLines(vec4 color, mat4 transform = mat4.identity) { glEnable(GL_LINE_SMOOTH); + glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE); + glBindVertexArray(dbgVAO); dbgShader.use(); @@ -133,5 +138,6 @@ void inDbgDrawLines(vec4 color, mat4 transform = mat4.identity) { glDrawElements(GL_LINES, indiceCount, GL_UNSIGNED_SHORT, null); glDisableVertexAttribArray(0); + glBlendFuncSeparate(GL_ONE, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE); glDisable(GL_LINE_SMOOTH); } \ No newline at end of file diff --git a/source/inochi2d/core/nodes/part/package.d b/source/inochi2d/core/nodes/part/package.d index 326f5b5..0a69fd2 100644 --- a/source/inochi2d/core/nodes/part/package.d +++ b/source/inochi2d/core/nodes/part/package.d @@ -484,7 +484,7 @@ void inDrawTextureAtPart(Texture texture, Part part) { partShader.use(); partShader.setUniform(mvp, inGetCamera().matrix * - mat4.translation(part.transform.matrix() * vec3(1, 1, 1)) + mat4.translation(vec3(part.transform.matrix() * vec4(1, 1, 1, 1))) ); partShader.setUniform(gopacity, part.opacity); diff --git a/source/inochi2d/core/package.d b/source/inochi2d/core/package.d index 78927c5..366fb53 100644 --- a/source/inochi2d/core/package.d +++ b/source/inochi2d/core/package.d @@ -41,6 +41,8 @@ private { GLuint fColor; GLuint fStencil; + vec4 inClearColor; + Shader[] blendingShaders; @@ -70,6 +72,8 @@ package(inochi2d) { // Some defaults that should be changed by app writer inCamera = new Camera; + inClearColor = vec4(0, 0, 0, 0); + // Shader for scene sceneShader = new Shader(import("scene.vert"), import("scene.frag")); sceneMVP = sceneShader.getUniformLocation("mvp"); @@ -95,7 +99,7 @@ package(inochi2d) { /** Begins rendering to the framebuffer */ -void inBeginScene() { +void inBeginScene() { glEnable(GL_BLEND); glDisable(GL_DEPTH_TEST); @@ -104,13 +108,13 @@ void inBeginScene() { // Bind our framebuffer glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fBuffer); - glClearColor(0, 0, 0, 0); + glClearColor(inClearColor.r, inClearColor.g, inClearColor.b, inClearColor.a); glClear(GL_COLOR_BUFFER_BIT); // Everything else is the actual texture used by the meshes at id 0 glActiveTexture(GL_TEXTURE0); - glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE); + glBlendFuncSeparate(GL_ONE, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); } /** @@ -151,7 +155,7 @@ void inDrawScene(vec4 area) { glDisable(GL_CULL_FACE); glDisable(GL_DEPTH_TEST); glEnable(GL_BLEND); - glBlendFuncSeparate(GL_ONE, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE); + glBlendFuncSeparate(GL_ONE, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); sceneShader.use(); sceneShader.setUniform(sceneMVP, @@ -264,4 +268,11 @@ void inDumpViewport(ref ubyte[] dumpTo) { ri++; } +} + +/** + Sets the background clear color +*/ +void inSetClearColor(float r, float g, float b, float a) { + inClearColor = vec4(r, g, b, a); } \ No newline at end of file diff --git a/source/inochi2d/core/texture.d b/source/inochi2d/core/texture.d index 6f2c0c3..a618788 100644 --- a/source/inochi2d/core/texture.d +++ b/source/inochi2d/core/texture.d @@ -202,7 +202,7 @@ public: // Set default filtering and wrapping this.setFiltering(Filtering.Linear); - this.setWrapping(Wrapping.Mirror); + this.setWrapping(Wrapping.Clamp); } /** @@ -362,4 +362,22 @@ void inEndTextureLoading() { enforce(started, "Texture loading pass not started!"); started = false; textureBindings.length = 0; +} + +void inTexPremultiply(ref ubyte[] data) { + foreach(i; 0..data.length/4) { + data[((i*4)+0)] = cast(ubyte)((cast(int)data[((i*4)+0)] * cast(int)data[((i*4)+3)])/255); + data[((i*4)+1)] = cast(ubyte)((cast(int)data[((i*4)+1)] * cast(int)data[((i*4)+3)])/255); + data[((i*4)+2)] = cast(ubyte)((cast(int)data[((i*4)+2)] * cast(int)data[((i*4)+3)])/255); + } +} + +void inTexUnPremuliply(ref ubyte[] data) { + foreach(i; 0..data.length/4) { + if (data[((i*4)+3)] == 0) continue; + + data[((i*4)+0)] = cast(ubyte)(cast(int)data[((i*4)+0)] * 255 / cast(int)data[((i*4)+3)]); + data[((i*4)+1)] = cast(ubyte)(cast(int)data[((i*4)+1)] * 255 / cast(int)data[((i*4)+3)]); + data[((i*4)+2)] = cast(ubyte)(cast(int)data[((i*4)+2)] * 255 / cast(int)data[((i*4)+3)]); + } } \ No newline at end of file