From 3505b2dd6a7ea5b3a4b964d508361154dc7c91bb Mon Sep 17 00:00:00 2001 From: minjaesong Date: Sat, 15 Jul 2017 18:35:57 +0900 Subject: [PATCH] bayer-dithering shader revisited --- assets/4096_bayer.frag | 83 +++++++++---------- src/net/torvald/dataclass/Float16.kt | 7 ++ src/net/torvald/terrarum/ColorLimiterTest.kt | 9 +- .../terrarum/worlddrawer/LightmapRenderer.kt | 4 +- 4 files changed, 54 insertions(+), 49 deletions(-) diff --git a/assets/4096_bayer.frag b/assets/4096_bayer.frag index 59cf3dc5c..36fc5a9f8 100644 --- a/assets/4096_bayer.frag +++ b/assets/4096_bayer.frag @@ -4,56 +4,53 @@ uniform sampler2D u_texture; -uniform mat4 Bayer; -uniform float monitorGamma; +//uniform mat4 bayer; +uniform float monitorGamma; // give 2.2f -vec4 gammaIn(vec4 col) { - return pow(col, vec4(vec3(monitorGamma), 1.0)); -} +int bayer[8][8] = { +{ 0, 32, 8, 40, 2, 34, 10, 42}, // 8x8 bayer ordered dithering +{48, 16, 56, 24, 50, 18, 58, 26}, // pattern. Each input pixel +{12, 44, 4, 36, 14, 46, 6, 38}, // is scaled to the 0..63 range +{60, 28, 52, 20, 62, 30, 54, 22}, // before looking in this table +{ 3, 35, 11, 43, 1, 33, 9, 41}, // to determine the action +{51, 19, 59, 27, 49, 17, 57, 25}, +{15, 47, 7, 39, 13, 45, 5, 37}, +{63, 31, 55, 23, 61, 29, 53, 21} }; // fun fact: you can calculate bayer value on-the-fly but LUT is faster +float bayerSize = 8.0; +float bayerDivider = bayerSize * bayerSize; -vec4 gammaOut(vec4 col) { - return pow(col, vec4(vec3(1.0 / monitorGamma), 1.0)); + +vec4 nearestColour(vec4 incolor) { + vec4 rgbaCounts = vec4(16.0, 16.0, 16.0, 1.0); + + + vec4 color = incolor; + + color.r = floor((rgbaCounts.r - 1.0) * color.r + 0.5) / (rgbaCounts.r - 1.0); + color.g = floor((rgbaCounts.g - 1.0) * color.g + 0.5) / (rgbaCounts.g - 1.0); + color.b = floor((rgbaCounts.b - 1.0) * color.b + 0.5) / (rgbaCounts.b - 1.0); + + if (rgbaCounts.a >= 2.0) { + color.a = floor((rgbaCounts.a - 1.0) * color.a + 0.5) / (rgbaCounts.a - 1.0); + } + else if (rgbaCounts.a == 1.0) { + color.a = (color.a >= 0.5f) ? 1.0 : 0.0; + } + else { + color.a = 1.0; + } + + return color; } void main(void) { // create texture coordinates based on pixelSize // - float pixelSize = 1.0; + vec4 inColor = texture2D(u_texture, v_texCoords); - vec2 pixelSizeVec = vec2(float(pixelSize), float(pixelSize)); + vec2 entry = mod(gl_FragCoord.xy, vec2(bayerSize, bayerSize)); - vec2 discrete = (gl_FragCoord.xy + 0.001) / v_texCoords / pixelSizeVec; - //vec2 discrete = (gl_FragCoord.xy) / v_texCoords / pixelSizeVec; + float r = 1.0 / monitorGamma; - discrete = floor(discrete * v_texCoords) / discrete; - - vec4 color = texture2D(u_texture, discrete).rgba; - - - // add Bayer matrix entry to current pixel // - vec2 entry = mod(gl_FragCoord.xy / pixelSizeVec, vec2(4, 4)); - - color.r = color.r + Bayer[int(entry.x)][int(entry.y)] / 17.0 - 0.5; - color.g = color.g + Bayer[int(entry.x)][int(entry.y)] / 17.0 - 0.5; - color.b = color.b + Bayer[int(entry.x)][int(entry.y)] / 17.0 - 0.5; - //color.a = color.a + Bayer[int(entry.x)][int(entry.y)] / 17.0 - 0.5; - - - // find nearest 8-bit color // - color.r = floor(15.0 * color.r + 0.5) / 15.0; - color.g = floor(15.0 * color.g + 0.5) / 15.0; - color.b = floor(15.0 * color.b + 0.5) / 15.0; - //color.a = floor(15.0 * color.a + 0.5) / 15.0; - - gl_FragColor = color; - - - - - - - - //vec4 color = texture2D(u_texture, v_texCoords); - //color = floor(15.0 * color + 0.5) / 15.0; -// - //gl_FragColor = color; + gl_FragColor = nearestColour(inColor + r * (bayer[int(entry.y)][int(entry.x)] / bayerDivider - 0.5)); + //gl_FragColor = nearestColour(inColor); } \ No newline at end of file diff --git a/src/net/torvald/dataclass/Float16.kt b/src/net/torvald/dataclass/Float16.kt index c0bb5a9bc..f04c421c5 100644 --- a/src/net/torvald/dataclass/Float16.kt +++ b/src/net/torvald/dataclass/Float16.kt @@ -23,6 +23,13 @@ class Float16() { bits = Float16.fromFloat(fval) } + + operator fun times(other: Float) = fromFloat(this.toFloat() * other) + operator fun times(other: Float16) = fromFloat(this.toFloat() * other.toFloat()) + + operator fun div(other: Float) = fromFloat(this.toFloat() / other) + operator fun div(other: Float16) = fromFloat(this.toFloat() / other.toFloat()) + // operators are stripped: you don't calculate from FP16; this is only for storing values // companion object { diff --git a/src/net/torvald/terrarum/ColorLimiterTest.kt b/src/net/torvald/terrarum/ColorLimiterTest.kt index 43ce686e6..676401f02 100644 --- a/src/net/torvald/terrarum/ColorLimiterTest.kt +++ b/src/net/torvald/terrarum/ColorLimiterTest.kt @@ -37,9 +37,9 @@ object ColorLimiterTest : ApplicationAdapter() { override fun create() { ShaderProgram.pedantic = false - shader4096 = ShaderProgram(Gdx.files.internal("assets/4096.vert"), Gdx.files.internal("assets/4096.frag")) + shader4096 = ShaderProgram(Gdx.files.internal("assets/4096.vert"), Gdx.files.internal("assets/4096_bayer.frag")) shader4096.begin() - //shader4096.setUniformMatrix("Bayer", Matrix4(floatArrayOf(0f,8f,2f,10f,12f,4f,14f,6f,3f,11f,1f,9f,15f,7f,13f,5f))) + shader4096.setUniformf("monitorGamma", 2.2f) shader4096.end() @@ -57,13 +57,14 @@ object ColorLimiterTest : ApplicationAdapter() { batch.inUse { batch.shader = shader4096 - //batch.shader.setUniformf("monitorGamma", 2.2f) - + shader4096.setUniformf("rgbaCounts", 16f, 16f, 16f, 16f) batch.color = Color.WHITE batch.draw(img, 0f, 0f) batch.shader = null + batch.color = Color.WHITE + batch.draw(img, img.width.toFloat(), 0f) } } diff --git a/src/net/torvald/terrarum/worlddrawer/LightmapRenderer.kt b/src/net/torvald/terrarum/worlddrawer/LightmapRenderer.kt index 4c203e2e9..50d999047 100644 --- a/src/net/torvald/terrarum/worlddrawer/LightmapRenderer.kt +++ b/src/net/torvald/terrarum/worlddrawer/LightmapRenderer.kt @@ -21,6 +21,8 @@ import java.util.* //typealias RGB10 = Int +// NOTE: no Float16 on this thing: 67 kB of memory footage is totally acceptable + object LightmapRenderer { private val world: GameWorld = Terrarum.ingame!!.world @@ -41,8 +43,6 @@ object LightmapRenderer { val LIGHTMAP_HEIGHT = Terrarum.ingame!!.ZOOM_MINIMUM.inv().times(Terrarum.HEIGHT) .div(FeaturesDrawer.TILE_SIZE).ceil() + overscan_open * 2 + 3 - //data class Lux(var r: Float16, var g: Float16, var b: Float16, var uv: Float16) - /** * Float value, 1.0 for 1023 */