bayer alpha for particles

This commit is contained in:
minjaesong
2024-04-17 03:05:24 +09:00
parent f0f358a15c
commit 5e85d560b0
6 changed files with 65 additions and 44 deletions

View File

@@ -0,0 +1,6 @@
package net.torvald.colourutil
/**
* Created by minjaesong on 2024-04-17.
*/

View File

@@ -7,6 +7,7 @@ import net.torvald.terrarum.*
import net.torvald.terrarum.gameactors.Actor import net.torvald.terrarum.gameactors.Actor
import net.torvald.terrarum.gameactors.Hitbox import net.torvald.terrarum.gameactors.Hitbox
import net.torvald.terrarum.gameactors.drawBodyInGoodPosition import net.torvald.terrarum.gameactors.drawBodyInGoodPosition
import net.torvald.terrarum.modulebasegame.IngameRenderer
import org.dyn4j.geometry.Vector2 import org.dyn4j.geometry.Vector2
/** /**
@@ -76,30 +77,29 @@ open class ParticleBase(renderOrder: Actor.RenderOrder, var despawnUponCollision
} }
open fun drawBody(frameDelta: Float, batch: SpriteBatch) { open fun drawBody(frameDelta: Float, batch: SpriteBatch) {
if (!flagDespawn) { defaultDrawFun(frameDelta, batch) { x, y -> batch.draw(body, x, y, hitbox.width.toFloat(), hitbox.height.toFloat()) }
batch.color = drawColour
drawBodyInGoodPosition(hitbox.startX.toFloat(), hitbox.startY.toFloat()) { x, y ->
batch.draw(body, x, y, hitbox.width.toFloat(), hitbox.height.toFloat())
}
}
} }
open fun drawGlow(frameDelta: Float, batch: SpriteBatch) { open fun drawGlow(frameDelta: Float, batch: SpriteBatch) {
if (!flagDespawn && glow != null) { if (glow != null)
batch.color = drawColour defaultDrawFun(frameDelta, batch) { x, y -> batch.draw(glow, x, y, hitbox.width.toFloat(), hitbox.height.toFloat()) }
drawBodyInGoodPosition(hitbox.startX.toFloat(), hitbox.startY.toFloat()) { x, y ->
batch.draw(glow, x, y, hitbox.width.toFloat(), hitbox.height.toFloat())
}
}
} }
open fun drawEmissive(frameDelta: Float, batch: SpriteBatch) { open fun drawEmissive(frameDelta: Float, batch: SpriteBatch) {
if (!flagDespawn && emissive != null) { if (emissive != null)
defaultDrawFun(frameDelta, batch) { x, y -> batch.draw(emissive, x, y, hitbox.width.toFloat(), hitbox.height.toFloat()) }
}
fun defaultDrawFun(frameDelta: Float, batch: SpriteBatch, drawJob: (x: Float, y: Float) -> Unit) {
val oldColour = batch.color.cpy()
if (!flagDespawn) {
batch.shader = IngameRenderer.shaderBayerAlpha
batch.color = drawColour batch.color = drawColour
drawBodyInGoodPosition(hitbox.startX.toFloat(), hitbox.startY.toFloat()) { x, y -> drawBodyInGoodPosition(hitbox.startX.toFloat(), hitbox.startY.toFloat()) { x, y ->
batch.draw(emissive, x, y, hitbox.width.toFloat(), hitbox.height.toFloat()) drawJob(x, y)
} }
} }
batch.color = oldColour
} }
open fun dispose() { open fun dispose() {

View File

@@ -88,15 +88,10 @@ class ParticleVanishingText(val text: String, x: Double, y: Double, noCollision:
} }
override fun drawBody(frameDelta: Float, batch: SpriteBatch) { override fun drawBody(frameDelta: Float, batch: SpriteBatch) {
if (!flagDespawn) { lines.forEachIndexed { index, line ->
val oldColour = batch.color.cpy() defaultDrawFun(frameDelta, batch) { x, y ->
batch.color = drawColour TinyAlphNum.draw(batch, line, x, y + TinyAlphNum.H * index)
lines.forEachIndexed { index, line ->
drawBodyInGoodPosition(hitbox.startX.toFloat(), hitbox.startY.toFloat() + TinyAlphNum.H * index) { x, y ->
TinyAlphNum.draw(batch, line, x, y )
}
} }
batch.color = oldColour
} }
} }
} }
@@ -136,13 +131,6 @@ open class ParticleVanishingSprite(val sprite: TextureRegionPack, val delay: Flo
} }
override fun drawBody(frameDelta: Float, batch: SpriteBatch) { override fun drawBody(frameDelta: Float, batch: SpriteBatch) {
if (!flagDespawn) { defaultDrawFun(frameDelta, batch) { x, y -> batch.draw(sprite.get(frame, row), x, y) }
val oldColour = batch.color.cpy()
batch.color = drawColour
drawBodyInGoodPosition(hitbox.startX.toFloat(), hitbox.startY.toFloat()) { x, y ->
batch.draw(sprite.get(frame, row), x, y)
}
batch.color = oldColour
}
} }
} }

View File

@@ -102,6 +102,8 @@ object IngameRenderer : Disposable {
val shaderForActors: ShaderProgram val shaderForActors: ShaderProgram
val shaderDemultiply: ShaderProgram val shaderDemultiply: ShaderProgram
val shaderBayerAlpha: ShaderProgram
val shaderVibrancy: ShaderProgram val shaderVibrancy: ShaderProgram
private val WIDTH = App.scr.width private val WIDTH = App.scr.width
@@ -144,6 +146,7 @@ object IngameRenderer : Disposable {
shaderBlendGlowTex1Flip = App.loadShaderFromClasspath("shaders/blendGlow.vert", "shaders/blendGlowTex1Flip.frag") shaderBlendGlowTex1Flip = App.loadShaderFromClasspath("shaders/blendGlow.vert", "shaders/blendGlowTex1Flip.frag")
shaderDemultiply = App.loadShaderFromClasspath("shaders/blendGlow.vert", "shaders/demultiply.frag") shaderDemultiply = App.loadShaderFromClasspath("shaders/blendGlow.vert", "shaders/demultiply.frag")
shaderBayerAlpha = App.loadShaderFromClasspath("shaders/blendGlow.vert", "shaders/bayeralpha.frag")
shaderKawaseDown = App.loadShaderFromClasspath("shaders/default.vert", "shaders/kawasedown.frag") shaderKawaseDown = App.loadShaderFromClasspath("shaders/default.vert", "shaders/kawasedown.frag")
shaderKawaseUp = App.loadShaderFromClasspath("shaders/default.vert", "shaders/kawaseup.frag") shaderKawaseUp = App.loadShaderFromClasspath("shaders/default.vert", "shaders/kawaseup.frag")
@@ -1176,6 +1179,8 @@ object IngameRenderer : Disposable {
shaderForActors.dispose() shaderForActors.dispose()
shaderDemultiply.dispose() shaderDemultiply.dispose()
shaderBayerAlpha.dispose()
shaderVibrancy.dispose() shaderVibrancy.dispose()
if (::fboRGBexport.isInitialized) fboRGBexport.tryDispose() if (::fboRGBexport.isInitialized) fboRGBexport.tryDispose()

View File

@@ -141,18 +141,18 @@ class FixtureMechanicalTines : Electric {
private fun prel(n1: Int, n2: Int, n3: Int, n4: Int, n5: Int): List<Long> { private fun prel(n1: Int, n2: Int, n3: Int, n4: Int, n5: Int): List<Long> {
return toPianoRoll( return toPianoRoll(
1L shl n1 to TICK_DIVISOR+2, 1L shl n2 to TICK_DIVISOR, 1L shl n3 to TICK_DIVISOR, 1L shl n4 to TICK_DIVISOR, 1L shl n1 to TICK_DIVISOR+2, 1L shl n2 to TICK_DIVISOR, 1L shl n3 to TICK_DIVISOR, 1L shl n4 to TICK_DIVISOR-1,
1L shl n5 to TICK_DIVISOR, 1L shl n3 to TICK_DIVISOR, 1L shl n4 to TICK_DIVISOR, 1L shl n5 to TICK_DIVISOR, 1L shl n5 to TICK_DIVISOR, 1L shl n3 to TICK_DIVISOR, 1L shl n4 to TICK_DIVISOR, 1L shl n5 to TICK_DIVISOR,
1L shl n1 to TICK_DIVISOR, 1L shl n2 to TICK_DIVISOR, 1L shl n3 to TICK_DIVISOR, 1L shl n4 to TICK_DIVISOR, 1L shl n1 to TICK_DIVISOR, 1L shl n2 to TICK_DIVISOR, 1L shl n3 to TICK_DIVISOR, 1L shl n4 to TICK_DIVISOR-1,
1L shl n5 to TICK_DIVISOR-1, 1L shl n3 to TICK_DIVISOR, 1L shl n4 to TICK_DIVISOR, 1L shl n5 to TICK_DIVISOR) 1L shl n5 to TICK_DIVISOR, 1L shl n3 to TICK_DIVISOR, 1L shl n4 to TICK_DIVISOR, 1L shl n5 to TICK_DIVISOR)
} }
private fun end1(n1: Int, n2: Int, n3: Int, n4: Int, n5: Int, n6: Int, n7: Int, n8: Int, n9: Int): List<Long> { private fun end1(n1: Int, n2: Int, n3: Int, n4: Int, n5: Int, n6: Int, n7: Int, n8: Int, n9: Int): List<Long> {
return toPianoRoll( return toPianoRoll(
1L shl n1 to TICK_DIVISOR+2, 1L shl n2 to TICK_DIVISOR, 1L shl n3 to TICK_DIVISOR, 1L shl n4 to TICK_DIVISOR, 1L shl n1 to TICK_DIVISOR+2, 1L shl n2 to TICK_DIVISOR, 1L shl n3 to TICK_DIVISOR, 1L shl n4 to TICK_DIVISOR-1,
1L shl n5 to TICK_DIVISOR, 1L shl n6 to TICK_DIVISOR, 1L shl n5 to TICK_DIVISOR, 1L shl n4 to TICK_DIVISOR, 1L shl n5 to TICK_DIVISOR, 1L shl n6 to TICK_DIVISOR, 1L shl n5 to TICK_DIVISOR, 1L shl n4 to TICK_DIVISOR,
1L shl n5 to TICK_DIVISOR, 1L shl n7 to TICK_DIVISOR, 1L shl n8 to TICK_DIVISOR, 1L shl n7 to TICK_DIVISOR, 1L shl n5 to TICK_DIVISOR, 1L shl n7 to TICK_DIVISOR, 1L shl n8 to TICK_DIVISOR, 1L shl n7 to TICK_DIVISOR-1,
1L shl n8 to TICK_DIVISOR-1, 1L shl n9 to TICK_DIVISOR, 1L shl n8 to TICK_DIVISOR, 1L shl n9 to TICK_DIVISOR) 1L shl n8 to TICK_DIVISOR, 1L shl n9 to TICK_DIVISOR, 1L shl n8 to TICK_DIVISOR, 1L shl n9 to TICK_DIVISOR)
} }
private fun end2(n1: Int, n2: Int, n3: Int, n4: Int, n5: Int, n6: Int, n7: Int, n8: Int, n9: Int): List<Long> { private fun end2(n1: Int, n2: Int, n3: Int, n4: Int, n5: Int, n6: Int, n7: Int, n8: Int, n9: Int): List<Long> {
@@ -204,7 +204,7 @@ object ParticleMusicalNoteFactory {
private val noteColours = (0..60).map { private val noteColours = (0..60).map {
val hue = it / 60f * 270f val hue = it / 60f * 270f
val saturation = 100f val saturation = 100f
val lightness = 80f val lightness = 70f
val (r, g, b) = HUSLColorConverter.hsluvToRgb(floatArrayOf(hue, saturation, lightness)) val (r, g, b) = HUSLColorConverter.hsluvToRgb(floatArrayOf(hue, saturation, lightness))
Color(r, g, b, 1f) Color(r, g, b, 1f)
} }
@@ -214,13 +214,7 @@ object ParticleMusicalNoteFactory {
} }
fun makeRandomParticle(note: Int, pos: Vector2): ParticleVanishingTexture { fun makeRandomParticle(note: Int, pos: Vector2): ParticleVanishingTexture {
val it = object : ParticleVanishingTexture(tex.get(rng.nextInt(3), rng.nextInt(2)), pos.x, pos.y, false) { val it = ParticleVanishingTexture(tex.get(rng.nextInt(3), rng.nextInt(2)), pos.x, pos.y, false)
override fun update(delta: Float) {
super.update(delta)
drawColour.a = ((lifetimeMax - lifetimeCounter) / lifetimeMax).pow(1f / 2.2f).coerceIn(0f, 1f)
}
}
// set flying velocity // set flying velocity
val direction = angles[note] val direction = angles[note]

View File

@@ -0,0 +1,28 @@
#ifdef GL_ES
precision mediump float;
#endif
in vec4 v_color;
in vec2 v_texCoords;
uniform sampler2D u_texture; // world texture, has alpha value that is meaningful
uniform float acount = 2.0;
out vec4 fragColor;
const int bayer[4 * 4] = int[](0,8,2,10,12,4,14,6,3,11,1,9,15,7,13,5);
const float bayerSize = 4.0;
const float bayerDivider = bayerSize * bayerSize;
float nearestAlpha(float alpha) {
return min(1.0, floor(alpha + 0.5));
}
void main() {
vec4 inColor = texture(u_texture, v_texCoords) * v_color;
vec2 entry = mod(gl_FragCoord.xy, vec2(bayerSize, bayerSize));
float alpha = nearestAlpha((inColor.a * 16.0 / 15.0) + (bayer[int(entry.y) * int(bayerSize) + int(entry.x)] / bayerDivider - 0.5));
fragColor = vec4(inColor.rgb, alpha);
}