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.icon.Icon;
|
||||||
import com.bartlomiejpluta.base.api.image.Image;
|
import com.bartlomiejpluta.base.api.image.Image;
|
||||||
import com.bartlomiejpluta.base.api.input.Input;
|
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.map.model.GameMap;
|
||||||
import com.bartlomiejpluta.base.api.runner.GameRunner;
|
import com.bartlomiejpluta.base.api.runner.GameRunner;
|
||||||
import com.bartlomiejpluta.base.api.screen.Screen;
|
import com.bartlomiejpluta.base.api.screen.Screen;
|
||||||
@@ -47,6 +48,8 @@ public interface Context extends Updatable, Renderable, Disposable {
|
|||||||
|
|
||||||
Entity createAbstractEntity();
|
Entity createAbstractEntity();
|
||||||
|
|
||||||
|
Light createLight();
|
||||||
|
|
||||||
Icon createIcon(String iconSetUid, int row, int column);
|
Icon createIcon(String iconSetUid, int row, int column);
|
||||||
|
|
||||||
Image getImage(String imageUid);
|
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.animation.Animation;
|
||||||
import com.bartlomiejpluta.base.api.event.Reactive;
|
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.api.map.model.GameMap;
|
||||||
import com.bartlomiejpluta.base.internal.logic.Updatable;
|
import com.bartlomiejpluta.base.internal.logic.Updatable;
|
||||||
import com.bartlomiejpluta.base.internal.render.Renderable;
|
import com.bartlomiejpluta.base.internal.render.Renderable;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public interface Layer extends Renderable, Updatable, Reactive {
|
public interface Layer extends Renderable, Updatable, Reactive {
|
||||||
GameMap getMap();
|
GameMap getMap();
|
||||||
|
|
||||||
void pushAnimation(Animation animation);
|
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;
|
package com.bartlomiejpluta.base.api.map.model;
|
||||||
|
|
||||||
import com.bartlomiejpluta.base.api.event.Reactive;
|
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.color.ColorLayer;
|
||||||
import com.bartlomiejpluta.base.api.map.layer.image.ImageLayer;
|
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.object.ObjectLayer;
|
||||||
import com.bartlomiejpluta.base.api.map.layer.tile.TileLayer;
|
import com.bartlomiejpluta.base.api.map.layer.tile.TileLayer;
|
||||||
import org.joml.Vector2fc;
|
import org.joml.Vector2fc;
|
||||||
|
import org.joml.Vector3fc;
|
||||||
|
|
||||||
public interface GameMap extends Reactive {
|
public interface GameMap extends Reactive {
|
||||||
float getWidth();
|
float getWidth();
|
||||||
@@ -20,6 +22,8 @@ public interface GameMap extends Reactive {
|
|||||||
|
|
||||||
Vector2fc getStepSize();
|
Vector2fc getStepSize();
|
||||||
|
|
||||||
|
Layer getLayer(int layerIndex);
|
||||||
|
|
||||||
TileLayer getTileLayer(int layerIndex);
|
TileLayer getTileLayer(int layerIndex);
|
||||||
|
|
||||||
ImageLayer getImageLayer(int layerIndex);
|
ImageLayer getImageLayer(int layerIndex);
|
||||||
@@ -27,4 +31,12 @@ public interface GameMap extends Reactive {
|
|||||||
ColorLayer getColorLayer(int layerIndex);
|
ColorLayer getColorLayer(int layerIndex);
|
||||||
|
|
||||||
ObjectLayer getObjectLayer(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 setUniform(String uniformName, int index, Uniform uniform);
|
||||||
|
|
||||||
ShaderManager setUniforms(String uniformName, Uniform[] uniforms);
|
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.icon.Icon;
|
||||||
import com.bartlomiejpluta.base.api.image.Image;
|
import com.bartlomiejpluta.base.api.image.Image;
|
||||||
import com.bartlomiejpluta.base.api.input.Input;
|
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.map.handler.MapHandler;
|
||||||
import com.bartlomiejpluta.base.api.runner.GameRunner;
|
import com.bartlomiejpluta.base.api.runner.GameRunner;
|
||||||
import com.bartlomiejpluta.base.api.screen.Screen;
|
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.IconManager;
|
||||||
import com.bartlomiejpluta.base.engine.world.icon.manager.IconSetManager;
|
import com.bartlomiejpluta.base.engine.world.icon.manager.IconSetManager;
|
||||||
import com.bartlomiejpluta.base.engine.world.image.manager.ImageManager;
|
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.manager.MapManager;
|
||||||
import com.bartlomiejpluta.base.engine.world.map.model.DefaultGameMap;
|
import com.bartlomiejpluta.base.engine.world.map.model.DefaultGameMap;
|
||||||
import com.bartlomiejpluta.base.internal.render.ShaderManager;
|
import com.bartlomiejpluta.base.internal.render.ShaderManager;
|
||||||
@@ -171,6 +173,11 @@ public class DefaultContext implements Context {
|
|||||||
return new AbstractEntity();
|
return new AbstractEntity();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Light createLight() {
|
||||||
|
return new DefaultLight();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Icon createIcon(@NonNull String iconSetUid, int row, int column) {
|
public Icon createIcon(@NonNull String iconSetUid, int row, int column) {
|
||||||
return iconManager.createIcon(iconSetUid, row, 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.camera.Camera;
|
||||||
import com.bartlomiejpluta.base.api.screen.Screen;
|
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.engine.core.gl.shader.constant.UniformName;
|
||||||
import com.bartlomiejpluta.base.internal.render.Renderable;
|
import com.bartlomiejpluta.base.internal.render.Renderable;
|
||||||
import com.bartlomiejpluta.base.internal.render.ShaderManager;
|
import com.bartlomiejpluta.base.internal.render.ShaderManager;
|
||||||
@@ -22,15 +24,27 @@ public class DefaultRenderer implements Renderer {
|
|||||||
public void init() {
|
public void init() {
|
||||||
log.info("Initializing renderer");
|
log.info("Initializing renderer");
|
||||||
shaderManager
|
shaderManager
|
||||||
.createShader("default", "/shaders/default.vs", "/shaders/default.fs")
|
.createShader("default", "/shaders/default.vs", "/shaders/default.fs")
|
||||||
.selectShader("default")
|
.selectShader("default")
|
||||||
.createUniform(UniformName.UNI_VIEW_MODEL_MATRIX)
|
.createUniform(UniformName.UNI_VIEW_MODEL_MATRIX)
|
||||||
.createUniform(UniformName.UNI_PROJECTION_MATRIX)
|
.createUniform(UniformName.UNI_MODEL_MATRIX)
|
||||||
.createUniform(UniformName.UNI_OBJECT_COLOR)
|
.createUniform(UniformName.UNI_PROJECTION_MATRIX)
|
||||||
.createUniform(UniformName.UNI_HAS_OBJECT_TEXTURE)
|
.createUniform(UniformName.UNI_OBJECT_COLOR)
|
||||||
.createUniform(UniformName.UNI_TEXTURE_SAMPLER)
|
.createUniform(UniformName.UNI_HAS_OBJECT_TEXTURE)
|
||||||
.createUniform(UniformName.UNI_SPRITE_SIZE)
|
.createUniform(UniformName.UNI_TEXTURE_SAMPLER)
|
||||||
.createUniform(UniformName.UNI_SPRITE_POSITION);
|
.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
|
@Override
|
||||||
@@ -39,6 +53,7 @@ public class DefaultRenderer implements Renderer {
|
|||||||
updateViewport(screen);
|
updateViewport(screen);
|
||||||
|
|
||||||
shaderManager.selectShader("default").useSelectedShader();
|
shaderManager.selectShader("default").useSelectedShader();
|
||||||
|
shaderManager.resetCounters();
|
||||||
|
|
||||||
// Important note:
|
// Important note:
|
||||||
// The camera render method must be invoked **before** each consecutive item renders
|
// 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 {
|
public interface UniformName {
|
||||||
String UNI_VIEW_MODEL_MATRIX = "viewModelMatrix";
|
String UNI_VIEW_MODEL_MATRIX = "viewModelMatrix";
|
||||||
|
String UNI_MODEL_MATRIX = "modelMatrix";
|
||||||
String UNI_PROJECTION_MATRIX = "projectionMatrix";
|
String UNI_PROJECTION_MATRIX = "projectionMatrix";
|
||||||
String UNI_OBJECT_COLOR = "objectColor";
|
String UNI_OBJECT_COLOR = "objectColor";
|
||||||
String UNI_HAS_OBJECT_TEXTURE = "hasTexture";
|
String UNI_HAS_OBJECT_TEXTURE = "hasTexture";
|
||||||
String UNI_TEXTURE_SAMPLER = "sampler";
|
String UNI_TEXTURE_SAMPLER = "sampler";
|
||||||
String UNI_SPRITE_SIZE = "spriteSize";
|
String UNI_SPRITE_SIZE = "spriteSize";
|
||||||
String UNI_SPRITE_POSITION = "spritePosition";
|
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;
|
package com.bartlomiejpluta.base.engine.core.gl.shader.manager;
|
||||||
|
|
||||||
import com.bartlomiejpluta.base.engine.core.gl.shader.program.GLShaderProgram;
|
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.engine.util.res.ResourcesManager;
|
||||||
import com.bartlomiejpluta.base.internal.render.ShaderManager;
|
import com.bartlomiejpluta.base.internal.render.ShaderManager;
|
||||||
import com.bartlomiejpluta.base.internal.render.ShaderProgram;
|
import com.bartlomiejpluta.base.internal.render.ShaderProgram;
|
||||||
@@ -13,6 +14,9 @@ import org.springframework.stereotype.Component;
|
|||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
|
import static java.lang.String.format;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@Component
|
@Component
|
||||||
@@ -20,6 +24,7 @@ import java.util.Map;
|
|||||||
public class DefaultShaderManager implements ShaderManager {
|
public class DefaultShaderManager implements ShaderManager {
|
||||||
private final ResourcesManager resourcesManager;
|
private final ResourcesManager resourcesManager;
|
||||||
private final Map<String, ShaderProgram> shaders = new HashMap<>();
|
private final Map<String, ShaderProgram> shaders = new HashMap<>();
|
||||||
|
private final Map<String, AtomicInteger> counters = new HashMap<>();
|
||||||
private ShaderProgram current;
|
private ShaderProgram current;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -142,6 +147,42 @@ public class DefaultShaderManager implements ShaderManager {
|
|||||||
return this;
|
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
|
@Override
|
||||||
public void cleanUp() {
|
public void cleanUp() {
|
||||||
log.info("Disposing shaders");
|
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.animation.Animation;
|
||||||
import com.bartlomiejpluta.base.api.camera.Camera;
|
import com.bartlomiejpluta.base.api.camera.Camera;
|
||||||
import com.bartlomiejpluta.base.api.event.Event;
|
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.layer.base.Layer;
|
||||||
import com.bartlomiejpluta.base.api.map.model.GameMap;
|
import com.bartlomiejpluta.base.api.map.model.GameMap;
|
||||||
import com.bartlomiejpluta.base.api.screen.Screen;
|
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.logic.Updatable;
|
||||||
import com.bartlomiejpluta.base.internal.render.ShaderManager;
|
import com.bartlomiejpluta.base.internal.render.ShaderManager;
|
||||||
|
import lombok.Getter;
|
||||||
import lombok.NonNull;
|
import lombok.NonNull;
|
||||||
import org.joml.Vector2fc;
|
import org.joml.Vector2fc;
|
||||||
|
|
||||||
@@ -23,6 +27,9 @@ public abstract class BaseLayer implements Layer, Updatable {
|
|||||||
|
|
||||||
protected final ArrayList<Animation> animations = new ArrayList<>();
|
protected final ArrayList<Animation> animations = new ArrayList<>();
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
protected final ArrayList<Light> lights = new ArrayList<>();
|
||||||
|
|
||||||
public BaseLayer(@NonNull GameMap map) {
|
public BaseLayer(@NonNull GameMap map) {
|
||||||
this.map = map;
|
this.map = map;
|
||||||
this.stepSize = map.getStepSize();
|
this.stepSize = map.getStepSize();
|
||||||
@@ -40,6 +47,26 @@ public abstract class BaseLayer implements Layer, Updatable {
|
|||||||
return map;
|
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
|
@Override
|
||||||
public void update(float dt) {
|
public void update(float dt) {
|
||||||
|
|
||||||
@@ -58,6 +85,11 @@ public abstract class BaseLayer implements Layer, Updatable {
|
|||||||
animation.onFinish(this);
|
animation.onFinish(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Disclaimer as above for lights
|
||||||
|
for (int i = 0; i < lights.size(); ++i) {
|
||||||
|
lights.get(i).update(dt);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -65,6 +97,12 @@ public abstract class BaseLayer implements Layer, Updatable {
|
|||||||
for (var animation : animations) {
|
for (var animation : animations) {
|
||||||
animation.render(screen, camera, shaderManager);
|
animation.render(screen, camera, shaderManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (var light : lights) {
|
||||||
|
light.render(screen, camera, shaderManager);
|
||||||
|
}
|
||||||
|
|
||||||
|
shaderManager.setUniformCounter(UniformName.UNI_ACTIVE_LIGHTS, CounterName.LIGHT);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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.layer.tile.TileLayer;
|
||||||
import com.bartlomiejpluta.base.api.map.model.GameMap;
|
import com.bartlomiejpluta.base.api.map.model.GameMap;
|
||||||
import com.bartlomiejpluta.base.api.screen.Screen;
|
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.util.mesh.MeshManager;
|
||||||
import com.bartlomiejpluta.base.engine.world.autotile.model.AutoTileSet;
|
import com.bartlomiejpluta.base.engine.world.autotile.model.AutoTileSet;
|
||||||
import com.bartlomiejpluta.base.engine.world.map.layer.autotile.DefaultAutoTileLayer;
|
import com.bartlomiejpluta.base.engine.world.map.layer.autotile.DefaultAutoTileLayer;
|
||||||
@@ -27,6 +28,7 @@ import lombok.Getter;
|
|||||||
import lombok.NonNull;
|
import lombok.NonNull;
|
||||||
import org.joml.Vector2f;
|
import org.joml.Vector2f;
|
||||||
import org.joml.Vector2fc;
|
import org.joml.Vector2fc;
|
||||||
|
import org.joml.Vector3f;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@@ -58,6 +60,9 @@ public class DefaultGameMap implements Renderable, Updatable, GameMap {
|
|||||||
@Getter
|
@Getter
|
||||||
private final String handler;
|
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) {
|
public DefaultGameMap(int tileWidth, int tileHeight, int rows, int columns, String handler) {
|
||||||
this.rows = rows;
|
this.rows = rows;
|
||||||
this.columns = columns;
|
this.columns = columns;
|
||||||
@@ -77,11 +82,18 @@ public class DefaultGameMap implements Renderable, Updatable, GameMap {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void render(Screen screen, Camera camera, ShaderManager shaderManager) {
|
public void render(Screen screen, Camera camera, ShaderManager shaderManager) {
|
||||||
|
shaderManager.setUniform(UniformName.UNI_AMBIENT, ambientColor);
|
||||||
|
|
||||||
for (var layer : layers) {
|
for (var layer : layers) {
|
||||||
layer.render(screen, camera, shaderManager);
|
layer.render(screen, camera, shaderManager);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Layer getLayer(int layerIndex) {
|
||||||
|
return layers.get(layerIndex);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TileLayer getTileLayer(int layerIndex) {
|
public TileLayer getTileLayer(int layerIndex) {
|
||||||
return (TileLayer) layers.get(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) {
|
public TileLayer createTileLayer(@NonNull TileSet tileSet) {
|
||||||
var layer = new DefaultTileLayer(this, tileSet, rows, columns);
|
var layer = new DefaultTileLayer(this, tileSet, rows, columns);
|
||||||
layers.add(layer);
|
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_VIEW_MODEL_MATRIX, camera.computeViewModelMatrix(getModelMatrix()));
|
||||||
|
shaderManager.setUniform(UniformName.UNI_MODEL_MATRIX, getModelMatrix());
|
||||||
material.render(screen, camera, shaderManager);
|
material.render(screen, camera, shaderManager);
|
||||||
mesh.render(screen, camera, shaderManager);
|
mesh.render(screen, camera, shaderManager);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,23 +1,39 @@
|
|||||||
#version 330
|
#version 330
|
||||||
|
|
||||||
|
struct Light
|
||||||
|
{
|
||||||
|
vec2 position;
|
||||||
|
vec3 intensity;
|
||||||
|
float constantAttenuation;
|
||||||
|
float linearAttenuation;
|
||||||
|
float quadraticAttenuation;
|
||||||
|
};
|
||||||
|
|
||||||
uniform vec4 objectColor;
|
uniform vec4 objectColor;
|
||||||
uniform int hasTexture;
|
uniform int hasTexture;
|
||||||
uniform sampler2D sampler;
|
uniform sampler2D sampler;
|
||||||
uniform vec2 spriteSize;
|
uniform vec2 spriteSize;
|
||||||
uniform vec2 spritePosition;
|
uniform vec2 spritePosition;
|
||||||
|
uniform vec3 ambient;
|
||||||
|
uniform Light lights[100];
|
||||||
|
uniform int activeLights;
|
||||||
|
|
||||||
|
in vec2 objectPosition;
|
||||||
in vec2 fragmentTexCoord;
|
in vec2 fragmentTexCoord;
|
||||||
|
|
||||||
out vec4 fragColor;
|
out vec4 fragColor;
|
||||||
|
|
||||||
void main()
|
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);
|
Light light = lights[i];
|
||||||
}
|
float dist = distance(light.position, objectPosition);
|
||||||
else
|
total.rgb += color.rgb * light.intensity.rgb / (light.constantAttenuation + light.linearAttenuation * dist + light.quadraticAttenuation * dist * dist);
|
||||||
{
|
|
||||||
fragColor = objectColor;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fragColor = total;
|
||||||
}
|
}
|
||||||
@@ -1,15 +1,18 @@
|
|||||||
#version 330
|
#version 330
|
||||||
|
|
||||||
uniform mat4 viewModelMatrix;
|
uniform mat4 viewModelMatrix;
|
||||||
|
uniform mat4 modelMatrix;
|
||||||
uniform mat4 projectionMatrix;
|
uniform mat4 projectionMatrix;
|
||||||
|
|
||||||
layout(location=0) in vec2 position;
|
layout(location=0) in vec2 position;
|
||||||
layout(location=1) in vec2 texCoord;
|
layout(location=1) in vec2 texCoord;
|
||||||
|
|
||||||
|
out vec2 objectPosition;
|
||||||
out vec2 fragmentTexCoord;
|
out vec2 fragmentTexCoord;
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
gl_Position = projectionMatrix * viewModelMatrix * vec4(position, 0.0, 1.0);
|
gl_Position = projectionMatrix * viewModelMatrix * vec4(position, 0.0, 1.0);
|
||||||
|
objectPosition = (modelMatrix * vec4(position, 0.0, 1.0)).xy;
|
||||||
fragmentTexCoord = texCoord;
|
fragmentTexCoord = texCoord;
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user