Create working lighting system

This commit is contained in:
2023-11-07 16:51:44 +01:00
parent a3b89de71a
commit e1ea66ccb3
18 changed files with 555 additions and 15 deletions

View File

@@ -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);

View File

@@ -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());
}
}

View File

@@ -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();
}

View File

@@ -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);
}

View File

@@ -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();
}

View File

@@ -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);
}
}

View File

@@ -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);

View File

@@ -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

View File

@@ -0,0 +1,5 @@
package com.bartlomiejpluta.base.engine.core.gl.shader.constant;
public interface CounterName {
String LIGHT = "LIGHT";
}

View File

@@ -0,0 +1,5 @@
package com.bartlomiejpluta.base.engine.core.gl.shader.constant;
public interface RenderConstants {
int MAX_LIGHTS = 100;
}

View File

@@ -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";
}

View File

@@ -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");

View File

@@ -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);
}
}

View File

@@ -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

View File

@@ -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);

View File

@@ -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);
}

View File

@@ -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;
}

View File

@@ -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;
}