Create working lighting system
This commit is contained in:
@@ -11,6 +11,7 @@ import com.bartlomiejpluta.base.api.gui.GUI;
|
||||
import com.bartlomiejpluta.base.api.icon.Icon;
|
||||
import com.bartlomiejpluta.base.api.image.Image;
|
||||
import com.bartlomiejpluta.base.api.input.Input;
|
||||
import com.bartlomiejpluta.base.api.light.Light;
|
||||
import com.bartlomiejpluta.base.api.map.model.GameMap;
|
||||
import com.bartlomiejpluta.base.api.runner.GameRunner;
|
||||
import com.bartlomiejpluta.base.api.screen.Screen;
|
||||
@@ -47,6 +48,8 @@ public interface Context extends Updatable, Renderable, Disposable {
|
||||
|
||||
Entity createAbstractEntity();
|
||||
|
||||
Light createLight();
|
||||
|
||||
Icon createIcon(String iconSetUid, int row, int column);
|
||||
|
||||
Image getImage(String imageUid);
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
package com.bartlomiejpluta.base.api.light;
|
||||
|
||||
import com.bartlomiejpluta.base.api.location.Locationable;
|
||||
import com.bartlomiejpluta.base.internal.logic.Updatable;
|
||||
import com.bartlomiejpluta.base.internal.render.Renderable;
|
||||
import org.joml.Vector3fc;
|
||||
|
||||
public interface Light extends Locationable, Updatable, Renderable {
|
||||
boolean isLuminescent();
|
||||
|
||||
void setLuminescent(boolean luminescent);
|
||||
|
||||
default void enableLuminescent() {
|
||||
setLuminescent(true);
|
||||
}
|
||||
|
||||
default void disableLuminescent() {
|
||||
setLuminescent(false);
|
||||
}
|
||||
|
||||
default void toggleLuminescent() {
|
||||
setLuminescent(!isLuminescent());
|
||||
}
|
||||
|
||||
Vector3fc getIntensity();
|
||||
|
||||
default void setIntensity(Vector3fc intensity) {
|
||||
setIntensity(intensity.x(), intensity.y(), intensity.z());
|
||||
}
|
||||
|
||||
void setIntensity(float red, float green, float blue);
|
||||
|
||||
float getConstantAttenuation();
|
||||
|
||||
float getLinearAttenuation();
|
||||
|
||||
float getQuadraticAttenuation();
|
||||
|
||||
void setConstantAttenuation(float attenuation);
|
||||
|
||||
void setLinearAttenuation(float attenuation);
|
||||
|
||||
void setQuadraticAttenuation(float attenuation);
|
||||
|
||||
default void setAttenuation(float constant, float linear, float quadratic) {
|
||||
setConstantAttenuation(constant);
|
||||
setLinearAttenuation(linear);
|
||||
setQuadraticAttenuation(quadratic);
|
||||
}
|
||||
|
||||
default void setAttenuation(Vector3fc attenuation) {
|
||||
setConstantAttenuation(attenuation.x());
|
||||
setLinearAttenuation(attenuation.y());
|
||||
setQuadraticAttenuation(attenuation.z());
|
||||
}
|
||||
}
|
||||
@@ -2,12 +2,23 @@ package com.bartlomiejpluta.base.api.map.layer.base;
|
||||
|
||||
import com.bartlomiejpluta.base.api.animation.Animation;
|
||||
import com.bartlomiejpluta.base.api.event.Reactive;
|
||||
import com.bartlomiejpluta.base.api.light.Light;
|
||||
import com.bartlomiejpluta.base.api.map.model.GameMap;
|
||||
import com.bartlomiejpluta.base.internal.logic.Updatable;
|
||||
import com.bartlomiejpluta.base.internal.render.Renderable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface Layer extends Renderable, Updatable, Reactive {
|
||||
GameMap getMap();
|
||||
|
||||
void pushAnimation(Animation animation);
|
||||
|
||||
void addLight(Light light);
|
||||
|
||||
void removeLight(Light light);
|
||||
|
||||
void clearLights();
|
||||
|
||||
List<Light> getLights();
|
||||
}
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
package com.bartlomiejpluta.base.api.map.model;
|
||||
|
||||
import com.bartlomiejpluta.base.api.event.Reactive;
|
||||
import com.bartlomiejpluta.base.api.map.layer.base.Layer;
|
||||
import com.bartlomiejpluta.base.api.map.layer.color.ColorLayer;
|
||||
import com.bartlomiejpluta.base.api.map.layer.image.ImageLayer;
|
||||
import com.bartlomiejpluta.base.api.map.layer.object.ObjectLayer;
|
||||
import com.bartlomiejpluta.base.api.map.layer.tile.TileLayer;
|
||||
import org.joml.Vector2fc;
|
||||
import org.joml.Vector3fc;
|
||||
|
||||
public interface GameMap extends Reactive {
|
||||
float getWidth();
|
||||
@@ -20,6 +22,8 @@ public interface GameMap extends Reactive {
|
||||
|
||||
Vector2fc getStepSize();
|
||||
|
||||
Layer getLayer(int layerIndex);
|
||||
|
||||
TileLayer getTileLayer(int layerIndex);
|
||||
|
||||
ImageLayer getImageLayer(int layerIndex);
|
||||
@@ -27,4 +31,12 @@ public interface GameMap extends Reactive {
|
||||
ColorLayer getColorLayer(int layerIndex);
|
||||
|
||||
ObjectLayer getObjectLayer(int layerIndex);
|
||||
|
||||
Vector3fc getAmbientColor();
|
||||
|
||||
default void setAmbientColor(Vector3fc color) {
|
||||
setAmbientColor(color.x(), color.y(), color.z());
|
||||
}
|
||||
|
||||
void setAmbientColor(float red, float green, float blue);
|
||||
}
|
||||
|
||||
@@ -41,4 +41,14 @@ public interface ShaderManager extends Cleanable {
|
||||
ShaderManager setUniform(String uniformName, int index, Uniform uniform);
|
||||
|
||||
ShaderManager setUniforms(String uniformName, Uniform[] uniforms);
|
||||
|
||||
ShaderManager createCounter(String counterName);
|
||||
|
||||
int nextNumber(String counterName);
|
||||
|
||||
int topNumber(String counterName);
|
||||
|
||||
ShaderManager setUniformCounter(String uniformName, String counterName);
|
||||
|
||||
ShaderManager resetCounters();
|
||||
}
|
||||
@@ -0,0 +1,233 @@
|
||||
package com.bartlomiejpluta.base.lib.light;
|
||||
|
||||
import com.bartlomiejpluta.base.api.camera.Camera;
|
||||
import com.bartlomiejpluta.base.api.light.Light;
|
||||
import com.bartlomiejpluta.base.api.location.Locationable;
|
||||
import com.bartlomiejpluta.base.api.move.Direction;
|
||||
import com.bartlomiejpluta.base.api.screen.Screen;
|
||||
import com.bartlomiejpluta.base.internal.object.Placeable;
|
||||
import com.bartlomiejpluta.base.internal.render.ShaderManager;
|
||||
import lombok.NonNull;
|
||||
import org.joml.Matrix4fc;
|
||||
import org.joml.Vector2fc;
|
||||
import org.joml.Vector2ic;
|
||||
import org.joml.Vector3fc;
|
||||
|
||||
public class LightDelegate implements Light {
|
||||
protected final Light light;
|
||||
|
||||
protected LightDelegate(@NonNull Light light) {
|
||||
this.light = light;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStepSize(float x, float y) {
|
||||
light.setStepSize(x, y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vector2ic getCoordinates() {
|
||||
return light.getCoordinates();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCoordinates(Vector2ic coordinates) {
|
||||
light.setCoordinates(coordinates);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCoordinates(int x, int y) {
|
||||
light.setCoordinates(x, y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vector2fc getPositionOffset() {
|
||||
return light.getPositionOffset();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPositionOffset(Vector2fc offset) {
|
||||
light.setPositionOffset(offset);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPositionOffset(float offsetX, float offsetY) {
|
||||
light.setPositionOffset(offsetX, offsetY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int chebyshevDistance(Locationable other) {
|
||||
return light.chebyshevDistance(other);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int manhattanDistance(Locationable other) {
|
||||
return light.manhattanDistance(other);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double euclideanDistance(Locationable other) {
|
||||
return light.euclideanDistance(other);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Direction getDirectionTowards(Locationable target) {
|
||||
return light.getDirectionTowards(target);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vector2fc getPosition() {
|
||||
return light.getPosition();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPosition(Vector2fc position) {
|
||||
light.setPosition(position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPosition(float x, float y) {
|
||||
light.setPosition(x, y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void movePosition(float x, float y) {
|
||||
light.movePosition(x, y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void movePosition(Vector2fc position) {
|
||||
light.movePosition(position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getRotation() {
|
||||
return light.getRotation();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRotation(float rotation) {
|
||||
light.setRotation(rotation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void moveRotation(float rotation) {
|
||||
light.moveRotation(rotation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getScaleX() {
|
||||
return light.getScaleX();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setScaleX(float scale) {
|
||||
light.setScaleX(scale);
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getScaleY() {
|
||||
return light.getScaleY();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setScaleY(float scale) {
|
||||
light.setScaleY(scale);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setScale(float scale) {
|
||||
light.setScale(scale);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setScale(float scaleX, float scaleY) {
|
||||
light.setScale(scaleX, scaleY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public float euclideanDistance(Placeable other) {
|
||||
return light.euclideanDistance(other);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double euclideanDistance(Vector2ic coordinates) {
|
||||
return light.euclideanDistance(coordinates);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int chebyshevDistance(Vector2ic coordinates) {
|
||||
return light.chebyshevDistance(coordinates);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int manhattanDistance(Vector2ic coordinates) {
|
||||
return light.manhattanDistance(coordinates);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Matrix4fc getModelMatrix() {
|
||||
return light.getModelMatrix();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLuminescent() {
|
||||
return light.isLuminescent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLuminescent(boolean luminescent) {
|
||||
light.setLuminescent(luminescent);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Vector3fc getIntensity() {
|
||||
return light.getIntensity();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setIntensity(float red, float green, float blue) {
|
||||
light.setIntensity(red, green, blue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getConstantAttenuation() {
|
||||
return light.getConstantAttenuation();
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getLinearAttenuation() {
|
||||
return light.getLinearAttenuation();
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getQuadraticAttenuation() {
|
||||
return light.getQuadraticAttenuation();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setConstantAttenuation(float attenuation) {
|
||||
light.setConstantAttenuation(attenuation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLinearAttenuation(float attenuation) {
|
||||
light.setLinearAttenuation(attenuation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setQuadraticAttenuation(float attenuation) {
|
||||
light.setQuadraticAttenuation(attenuation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(float dt) {
|
||||
light.update(dt);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(Screen screen, Camera camera, ShaderManager shaderManager) {
|
||||
light.render(screen, camera, shaderManager);
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,7 @@ import com.bartlomiejpluta.base.api.gui.GUI;
|
||||
import com.bartlomiejpluta.base.api.icon.Icon;
|
||||
import com.bartlomiejpluta.base.api.image.Image;
|
||||
import com.bartlomiejpluta.base.api.input.Input;
|
||||
import com.bartlomiejpluta.base.api.light.Light;
|
||||
import com.bartlomiejpluta.base.api.map.handler.MapHandler;
|
||||
import com.bartlomiejpluta.base.api.runner.GameRunner;
|
||||
import com.bartlomiejpluta.base.api.screen.Screen;
|
||||
@@ -29,6 +30,7 @@ import com.bartlomiejpluta.base.engine.world.entity.AbstractEntity;
|
||||
import com.bartlomiejpluta.base.engine.world.icon.manager.IconManager;
|
||||
import com.bartlomiejpluta.base.engine.world.icon.manager.IconSetManager;
|
||||
import com.bartlomiejpluta.base.engine.world.image.manager.ImageManager;
|
||||
import com.bartlomiejpluta.base.engine.world.light.DefaultLight;
|
||||
import com.bartlomiejpluta.base.engine.world.map.manager.MapManager;
|
||||
import com.bartlomiejpluta.base.engine.world.map.model.DefaultGameMap;
|
||||
import com.bartlomiejpluta.base.internal.render.ShaderManager;
|
||||
@@ -171,6 +173,11 @@ public class DefaultContext implements Context {
|
||||
return new AbstractEntity();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Light createLight() {
|
||||
return new DefaultLight();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Icon createIcon(@NonNull String iconSetUid, int row, int column) {
|
||||
return iconManager.createIcon(iconSetUid, row, column);
|
||||
|
||||
@@ -2,6 +2,8 @@ package com.bartlomiejpluta.base.engine.core.gl.render;
|
||||
|
||||
import com.bartlomiejpluta.base.api.camera.Camera;
|
||||
import com.bartlomiejpluta.base.api.screen.Screen;
|
||||
import com.bartlomiejpluta.base.engine.core.gl.shader.constant.CounterName;
|
||||
import com.bartlomiejpluta.base.engine.core.gl.shader.constant.RenderConstants;
|
||||
import com.bartlomiejpluta.base.engine.core.gl.shader.constant.UniformName;
|
||||
import com.bartlomiejpluta.base.internal.render.Renderable;
|
||||
import com.bartlomiejpluta.base.internal.render.ShaderManager;
|
||||
@@ -22,15 +24,27 @@ public class DefaultRenderer implements Renderer {
|
||||
public void init() {
|
||||
log.info("Initializing renderer");
|
||||
shaderManager
|
||||
.createShader("default", "/shaders/default.vs", "/shaders/default.fs")
|
||||
.selectShader("default")
|
||||
.createUniform(UniformName.UNI_VIEW_MODEL_MATRIX)
|
||||
.createUniform(UniformName.UNI_PROJECTION_MATRIX)
|
||||
.createUniform(UniformName.UNI_OBJECT_COLOR)
|
||||
.createUniform(UniformName.UNI_HAS_OBJECT_TEXTURE)
|
||||
.createUniform(UniformName.UNI_TEXTURE_SAMPLER)
|
||||
.createUniform(UniformName.UNI_SPRITE_SIZE)
|
||||
.createUniform(UniformName.UNI_SPRITE_POSITION);
|
||||
.createShader("default", "/shaders/default.vs", "/shaders/default.fs")
|
||||
.selectShader("default")
|
||||
.createUniform(UniformName.UNI_VIEW_MODEL_MATRIX)
|
||||
.createUniform(UniformName.UNI_MODEL_MATRIX)
|
||||
.createUniform(UniformName.UNI_PROJECTION_MATRIX)
|
||||
.createUniform(UniformName.UNI_OBJECT_COLOR)
|
||||
.createUniform(UniformName.UNI_HAS_OBJECT_TEXTURE)
|
||||
.createUniform(UniformName.UNI_TEXTURE_SAMPLER)
|
||||
.createUniform(UniformName.UNI_SPRITE_SIZE)
|
||||
.createUniform(UniformName.UNI_SPRITE_POSITION)
|
||||
.createUniform(UniformName.UNI_AMBIENT)
|
||||
.createUniform(UniformName.UNI_ACTIVE_LIGHTS)
|
||||
.createCounter(CounterName.LIGHT);
|
||||
|
||||
for(int i=0; i<RenderConstants.MAX_LIGHTS; ++i) {
|
||||
shaderManager.createUniform(UniformName.UNI_LIGHTS + "[" + i + "].position");
|
||||
shaderManager.createUniform(UniformName.UNI_LIGHTS + "[" + i + "].intensity");
|
||||
shaderManager.createUniform(UniformName.UNI_LIGHTS + "[" + i + "].constantAttenuation");
|
||||
shaderManager.createUniform(UniformName.UNI_LIGHTS + "[" + i + "].linearAttenuation");
|
||||
shaderManager.createUniform(UniformName.UNI_LIGHTS + "[" + i + "].quadraticAttenuation");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -39,6 +53,7 @@ public class DefaultRenderer implements Renderer {
|
||||
updateViewport(screen);
|
||||
|
||||
shaderManager.selectShader("default").useSelectedShader();
|
||||
shaderManager.resetCounters();
|
||||
|
||||
// Important note:
|
||||
// The camera render method must be invoked **before** each consecutive item renders
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.bartlomiejpluta.base.engine.core.gl.shader.constant;
|
||||
|
||||
public interface CounterName {
|
||||
String LIGHT = "LIGHT";
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.bartlomiejpluta.base.engine.core.gl.shader.constant;
|
||||
|
||||
public interface RenderConstants {
|
||||
int MAX_LIGHTS = 100;
|
||||
}
|
||||
@@ -2,10 +2,14 @@ package com.bartlomiejpluta.base.engine.core.gl.shader.constant;
|
||||
|
||||
public interface UniformName {
|
||||
String UNI_VIEW_MODEL_MATRIX = "viewModelMatrix";
|
||||
String UNI_MODEL_MATRIX = "modelMatrix";
|
||||
String UNI_PROJECTION_MATRIX = "projectionMatrix";
|
||||
String UNI_OBJECT_COLOR = "objectColor";
|
||||
String UNI_HAS_OBJECT_TEXTURE = "hasTexture";
|
||||
String UNI_TEXTURE_SAMPLER = "sampler";
|
||||
String UNI_SPRITE_SIZE = "spriteSize";
|
||||
String UNI_SPRITE_POSITION = "spritePosition";
|
||||
String UNI_LIGHTS = "lights";
|
||||
String UNI_ACTIVE_LIGHTS = "activeLights";
|
||||
String UNI_AMBIENT = "ambient";
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.bartlomiejpluta.base.engine.core.gl.shader.manager;
|
||||
|
||||
import com.bartlomiejpluta.base.engine.core.gl.shader.program.GLShaderProgram;
|
||||
import com.bartlomiejpluta.base.engine.error.AppException;
|
||||
import com.bartlomiejpluta.base.engine.util.res.ResourcesManager;
|
||||
import com.bartlomiejpluta.base.internal.render.ShaderManager;
|
||||
import com.bartlomiejpluta.base.internal.render.ShaderProgram;
|
||||
@@ -13,6 +14,9 @@ import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import static java.lang.String.format;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
@@ -20,6 +24,7 @@ import java.util.Map;
|
||||
public class DefaultShaderManager implements ShaderManager {
|
||||
private final ResourcesManager resourcesManager;
|
||||
private final Map<String, ShaderProgram> shaders = new HashMap<>();
|
||||
private final Map<String, AtomicInteger> counters = new HashMap<>();
|
||||
private ShaderProgram current;
|
||||
|
||||
@Override
|
||||
@@ -142,6 +147,42 @@ public class DefaultShaderManager implements ShaderManager {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ShaderManager createCounter(String counterName) {
|
||||
if (counters.containsKey(counterName)) {
|
||||
throw new AppException(format("The [%s] counter already exists", counterName));
|
||||
}
|
||||
|
||||
log.info("Creating {} uniform counter", counterName);
|
||||
counters.put(counterName, new AtomicInteger(0));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int nextNumber(String counterName) {
|
||||
return counters.get(counterName).getAndIncrement();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int topNumber(String counterName) {
|
||||
return counters.get(counterName).get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ShaderManager setUniformCounter(String uniformName, String counterName) {
|
||||
setUniform(uniformName, counters.get(counterName).get());
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ShaderManager resetCounters() {
|
||||
for(var counter : counters.values()) {
|
||||
counter.set(0);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanUp() {
|
||||
log.info("Disposing shaders");
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
package com.bartlomiejpluta.base.engine.world.light;
|
||||
|
||||
import com.bartlomiejpluta.base.api.camera.Camera;
|
||||
import com.bartlomiejpluta.base.api.light.Light;
|
||||
import com.bartlomiejpluta.base.api.screen.Screen;
|
||||
import com.bartlomiejpluta.base.engine.core.gl.shader.constant.CounterName;
|
||||
import com.bartlomiejpluta.base.engine.core.gl.shader.constant.UniformName;
|
||||
import com.bartlomiejpluta.base.engine.world.location.LocationableModel;
|
||||
import com.bartlomiejpluta.base.internal.render.ShaderManager;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.joml.Vector2f;
|
||||
import org.joml.Vector3f;
|
||||
import org.joml.Vector3fc;
|
||||
|
||||
public class DefaultLight extends LocationableModel implements Light {
|
||||
private final Vector3f intensity = new Vector3f(1f, 1f, 1f);
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
private boolean luminescent;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
private float constantAttenuation = 1f;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
private float linearAttenuation = 0f;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
private float quadraticAttenuation = 1f;
|
||||
|
||||
@Override
|
||||
public Vector3fc getIntensity() {
|
||||
return intensity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setIntensity(float red, float green, float blue) {
|
||||
this.intensity.x = red;
|
||||
this.intensity.y = green;
|
||||
this.intensity.z = blue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(float dt) {
|
||||
// noop
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(Screen screen, Camera camera, ShaderManager shaderManager) {
|
||||
var lightNumber = shaderManager.nextNumber(CounterName.LIGHT);
|
||||
shaderManager.setUniform(UniformName.UNI_LIGHTS + "[" + lightNumber + "].position", position);
|
||||
shaderManager.setUniform(UniformName.UNI_LIGHTS + "[" + lightNumber + "].intensity", intensity);
|
||||
shaderManager.setUniform(UniformName.UNI_LIGHTS + "[" + lightNumber + "].constantAttenuation", constantAttenuation);
|
||||
shaderManager.setUniform(UniformName.UNI_LIGHTS + "[" + lightNumber + "].linearAttenuation", linearAttenuation);
|
||||
shaderManager.setUniform(UniformName.UNI_LIGHTS + "[" + lightNumber + "].quadraticAttenuation", quadraticAttenuation);
|
||||
}
|
||||
}
|
||||
@@ -3,11 +3,15 @@ package com.bartlomiejpluta.base.engine.world.map.layer.base;
|
||||
import com.bartlomiejpluta.base.api.animation.Animation;
|
||||
import com.bartlomiejpluta.base.api.camera.Camera;
|
||||
import com.bartlomiejpluta.base.api.event.Event;
|
||||
import com.bartlomiejpluta.base.api.light.Light;
|
||||
import com.bartlomiejpluta.base.api.map.layer.base.Layer;
|
||||
import com.bartlomiejpluta.base.api.map.model.GameMap;
|
||||
import com.bartlomiejpluta.base.api.screen.Screen;
|
||||
import com.bartlomiejpluta.base.engine.core.gl.shader.constant.CounterName;
|
||||
import com.bartlomiejpluta.base.engine.core.gl.shader.constant.UniformName;
|
||||
import com.bartlomiejpluta.base.internal.logic.Updatable;
|
||||
import com.bartlomiejpluta.base.internal.render.ShaderManager;
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
import org.joml.Vector2fc;
|
||||
|
||||
@@ -23,6 +27,9 @@ public abstract class BaseLayer implements Layer, Updatable {
|
||||
|
||||
protected final ArrayList<Animation> animations = new ArrayList<>();
|
||||
|
||||
@Getter
|
||||
protected final ArrayList<Light> lights = new ArrayList<>();
|
||||
|
||||
public BaseLayer(@NonNull GameMap map) {
|
||||
this.map = map;
|
||||
this.stepSize = map.getStepSize();
|
||||
@@ -40,6 +47,26 @@ public abstract class BaseLayer implements Layer, Updatable {
|
||||
return map;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addLight(Light light) {
|
||||
lights.add(light);
|
||||
light.setStepSize(stepSize.x(), stepSize.y());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeLight(Light light) {
|
||||
// Disclaimer
|
||||
// This is a workaround for concurrent modification exception
|
||||
// which is thrown when entity is tried to be removed
|
||||
// in the body of for-each-entity loop
|
||||
lights.remove(lights.indexOf(light));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearLights() {
|
||||
lights.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(float dt) {
|
||||
|
||||
@@ -58,6 +85,11 @@ public abstract class BaseLayer implements Layer, Updatable {
|
||||
animation.onFinish(this);
|
||||
}
|
||||
}
|
||||
|
||||
// Disclaimer as above for lights
|
||||
for (int i = 0; i < lights.size(); ++i) {
|
||||
lights.get(i).update(dt);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -65,6 +97,12 @@ public abstract class BaseLayer implements Layer, Updatable {
|
||||
for (var animation : animations) {
|
||||
animation.render(screen, camera, shaderManager);
|
||||
}
|
||||
|
||||
for (var light : lights) {
|
||||
light.render(screen, camera, shaderManager);
|
||||
}
|
||||
|
||||
shaderManager.setUniformCounter(UniformName.UNI_ACTIVE_LIGHTS, CounterName.LIGHT);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -12,6 +12,7 @@ import com.bartlomiejpluta.base.api.map.layer.object.PassageAbility;
|
||||
import com.bartlomiejpluta.base.api.map.layer.tile.TileLayer;
|
||||
import com.bartlomiejpluta.base.api.map.model.GameMap;
|
||||
import com.bartlomiejpluta.base.api.screen.Screen;
|
||||
import com.bartlomiejpluta.base.engine.core.gl.shader.constant.UniformName;
|
||||
import com.bartlomiejpluta.base.engine.util.mesh.MeshManager;
|
||||
import com.bartlomiejpluta.base.engine.world.autotile.model.AutoTileSet;
|
||||
import com.bartlomiejpluta.base.engine.world.map.layer.autotile.DefaultAutoTileLayer;
|
||||
@@ -27,6 +28,7 @@ import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
import org.joml.Vector2f;
|
||||
import org.joml.Vector2fc;
|
||||
import org.joml.Vector3f;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
@@ -58,6 +60,9 @@ public class DefaultGameMap implements Renderable, Updatable, GameMap {
|
||||
@Getter
|
||||
private final String handler;
|
||||
|
||||
@Getter
|
||||
private final Vector3f ambientColor = new Vector3f(1, 1, 1);
|
||||
|
||||
public DefaultGameMap(int tileWidth, int tileHeight, int rows, int columns, String handler) {
|
||||
this.rows = rows;
|
||||
this.columns = columns;
|
||||
@@ -77,11 +82,18 @@ public class DefaultGameMap implements Renderable, Updatable, GameMap {
|
||||
|
||||
@Override
|
||||
public void render(Screen screen, Camera camera, ShaderManager shaderManager) {
|
||||
shaderManager.setUniform(UniformName.UNI_AMBIENT, ambientColor);
|
||||
|
||||
for (var layer : layers) {
|
||||
layer.render(screen, camera, shaderManager);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Layer getLayer(int layerIndex) {
|
||||
return layers.get(layerIndex);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TileLayer getTileLayer(int layerIndex) {
|
||||
return (TileLayer) layers.get(layerIndex);
|
||||
@@ -113,6 +125,13 @@ public class DefaultGameMap implements Renderable, Updatable, GameMap {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAmbientColor(float red, float green, float blue) {
|
||||
this.ambientColor.x = red;
|
||||
this.ambientColor.y = green;
|
||||
this.ambientColor.z = blue;
|
||||
}
|
||||
|
||||
public TileLayer createTileLayer(@NonNull TileSet tileSet) {
|
||||
var layer = new DefaultTileLayer(this, tileSet, rows, columns);
|
||||
layers.add(layer);
|
||||
|
||||
@@ -38,6 +38,7 @@ public abstract class Sprite extends LocationableModel implements Renderable {
|
||||
}
|
||||
|
||||
shaderManager.setUniform(UniformName.UNI_VIEW_MODEL_MATRIX, camera.computeViewModelMatrix(getModelMatrix()));
|
||||
shaderManager.setUniform(UniformName.UNI_MODEL_MATRIX, getModelMatrix());
|
||||
material.render(screen, camera, shaderManager);
|
||||
mesh.render(screen, camera, shaderManager);
|
||||
}
|
||||
|
||||
@@ -1,23 +1,39 @@
|
||||
#version 330
|
||||
|
||||
struct Light
|
||||
{
|
||||
vec2 position;
|
||||
vec3 intensity;
|
||||
float constantAttenuation;
|
||||
float linearAttenuation;
|
||||
float quadraticAttenuation;
|
||||
};
|
||||
|
||||
uniform vec4 objectColor;
|
||||
uniform int hasTexture;
|
||||
uniform sampler2D sampler;
|
||||
uniform vec2 spriteSize;
|
||||
uniform vec2 spritePosition;
|
||||
uniform vec3 ambient;
|
||||
uniform Light lights[100];
|
||||
uniform int activeLights;
|
||||
|
||||
in vec2 objectPosition;
|
||||
in vec2 fragmentTexCoord;
|
||||
|
||||
out vec4 fragColor;
|
||||
|
||||
void main()
|
||||
{
|
||||
if(hasTexture == 1)
|
||||
vec4 color = hasTexture == 1 ? objectColor * texture(sampler, fragmentTexCoord * spriteSize + spritePosition) : objectColor;
|
||||
vec4 total = vec4(color.rgb * ambient, color.a);
|
||||
|
||||
for(int i=0; i<activeLights; ++i)
|
||||
{
|
||||
fragColor = objectColor * texture(sampler, fragmentTexCoord * spriteSize + spritePosition);
|
||||
}
|
||||
else
|
||||
{
|
||||
fragColor = objectColor;
|
||||
Light light = lights[i];
|
||||
float dist = distance(light.position, objectPosition);
|
||||
total.rgb += color.rgb * light.intensity.rgb / (light.constantAttenuation + light.linearAttenuation * dist + light.quadraticAttenuation * dist * dist);
|
||||
}
|
||||
|
||||
fragColor = total;
|
||||
}
|
||||
@@ -1,15 +1,18 @@
|
||||
#version 330
|
||||
|
||||
uniform mat4 viewModelMatrix;
|
||||
uniform mat4 modelMatrix;
|
||||
uniform mat4 projectionMatrix;
|
||||
|
||||
layout(location=0) in vec2 position;
|
||||
layout(location=1) in vec2 texCoord;
|
||||
|
||||
out vec2 objectPosition;
|
||||
out vec2 fragmentTexCoord;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = projectionMatrix * viewModelMatrix * vec4(position, 0.0, 1.0);
|
||||
objectPosition = (modelMatrix * vec4(position, 0.0, 1.0)).xy;
|
||||
fragmentTexCoord = texCoord;
|
||||
}
|
||||
Reference in New Issue
Block a user