Made dynamic lighting smoother

This commit is contained in:
josua 2020-06-24 11:07:41 +10:00
parent 0ee4243011
commit a0d6d87dcf
13 changed files with 99 additions and 326 deletions

View File

@ -1,9 +1,5 @@
package projectzombie.display; package projectzombie.display;
import static org.lwjgl.opengl.GL11.GL_FLOAT;
import static org.lwjgl.opengl.GL20.glEnableVertexAttribArray;
import static org.lwjgl.opengl.GL20.glVertexAttribPointer;
import java.nio.IntBuffer; import java.nio.IntBuffer;
import org.lwjgl.BufferUtils; import org.lwjgl.BufferUtils;
@ -147,7 +143,7 @@ public class DisplayWindow implements IMainloopTask
// Bind the lightmap // Bind the lightmap
GL33.glActiveTexture(GL33.GL_TEXTURE1); GL33.glActiveTexture(GL33.GL_TEXTURE1);
GL33.glBindTexture(GL33.GL_TEXTURE_2D, TileLighting.lightmap_src); GL33.glBindTexture(GL33.GL_TEXTURE_2D, TileLighting.lightmap);
// Render everything // Render everything
DisplayRender.render(w[0], h[0]); DisplayRender.render(w[0], h[0]);

View File

@ -9,6 +9,7 @@ import bdf.types.BdfNamedList;
import bdf.types.BdfObject; import bdf.types.BdfObject;
import gl_engine.MathHelpers; import gl_engine.MathHelpers;
import gl_engine.range.Range2i; import gl_engine.range.Range2i;
import gl_engine.vec.Vec2d;
import gl_engine.vec.Vec2i; import gl_engine.vec.Vec2i;
import projectzombie.Main; import projectzombie.Main;
import projectzombie.display.Camera; import projectzombie.display.Camera;
@ -22,19 +23,19 @@ import projectzombie.world.layer.Layer;
public class TileLighting public class TileLighting
{ {
private static class Lighting { private static class Lighting {
float[] p_src; float[] p;
float[] p_day;
int w, h; int w, h;
int x, y; int x, y;
private int getID(int x, int y) { private int getID(int x, int y) {
return x + y * w; return (x + y * w) * 3 + 1;
} }
} }
private static int lighting_last_x = 0;
private static int lighting_last_y = 0;
private static boolean lighting_dirty = false; private static boolean lighting_dirty = false;
public static int lightmap_src; public static int lightmap;
public static int lightmap_day;
private static Lighting lighting; private static Lighting lighting;
@ -51,7 +52,7 @@ public class TileLighting
} }
public TileLighting() { public TileLighting() {
lightmap_src = GL33.glGenTextures(); lightmap = GL33.glGenTextures();
} }
public static void update() public static void update()
@ -131,7 +132,7 @@ public class TileLighting
MathHelpers.floor(player.pos.y / 16) - Chunk.RENDER_DISTANCE); MathHelpers.floor(player.pos.y / 16) - Chunk.RENDER_DISTANCE);
} }
private static void calculateLight(Layer layer, Lighting lighting, float[] pixels, int x, int y, float level, boolean ignore) private static void calculateLight(Layer layer, Lighting lighting, float[] pixels, int x, int y, float level)
{ {
if(x < 0 || y < 0 || x >= lighting.w || y >= lighting.h) { if(x < 0 || y < 0 || x >= lighting.w || y >= lighting.h) {
return; return;
@ -143,7 +144,7 @@ public class TileLighting
Vec2i tpos = new Vec2i(x + lighting.x * 16, y + lighting.y * 16); Vec2i tpos = new Vec2i(x + lighting.x * 16, y + lighting.y * 16);
int tid = tpos.getId(Chunk.CHUNK_SIZE); int tid = tpos.getId(Chunk.CHUNK_SIZE);
if(level_current >= level && !ignore) { if(level_current >= level) {
return; return;
} }
@ -164,7 +165,64 @@ public class TileLighting
}; };
for(int i=0;i<8;i+=2) { for(int i=0;i<8;i+=2) {
calculateLight(layer, lighting, pixels, adjacent[i], adjacent[i+1], level_next, false); calculateLight(layer, lighting, pixels, adjacent[i], adjacent[i+1], level_next);
}
}
private static void calculateEntityLighting(Layer layer, Lighting lighting, Entity entity, float[] pixels)
{
if(!entity.emitsLight) {
return;
}
double level = entity.getLightLevel();
if(level <= 0) {
return;
}
if(level > 1) {
level = 1;
}
int[] positions = {
0, 0,
1, 0,
1, 1,
0, 1
};
for(int i=0;i<positions.length;i+=2)
{
int x = (int)Math.round(entity.pos.x) - positions[i+0];
int y = (int)Math.round(entity.pos.y) - positions[i+1];
Vec2i lpos = new Vec2i(x, y).subtract(new Vec2i(lighting.x * 16, lighting.y * 16));
if(lpos.x < 0 || lpos.y < 0 || lpos.x >= lighting.w || lpos.y >= lighting.h) {
continue;
}
int id = lighting.getID(lpos.x, lpos.y);
float level_current = pixels[id];
Vec2i tpos = new Vec2i(x, y);
int tid = tpos.getId(Chunk.CHUNK_SIZE);
if(level_current >= level) {
continue;
}
Chunk chunk = layer.getChunk(tpos);
TileState ft = chunk.getFrontTile(tid);
TileState bt = chunk.getBackTile(tid);
double dissipation = Math.max(ft.tile.getLightDissipation(ft), bt.tile.getLightDissipation(bt));
double level2 = level - dissipation * (Math.abs(x + 0.5 - entity.pos.x) + Math.abs(y + 0.5 - entity.pos.y));
//pixels[id] = (float)level2;
calculateLight(layer, lighting, pixels, lpos.x, lpos.y, (float)level2);
} }
} }
@ -173,28 +231,14 @@ public class TileLighting
Lighting lighting = getLighting(); Lighting lighting = getLighting();
// Copy the pixels // Copy the pixels
float[] pixels = new float[lighting.p_src.length]; float[] pixels = new float[lighting.p.length];
for(int i=0;i<pixels.length;i++) { for(int i=0;i<pixels.length;i++) {
pixels[i] = lighting.p_src[i]; pixels[i] = lighting.p[i];
} }
Layer layer = Main.world.getLayer(); Layer layer = Main.world.getLayer();
lighting: { calculateEntityLighting(layer, lighting, Main.player, pixels);
double level = Main.player.getLightLevel();
if(level <= 0) {
break lighting;
}
if(level > 1) {
level = 1;
}
Vec2i lpos = Main.player.pos.toInt().subtract(new Vec2i(lighting.x * 16, lighting.y * 16));
calculateLight(layer, lighting, pixels, lpos.x, lpos.y, (float)level, true);
}
for(int cx=-Chunk.RENDER_DISTANCE;cx<=Chunk.RENDER_DISTANCE;cx++) { for(int cx=-Chunk.RENDER_DISTANCE;cx<=Chunk.RENDER_DISTANCE;cx++) {
for(int cy=-Chunk.RENDER_DISTANCE;cy<=Chunk.RENDER_DISTANCE;cy++) for(int cy=-Chunk.RENDER_DISTANCE;cy<=Chunk.RENDER_DISTANCE;cy++)
@ -205,37 +249,15 @@ public class TileLighting
Chunk chunk = layer.chunks.get(cpos); Chunk chunk = layer.chunks.get(cpos);
for(Entity entity : chunk.entities) for(Entity entity : chunk.entities) {
{ calculateEntityLighting(layer, lighting, entity, pixels);
if(!entity.emitsLight) {
continue;
}
double level = entity.getLightLevel();
if(level <= 0) {
continue;
}
if(level > 1) {
level = 1;
}
Vec2i lpos = entity.pos.toInt().subtract(new Vec2i(lighting.x * 16, lighting.y * 16));
calculateLight(layer, lighting, pixels, lpos.x, lpos.y, (float)level, true);
} }
} }
} }
// Update the texture // Update the texture
GL33.glBindTexture(GL33.GL_TEXTURE_2D, lightmap_src); GL33.glBindTexture(GL33.GL_TEXTURE_2D, lightmap);
GL33.glTexImage2D(GL33.GL_TEXTURE_2D, 0, GL33.GL_RGB, lighting.w, lighting.h, 0, GL33.GL_RGB, GL33.GL_FLOAT, pixels);
GL33.glTexImage2D(
GL33.GL_TEXTURE_2D, 0, GL33.GL_LUMINANCE,
lighting.w, lighting.h, 0, GL33.GL_LUMINANCE,
GL33.GL_FLOAT, pixels);
GL33.glGenerateMipmap(GL33.GL_TEXTURE_2D); GL33.glGenerateMipmap(GL33.GL_TEXTURE_2D);
// Set the texture location data // Set the texture location data
@ -246,7 +268,7 @@ public class TileLighting
public static void clearLighting() public static void clearLighting()
{ {
Lighting lighting = new Lighting(); Lighting lighting = new Lighting();
lighting.p_src = new float[2]; lighting.p = new float[3];
lighting.w = 1; lighting.w = 1;
lighting.h = 1; lighting.h = 1;
lighting.x = 0; lighting.x = 0;
@ -264,8 +286,15 @@ public class TileLighting
int x = nl.get("x").getInteger(); int x = nl.get("x").getInteger();
int y = nl.get("y").getInteger(); int y = nl.get("y").getInteger();
float[] pixels = new float[width*height*3];
for(int i=0;i<width*height;i++) {
pixels[i*3+0] = light[i*2+0];
pixels[i*3+1] = light[i*2+1];
}
Lighting lighting = new Lighting(); Lighting lighting = new Lighting();
lighting.p_src = light; lighting.p = pixels;
lighting.w = width; lighting.w = width;
lighting.h = height; lighting.h = height;
lighting.x = x; lighting.x = x;

View File

@ -14,7 +14,6 @@ import projectzombie.init.Models;
import projectzombie.init.Sounds; import projectzombie.init.Sounds;
import projectzombie.init.Tiles; import projectzombie.init.Tiles;
import projectzombie.model.Model; import projectzombie.model.Model;
import projectzombie.util.gl.texture.IHasTexture;
import projectzombie.util.math.TileState; import projectzombie.util.math.TileState;
import projectzombie.world.chunk.Chunk; import projectzombie.world.chunk.Chunk;
import projectzombie.world.layer.Layer; import projectzombie.world.layer.Layer;
@ -112,14 +111,14 @@ public class EntityExplosion extends Entity
// Set the tiles // Set the tiles
if(!bts.tile.unbreakable) { if(!bts.tile.unbreakable) {
l.setBackTile(ets, tpos); l.setBackTile(ets, tpos);
if(fts.tile instanceof IHasTexture) //if(fts.tile instanceof IHasTexture)
l.spawnEntity(new ParticleBreak(new Vec2d(tpos.x+rand.nextDouble(), tpos.y+rand.nextDouble()), bts, 1)); //l.spawnEntity(new ParticleBreak(new Vec2d(tpos.x+rand.nextDouble(), tpos.y+rand.nextDouble()), bts, 1));
} }
if(!fts.tile.unbreakable) { if(!fts.tile.unbreakable) {
l.setFrontTile(Tiles.VOID.getDefaultState(), tpos); l.setFrontTile(Tiles.VOID.getDefaultState(), tpos);
if(fts.tile instanceof IHasTexture) //if(fts.tile instanceof IHasTexture)
l.spawnEntity(new ParticleBreak(new Vec2d(tpos.x+rand.nextDouble(), tpos.y+rand.nextDouble()), fts, 1)); //l.spawnEntity(new ParticleBreak(new Vec2d(tpos.x+rand.nextDouble(), tpos.y+rand.nextDouble()), fts, 1));
} }
if(upto + multiplier > entities.length) { if(upto + multiplier > entities.length) {

View File

@ -107,6 +107,8 @@ public class EntityPlayer extends Entity implements EntityAlive, EntityInventory
// Create the inventory // Create the inventory
inventory = new Inventory(10); inventory = new Inventory(10);
inventory.addItem(new ItemStack(Items.LANTERN, 99, (short)0));
} }
@Override @Override

View File

@ -1,6 +0,0 @@
package projectzombie.util.gl.texture;
public interface IHasTexture
{
public TextureReference getTexture();
}

View File

@ -1,62 +0,0 @@
package projectzombie.util.gl.texture;
import java.nio.ByteBuffer;
import org.lwjgl.stb.STBImage;
import projectzombie.resources.Resource;
public class Texture
{
private ByteBuffer texture;
private int width;
private int height;
private int channels;
public Texture(Resource tex)
{
// Get the width, height, and channels
int width[] = {0};
int height[] = {0};
int channels[] = {0};
// Load the texture with STBImage
this.texture = STBImage.stbi_load_from_memory(
tex.getByteBuffer(),
width, height, channels,
STBImage.STBI_rgb_alpha);
// Check for a failure
String failure = STBImage.stbi_failure_reason();
if(failure != "") {
System.out.println("STB: "+failure);
}
// Store the image data
this.width = width[0];
this.height = height[0];
this.channels = channels[0];
System.out.println("w:"+this.width+" h:"+this.height+" c:"+this.channels);
}
public int getWidth() {
return this.width;
}
public int getHeight() {
return this.height;
}
public int getChannels() {
return this.channels;
}
public ByteBuffer getByteBuffer() {
return this.texture;
}
public void free() {
//STBImage.stbi_image_free(this.texture);
}
}

View File

@ -1,77 +0,0 @@
package projectzombie.util.gl.texture;
import static org.lwjgl.opengl.GL11.GL_NEAREST;
import static org.lwjgl.opengl.GL11.GL_RGBA;
import static org.lwjgl.opengl.GL11.GL_TEXTURE_2D;
import static org.lwjgl.opengl.GL11.GL_TEXTURE_MAG_FILTER;
import static org.lwjgl.opengl.GL11.GL_TEXTURE_MIN_FILTER;
import static org.lwjgl.opengl.GL11.GL_UNSIGNED_BYTE;
import static org.lwjgl.opengl.GL11.glBindTexture;
import static org.lwjgl.opengl.GL11.glGenTextures;
import static org.lwjgl.opengl.GL11.glTexImage2D;
import static org.lwjgl.opengl.GL11.glTexParameteri;
import projectzombie.resources.Resource;
public class TextureMap
{
private int texture_gl;
private int max_x;
private int max_y;
private int scale;
private Resource resource;
public TextureMap(int scale, Resource resource) {
this.scale = scale;
this.resource = resource;
}
public void init()
{
// Generate and bind the texture map
this.texture_gl = glGenTextures();
glBindTexture(GL_TEXTURE_2D, this.texture_gl);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
// Load the texture into opengl
Texture texture = new Texture(resource);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
texture.getWidth(), texture.getHeight(),
0, GL_RGBA, GL_UNSIGNED_BYTE, texture.getByteBuffer());
// Store the width and height variables
this.max_x = texture.getWidth();
this.max_y = texture.getHeight();
System.out.println("texmap: "+texture_gl);
// Free the texture
//texture.free();
}
public TextureReference getTextureReference(int start_x, int end_x, int start_y, int end_y) {
return new TextureReference(start_x * scale, end_x * scale, start_y * scale, end_y * scale)
{
@Override
public int getMaxX() {
return max_x;
}
@Override
public int getMaxY() {
return max_y;
}
};
}
public void bindTexture() {
glBindTexture(GL_TEXTURE_2D, texture_gl);
}
public void unbindTexture() {
glBindTexture(GL_TEXTURE_2D, 0);
}
}

View File

@ -1,58 +0,0 @@
package projectzombie.util.gl.texture;
import static org.lwjgl.opengl.GL11.glTexCoord2f;
import gl_engine.MathHelpers;
public abstract class TextureReference
{
public int start_x;
public int start_y;
public int end_x;
public int end_y;
public static final TextureReference EMPTY = new TextureReferenceEmpty();
TextureReference() {
}
public TextureReference getTextureReference(int start_x, int end_x, int start_y, int end_y) {
TextureReference parent = this;
return new TextureReference(start_x, end_x, start_y, end_y)
{
@Override
public int getMaxX() {
return parent.getMaxX();
}
@Override
public int getMaxY() {
return parent.getMaxY();
}
};
}
public TextureReference(int start_x, int end_x, int start_y, int end_y)
{
// Save all the specified values
this.start_x = start_x;
this.start_y = start_y;
this.end_x = end_x;
this.end_y = end_y;
}
public void texCoord(double x, double y)
{
// Create texture coordinates
float cx = (float) ( MathHelpers.map(x, 0, 1, start_x, end_x) / (double) this.getMaxX() );
float cy = (float) ( MathHelpers.map(y, 0, 1, start_y, end_y) / (double) this.getMaxY() );
// Send the coordinates from the texture map to opengl
glTexCoord2f(cx, cy);
}
public abstract int getMaxX();
public abstract int getMaxY();
}

View File

@ -1,24 +0,0 @@
package projectzombie.util.gl.texture;
class TextureReferenceEmpty extends TextureReference
{
public TextureReferenceEmpty() {
super(0, 0, 0, 0);
}
@Override
public int getMaxX() {
return 0;
}
@Override
public int getMaxY() {
return 0;
}
@Override
public void texCoord(double x, double y) {
}
}

View File

@ -1,20 +0,0 @@
package projectzombie.util.gl.texture;
import java.util.Random;
import projectzombie.util.math.random.RandomHelpers;
public class TextureReferenceRandom
{
private static final Random rand = new Random();
private TextureReference[] textures;
public TextureReferenceRandom(TextureReference ... textures) {
this.textures = textures;
}
public TextureReference getTexture() {
return textures[RandomHelpers.randrange(rand, textures.length)];
}
}

View File

@ -32,14 +32,18 @@ vec3 biggest(vec3 a, vec3 b) {
a.z > b.z ? a.z : b.z); a.z > b.z ? a.z : b.z);
} }
float scaleLight(float level) {
return pow(level, 1.5);
}
void main() void main()
{ {
vec4 light = texture(lightmap, vec2( vec4 light = texture(lightmap, vec2(
map(pLightMapPos.x, lightmap_offset.x, lightmap_offset.x + lightmap_size.x, 0, 1), map((pLightMapPos.x), lightmap_offset.x, lightmap_offset.x + lightmap_size.x, 0, 1),
map(pLightMapPos.z, lightmap_offset.y, lightmap_offset.y + lightmap_size.y, 0, 1))); map((pLightMapPos.z), lightmap_offset.y, lightmap_offset.y + lightmap_size.y, 0, 1)));
vec3 light_day = mapVec(light.r, 0, 1, lighting_day_low, lighting_day_high); vec3 light_day = mapVec(scaleLight(light.r), 0, 1, lighting_day_low, lighting_day_high);
vec3 light_src = vec3(1, 1, 1) * (light.g - abs(pLightMapPos.y) * 0.1); vec3 light_src = vec3(1, 1, 1) * (scaleLight(light.g) - abs(pLightMapPos.y) * 0.1);
FragColor = texture(atlas, pTexture) * color * vec4(biggest(light_day, light_src), 1); FragColor = texture(atlas, pTexture) * color * vec4(biggest(light_day, light_src), 1);

View File

@ -31,16 +31,6 @@ mat4 translate(vec3 vec)
return result; return result;
} }
vec3 mapVec(float x, float in_min, float in_max, vec3 out_min, vec3 out_max) {
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}
vec3 biggest(vec3 a, vec3 b) {
return vec3(a.x > b.x ? a.x : b.x,
a.y > b.y ? a.y : b.y,
a.z > b.z ? a.z : b.z);
}
float getTexY() float getTexY()
{ {
float animate_count = aFlags.x; float animate_count = aFlags.x;

View File

@ -6,5 +6,5 @@ out vec4 FragColor;
void main() void main()
{ {
FragColor = vec4(texture(lightmap, TexCoord).rgb, 1); FragColor = vec4(texture(lightmap, TexCoord).rg, 0, 1);
} }