Compare commits

..

7 Commits

Author SHA1 Message Date
minjaesong
a24eab209b shallow shadow improvements 2024-11-24 19:13:12 +09:00
minjaesong
6ec5ba5603 no shadows against skybox 2024-11-24 18:52:44 +09:00
minjaesong
8cf4b5d9a9 shadows around actors as well as terrain 2024-11-24 17:02:00 +09:00
minjaesong
5bf60cfa82 now terrain also lives on its own framebuffer 2024-11-24 13:19:20 +09:00
minjaesong
5cc7db8ecc putting some actors into their own framebuffer for shadowing 2024-11-24 13:10:08 +09:00
minjaesong
89b12aabb4 new debug cmd ExportFBO 2024-11-24 12:53:44 +09:00
minjaesong
f5846d9bae screen blur helper class 2024-11-23 21:17:16 +09:00
21 changed files with 510 additions and 198 deletions

View File

@@ -3,6 +3,7 @@ CheatWarnTest
CodexEdictis
ExportAtlas
ExportCodices
ExportFBO
ExportMap
ExportMap2
ExportWorld
1 CatStdout
3 CodexEdictis
4 ExportAtlas
5 ExportCodices
6 ExportFBO
7 ExportMap
8 ExportMap2
9 ExportWorld

View File

@@ -38,6 +38,7 @@ import net.torvald.terrarum.modulebasegame.IngameRenderer;
import net.torvald.terrarum.modulebasegame.TerrarumIngame;
import net.torvald.terrarum.modulebasegame.ui.ItemSlotImageFactory;
import net.torvald.terrarum.serialise.WriteConfig;
import net.torvald.terrarum.ui.BlurMgr;
import net.torvald.terrarum.ui.Toolkit;
import net.torvald.terrarum.utils.JsonFetcher;
import net.torvald.terrarum.worlddrawer.CreateTileAtlas;
@@ -52,12 +53,14 @@ import org.apache.commons.csv.CSVParser;
import org.lwjgl.PointerBuffer;
import org.lwjgl.glfw.GLFW;
import javax.tools.Tool;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.*;
import java.util.stream.Stream;
import java.util.zip.Deflater;
import static java.lang.Thread.MAX_PRIORITY;
import static net.torvald.terrarum.TerrarumKt.*;
@@ -764,7 +767,7 @@ public class App implements ApplicationListener {
FrameBufferManager.begin(fb);
try {
Pixmap p = Pixmap.createFromFrameBuffer(0, 0, fb.getWidth(), fb.getHeight());
PixmapIO.writePNG(Gdx.files.absolute(defaultDir+"/Screenshot-"+String.valueOf(System.currentTimeMillis())+".png"), p, 9, true);
PixmapIO.writePNG(Gdx.files.absolute(defaultDir+"/Screenshot-"+String.valueOf(System.currentTimeMillis())+".png"), p, Deflater.DEFAULT_COMPRESSION, true);
p.dispose();
}
catch (Throwable e) {
@@ -1026,6 +1029,9 @@ public class App implements ApplicationListener {
deleteTempfiles();
Toolkit.INSTANCE.dispose();
BlurMgr.INSTANCE.dispose();
disposables.forEach((it) -> {
try {
it.dispose();

View File

@@ -69,7 +69,7 @@ basegame
* e.g. 0x02010034 will be translated as 2.1.52
*
*/
const val VERSION_RAW: Long = 0x0000_000005_000000
const val VERSION_RAW: Long = 0x0000_000005_000001
// Commit counts up to the Release 0.3.0: 2259
// Commit counts up to the Release 0.3.1: 2278
// Commit counts up to the Release 0.3.2: 2732
@@ -78,6 +78,7 @@ basegame
// Commit counts up to the Release 0.4.1: 3678
// Commit counts up to the Release 0.4.2: 3762
// Commit counts up to the Release 0.5.0: 4090
// Commit counts up to the Release 0.5.1: 4097
val DEV_CYCLE: Map<String, Long> = mapOf(
"Alpha" to 0x0000_000004_000000,

View File

@@ -95,7 +95,7 @@ class UIFakeBlurOverlay(val blurRadius: Float, val nodarken: Boolean) : UICanvas
batchDrawCol.a = openness
batch.color = batchDrawCol
if (App.getConfigBoolean("fx_backgroundblur")) {
Toolkit.blurEntireScreen(batch, camera as OrthographicCamera, blurRadius * openness, 0, 0, width, height)
Toolkit.blurEntireScreen(batch, blurRadius * openness, 0, 0, width, height)
}
if (!nodarken) {

View File

@@ -67,7 +67,7 @@ class SavegameCracker(
private val cmds: HashMap<String, KFunction<*>> = HashMap()
init {
SavegameCracker::class.declaredFunctions
.filter { it.findAnnotation<Command>() != null }
.filter { it.findAnnotation<SavegameCrackerCommand>() != null }
// .forEach { it.isAccessible = true; cmds[it.name] = it }
.forEach { cmds[it.name] = it }
}
@@ -100,7 +100,7 @@ class SavegameCracker(
printerrln("${args[0]}: command not found")
else {
try {
val annot = it.findAnnotation<Command>()!!
val annot = it.findAnnotation<SavegameCrackerCommand>()!!
// check arguments
val synopsis = annot.synopsis.split(' ').filter { it.isNotBlank() }
// print out synopsis
@@ -185,14 +185,14 @@ class SavegameCracker(
return this + sb.toString()
}
@Command("Loads a disk archive", "path-to-file")
@SavegameCrackerCommand("Loads a disk archive", "path-to-file")
fun load(args: List<String>) {
file = File(args[1])
disk = VDUtil.readDiskArchive(file!!, Level.INFO) { printerrln("# Warning: $it") }
file!!.copyTo(File(file!!.absolutePath + ".bak"), true)
}
@Command("Lists contents of the disk")
@SavegameCrackerCommand("Lists contents of the disk")
fun ls(args: List<String>) {
letdisk {
it.entries.toSortedMap().forEach { (i, entry) ->
@@ -207,19 +207,19 @@ class SavegameCracker(
}
}
@Command("Prints out available commands and their usage")
@SavegameCrackerCommand("Prints out available commands and their usage")
fun help(args: List<String>) {
cmds.forEach { name, it ->
println("$ccNoun${name.padStart(8)}$cc0 - ${it.findAnnotation<Command>()!!.help}")
println("$ccNoun${name.padStart(8)}$cc0 - ${it.findAnnotation<SavegameCrackerCommand>()!!.help}")
}
}
@Command("Exits the program")
@SavegameCrackerCommand("Exits the program")
fun exit(args: List<String>) { this.exit = true }
@Command("Exits the program")
@SavegameCrackerCommand("Exits the program")
fun quit(args: List<String>) = exit(args)
@Command("Exports contents of the entry into a real file", "entry-id output-file")
@SavegameCrackerCommand("Exports contents of the entry into a real file", "entry-id output-file")
fun export(args: List<String>) {
letdisk {
val entryID = args[1].toLong(10)
@@ -228,7 +228,7 @@ class SavegameCracker(
}
}
@Command("Changes one entry-ID into another", "change-from change-to")
@SavegameCrackerCommand("Changes one entry-ID into another", "change-from change-to")
fun renum(args: List<String>) {
letdisk {
val id0 = args[1].toLong(10)
@@ -244,7 +244,7 @@ class SavegameCracker(
}
}
@Command("Imports a real file onto the savefile", "input-file entry-id")
@SavegameCrackerCommand("Imports a real file onto the savefile", "input-file entry-id")
fun import(args: List<String>) {
letdisk {
val file = File(args[1])
@@ -257,7 +257,7 @@ class SavegameCracker(
}
}
@Command("Removes a file within the savefile", "entry-id")
@SavegameCrackerCommand("Removes a file within the savefile", "entry-id")
fun rm(args: List<String>) {
letdisk {
val id = args[1].toLong(10)
@@ -266,14 +266,14 @@ class SavegameCracker(
}
}
@Command("Saves changes onto the savefile")
@SavegameCrackerCommand("Saves changes onto the savefile")
fun save(args: List<String>) {
letdisk {
VDUtil.dumpToRealMachine(it, file!!)
}
}
@Command("Retrieves all UUIDs found (player UUID, current world UUID, etc.")
@SavegameCrackerCommand("Retrieves all UUIDs found (player UUID, current world UUID, etc.")
fun uuid(args: List<String>) {
letdisk {
val jsonFile = it.getFile(-1) ?: throw FileNotFoundException("savegameinfo.json (entry ID -1) not found")
@@ -294,7 +294,7 @@ class SavegameCracker(
}
}
@Command("Removes the specified chunk(s) completely", "IDs")
@SavegameCrackerCommand("Removes the specified chunk(s) completely", "IDs")
fun discardchunk(args: List<String>) {
letdisk { disk ->
val ids = args[1]
@@ -320,7 +320,7 @@ class SavegameCracker(
}
}
internal annotation class Command(val help: String = "", val synopsis: String = "")
internal annotation class SavegameCrackerCommand(val help: String = "", val synopsis: String = "")
fun main(args: Array<String>) {
SavegameCracker(args).invoke()

View File

@@ -17,7 +17,6 @@ import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZE
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZED
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZEF
import net.torvald.terrarum.blockproperties.Block
import net.torvald.terrarum.blockproperties.FluidCodex
import net.torvald.terrarum.gameactors.ActorWithBody
import net.torvald.terrarum.gameactors.ActorWithBody.Companion.METER
import net.torvald.terrarum.gameactors.ActorWithBody.Companion.PHYS_EPSILON_DIST
@@ -32,6 +31,7 @@ import net.torvald.terrarum.gameworld.fmod
import net.torvald.terrarum.modulebasegame.gameactors.Pocketed
import net.torvald.terrarum.modulebasegame.gameitems.ItemThrowable
import net.torvald.terrarum.modulebasegame.gameitems.getThrowPosAndVector
import net.torvald.terrarum.ui.BlurMgr
import net.torvald.terrarum.ui.Toolkit
import net.torvald.terrarum.weather.WeatherMixer
import net.torvald.terrarum.worlddrawer.BlocksDrawer
@@ -75,6 +75,17 @@ object IngameRenderer : Disposable {
private lateinit var fboA_lightMixed: Float16FrameBuffer
private lateinit var fboEmissive: Float16FrameBuffer
private lateinit var fboMixedOut: Float16FrameBuffer
private lateinit var fboRGBactorsBehind: Float16FrameBuffer // for small shadow eff; A channel is for glow effects so they don't get shadow effects
private lateinit var fboRGBactorsMiddle: Float16FrameBuffer // for large shadow eff; A channel is for glow effects so they don't get shadow effects
private lateinit var fboRGBterrain: Float16FrameBuffer // for large shadow eff; A channel is for glow effects so they don't get shadow effects
private lateinit var fboRGBactorsBehindShadow: Float16FrameBuffer // for small shadow eff; A channel is for glow effects so they don't get shadow effects
private lateinit var fboRGBactorsMiddleShadow: Float16FrameBuffer // for large shadow eff; A channel is for glow effects so they don't get shadow effects
private lateinit var fboRGBterrainShadow: Float16FrameBuffer // for large shadow eff; A channel is for glow effects so they don't get shadow effects
private lateinit var fboRGBwall: Float16FrameBuffer // for masking away the shadows
private lateinit var rgbTex: TextureRegion
private lateinit var aTex: TextureRegion
private lateinit var mixedOutTex: TextureRegion
@@ -104,6 +115,8 @@ object IngameRenderer : Disposable {
val shaderBlendGlow: ShaderProgram
val shaderBlendGlowTex1Flip: ShaderProgram
val shaderForActors: ShaderProgram
val shaderShadowShallow: ShaderProgram
val shaderShadowDeep: ShaderProgram
val shaderDemultiply: ShaderProgram
val shaderBayerAlpha: ShaderProgram
@@ -146,6 +159,8 @@ object IngameRenderer : Disposable {
shaderForActors = App.loadShaderFromClasspath("shaders/default.vert", "shaders/actors.frag")
shaderShadowShallow = App.loadShaderFromClasspath("shaders/default.vert", "shaders/shadowshallow.frag")
shaderShadowDeep = App.loadShaderFromClasspath("shaders/default.vert", "shaders/shadowdeep.frag")
shaderBlendGlow = App.loadShaderFromClasspath("shaders/blendGlow.vert", "shaders/blendGlow.frag")
shaderBlendGlowTex1Flip = App.loadShaderFromClasspath("shaders/blendGlow.vert", "shaders/blendGlowTex1Flip.frag")
shaderDemultiply = App.loadShaderFromClasspath("shaders/blendGlow.vert", "shaders/demultiply.frag")
@@ -497,10 +512,9 @@ object IngameRenderer : Disposable {
fboRGB_lightMixed0.inAction(null, null) { clearBuffer() }
fboRGB_lightMixed.inAction(null, null) { clearBuffer() }
fboRGB.inAction(camera, batch) {
fboRGBactorsBehind.inAction(camera, batch) {
clearBuffer()
setCameraPosition(0f, 0f)
BlocksDrawer.drawWall(batch.projectionMatrix, false)
batch.inUse {
batch.shader = shaderForActors
@@ -508,21 +522,103 @@ object IngameRenderer : Disposable {
moveCameraToWorldCoord()
actorsRenderFarBehind?.forEach { it.drawBody(frameDelta, batch) }
actorsRenderBehind?.forEach { it.drawBody(frameDelta, batch) }
}
}
BlurMgr.makeBlur(fboRGBactorsBehind, fboRGBactorsBehindShadow, 0.25f)
fboRGBactorsMiddle.inAction(camera, batch) {
clearBuffer()
setCameraPosition(0f, 0f)
batch.inUse {
batch.shader = shaderForActors
batch.color = Color.WHITE
moveCameraToWorldCoord()
actorsRenderMiddle?.forEach { it.drawBody(frameDelta, batch) }
}
}
BlurMgr.makeBlur(fboRGBactorsMiddle, fboRGBactorsMiddleShadow, 2.5f)
fboRGBwall.inAction(camera, batch) {
clearBuffer()
setCameraPosition(0f, 0f)
BlocksDrawer.drawWall(batch.projectionMatrix, false)
}
fboRGBterrain.inAction(camera, batch) {
clearBuffer()
setCameraPosition(0f, 0f)
BlocksDrawer.drawTerrain(batch.projectionMatrix, false)
}
BlurMgr.makeBlur(fboRGBterrain, fboRGBterrainShadow, 2.5f)
/////////////////////////////////////////////////////////////////////////////////////////////////////
fboRGB.inAction(camera, batch) {
setCameraPosition(0f, 0f)
batch.inUse {
batch.shader = null
batch.color = Color.WHITE
batch.drawFlipped(fboRGBwall.colorBufferTexture, 0f, 0f)
}
// draw actor shadow BEFORE the terrain draw
fboRGBwall.colorBufferTexture.bind(1)
Gdx.gl.glActiveTexture(GL20.GL_TEXTURE0) // so that batch that comes next will bind any tex to it
batch.inUse {
batch.shader = shaderShadowShallow
shaderShadowShallow.setUniformi("u_wall", 1)
setCameraPosition(0f, 0f)
batch.drawFlipped(fboRGBactorsBehindShadow.colorBufferTexture, 0f, 0f)
}
fboRGBwall.colorBufferTexture.bind(1)
Gdx.gl.glActiveTexture(GL20.GL_TEXTURE0) // so that batch that comes next will bind any tex to it
batch.inUse {
batch.shader = shaderShadowDeep
shaderShadowDeep.setUniformi("u_wall", 1)
setCameraPosition(0f, 0f)
batch.drawFlipped(fboRGBterrainShadow.colorBufferTexture, 0f, 0f)
batch.drawFlipped(fboRGBactorsMiddleShadow.colorBufferTexture, 0f, 0f)
}
// Gdx.gl20.glActiveTexture(0)
// draw behind actors and particles
batch.inUse {
batch.shader = shaderForActors
batch.color = Color.WHITE
setCameraPosition(0f, 0f)
batch.color = Color.WHITE
batch.drawFlipped(fboRGBactorsBehind.colorBufferTexture, 0f, 0f)
moveCameraToWorldCoord()
particlesContainer?.forEach { it.drawBody(frameDelta, batch) }
}
setCameraPosition(0f, 0f)
BlocksDrawer.drawTerrain(batch.projectionMatrix, false)
// draw just the terrain
batch.inUse {
batch.shader = null
setCameraPosition(0f, 0f)
batch.color = Color.WHITE
batch.drawFlipped(fboRGBterrain.colorBufferTexture, 0f, 0f)
}
batch.shader = shaderForActors
batch.inUse {
batch.shader = shaderForActors
batch.color = Color.WHITE
/////////////////
// draw actors //
/////////////////
setCameraPosition(0f, 0f)
batch.color = Color.WHITE
batch.drawFlipped(fboRGBactorsMiddle.colorBufferTexture, 0f, 0f)
moveCameraToWorldCoord()
actorsRenderMiddle?.forEach { it.drawBody(frameDelta, batch) }
actorsRenderMidTop?.forEach { it.drawBody(frameDelta, batch) }
player?.drawBody(frameDelta, batch)
actorsRenderFront?.forEach { it.drawBody(frameDelta, batch) }
@@ -1209,6 +1305,13 @@ object IngameRenderer : Disposable {
fboA_lightMixed = Float16FrameBuffer(width, height, false)
fboEmissive = Float16FrameBuffer(width, height, false)
fboMixedOut = Float16FrameBuffer(width, height, false)
fboRGBactorsBehind = Float16FrameBuffer(width, height, false)
fboRGBactorsMiddle = Float16FrameBuffer(width, height, false)
fboRGBterrain = Float16FrameBuffer(width, height, false)
fboRGBactorsBehindShadow = Float16FrameBuffer(width, height, false)
fboRGBactorsMiddleShadow = Float16FrameBuffer(width, height, false)
fboRGBterrainShadow = Float16FrameBuffer(width, height, false)
fboRGBwall = Float16FrameBuffer(width, height, false)
lightmapFbo = Float16FrameBuffer(
LightmapRenderer.lightBuffer.width * LightmapRenderer.DRAW_TILE_SIZE.toInt(),
LightmapRenderer.lightBuffer.height * LightmapRenderer.DRAW_TILE_SIZE.toInt(),
@@ -1271,6 +1374,13 @@ object IngameRenderer : Disposable {
if (::fboEmissive.isInitialized) fboEmissive.tryDispose()
if (::fboMixedOut.isInitialized) fboMixedOut.tryDispose()
if (::lightmapFbo.isInitialized) lightmapFbo.tryDispose()
if (::fboRGBactorsBehind.isInitialized) fboRGBactorsBehind.tryDispose()
if (::fboRGBactorsMiddle.isInitialized) fboRGBactorsMiddle.tryDispose()
if (::fboRGBterrain.isInitialized) fboRGBterrain.tryDispose()
if (::fboRGBactorsBehindShadow.isInitialized) fboRGBactorsBehindShadow.tryDispose()
if (::fboRGBactorsMiddleShadow.isInitialized) fboRGBactorsMiddleShadow.tryDispose()
if (::fboRGBterrainShadow.isInitialized) fboRGBterrainShadow.tryDispose()
if (::fboRGBwall.isInitialized) fboRGBwall.tryDispose()
blurtex0.tryDispose()
@@ -1294,6 +1404,8 @@ object IngameRenderer : Disposable {
shaderBlendGlow.dispose()
shaderBlendGlowTex1Flip.dispose()
shaderForActors.dispose()
shaderShadowShallow.dispose()
shaderShadowDeep.dispose()
shaderDemultiply.dispose()
shaderBayerAlpha.dispose()

View File

@@ -0,0 +1,142 @@
package net.torvald.terrarum.modulebasegame.console
import com.badlogic.gdx.Gdx
import com.badlogic.gdx.graphics.GL20
import com.badlogic.gdx.graphics.GL30
import com.badlogic.gdx.graphics.Pixmap
import com.badlogic.gdx.graphics.PixmapIO
import com.badlogic.gdx.graphics.glutils.Float16FrameBuffer
import com.badlogic.gdx.graphics.glutils.FrameBuffer
import com.badlogic.gdx.utils.BufferUtils
import net.torvald.reflection.extortField
import net.torvald.terrarum.App
import net.torvald.terrarum.ccG
import net.torvald.terrarum.ccO
import net.torvald.terrarum.ccW
import net.torvald.terrarum.console.ConsoleCommand
import net.torvald.terrarum.console.Echo
import net.torvald.terrarum.console.EchoError
import net.torvald.terrarum.modulebasegame.IngameRenderer
import net.torvald.unicode.BULLET
import net.torvald.unicode.EMDASH
import java.nio.ByteBuffer
import java.util.zip.Deflater
import kotlin.reflect.KFunction
import kotlin.reflect.full.declaredFunctions
import kotlin.reflect.full.findAnnotation
import kotlin.reflect.full.hasAnnotation
/**
* Created by minjaesong on 2024-11-24.
*/
internal object ExportFBO : ConsoleCommand {
private val cmds: HashMap<String, KFunction<*>> = HashMap()
private val helpMessages: List<Pair<String, String>>
init {
val helpMsgs: HashMap<String, String> = HashMap()
ExportFBO::class.declaredFunctions.filter { it.hasAnnotation<ExportFBOCmd>() }.forEach {
cmds[it.name.lowercase()] = it
helpMsgs[it.name.lowercase()] = it.findAnnotation<ExportFBOCmd>()!!.description
}
helpMessages = helpMsgs.keys.toList().sorted().map {
it to helpMsgs[it]!!
}
}
override fun execute(args: Array<String>) {
if (args.size != 3) { printUsage(); return }
val fn = cmds[args[1].lowercase()]
if (fn == null) { printUsage(); return }
try {
val filename = "${args[2]}-${args[1]}.png"
val fileHandle = Gdx.files.absolute("${App.defaultDir}/Exports/$filename")
val fbo = fn.call(this) as FrameBuffer
// cannot use createFromFrameBuffer because the specific FBO must be bound in a way we can control
val pixels: ByteBuffer = BufferUtils.newByteBuffer(fbo.width * fbo.height * 4)
Gdx.gl.glBindFramebuffer(GL20.GL_FRAMEBUFFER, fbo.framebufferHandle)
Gdx.gl.glReadPixels(0, 0, fbo.width, fbo.height, GL30.GL_RGBA, GL30.GL_UNSIGNED_BYTE, pixels)
Gdx.gl.glBindFramebuffer(GL20.GL_FRAMEBUFFER, 0)
val pixmap: Pixmap = Pixmap(fbo.width, fbo.height, Pixmap.Format.RGBA8888)
BufferUtils.copy(pixels, pixmap.pixels, pixels.capacity())
PixmapIO.writePNG(fileHandle, pixmap, Deflater.DEFAULT_COMPRESSION, true)
Echo("Framebuffer exported to$ccG Exports/$filename")
}
catch (e: Throwable) {
EchoError("Could not retrieve the framebuffer: ${e.message}")
System.err.println(e)
return
}
}
override fun printUsage() {
Echo("Usage: exportfbo <identifier> <filename without extension>")
Echo("Available identifiers are:")
helpMessages.forEach { (name, desc) ->
Echo(" $BULLET $ccG$name $ccW$EMDASH $ccO$desc")
}
}
@ExportFBOCmd("Main RGB channel of the IngameRenderer without lighting")
fun fborgb(): FrameBuffer {
return IngameRenderer.extortField<Float16FrameBuffer>("fboRGB")!!
}
@ExportFBOCmd("Main A channel of the IngameRenderer without lighting")
fun fboa(): FrameBuffer {
return IngameRenderer.extortField<Float16FrameBuffer>("fboA")!!
}
@ExportFBOCmd("Main Emissive channel of the IngameRenderer without lighting")
fun fboemissive(): FrameBuffer {
return IngameRenderer.extortField<Float16FrameBuffer>("fboEmissive")!!
}
@ExportFBOCmd("Framebuffer for render-behind actors used for creating shallow shadow effects")
fun fborgbactorsbehind(): FrameBuffer {
return IngameRenderer.extortField<Float16FrameBuffer>("fboRGBactorsBehind")!!
}
@ExportFBOCmd("Framebuffer for render-middle actors used for creating large shadow effects")
fun fborgbactorsmiddle(): FrameBuffer {
return IngameRenderer.extortField<Float16FrameBuffer>("fboRGBactorsMiddle")!!
}
@ExportFBOCmd("Framebuffer for terrain blocks used for creating large shadow effects")
fun fborgbterrain(): FrameBuffer {
return IngameRenderer.extortField<Float16FrameBuffer>("fboRGBterrain")!!
}
@ExportFBOCmd("Framebuffer for render-behind actors used for creating shallow shadow effects")
fun fborgbactorsbehindshadow(): FrameBuffer {
return IngameRenderer.extortField<Float16FrameBuffer>("fboRGBactorsBehindShadow")!!
}
@ExportFBOCmd("Framebuffer for render-middle actors used for creating large shadow effects")
fun fborgbactorsmiddleshadow(): FrameBuffer {
return IngameRenderer.extortField<Float16FrameBuffer>("fboRGBactorsMiddleShadow")!!
}
@ExportFBOCmd("Framebuffer for terrain blocks used for creating large shadow effects")
fun fborgbterrainshadow(): FrameBuffer {
return IngameRenderer.extortField<Float16FrameBuffer>("fboRGBterrainShadow")!!
}
@ExportFBOCmd("Framebuffer for wall blocks")
fun fborgbwall(): FrameBuffer {
return IngameRenderer.extortField<Float16FrameBuffer>("fboRGBwall")!!
}
}
internal annotation class ExportFBOCmd(val description: String)

View File

@@ -14,11 +14,12 @@ import org.dyn4j.geometry.Vector2
*/
class FixtureLogicSignalAdder : Electric, Reorientable {
@Transient override val spawnNeedsFloor = true
@Transient override val spawnNeedsFloor = false
@Transient override val spawnNeedsWall = true
constructor() : super(
BlockBox(BlockBox.NO_COLLISION, 2, 2),
renderOrder = RenderOrder.BEHIND,
nameFun = { Lang["ITEM_LOGIC_SIGNAL_ADDER"] }
)

View File

@@ -34,11 +34,12 @@ interface Reorientable {
*/
class FixtureLogicSignalBlocker : Electric, Reorientable {
@Transient override val spawnNeedsFloor = true
@Transient override val spawnNeedsFloor = false
@Transient override val spawnNeedsWall = true
constructor() : super(
BlockBox(BlockBox.NO_COLLISION, 2, 2),
renderOrder = RenderOrder.BEHIND,
nameFun = { Lang["ITEM_LOGIC_SIGNAL_BLOCKER"] }
)

View File

@@ -18,6 +18,7 @@ class FixtureLogicSignalBulb : Electric {
constructor() : super(
BlockBox(BlockBox.NO_COLLISION, 1, 1),
renderOrder = RenderOrder.BEHIND,
nameFun = { Lang["ITEM_COPPER_BULB"] }
)

View File

@@ -16,11 +16,12 @@ import org.dyn4j.geometry.Vector2
*/
class FixtureLogicSignalLatch : Electric, Reorientable {
@Transient override val spawnNeedsFloor = true
@Transient override val spawnNeedsFloor = false
@Transient override val spawnNeedsWall = true
constructor() : super(
BlockBox(BlockBox.NO_COLLISION, 2, 3),
renderOrder = RenderOrder.BEHIND,
nameFun = { Lang["ITEM_LOGIC_SIGNAL_LATCH"] }
)

View File

@@ -16,11 +16,12 @@ import org.dyn4j.geometry.Vector2
class FixtureLogicSignalRepeaterHorz : Electric, Reorientable {
@Transient override val spawnNeedsFloor = true
@Transient override val spawnNeedsFloor = false
@Transient override val spawnNeedsWall = true
constructor() : super(
BlockBox(BlockBox.NO_COLLISION, 2, 1),
renderOrder = RenderOrder.BEHIND,
nameFun = { Lang["ITEM_LOGIC_SIGNAL_REPEATER"] }
)

View File

@@ -16,11 +16,12 @@ import org.dyn4j.geometry.Vector2
*/
class FixtureLogicSignalSwitchManual : Electric {
@Transient override val spawnNeedsFloor = true
@Transient override val spawnNeedsFloor = false
@Transient override val spawnNeedsWall = true
constructor() : super(
BlockBox(BlockBox.NO_COLLISION, 1, 1),
renderOrder = RenderOrder.BEHIND,
nameFun = { Lang["ITEM_LOGIC_SIGNAL_SWITCH"] }
)
@@ -74,11 +75,12 @@ class FixtureLogicSignalSwitchManual : Electric {
*/
class FixtureLogicSignalPushbutton : Electric {
@Transient override val spawnNeedsFloor = true
@Transient override val spawnNeedsFloor = false
@Transient override val spawnNeedsWall = true
constructor() : super(
BlockBox(BlockBox.NO_COLLISION, 1, 1),
renderOrder = RenderOrder.BEHIND,
nameFun = { Lang["ITEM_LOGIC_SIGNAL_PUSHBUTTON"] }
)

View File

@@ -35,7 +35,7 @@ class UICheatDetected : UICanvas() {
Terrarum.ingame?.consoleHandler?.setAsClose()
Terrarum.ingame?.consoleHandler?.isVisible = false
Toolkit.blurEntireScreen(batch, camera as OrthographicCamera, 2f, 0, 0, width, height)
Toolkit.blurEntireScreen(batch, 2f, 0, 0, width, height)
batch.color = backgroundCol
Toolkit.fillArea(batch, 0f, 0f, width.toFloat(), height.toFloat())
@@ -80,7 +80,7 @@ class UIPauseTheGame : UICanvas() {
Terrarum.ingame?.consoleHandler?.setAsClose()
Terrarum.ingame?.consoleHandler?.isVisible = false
Toolkit.blurEntireScreen(batch, camera as OrthographicCamera, 2f, 0, 0, width, height)
Toolkit.blurEntireScreen(batch, 2f, 0, 0, width, height)
batch.color = backgroundCol
Toolkit.fillArea(batch, 0f, 0f, width.toFloat(), height.toFloat())

View File

@@ -0,0 +1,159 @@
package net.torvald.terrarum.ui
import com.badlogic.gdx.graphics.*
import com.badlogic.gdx.graphics.g2d.SpriteBatch
import com.badlogic.gdx.graphics.glutils.Float16FrameBuffer
import com.badlogic.gdx.graphics.glutils.FrameBuffer
import com.jme3.math.FastMath
import net.torvald.terrarum.App
import net.torvald.terrarum.ceilToInt
import net.torvald.terrarum.gdxClearAndEnableBlend
import net.torvald.terrarum.inAction
/**
* Created by minjaesong on 2024-11-23.
*/
object BlurMgr {
private class FrameBufferSet(val width: Int, val height: Int) {
private val internalWidth = (width.toFloat() / 4f).ceilToInt() * 4
private val internalHeight = (height.toFloat() / 4f).ceilToInt() * 4
val full = Float16FrameBuffer(width, height, false)
val half = Float16FrameBuffer(internalWidth / 2, internalHeight / 2, false)
val quarter = Float16FrameBuffer(internalWidth / 4, internalHeight / 4, false)
val camera = OrthographicCamera(width.toFloat(), height.toFloat())
val quadFull = Mesh(
true, 4, 4,
VertexAttribute.Position(),
VertexAttribute.ColorUnpacked(),
VertexAttribute.TexCoords(0)
)
val quadHalf = Mesh(
true, 4, 4,
VertexAttribute.Position(),
VertexAttribute.ColorUnpacked(),
VertexAttribute.TexCoords(0)
)
val quadQuarter = Mesh(
true, 4, 4,
VertexAttribute.Position(),
VertexAttribute.ColorUnpacked(),
VertexAttribute.TexCoords(0)
)
init {
camera.setToOrtho(true)
quadFull.setVertices(floatArrayOf(
0f,0f,0f, 1f,1f,1f,1f, 0f,1f,
width.toFloat(),0f,0f, 1f,1f,1f,1f, 1f,1f,
width.toFloat(), height.toFloat(),0f, 1f,1f,1f,1f, 1f,0f,
0f, height.toFloat(),0f, 1f,1f,1f,1f, 0f,0f))
quadFull.setIndices(shortArrayOf(0, 1, 2, 3))
quadHalf.setVertices(floatArrayOf(
0f,0f,0f, 1f,1f,1f,1f, 0f,1f,
width.div(2).toFloat(),0f,0f, 1f,1f,1f,1f, 1f,1f,
width.div(2).toFloat(), height.div(2).toFloat(),0f, 1f,1f,1f,1f, 1f,0f,
0f, height.div(2).toFloat(),0f, 1f,1f,1f,1f, 0f,0f))
quadHalf.setIndices(shortArrayOf(0, 1, 2, 3))
quadQuarter.setVertices(floatArrayOf(
0f,0f,0f, 1f,1f,1f,1f, 0f,1f,
width.div(4).toFloat(),0f,0f, 1f,1f,1f,1f, 1f,1f,
width.div(4).toFloat(), height.div(4).toFloat(),0f, 1f,1f,1f,1f, 1f,0f,
0f, height.div(4).toFloat(),0f, 1f,1f,1f,1f, 0f,0f))
quadQuarter.setIndices(shortArrayOf(0, 1, 2, 3))
}
fun dispose() {
full.dispose()
half.dispose()
quarter.dispose()
}
}
private val fboDict = HashMap<Long, FrameBufferSet>()
private lateinit var blurtex0: Texture
private lateinit var blurtex1: Texture
private lateinit var blurtex2: Texture
private lateinit var blurtex3: Texture
private val shaderKawaseDown = App.loadShaderFromClasspath("shaders/default.vert", "shaders/kawasedown.frag")
private val shaderKawaseUp = App.loadShaderFromClasspath("shaders/default.vert", "shaders/kawaseup.frag")
fun makeBlur(`in`: FrameBuffer, out: FrameBuffer, strength: Float) {
assert(`in`.width == out.width && `in`.height == out.height) {
"Input and Output dimension mismatch: In(${`in`.width}x${`in`.height}), Out(${out.width}x${out.height})"
}
val fbos = fboDict.getOrPut(`in`.width.toLong().shl(32) or `in`.height.toLong()) {
FrameBufferSet(`in`.width, `in`.height)
}
val batch: SpriteBatch? = null // placeholder
val radius3 = FastMath.pow(strength / 2, 0.5f)//(blurRadius - 3f) / 8f
fbos.half.inAction(fbos.camera, batch) {
gdxClearAndEnableBlend(0f,0f,0f,0f)
blurtex0 = `in`.colorBufferTexture
blurtex0.setFilter(Texture.TextureFilter.Linear, Texture.TextureFilter.Linear)
blurtex0.bind(0)
shaderKawaseDown.bind()
shaderKawaseDown.setUniformMatrix("u_projTrans", fbos.camera.combined)
shaderKawaseDown.setUniformi("u_texture", 0)
shaderKawaseDown.setUniformf("halfpixel", radius3 / fbos.half.width, radius3 / fbos.half.height)
fbos.quadHalf.render(shaderKawaseDown, GL20.GL_TRIANGLE_FAN)
}
fbos.quarter.inAction(fbos.camera, batch) {
gdxClearAndEnableBlend(0f,0f,0f,0f)
blurtex1 = fbos.half.colorBufferTexture
blurtex1.setFilter(Texture.TextureFilter.Linear, Texture.TextureFilter.Linear)
blurtex1.bind(0)
shaderKawaseDown.bind()
shaderKawaseDown.setUniformMatrix("u_projTrans", fbos.camera.combined)
shaderKawaseDown.setUniformi("u_texture", 0)
shaderKawaseDown.setUniformf("halfpixel", radius3 / fbos.quarter.width, radius3 / fbos.quarter.height)
fbos.quadQuarter.render(shaderKawaseDown, GL20.GL_TRIANGLE_FAN)
}
fbos.half.inAction(fbos.camera, batch) {
gdxClearAndEnableBlend(0f,0f,0f,0f)
blurtex2 = fbos.quarter.colorBufferTexture
blurtex2.setFilter(Texture.TextureFilter.Linear, Texture.TextureFilter.Linear)
blurtex2.bind(0)
shaderKawaseUp.bind()
shaderKawaseUp.setUniformMatrix("u_projTrans", fbos.camera.combined)
shaderKawaseUp.setUniformi("u_texture", 0)
shaderKawaseUp.setUniformf("halfpixel", radius3 / fbos.quarter.width, radius3 / fbos.quarter.height)
fbos.quadHalf.render(shaderKawaseUp, GL20.GL_TRIANGLE_FAN)
}
out.inAction(fbos.camera, batch) {
gdxClearAndEnableBlend(0f,0f,0f,0f)
blurtex3 = fbos.half.colorBufferTexture
blurtex3.setFilter(Texture.TextureFilter.Linear, Texture.TextureFilter.Linear)
blurtex3.bind(0)
shaderKawaseUp.bind()
shaderKawaseUp.setUniformMatrix("u_projTrans", fbos.camera.combined)
shaderKawaseUp.setUniformi("u_texture", 0)
shaderKawaseUp.setUniformf("halfpixel", radius3 / fbos.half.width, radius3 / fbos.half.height)
fbos.quadFull.render(shaderKawaseUp, GL20.GL_TRIANGLE_FAN)
}
}
fun dispose() {
fboDict.values.forEach { it.dispose() }
shaderKawaseUp.dispose()
shaderKawaseDown.dispose()
}
}

View File

@@ -40,12 +40,12 @@ class ConsoleWindow : UICanvas() {
private var commandHistory = CircularArray<String>(COMMAND_HISTORY_MAX, true)
private val LINE_HEIGHT = 20
private val MESSAGES_DISPLAY_COUNT = 11
private val MESSAGES_DISPLAY_COUNT = 12
private val inputToMsgboxGap = 3
override var width: Int = App.scr.width
override var height: Int = LINE_HEIGHT * (MESSAGES_DISPLAY_COUNT + 1) + inputToMsgboxGap
override var height: Int = LINE_HEIGHT * (MESSAGES_DISPLAY_COUNT + 1) + inputToMsgboxGap + 4
override var openCloseTime = 0f

View File

@@ -44,19 +44,7 @@ object Toolkit : Disposable {
*/
}
private val shaderKawaseDown = App.loadShaderFromClasspath("shaders/default.vert", "shaders/kawasedown.frag")
private val shaderKawaseUp = App.loadShaderFromClasspath("shaders/default.vert", "shaders/kawaseup.frag")
private val shaderBoxDown = App.loadShaderFromClasspath("shaders/default.vert", "shaders/boxdown.frag")
private val shaderBoxUp = App.loadShaderFromClasspath("shaders/default.vert", "shaders/boxup.frag")
private lateinit var fboBlur: Float16FrameBuffer
private lateinit var fboBlurHalf: Float16FrameBuffer
private lateinit var fboBlurQuarter: Float16FrameBuffer
private lateinit var blurWriteQuad: Mesh
private lateinit var blurWriteQuad2: Mesh
private lateinit var blurWriteQuad4: Mesh
// val baloonTile = TextureRegionPack("assets/graphics/gui/message_black_tileable.tga", 36, 36)
val shadowTile = TextureRegionPack("assets/graphics/gui/blur_shadow.tga", 32, 32)
@@ -82,19 +70,6 @@ object Toolkit : Disposable {
// baloonTile.dispose()
textureWhiteSquare.dispose()
textureWhiteCircle.dispose()
fboBlur.dispose()
fboBlurHalf.dispose()
fboBlurQuarter.dispose()
blurWriteQuad.dispose()
blurWriteQuad2.dispose()
blurWriteQuad4.dispose()
shaderKawaseUp.dispose()
shaderKawaseDown.dispose()
shaderBoxDown.dispose()
shaderBoxUp.dispose()
}
val drawWidth: Int
@@ -201,87 +176,11 @@ object Toolkit : Disposable {
pixmap.fillRectangle(x + w, y, 1, h)
}
private lateinit var blurtex0: Texture
private lateinit var blurtex1: Texture
private lateinit var blurtex2: Texture
private lateinit var blurtex3: Texture
fun blurEntireScreen(batch: SpriteBatch, camera: OrthographicCamera, blurRadius0: Float, x: Int, y: Int, w: Int, h: Int) {
fun blurEntireScreen(batch: SpriteBatch, blurRadius0: Float, x: Int, y: Int, w: Int, h: Int) {
batch.end()
// val blurRadius = FastMath.pow(blurRadius0, 0.5f)
val renderTarget = FrameBufferManager.peek()
//if (blurRadius > 3f) {
val radius3 = FastMath.pow(blurRadius0 / 2, 0.5f)//(blurRadius - 3f) / 8f
fboBlurHalf.inAction(camera, batch) {
blurtex0 = renderTarget.colorBufferTexture
blurtex0.setFilter(Texture.TextureFilter.Linear, Texture.TextureFilter.Linear)
blurtex0.bind(0)
shaderKawaseDown.bind()
shaderKawaseDown.setUniformMatrix("u_projTrans", camera.combined)
shaderKawaseDown.setUniformi("u_texture", 0)
shaderKawaseDown.setUniformf("halfpixel", radius3 / fboBlurHalf.width, radius3 / fboBlurHalf.height)
blurWriteQuad2.render(shaderKawaseDown, GL20.GL_TRIANGLE_FAN)
}
fboBlurQuarter.inAction(camera, batch) {
blurtex1 = fboBlurHalf.colorBufferTexture
blurtex1.setFilter(Texture.TextureFilter.Linear, Texture.TextureFilter.Linear)
blurtex1.bind(0)
shaderKawaseDown.bind()
shaderKawaseDown.setUniformMatrix("u_projTrans", camera.combined)
shaderKawaseDown.setUniformi("u_texture", 0)
shaderKawaseDown.setUniformf("halfpixel", radius3 / fboBlurQuarter.width, radius3 / fboBlurQuarter.height)
blurWriteQuad4.render(shaderKawaseDown, GL20.GL_TRIANGLE_FAN)
}
fboBlurHalf.inAction(camera, batch) {
blurtex2 = fboBlurQuarter.colorBufferTexture
blurtex2.setFilter(Texture.TextureFilter.Linear, Texture.TextureFilter.Linear)
blurtex2.bind(0)
shaderKawaseUp.bind()
shaderKawaseUp.setUniformMatrix("u_projTrans", camera.combined)
shaderKawaseUp.setUniformi("u_texture", 0)
shaderKawaseUp.setUniformf("halfpixel", radius3 / fboBlurQuarter.width, radius3 / fboBlurQuarter.height)
blurWriteQuad2.render(shaderKawaseUp, GL20.GL_TRIANGLE_FAN)
}
fboBlur.inAction(camera, batch) {
blurtex3 = fboBlurHalf.colorBufferTexture
blurtex3.setFilter(Texture.TextureFilter.Linear, Texture.TextureFilter.Linear)
blurtex3.bind(0)
shaderKawaseUp.bind()
shaderKawaseUp.setUniformMatrix("u_projTrans", camera.combined)
shaderKawaseUp.setUniformi("u_texture", 0)
shaderKawaseUp.setUniformf("halfpixel", radius3 / fboBlurHalf.width, radius3 / fboBlurHalf.height)
blurWriteQuad.render(shaderKawaseUp, GL20.GL_TRIANGLE_FAN)
}
//}
/*fboBlurHalf.inAction(camera, batch) {
blurtex2 = renderTarget.colorBufferTexture
blurtex2.setFilter(Texture.TextureFilter.Linear, Texture.TextureFilter.Linear)
blurtex2.bind(0)
shaderKawaseDown.bind()
shaderKawaseDown.setUniformMatrix("u_projTrans", camera.combined)
shaderKawaseDown.setUniformi("u_texture", 0)
shaderKawaseDown.setUniformf("halfpixel", blurRadius / fboBlurHalf.width, blurRadius / fboBlurHalf.height)
blurWriteQuad2.render(shaderKawaseDown, GL20.GL_TRIANGLE_FAN)
}
fboBlur.inAction(camera, batch) {
blurtex3 = fboBlurHalf.colorBufferTexture
blurtex3.setFilter(Texture.TextureFilter.Linear, Texture.TextureFilter.Linear)
blurtex3.bind(0)
shaderKawaseUp.bind()
shaderKawaseUp.setUniformMatrix("u_projTrans", camera.combined)
shaderKawaseUp.setUniformi("u_texture", 0)
shaderKawaseUp.setUniformf("halfpixel", blurRadius / fboBlurHalf.width, blurRadius / fboBlurHalf.height)
blurWriteQuad.render(shaderKawaseUp, GL20.GL_TRIANGLE_FAN)
}*/
BlurMgr.makeBlur(renderTarget, fboBlur, blurRadius0)
Gdx.gl.glActiveTexture(GL20.GL_TEXTURE0) // so that batch that comes next will bind any tex to it
@@ -344,33 +243,9 @@ object Toolkit : Disposable {
init = true
}
else {
blurWriteQuad.dispose()
blurWriteQuad2.dispose()
blurWriteQuad4.dispose()
fboBlur.dispose()
fboBlurHalf.dispose()
fboBlurQuarter.dispose()
}
blurWriteQuad = Mesh(
true, 4, 4,
VertexAttribute.Position(),
VertexAttribute.ColorUnpacked(),
VertexAttribute.TexCoords(0)
)
blurWriteQuad2 = Mesh(
true, 4, 4,
VertexAttribute.Position(),
VertexAttribute.ColorUnpacked(),
VertexAttribute.TexCoords(0)
)
blurWriteQuad4 = Mesh(
true, 4, 4,
VertexAttribute.Position(),
VertexAttribute.ColorUnpacked(),
VertexAttribute.TexCoords(0)
)
val fw = App.scr.width//MathUtils.nextPowerOfTwo(App.scr.width)
val fh = App.scr.height//MathUtils.nextPowerOfTwo(App.scr.height)
@@ -379,36 +254,5 @@ object Toolkit : Disposable {
fh,
false
)
fboBlurHalf = Float16FrameBuffer(
fw / 2,
fh / 2,
false
)
fboBlurQuarter = Float16FrameBuffer(
fw / 4,
fh / 4,
false
)
blurWriteQuad.setVertices(floatArrayOf(
0f,0f,0f, 1f,1f,1f,1f, 0f,1f,
fw.toFloat(),0f,0f, 1f,1f,1f,1f, 1f,1f,
fw.toFloat(), fh.toFloat(),0f, 1f,1f,1f,1f, 1f,0f,
0f, fh.toFloat(),0f, 1f,1f,1f,1f, 0f,0f))
blurWriteQuad.setIndices(shortArrayOf(0, 1, 2, 3))
blurWriteQuad2.setVertices(floatArrayOf(
0f,0f,0f, 1f,1f,1f,1f, 0f,1f,
fw.div(2).toFloat(),0f,0f, 1f,1f,1f,1f, 1f,1f,
fw.div(2).toFloat(), fh.div(2).toFloat(),0f, 1f,1f,1f,1f, 1f,0f,
0f, fh.div(2).toFloat(),0f, 1f,1f,1f,1f, 0f,0f))
blurWriteQuad2.setIndices(shortArrayOf(0, 1, 2, 3))
blurWriteQuad4.setVertices(floatArrayOf(
0f,0f,0f, 1f,1f,1f,1f, 0f,1f,
fw.div(4).toFloat(),0f,0f, 1f,1f,1f,1f, 1f,1f,
fw.div(4).toFloat(), fh.div(4).toFloat(),0f, 1f,1f,1f,1f, 1f,0f,
0f, fh.div(4).toFloat(),0f, 1f,1f,1f,1f, 0f,0f))
blurWriteQuad4.setIndices(shortArrayOf(0, 1, 2, 3))
}
}

View File

@@ -278,7 +278,7 @@ internal object BlocksDrawer {
fillInTileBuffer(TERRAIN) // regular tiles
fillInTileBuffer(ORES)
fillInTileBuffer(FLUID)
fillInTileBuffer(OCCLUSION)
// fillInTileBuffer(OCCLUSION)
prepareDrawBuffers()
}
}
@@ -289,7 +289,7 @@ internal object BlocksDrawer {
renderUsingBuffer(WALL, projectionMatrix, drawGlow, drawEmissive)
gdxBlendMul()
renderUsingBuffer(OCCLUSION, projectionMatrix, false, drawEmissive)
// renderUsingBuffer(OCCLUSION, projectionMatrix, false, drawEmissive)
}

View File

@@ -260,7 +260,7 @@ class CreateTileAtlas {
}
// test print
PixmapIO2.writeTGA(Gdx.files.absolute("${App.defaultDir}/atlas.tga"), atlas, false)
// PixmapIO2.writeTGA(Gdx.files.absolute("${App.defaultDir}/atlas.tga"), atlas, false)
// PixmapIO2.writeTGA(Gdx.files.absolute("${AppLoader.defaultDir}/atlasGlow.tga"), atlasGlow, false)
// PixmapIO2.writeTGA(Gdx.files.absolute("${App.defaultDir}/atlas_0.tga"), atlasPrevernal, false)

View File

@@ -0,0 +1,20 @@
#ifdef GL_ES
precision mediump float;
#endif
in vec4 v_color;
in vec4 v_generic;
in vec2 v_texCoords;
uniform sampler2D u_texture;
uniform sampler2D u_wall;
out vec4 fragColor;
vec4 mult = vec4(0.0, 0.0, 0.0, 1.0);
void main() {
vec4 backcol = texture(u_wall, v_texCoords);
vec4 incol = texture(u_texture, v_texCoords);
vec4 outcol = vec4(incol.rgb, backcol.a * pow(incol.a, 1.4142));
fragColor = mult * outcol;
}

View File

@@ -0,0 +1,20 @@
#ifdef GL_ES
precision mediump float;
#endif
in vec4 v_color;
in vec4 v_generic;
in vec2 v_texCoords;
uniform sampler2D u_texture;
uniform sampler2D u_wall;
out vec4 fragColor;
vec4 mult = vec4(0.0, 0.0, 0.0, 1.4142);
void main() {
vec4 backcol = texture(u_wall, v_texCoords);
vec4 incol = texture(u_texture, v_texCoords);
vec4 outcol = vec4(incol.rgb, backcol.a * pow(incol.a, 2.0));
fragColor = mult * outcol;
}