From d045560ef5fc644725e03508d5232547ed51cb19 Mon Sep 17 00:00:00 2001 From: a dinosaur Date: Thu, 17 Aug 2023 21:17:28 +1000 Subject: [PATCH] un-hardcode fog config --- src/main/kotlin/CustomDefaultShader.kt | 71 ++++++++++++++++ .../kotlin/CustomDefaultShaderProvider.kt | 34 ++++++++ src/main/kotlin/CustomFloatAttribute.kt | 21 +++++ src/main/kotlin/CustomIntAttribute.kt | 37 +++++++++ src/main/kotlin/Game.kt | 31 ++++--- src/main/kotlin/Util.kt | 6 ++ src/main/resources/lit.frag.glsl | 81 +++++++------------ 7 files changed, 218 insertions(+), 63 deletions(-) create mode 100644 src/main/kotlin/CustomDefaultShader.kt create mode 100644 src/main/kotlin/CustomDefaultShaderProvider.kt create mode 100644 src/main/kotlin/CustomFloatAttribute.kt create mode 100644 src/main/kotlin/CustomIntAttribute.kt diff --git a/src/main/kotlin/CustomDefaultShader.kt b/src/main/kotlin/CustomDefaultShader.kt new file mode 100644 index 0000000..eda4cad --- /dev/null +++ b/src/main/kotlin/CustomDefaultShader.kt @@ -0,0 +1,71 @@ +package gay.pizza.CavesOfJolk + +import com.badlogic.gdx.graphics.g3d.Attributes +import com.badlogic.gdx.graphics.g3d.Renderable +import com.badlogic.gdx.graphics.g3d.attributes.ColorAttribute +import com.badlogic.gdx.graphics.g3d.shaders.DefaultShader + +class CustomDefaultShader(renderable: Renderable, config: Config): + DefaultShader(renderable, config, createPrefix(renderable, config)) +{ + companion object + { + fun createPrefix(renderable: Renderable, config: Config): String + { + var prefix = DefaultShader.createPrefix(renderable, config) + + val attribs = Attributes() + renderable.environment.let { attribs.set(it) } + renderable.material.let { attribs.set(it) } + + if (attribs.has(ColorAttribute.Fog)) + { + prefix += "#define fog${ + when (attribs.get(CustomIntAttribute.FogMode)?.value + ?: CustomIntAttribute.FogModes.Distance.toInt()) { + CustomIntAttribute.FogModes.Distance.toInt() -> "Distance" + CustomIntAttribute.FogModes.Depth.toInt() -> "Depth" + else -> throw IndexOutOfBoundsException() + } + }Flag\n" + prefix += "#define fog${ + when (attribs.get(CustomIntAttribute.FogType)?.value + ?: CustomIntAttribute.FogTypes.Original.toInt()) { + CustomIntAttribute.FogTypes.Original.toInt() -> "Original" + CustomIntAttribute.FogTypes.Linear.toInt() -> "Linear" + CustomIntAttribute.FogTypes.Smooth.toInt() -> "Smooth" + CustomIntAttribute.FogTypes.InvSquare.toInt() -> "InvSquare" + CustomIntAttribute.FogTypes.Exp.toInt() -> "Exp" + CustomIntAttribute.FogTypes.Exp2.toInt() -> "Exp2" + else -> throw IndexOutOfBoundsException() + } + }Flag\n" + } + + return prefix + } + + object Inputs + { + val fogNear = Uniform("u_fogNear") + val fogFar = Uniform("u_fogFar") + val fogDensity = Uniform("u_fogDensity") + } + } + + private val u_fogNear = register(Inputs.fogNear) + private val u_fogFar = register(Inputs.fogFar) + private val u_fogDensity = register(Inputs.fogDensity) + + override fun bindLights(renderable: Renderable?, attributes: Attributes?) + { + if (attributes == null) + return + + attributes.get(CustomFloatAttribute.FogNear)?.let { set(u_fogNear, it.value) } + attributes.get(CustomFloatAttribute.FogFar)?.let { set(u_fogFar, it.value) } + attributes.get(CustomFloatAttribute.FogDensity)?.let { set(u_fogDensity, it.value) } + + super.bindLights(renderable, attributes) + } +} diff --git a/src/main/kotlin/CustomDefaultShaderProvider.kt b/src/main/kotlin/CustomDefaultShaderProvider.kt new file mode 100644 index 0000000..f8323cb --- /dev/null +++ b/src/main/kotlin/CustomDefaultShaderProvider.kt @@ -0,0 +1,34 @@ +package gay.pizza.CavesOfJolk + +import com.badlogic.gdx.Gdx +import com.badlogic.gdx.graphics.g3d.Renderable +import com.badlogic.gdx.graphics.g3d.Shader +import com.badlogic.gdx.graphics.g3d.attributes.ColorAttribute +import com.badlogic.gdx.graphics.g3d.shaders.DefaultShader +import com.badlogic.gdx.graphics.g3d.utils.DefaultShaderProvider + +class CustomDefaultShaderProvider(config: DefaultShader.Config): DefaultShaderProvider(config) +{ + init + { + if (config.vertexShader == null) + config.vertexShader = Gdx.files.internal("lit.vert.glsl").readString() + if (config.fragmentShader == null) + config.fragmentShader = Gdx.files.internal("lit.frag.glsl").readString() + } + + override fun createShader(renderable: Renderable): Shader + { + val renderableMask = renderable.environment.mask or renderable.material.mask + + val fogMask = + CustomIntAttribute.FogMode or + CustomIntAttribute.FogType or + CustomFloatAttribute.FogNear or + CustomFloatAttribute.FogFar or + CustomFloatAttribute.FogDensity + if ((renderableMask and ColorAttribute.Fog == ColorAttribute.Fog) && (renderableMask and fogMask != 0L)) + return CustomDefaultShader(renderable, config) + return super.createShader(renderable) + } +} diff --git a/src/main/kotlin/CustomFloatAttribute.kt b/src/main/kotlin/CustomFloatAttribute.kt new file mode 100644 index 0000000..2171dfd --- /dev/null +++ b/src/main/kotlin/CustomFloatAttribute.kt @@ -0,0 +1,21 @@ +package gay.pizza.CavesOfJolk + +import com.badlogic.gdx.graphics.g3d.attributes.FloatAttribute + +class CustomFloatAttribute private constructor(type: Long, value: Float): FloatAttribute(type, value) +{ + companion object + { + const val FogNearAlias = "fogNear" + val FogNear = register(FogNearAlias) + fun createFogNear(value: Float) = CustomFloatAttribute(FogNear, value) + + const val FogFarAlias = "fogFar" + val FogFar = register(FogFarAlias) + fun createFogFar(value: Float) = CustomFloatAttribute(FogFar, value) + + const val FogDensityAlias = "fogDensity" + val FogDensity = register(FogDensityAlias) + fun createFogDensity(value: Float) = CustomFloatAttribute(FogDensity, value) + } +} diff --git a/src/main/kotlin/CustomIntAttribute.kt b/src/main/kotlin/CustomIntAttribute.kt new file mode 100644 index 0000000..3ee4e98 --- /dev/null +++ b/src/main/kotlin/CustomIntAttribute.kt @@ -0,0 +1,37 @@ +package gay.pizza.CavesOfJolk + +import com.badlogic.gdx.graphics.g3d.attributes.IntAttribute + +class CustomIntAttribute private constructor(type: Long, value: Int): IntAttribute(type, value) +{ + enum class FogModes(private val value: Int) + { + Distance(0), + Depth(1); + + fun toInt() = value + } + + enum class FogTypes(private val value: Int) + { + Original(0), + Linear(1), + Smooth(2), + InvSquare(3), + Exp(4), + Exp2(5); + + fun toInt() = value + } + + companion object + { + const val FogModeAlias = "fogMode" + val FogMode = register(FogModeAlias) + fun createFogMode(value: FogModes) = CustomIntAttribute(FogMode, value.toInt()) + + const val FogTypeAlias = "fogType" + val FogType = register(FogTypeAlias) + fun createFogType(value: FogTypes) = CustomIntAttribute(FogType, value.toInt()) + } +} diff --git a/src/main/kotlin/Game.kt b/src/main/kotlin/Game.kt index 1878012..8b44b0b 100644 --- a/src/main/kotlin/Game.kt +++ b/src/main/kotlin/Game.kt @@ -2,7 +2,6 @@ package gay.pizza.CavesOfJolk import com.badlogic.gdx.ApplicationAdapter import com.badlogic.gdx.Gdx -import com.badlogic.gdx.audio.Sound import com.badlogic.gdx.graphics.* import com.badlogic.gdx.graphics.g2d.BitmapFont import com.badlogic.gdx.graphics.g2d.SpriteBatch @@ -13,7 +12,6 @@ import com.badlogic.gdx.graphics.g3d.attributes.IntAttribute import com.badlogic.gdx.graphics.g3d.attributes.TextureAttribute import com.badlogic.gdx.graphics.g3d.environment.DirectionalLight import com.badlogic.gdx.graphics.g3d.shaders.DefaultShader -import com.badlogic.gdx.graphics.g3d.utils.DefaultShaderProvider import com.badlogic.gdx.graphics.g3d.utils.ModelBuilder import com.badlogic.gdx.graphics.g3d.utils.TextureDescriptor import com.badlogic.gdx.math.* @@ -24,7 +22,6 @@ class Game: ApplicationAdapter() { private lateinit var texJolk: Texture private lateinit var fntComic: BitmapFont - private lateinit var nut: Sound private lateinit var cube: Model private lateinit var floor: Model @@ -95,18 +92,28 @@ class Game: ApplicationAdapter() spriteBatch = SpriteBatch() env = Environment() - env.set(IntAttribute.createCullFace(GL20.GL_BACK)) - env.set(ColorAttribute.createAmbientLight(XnaColor.DarkSlateGray.lighten(-0.6))) - env.set(ColorAttribute.createFog(XnaColor.CornflowerBlue)) + env.set( + IntAttribute.createCullFace(GL20.GL_BACK), + ColorAttribute.createAmbientLight(XnaColor.DarkSlateGray.lighten(-0.6)), + ColorAttribute.createFog(XnaColor.CornflowerBlue)) + env.set( + CustomIntAttribute.createFogMode(CustomIntAttribute.FogModes.Depth), + CustomIntAttribute.createFogType(CustomIntAttribute.FogTypes.Smooth), + CustomFloatAttribute.createFogNear(0.75f), + CustomFloatAttribute.createFogFar(20.5f)) + /* + env.set( + CustomIntAttribute.createFogMode(CustomIntAttribute.FogModes.Distance), + CustomIntAttribute.createFogType(CustomIntAttribute.FogTypes.Exp2), + CustomFloatAttribute.createFogDensity(0.1f)) + */ env.add(DirectionalLight().set(XnaColor.White, Vector3(1.0f, -1.0f, -1.0f).nor())) - val shaderConfig = DefaultShader.Config( - Gdx.files.internal("lit.vert.glsl").readString(), - Gdx.files.internal("lit.frag.glsl").readString()) + val shaderConfig = DefaultShader.Config() shaderConfig.numDirectionalLights = 1 shaderConfig.numPointLights = 0 shaderConfig.numBones = 0 - modelBatch = ModelBatch(DefaultShaderProvider(shaderConfig)) + modelBatch = ModelBatch(CustomDefaultShaderProvider(shaderConfig)) colin = Colin() @@ -136,9 +143,7 @@ class Game: ApplicationAdapter() val deltaTime = Gdx.graphics.deltaTime update(deltaTime) - val fogColour = XnaColor.CornflowerBlue.lighten(Math.sin(0.056 * jolkRot.toDouble()) * 0.15 - 0.15) - ScreenUtils.clear(fogColour, true) - env.set(ColorAttribute.createFog(fogColour)) + ScreenUtils.clear(XnaColor.CornflowerBlue, true) val jolkPos = Vector3(0.0f, 1.0f + MathUtils.sin(jolkRot * 0.25f) * 0.25f, -4.0f) val world = Matrix4() diff --git a/src/main/kotlin/Util.kt b/src/main/kotlin/Util.kt index 431b399..8cc9c43 100644 --- a/src/main/kotlin/Util.kt +++ b/src/main/kotlin/Util.kt @@ -1,6 +1,8 @@ package gay.pizza.CavesOfJolk import com.badlogic.gdx.graphics.Color +import com.badlogic.gdx.graphics.g3d.Attribute +import com.badlogic.gdx.graphics.g3d.Attributes import com.badlogic.gdx.math.MathUtils import com.badlogic.gdx.math.Vector2 import ktx.math.div @@ -58,3 +60,7 @@ fun Color.mix(rhs: Color, x: Float) = Color( MathUtils.lerp(this.g, rhs.g, x), MathUtils.lerp(this.b, rhs.b, x), MathUtils.lerp(this.a, rhs.a, x)) + +//FIXME: find some way to get rid of these warnings +@Suppress("EXTENSION_SHADOWED_BY_MEMBER", "UNCHECKED_CAST") +fun Attributes.get(type: Long) = get(type) as? T diff --git a/src/main/resources/lit.frag.glsl b/src/main/resources/lit.frag.glsl index 908007c..94eb43c 100644 --- a/src/main/resources/lit.frag.glsl +++ b/src/main/resources/lit.frag.glsl @@ -88,7 +88,14 @@ uniform vec4 u_cameraPosition; #ifdef fogFlag uniform vec4 u_fogColor; -varying float v_fog; + +#if defined(fogLinearFlag) || defined(fogSmoothFlag) || defined(fogInvSquareFlag) +uniform float u_fogNear; +uniform float u_fogFar; +#elif defined(fogExpFlag) || defined(fogExp2Flag) +uniform float u_fogDensity; +#endif + #endif // fogFlag uniform mat4 u_projViewTrans; @@ -174,68 +181,42 @@ void main() fragment = diffuse.rgb; #endif // lightingFlag -#ifdef fogFlag -#define fogDistance -//#define fogDepth +#ifdef fogOriginalFlag + vec3 fogVec = u_cameraPosition.xyz - v_worldPosition.xyz; + float fogDist = dot(fogVec, fogVec); + float fog = min(fogDist * u_cameraPosition.w, 1.0); +#elif defined(fogDistanceFlag) + float fogDist = length(v_worldPosition.xyz - u_cameraPosition.xyz); +#elif defined(fogDepthFlag) + float fogDist = gl_FragCoord.z / gl_FragCoord.w; +#endif // fogOriginalFlag || fogDistanceFlag || fogDepthFlag -//#define fogOriginal -//#define fogLinear -#define fogSmooth -//#define fogInvSquare -//#define fogExp -//#define fogExp2 - -#if defined(fogLinear) || defined(fogSmooth) || defined(fogInvSquare) - float near = 1.5; - float far = 20.5; -#elif defined(fogExp) || defined(fogExp2) - float density = 0.12; -#endif - -#ifdef fogOriginal - vec3 fvec = u_cameraPosition.xyz - v_worldPosition.xyz; - float flen = dot(fvec, fvec); - float fog = min(flen * u_cameraPosition.w, 1.0); -#elif defined(fogDistance) - float flen = length(v_worldPosition.xyz - u_cameraPosition.xyz); -#elif defined(fogDepth) - float flen = gl_FragCoord.z / gl_FragCoord.w; -#endif // fogOriginal || fogDistance || fogDepth - -#ifdef fogLinear +#ifdef fogLinearFlag // fog = saturate(linearstep(near, far, x)) - float fog = clamp((flen - near) / (far - near), 0.0, 1.0); -#elif defined(fogSmooth) + float fog = clamp((fogDist - u_fogNear) / (u_fogFar - u_fogNear), 0.0, 1.0); +#elif defined(fogSmoothFlag) // fog = smoothstep(saturate(linearstep(near, far, x))) - float fog = clamp((flen - near) / (far - near), 0.0, 1.0); + float fog = clamp((fogDist - u_fogNear) / (u_fogFar - u_fogNear), 0.0, 1.0); fog = fog * fog * (3.0 - 2.0 * fog); //fog = fog * fog * fog * (fog * (6.0 * fog - 15.0) + 10.0); -#elif defined(fogInvSquare) +#elif defined(fogInvSquareFlag) // fog = isqstep(saturate(linearstep(near, far, x))) - float fog = clamp((flen - near) / (far - near), 0.0, 1.0); + float fog = clamp((fogDist - u_fogNear) / (u_fogFar - u_fogNear), 0.0, 1.0); fog = 1.0 - fog; fog = 1.0 - fog * fog; -#elif defined(fogExp) - float fog = max(1.0 - exp(-density * flen), 0.0); -#elif defined(fogExp2) - float dz = density * flen; +#elif defined(fogExpFlag) + // todo: can precompute some stuff in uniforms + float fog = max(1.0 - exp(-u_fogDensity * fogDist), 0.0); +#elif defined(fogExp2Flag) + // todo: can precompute some stuff in uniforms + float dz = u_fogDensity * fogDist; float fog = max(1.0 - exp(-dz * dz), 0.0); -#endif // fogLinear || fogSmooth || fogInvSquare || fogExp || fogExp2 +#endif // fogLinearFlag || fogSmoothFlag || fogInvSquareFlag || fogExpFlag || fogExp2Flag +#ifdef fogFlag vec3 fogColor = u_fogColor.rgb; fogColor = linearEncode(fogColor); fragment = mix(fragment, fogColor, fog); #endif // fogFlag gl_FragColor = vec4(linearDecode(fragment), diffuse.a); - /* - if (gl_FragCoord.x > 1280.0) - { - if (fog <= 0.0) - gl_FragColor = vec4(1.0, 0.0, 1.0, diffuse.a); - else if (fog >= 1.0) - gl_FragColor = vec4(1.0, 0.0, 0.0, diffuse.a); - else - gl_FragColor = vec4(fog, fog, 0.0, diffuse.a); - } - */ }