diff --git a/src/net/torvald/terrarum/worlddrawer/FireRecalculateEvent.c b/src/net/torvald/terrarum/worlddrawer/FireRecalculateEvent.c new file mode 100644 index 000000000..ce5a19772 --- /dev/null +++ b/src/net/torvald/terrarum/worlddrawer/FireRecalculateEvent.c @@ -0,0 +1,206 @@ +#include +#include +#include "net_torvald_terrarum_worlddrawer_LightmapRenderer.h" + +/* +compile required headers with: +"C:\Program Files\Java\jdk1.8.0_131\bin\javah.exe" -jni -cp "./lib/gdx.jar;C:\Users\minjaesong\.IdeaIC2018.3\config\plugins\JBSDKDownloadHelper\lib\kotlin-runtime.jar;C:\Users\minjaesong\Documents\terr +arum\build\libs\Terrarum-0.2.jar" net.torvald.terrarum.worlddrawer.LightmapRenderer + +get method signatures with: +"C:\Program Files\Java\jdk1.8.0_131\bin\javap.exe" -s -p -cp "./lib/gdx.jar;C:\Users\minjaesong\.IdeaIC2018.3\config\plugins\JBSDKDownloadHelper\lib\kotlin-runtime.jar;C:\Users\minjaesong\Documents\ter +rarum\build\libs\Terrarum-0.2.jar" net.torvald.terrarum.gameworld.GameWorld +*/ + +#define vec4 __m128 +#define overscan_open net_torvald_terrarum_worlddrawer_LightmapRenderer_overscan_open +#define DIV_FLOAT net_torvald_terrarum_worlddrawer_LightmapRenderer_DIV_FLOAT + + +typedef struct { + int type; + float fill; +} FluidInfo; + +vec4 lightLevelThis; +jobject thisTerrain, thisWall, thisFluid; +vec4 fluidAmountToCol; +vec4 thisTileLuminosity, thisTileOpacity, thisTileOpacity2, sunLight; + +const vec4 lightMagic = _mm_set1_ps(8); +const vec4 oneVec = _mm_set1_ps(1); +const vec4 zeroVec = _mm_set1_ps(0); +const vec4 sqrt2Vec = _mm_set1_ps(1.41421356f); + +int LIGHTMAP_WIDTH; +int for_x_start = 0; +int for_y_start = 0; +int for_x_end = 0; +int for_y_end = 0; + +void getLightsAndShades(JNIEnv *env, jclass cls, jobject obj, int x, int y) { + // get world first + jfieldID fid = (*env)->GetFieldID(env, cls, "world", "Lnet/torvald/terrarum/gameworld/GameWorld;"); + jobject worldobj = (*env)->GetObjectField(env, obj, fid); + jclass worldcls = (*env)->GetObjectClass(env, worldobj); + + // get method IDs + jmethodID getTerrain_mid = (*env)->GetMethodID(env, worldcls, "getTileFromTerrain", "(II)Ljava/lang/Integer;") + jmethodID getFluid_mid = (*env)->GetMethodID(env, worldcls, "getFluid", "(II)Lnet/torvald/terrarum/gameworld/GameWorld$FluidInfo;") + jmethodID getWall_mid = (*env)->GetMethodID(env, worldcls, "getTileFromWall", "(II)Ljava/lang/Integer;") + jmethodID getSun_mid = (*env)->GetMethodID(env, worldcls, "getGlobalLight", "()Lcom/badlogic/gdx/graphics/Color;") + + // populate the vars + thisTerrain = (*env)->CallObjectMethod(env, worldobj, getTerrain_mid, x, y); + thisFluid = (*env)->CallObjectMethod(env, worldobj, getFluid_mid, x, y); + thisWall = (*env)->CallObjectMethod(env, worldobj, getWall_mid, x, y); + + // set sunlight + jobject sun_gdxcolor = (*env)->CallObjectMethod(env, worldobj, getSun_mid, x, y); + jclass gdxcolor_cls = (*env)->GetObjectClass(env, sun_gdxcolor); + jfieldID sunfid = (*env)->GetFieldID(env, gdxcolor_cls, "r", "F"); + float sunr = GetFloatField(env, sun_gdxcolor, sunfid) * DIV_FLOAT; + sunfid = (*env)->GetFieldID(env, gdxcolor_cls, "g", "F"); + float sung = GetFloatField(env, sun_gdxcolor, sunfid) * DIV_FLOAT; + sunfid = (*env)->GetFieldID(env, gdxcolor_cls, "b", "F"); + float sunb = GetFloatField(env, sun_gdxcolor, sunfid) * DIV_FLOAT; + sunfid = (*env)->GetFieldID(env, gdxcolor_cls, "a", "F"); + float suna = GetFloatField(env, sun_gdxcolor, sunfid) * DIV_FLOAT; + + // TODO check rgba argument order (RGBA or ABGR, intel doc is confusing) + sunLight = _mm_set_ps(sunr, sung, sunb, suna); + + // get fluid info + jclass fluid_cls = (*env)->GetObjectClass(env, thisFluid); + jfieldID fluidfid = (*env)->GetFieldID(env, fluid_cls, "type", "I"); + jint fluidType = GetIntField(env, thisFluid, fluidfid); + fluidfid = (*env)->GetFieldID(env, fluid_cls, "amount", "F"); + jfloat fluidFill = GetIntField(env, thisFluid, fluidfid); + + + lightLevelThis = _mm_set1_ps(0); + + if (fluidType != 0) { + fluidAmountToCol = _mm_set1_ps(fluidFill); + thisTileLuminosity = + } + +} + +vec4 _mm_darken_ps(vec4 data, vec4 darken) { + // data * (1f - darken * lightMagic) + return _mm_mul_ps( + data, + _mm_sub_ps( + oneVec, + mm_mul_ps( + darken, + lightMagic + ) + ) + ); +} + +vec4 calculate(int x, int y) { + getLightsAndShades(x, y); + + lightLevelThis = _mm_max_ps(lightLevelThis, _mm_darken_ps(getLightInternal(x - 1, y - 1), thisTileOpacity2)); + lightLevelThis = _mm_max_ps(lightLevelThis, _mm_darken_ps(getLightInternal(x + 1, y - 1), thisTileOpacity2)); + lightLevelThis = _mm_max_ps(lightLevelThis, _mm_darken_ps(getLightInternal(x - 1, y + 1), thisTileOpacity2)); + lightLevelThis = _mm_max_ps(lightLevelThis, _mm_darken_ps(getLightInternal(x + 1, y + 1), thisTileOpacity2)); + + lightLevelThis = _mm_max_ps(lightLevelThis, _mm_darken_ps(getLightInternal(x , y - 1), thisTileOpacity)); + lightLevelThis = _mm_max_ps(lightLevelThis, _mm_darken_ps(getLightInternal(x , y + 1), thisTileOpacity)); + lightLevelThis = _mm_max_ps(lightLevelThis, _mm_darken_ps(getLightInternal(x - 1, y ), thisTileOpacity)); + lightLevelThis = _mm_max_ps(lightLevelThis, _mm_darken_ps(getLightInternal(x + 1, y ), thisTileOpacity)); + + return lightLevelThis +} + +void setLightOf(JNIEnv *env, jclass cls, int x, int y, vec4 colour) { + if (y - for_y_start + overscan_open >= 0 && + y - for_y_start + overscan_open < LIGHTMAP_HEIGHT && + + x - for_x_start + overscan_open >= 0 && + x - for_x_start + overscan_open < LIGHTMAP_WIDTH) { + + int ypos = y - for_y_start + overscan_open + int xpos = x - for_x_start + overscan_open + + // unpack our vector + float[4] vector; + _mm_store_ps(vector *, colour); + + // get the array + jfieldID fid = (*env)->GetFieldID(env, cls, "lightmap", "F"); + jfloat * list = (*env)->GetFloatArrayElements(env, jfloatarray, null); + + // set r/g/b/a values + list[4 * (ypos * LIGHTMAP_WIDTH + xpos)] = vector[0]; + list[4 * (ypos * LIGHTMAP_WIDTH + xpos) + 1] = vector[1]; + list[4 * (ypos * LIGHTMAP_WIDTH + xpos) + 2] = vector[2]; + list[4 * (ypos * LIGHTMAP_WIDTH + xpos) + 3] = vector[3]; + + //list[4 * ypos * LIGHTMAP_WIDTH + xpos] = colour + } +} + +vec4 getLightInternal(JNIEnv *env, jobject obj, int x, int y) { + if (y - for_y_start + overscan_open >= 0 && + y - for_y_start + overscan_open < LIGHTMAP_HEIGHT && + + x - for_x_start + overscan_open >= 0 && + x - for_x_start + overscan_open < LIGHTMAP_WIDTH) { + + int ypos = y - for_y_start + overscan_open + int xpos = x - for_x_start + overscan_open + + // get the array + jclass cls = (*env)->GetObjectClass(env, obj); + jfieldID fid = (*env)->GetFieldID(env, cls, "lightmap", "F"); + jfloat * list = (*env)->GetFloatArrayElements(env, jfloatarray, null); + + float r = list[4 * (ypos * LIGHTMAP_WIDTH + xpos)]; + float g = list[4 * (ypos * LIGHTMAP_WIDTH + xpos) + 1]; + float b = list[4 * (ypos * LIGHTMAP_WIDTH + xpos) + 2]; + float a = list[4 * (ypos * LIGHTMAP_WIDTH + xpos) + 3]; + + // TODO check rgba argument order (RGBA or ABGR, intel doc is confusing) + return _mm_set_ps(r, g, b, a); + } +} + +JNIEXPORT void JNICALL Java_net_torvald_terrarum_worlddrawer_LightmapRenderer_fireRecalculateEventJNI(JNIEnv *env, jobject object) { + // update (read) variables + jclass cls = (*env)->GetObjectClass(env, object); + jfieldID fid = (*env)->GetFieldID(env, cls, "LIGHTMAP_WIDTH", "I"); + LIGHTMAP_WIDTH = (*env)->GetIntField(env, obj, fid); + fid = (*env)->GetFieldID(env, cls, "for_x_start", "I"); + for_x_start = (*env)->GetIntField(env, obj, fid); + fid = (*env)->GetFieldID(env, cls, "for_y_start", "I"); + for_y_start = (*env)->GetIntField(env, obj, fid); + fid = (*env)->GetFieldID(env, cls, "for_x_end", "I"); + for_x_end = (*env)->GetIntField(env, obj, fid); + fid = (*env)->GetFieldID(env, cls, "for_y_end", "I"); + for_y_end = (*env)->GetIntField(env, obj, fid); + + + /** + * Updating order: + * ,--------. ,--+-----. ,-----+--. ,--------. - + * |↘ | | | 3| |3 | | | ↙| ↕︎ overscan_open / overscan_opaque + * | ,-----+ | | 2 | | 2 | | +-----. | - depending on the noop_mask + * | |1 | | |1 | | 1| | | 1| | + * | | 2 | | `-----+ +-----' | | 2 | | + * | | 3| |↗ | | ↖| |3 | | + * `--+-----' `--------' `--------' `-----+--' + * round: 1 2 3 4 + * Run in this order: 0-2-3-4-1 + * zero means we wipe out lightmap. + * But why start from 2? No special reason. + */ + + + + return; +} diff --git a/src/net/torvald/terrarum/worlddrawer/LightmapRendererNew.kt b/src/net/torvald/terrarum/worlddrawer/LightmapRendererNew.kt index 728b78ad7..77fc353bf 100644 --- a/src/net/torvald/terrarum/worlddrawer/LightmapRendererNew.kt +++ b/src/net/torvald/terrarum/worlddrawer/LightmapRendererNew.kt @@ -12,14 +12,12 @@ import net.torvald.terrarum.blockproperties.Block import net.torvald.terrarum.blockproperties.BlockCodex import net.torvald.terrarum.blockproperties.Fluid import net.torvald.terrarum.concurrent.ParallelUtils.sliceEvenly -import net.torvald.terrarum.concurrent.ThreadParallel import net.torvald.terrarum.gameactors.ActorWBMovable import net.torvald.terrarum.gameactors.Luminous import net.torvald.terrarum.gameworld.BlockAddress import net.torvald.terrarum.gameworld.GameWorld import net.torvald.terrarum.modulebasegame.IngameRenderer import net.torvald.terrarum.realestate.LandUtil -import java.util.concurrent.atomic.AtomicReferenceArray /** * Sub-portion of IngameRenderer. You are not supposed to directly deal with this. @@ -53,7 +51,7 @@ object LightmapRenderer { }*/ for (i in 0 until lightmap.size) { - lightmap[i] = colourNull + lightmap[i] = 0f } makeUpdateTaskList() @@ -84,7 +82,7 @@ object LightmapRenderer { */ // it utilises alpha channel to determine brightness of "glow" sprites (so that alpha channel works like UV light) //private val lightmap: Array> = Array(LIGHTMAP_HEIGHT) { Array(LIGHTMAP_WIDTH, { Color(0f,0f,0f,0f) }) } // Can't use framebuffer/pixmap -- this is a fvec4 array, whereas they are ivec4. - private val lightmap: Array = Array(LIGHTMAP_WIDTH * LIGHTMAP_HEIGHT) { Color(0f,0f,0f,0f) } // Can't use framebuffer/pixmap -- this is a fvec4 array, whereas they are ivec4. + private val lightmap: Array = Array(LIGHTMAP_WIDTH * LIGHTMAP_HEIGHT * 4) { 0f } // Can't use framebuffer/pixmap -- this is a fvec4 array, whereas they are ivec4. private val lanternMap = HashMap((Terrarum.ingame?.ACTORCONTAINER_INITIAL_SIZE ?: 2) * 4) private lateinit var texturedLightMap: FrameBuffer @@ -202,7 +200,12 @@ object LightmapRenderer { val xpos = x - for_x_start + overscan_open //return lightmap[ypos][xpos] - return lightmap[ypos * LIGHTMAP_WIDTH + xpos] + return Color( + lightmap[4 * (ypos * LIGHTMAP_WIDTH + xpos)], + lightmap[4 * (ypos * LIGHTMAP_WIDTH + xpos) + 1], + lightmap[4 * (ypos * LIGHTMAP_WIDTH + xpos) + 2], + lightmap[4 * (ypos * LIGHTMAP_WIDTH + xpos) + 3] + ) } return null @@ -221,7 +224,7 @@ object LightmapRenderer { * @param colour Color to write * @param applyFun A function ```foo(old_colour, given_colour)``` */ - private fun setLightOf(list: Array, x: Int, y: Int, colour: Color, applyFun: (Color, Color) -> Color = { _, c -> c }) { + private fun setLightOf(list: Array, x: Int, y: Int, colour: Color) { if (y - for_y_start + overscan_open in 0 until LIGHTMAP_HEIGHT && x - for_x_start + overscan_open in 0 until LIGHTMAP_WIDTH) { @@ -229,7 +232,12 @@ object LightmapRenderer { val xpos = x - for_x_start + overscan_open //lightmap[ypos][xpos] = applyFun.invoke(list[ypos][xpos], colour) - list[ypos * LIGHTMAP_WIDTH + xpos] = applyFun.invoke(list[ypos * LIGHTMAP_WIDTH + xpos], colour) + //list[ypos * LIGHTMAP_WIDTH + xpos] = applyFun.invoke(list[ypos * LIGHTMAP_WIDTH + xpos], colour) + + list[4 * (ypos * LIGHTMAP_WIDTH + xpos)] = colour.r + list[4 * (ypos * LIGHTMAP_WIDTH + xpos) + 1] = colour.g + list[4 * (ypos * LIGHTMAP_WIDTH + xpos) + 2] = colour.b + list[4 * (ypos * LIGHTMAP_WIDTH + xpos) + 3] = colour.a } } @@ -262,189 +270,98 @@ object LightmapRenderer { buildLanternmap() } // usually takes 3000 ns - if (!SHADER_LIGHTING) { - /** - * Updating order: - * ,--------. ,--+-----. ,-----+--. ,--------. - - * |↘ | | | 3| |3 | | | ↙| ↕︎ overscan_open / overscan_opaque - * | ,-----+ | | 2 | | 2 | | +-----. | - depending on the noop_mask - * | |1 | | |1 | | 1| | | 1| | - * | | 2 | | `-----+ +-----' | | 2 | | - * | | 3| |↗ | | ↖| |3 | | - * `--+-----' `--------' `--------' `-----+--' - * round: 1 2 3 4 - * for all lightmap[y][x], run in this order: 2-3-4-1-2 - * If you run only 4 sets, orthogonal/diagonal artefacts are bound to occur, - * it seems 5-pass is mandatory - */ - // wipe out lightmap - AppLoader.measureDebugTime("Renderer.Light0") { - //for (ky in 0 until lightmap.size) for (kx in 0 until lightmap[0].size) lightmap[ky][kx] = colourNull - for (k in 0 until lightmap.size) lightmap[k] = colourNull - // when disabled, light will "decay out" instead of "instantly out", which can have a cool effect - // but the performance boost is measly 0.1 ms on 6700K - } - // O((5*9)n) == O(n) where n is a size of the map. - // Because of inevitable overlaps on the area, it only works with MAX blend - - - // each usually takes 8 000 000..12 000 000 miliseconds total when not threaded - - if (!AppLoader.getConfigBoolean("multithreadedlight")) { - //val workMap = Array(lightmap.size) { colourNull } - - // The skipping is dependent on how you get ambient light, - // in this case we have 'spillage' due to the fact calculate() samples 3x3 area. - - // FIXME theoretically skipping shouldn't work (light can be anywhere on the screen, not just centre - // but how does it actually work ?!?!?!!?!?!?!? - // because things are filled in subsequent frames ? - // because of not wiping out prev map ! (if pass=1 also calculates ambience, was disabled to not have to wipe out) - - // Round 2 - AppLoader.measureDebugTime("Renderer.Light1") { - for (y in for_y_end + overscan_open downTo for_y_start) { - for (x in for_x_start - overscan_open..for_x_end) { - setLightOf(lightmap, x, y, calculate(x, y)) - } - } - } - - // Round 3 - AppLoader.measureDebugTime("Renderer.Light2") { - for (y in for_y_end + overscan_open downTo for_y_start) { - for (x in for_x_end + overscan_open downTo for_x_start) { - setLightOf(lightmap, x, y, calculate(x, y)) - } - } - } - - // Round 4 - AppLoader.measureDebugTime("Renderer.Light3") { - for (y in for_y_start - overscan_open..for_y_end) { - for (x in for_x_end + overscan_open downTo for_x_start) { - setLightOf(lightmap, x, y, calculate(x, y)) - } - } - } - - // Round 1 - AppLoader.measureDebugTime("Renderer.Light4") { - for (y in for_y_start - overscan_open..for_y_end) { - for (x in for_x_start - overscan_open..for_x_end) { - setLightOf(lightmap, x, y, calculate(x, y)) - } - } - } - - AppLoader.addDebugTime("Renderer.LightTotal", - "Renderer.Light1", - "Renderer.Light2", - "Renderer.Light3", - "Renderer.Light4", - "Renderer.Light0" - ) - } - else if (world.worldIndex != -1) { // to avoid updating on the null world - val buf = AtomicReferenceArray(lightmap.size) - - AppLoader.measureDebugTime("Renderer.LightPrlPre") { - // update the content of buf using maxBlend -- it's not meant for overwrite - - updateMessages.forEachIndexed { index, msg -> - ThreadParallel.map(index, "Light") { - // for the message slices... - msg.forEach { m -> - // update the content of buf using maxBlend -- it's not meant for overwrite - buf.getAndUpdate(m.y * LIGHTMAP_WIDTH + m.x) { oldCol -> - val ux = m.x + for_x_start - overscan_open - val uy = m.y + for_y_start - overscan_open - - (oldCol ?: colourNull) maxBlend calculate(ux, uy) - } - } - } - } - } - - AppLoader.measureDebugTime("Renderer.LightPrlRun") { - ThreadParallel.startAllWaitForDie() - } - - AppLoader.measureDebugTime("Renderer.LightPrlPost") { - // copy to lightmap - for (k in 0 until lightmap.size) { - lightmap[k] = buf.getPlain(k) ?: colourNull - } - } - - AppLoader.addDebugTime("Renderer.LightTotal", - "Renderer.LightPrlPre", - "Renderer.LightPrlRun", - "Renderer.LightPrlPost" - ) - } - } - else { - AppLoader.measureDebugTime("Renderer.LightGPU") { - - // prepare necessary textures (lightmap, shademap) for the input. - for (ty in 0 until LIGHTMAP_HEIGHT) { - for (tx in 0 until LIGHTMAP_WIDTH) { - val wx = tx + for_x_start - overscan_open - val wy = ty + for_y_start - overscan_open - - // Several variables will be altered by this. See its documentation. - getLightsAndShades(wx, wy) - - texturedLightSourcePixmap.drawPixel(tx, ty, lightLevelThis.toRGBA()) - texturedShadeSourcePixmap.drawPixel(tx, ty, thisTileOpacity.toRGBA()) - - - - /*if (wy in for_y_start..for_y_end && wx in for_x_start..for_x_end) { - texturedLightSourcePixmap.drawPixel(tx, ty, 0x00FFFFFF) - } - else { - texturedLightSourcePixmap.drawPixel(tx, ty, 0xFF000000.toInt()) - }*/ - - } - } - - texturedLightSources.dispose() - texturedLightSources = Texture(texturedLightSourcePixmap) - - texturedShadeSources.dispose() - texturedShadeSources = Texture(texturedShadeSourcePixmap) - - - texturedLightMap.inAction(texturedLightCamera, null) { - gdxClearAndSetBlend(0f,0f,0f,0f) - Gdx.gl.glDisable(GL20.GL_BLEND) - - texturedShadeSources.bind(SHADEMAP_UNIT) - texturedLightSources.bind(LIGHTMAP_UNIT) - - lightCalcShader.begin() - // it seems that every time shader ends, uniforms reset themselves. - lightCalcShader.setUniformMatrix("u_projTrans", texturedLightCamera.combined) - lightCalcShader.setUniformf("outSize", LIGHTMAP_WIDTH.toFloat(), LIGHTMAP_HEIGHT.toFloat()) - lightCalcShader.setUniformi("shades", SHADEMAP_UNIT) - lightCalcShader.setUniformi("lights", LIGHTMAP_UNIT) - texturedLightQuad.render(lightCalcShader, GL20.GL_TRIANGLES) - lightCalcShader.end() - } - - Gdx.gl.glActiveTexture(GL20.GL_TEXTURE0) // so that batch that comes next will bind any tex to it - - - } - } + fireRecalculateEventJava() } + private fun fireRecalculateEventJava() { + /** + * Updating order: + * ,--------. ,--+-----. ,-----+--. ,--------. - + * |↘ | | | 3| |3 | | | ↙| ↕︎ overscan_open / overscan_opaque + * | ,-----+ | | 2 | | 2 | | +-----. | - depending on the noop_mask + * | |1 | | |1 | | 1| | | 1| | + * | | 2 | | `-----+ +-----' | | 2 | | + * | | 3| |↗ | | ↖| |3 | | + * `--+-----' `--------' `--------' `-----+--' + * round: 1 2 3 4 + * Run in this order: 0-2-3-4-1 + * zero means we wipe out lightmap. + * But why start from 2? No special reason. + */ + + + // wipe out lightmap + AppLoader.measureDebugTime("Renderer.Light0") { + //for (ky in 0 until lightmap.size) for (kx in 0 until lightmap[0].size) lightmap[ky][kx] = colourNull + for (k in 0 until lightmap.size) lightmap[k] = 0f + // when disabled, light will "decay out" instead of "instantly out", which can have a cool effect + // but the performance boost is measly 0.1 ms on 6700K + } + // O((5*9)n) == O(n) where n is a size of the map. + // Because of inevitable overlaps on the area, it only works with MAX blend + + + // each usually takes 8 000 000..12 000 000 miliseconds total when not threaded + + //val workMap = Array(lightmap.size) { colourNull } + + // The skipping is dependent on how you get ambient light, + // in this case we have 'spillage' due to the fact calculate() samples 3x3 area. + + // FIXME theoretically skipping shouldn't work (light can be anywhere on the screen, not just centre + // but how does it actually work ?!?!?!!?!?!?!? + // because things are filled in subsequent frames ? + // because of not wiping out prev map ! (if pass=1 also calculates ambience, was disabled to not have to wipe out) + + // Round 2 + AppLoader.measureDebugTime("Renderer.Light1") { + for (y in for_y_end + overscan_open downTo for_y_start) { + for (x in for_x_start - overscan_open..for_x_end) { + setLightOf(lightmap, x, y, calculate(x, y)) + } + } + } + + // Round 3 + AppLoader.measureDebugTime("Renderer.Light2") { + for (y in for_y_end + overscan_open downTo for_y_start) { + for (x in for_x_end + overscan_open downTo for_x_start) { + setLightOf(lightmap, x, y, calculate(x, y)) + } + } + } + + // Round 4 + AppLoader.measureDebugTime("Renderer.Light3") { + for (y in for_y_start - overscan_open..for_y_end) { + for (x in for_x_end + overscan_open downTo for_x_start) { + setLightOf(lightmap, x, y, calculate(x, y)) + } + } + } + + // Round 1 + AppLoader.measureDebugTime("Renderer.Light4") { + for (y in for_y_start - overscan_open..for_y_end) { + for (x in for_x_start - overscan_open..for_x_end) { + setLightOf(lightmap, x, y, calculate(x, y)) + } + } + } + + AppLoader.addDebugTime("Renderer.LightTotal", + "Renderer.Light1", + "Renderer.Light2", + "Renderer.Light3", + "Renderer.Light4", + "Renderer.Light0" + ) + + } + + private external fun fireRecalculateEventJNI() @@ -660,47 +577,41 @@ object LightmapRenderer { val this_y_end = for_y_end// + overscan_open // wipe out beforehand. You DO need this - if (!SHADER_LIGHTING) { - lightBuffer.blending = Pixmap.Blending.None // gonna overwrite (remove this line causes the world to go bit darker) - lightBuffer.setColor(colourNull) - lightBuffer.fill() + lightBuffer.blending = Pixmap.Blending.None // gonna overwrite (remove this line causes the world to go bit darker) + lightBuffer.setColor(colourNull) + lightBuffer.fill() - // write to colour buffer - for (y in this_y_start..this_y_end) { - //println("y: $y, this_y_start: $this_y_start") - if (y == this_y_start && this_y_start == 0) { - //throw Error("Fuck hits again...") - } - - for (x in this_x_start..this_x_end) { - - val color = (getLightForOpaque(x, y) ?: Color(0f, 0f, 0f, 0f)).normaliseToHDR() - - lightBuffer.setColor(color) - - //lightBuffer.drawPixel(x - this_x_start, y - this_y_start) - - lightBuffer.drawPixel(x - this_x_start, lightBuffer.height - 1 - y + this_y_start) // flip Y - } + // write to colour buffer + for (y in this_y_start..this_y_end) { + //println("y: $y, this_y_start: $this_y_start") + if (y == this_y_start && this_y_start == 0) { + //throw Error("Fuck hits again...") } + for (x in this_x_start..this_x_end) { - // draw to the batch - _lightBufferAsTex.dispose() - _lightBufferAsTex = Texture(lightBuffer) - _lightBufferAsTex.setFilter(Texture.TextureFilter.Nearest, Texture.TextureFilter.Nearest) + val color = (getLightForOpaque(x, y) ?: Color(0f, 0f, 0f, 0f)).normaliseToHDR() + lightBuffer.setColor(color) - Gdx.gl.glActiveTexture(GL20.GL_TEXTURE0) // so that batch that comes next will bind any tex to it - // we might not need shader here... - //batch.draw(lightBufferAsTex, 0f, 0f, lightBufferAsTex.width.toFloat(), lightBufferAsTex.height.toFloat()) - batch.draw(_lightBufferAsTex, 0f, 0f, _lightBufferAsTex.width * DRAW_TILE_SIZE, _lightBufferAsTex.height * DRAW_TILE_SIZE) - } - else { - Gdx.gl.glActiveTexture(GL20.GL_TEXTURE0) // so that batch that comes next will bind any tex to it - batch.draw(texturedLightMap.colorBufferTexture, -overscan_open * DRAW_TILE_SIZE, -overscan_open * DRAW_TILE_SIZE, texturedLightMap.width * DRAW_TILE_SIZE, texturedLightMap.height * DRAW_TILE_SIZE) + //lightBuffer.drawPixel(x - this_x_start, y - this_y_start) + + lightBuffer.drawPixel(x - this_x_start, lightBuffer.height - 1 - y + this_y_start) // flip Y + } } + + + // draw to the batch + _lightBufferAsTex.dispose() + _lightBufferAsTex = Texture(lightBuffer) + _lightBufferAsTex.setFilter(Texture.TextureFilter.Nearest, Texture.TextureFilter.Nearest) + + + Gdx.gl.glActiveTexture(GL20.GL_TEXTURE0) // so that batch that comes next will bind any tex to it + // we might not need shader here... + //batch.draw(lightBufferAsTex, 0f, 0f, lightBufferAsTex.width.toFloat(), lightBufferAsTex.height.toFloat()) + batch.draw(_lightBufferAsTex, 0f, 0f, _lightBufferAsTex.width * DRAW_TILE_SIZE, _lightBufferAsTex.height * DRAW_TILE_SIZE) } } @@ -1014,10 +925,12 @@ object LightmapRenderer { for (x in overscan_open..render_width + overscan_open + 1) { try { //val colour = lightmap[y][x] - val colour = lightmap[y * LIGHTMAP_WIDTH + x] - reds[minOf(CHANNEL_MAX, colour.r.times(MUL).floorInt())] += 1 - greens[minOf(CHANNEL_MAX, colour.g.times(MUL).floorInt())] += 1 - blues[minOf(CHANNEL_MAX, colour.b.times(MUL).floorInt())] += 1 + val colourR = lightmap[4 * (y * LIGHTMAP_WIDTH + x)] + val colourG = lightmap[4 * (y * LIGHTMAP_WIDTH + x) + 1] + val colourB = lightmap[4 * (y * LIGHTMAP_WIDTH + x) + 2] + reds[minOf(CHANNEL_MAX, colourR.times(MUL).floorInt())] += 1 + greens[minOf(CHANNEL_MAX, colourG.times(MUL).floorInt())] += 1 + blues[minOf(CHANNEL_MAX, colourB.times(MUL).floorInt())] += 1 } catch (e: ArrayIndexOutOfBoundsException) { } } diff --git a/src/net/torvald/terrarum/worlddrawer/net_torvald_terrarum_worlddrawer_LightmapRenderer.h b/src/net/torvald/terrarum/worlddrawer/net_torvald_terrarum_worlddrawer_LightmapRenderer.h new file mode 100644 index 000000000..912d6117b --- /dev/null +++ b/src/net/torvald/terrarum/worlddrawer/net_torvald_terrarum_worlddrawer_LightmapRenderer.h @@ -0,0 +1,59 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* Header for class net_torvald_terrarum_worlddrawer_LightmapRenderer */ + +#ifndef _Included_net_torvald_terrarum_worlddrawer_LightmapRenderer +#define _Included_net_torvald_terrarum_worlddrawer_LightmapRenderer +#ifdef __cplusplus +extern "C" { +#endif +#undef net_torvald_terrarum_worlddrawer_LightmapRenderer_overscan_open +#define net_torvald_terrarum_worlddrawer_LightmapRenderer_overscan_open 32L +#undef net_torvald_terrarum_worlddrawer_LightmapRenderer_overscan_opaque +#define net_torvald_terrarum_worlddrawer_LightmapRenderer_overscan_opaque 8L +#undef net_torvald_terrarum_worlddrawer_LightmapRenderer_LIGHTMAP_UNIT +#define net_torvald_terrarum_worlddrawer_LightmapRenderer_LIGHTMAP_UNIT 0L +#undef net_torvald_terrarum_worlddrawer_LightmapRenderer_SHADEMAP_UNIT +#define net_torvald_terrarum_worlddrawer_LightmapRenderer_SHADEMAP_UNIT 1L +#undef net_torvald_terrarum_worlddrawer_LightmapRenderer_AIR +#define net_torvald_terrarum_worlddrawer_LightmapRenderer_AIR 0L +#undef net_torvald_terrarum_worlddrawer_LightmapRenderer_TILE_SIZE +#define net_torvald_terrarum_worlddrawer_LightmapRenderer_TILE_SIZE 16L +#undef net_torvald_terrarum_worlddrawer_LightmapRenderer_DRAW_TILE_SIZE +#define net_torvald_terrarum_worlddrawer_LightmapRenderer_DRAW_TILE_SIZE 4.0f +#undef net_torvald_terrarum_worlddrawer_LightmapRenderer_MUL +#define net_torvald_terrarum_worlddrawer_LightmapRenderer_MUL 1024L +#undef net_torvald_terrarum_worlddrawer_LightmapRenderer_CHANNEL_MAX_DECIMAL +#define net_torvald_terrarum_worlddrawer_LightmapRenderer_CHANNEL_MAX_DECIMAL 1.0f +#undef net_torvald_terrarum_worlddrawer_LightmapRenderer_MUL_2 +#define net_torvald_terrarum_worlddrawer_LightmapRenderer_MUL_2 1048576L +#undef net_torvald_terrarum_worlddrawer_LightmapRenderer_CHANNEL_MAX +#define net_torvald_terrarum_worlddrawer_LightmapRenderer_CHANNEL_MAX 1023L +#undef net_torvald_terrarum_worlddrawer_LightmapRenderer_CHANNEL_MAX_FLOAT +#define net_torvald_terrarum_worlddrawer_LightmapRenderer_CHANNEL_MAX_FLOAT 1023.0f +#undef net_torvald_terrarum_worlddrawer_LightmapRenderer_COLOUR_RANGE_SIZE +#define net_torvald_terrarum_worlddrawer_LightmapRenderer_COLOUR_RANGE_SIZE 1073741824L +#undef net_torvald_terrarum_worlddrawer_LightmapRenderer_MUL_FLOAT +#define net_torvald_terrarum_worlddrawer_LightmapRenderer_MUL_FLOAT 4.0f +#undef net_torvald_terrarum_worlddrawer_LightmapRenderer_DIV_FLOAT +#define net_torvald_terrarum_worlddrawer_LightmapRenderer_DIV_FLOAT 0.25f +#undef net_torvald_terrarum_worlddrawer_LightmapRenderer_DRAW_FOR_RGB +#define net_torvald_terrarum_worlddrawer_LightmapRenderer_DRAW_FOR_RGB 65520L +#undef net_torvald_terrarum_worlddrawer_LightmapRenderer_DRAW_FOR_ALPHA +#define net_torvald_terrarum_worlddrawer_LightmapRenderer_DRAW_FOR_ALPHA 15L +#undef net_torvald_terrarum_worlddrawer_LightmapRenderer_epsilon +#define net_torvald_terrarum_worlddrawer_LightmapRenderer_epsilon 9.765625E-4f +#undef net_torvald_terrarum_worlddrawer_LightmapRenderer_lightScalingMagic +#define net_torvald_terrarum_worlddrawer_LightmapRenderer_lightScalingMagic 8.0f +/* + * Class: net_torvald_terrarum_worlddrawer_LightmapRenderer + * Method: fireRecalculateEventJNI + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_net_torvald_terrarum_worlddrawer_LightmapRenderer_fireRecalculateEventJNI + (JNIEnv *, jobject); + +#ifdef __cplusplus +} +#endif +#endif