This commit is contained in:
minjaesong
2019-02-04 04:29:18 +09:00
parent 3f108a6ea9
commit 78bbd9c051
3 changed files with 401 additions and 223 deletions

View File

@@ -0,0 +1,206 @@
#include <xmmintrin.h>
#include <jni.h>
#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;
}

View File

@@ -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<Color>> = 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<Color> = 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<Float> = 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<BlockAddress, Color>((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<Color>, x: Int, y: Int, colour: Color, applyFun: (Color, Color) -> Color = { _, c -> c }) {
private fun setLightOf(list: Array<Float>, 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<Color>(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) { }
}

View File

@@ -0,0 +1,59 @@
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* 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