package com.thecherno.ld29.graphics;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL20.*;
import java.util.List;
import org.lwjgl.util.vector.Vector2f;
import org.lwjgl.util.vector.Vector3f;
import com.thecherno.ld29.entity.Entity;
public class Light {
public int x, y;
private int xOffset, yOffset;
public Vector3f vc;
private int color;
public float intensity = 1.0f;
private float radi = 0.4f;
public float dir = 0;
public Light(int x, int y, int color) {
this.x = x;
this.y = y;
this.color = color;
this.vc = new Vector3f(((color & 0xff0000) >> 16) / 255.0f + radi, ((color & 0xff00) >> 8) / 255.0f + radi, (color & 0xff) / 255.0f + radi);
}
public Light(int x, int y, int color, float intensity) {
this.x = x;
this.y = y;
this.color = color;
this.intensity = intensity;
this.vc = new Vector3f(((color & 0xff0000) >> 16) / 255.0f + radi, ((color & 0xff00) >> 8) / 255.0f + radi, (color & 0xff) / 255.0f + radi);
}
public void bindUniforms(int shader) {
int uniform = glGetUniformLocation(shader, "lightPosition");
glUniform2f(uniform, x - xOffset, 540.0f - y + yOffset);
uniform = glGetUniformLocation(shader, "lightColor");
glUniform3f(uniform, vc.x, vc.y, vc.z);
uniform = glGetUniformLocation(shader, "lightIntensity");
glUniform1f(uniform, intensity);
}
public void setWhiteness(float whiteness) {
vc = new Vector3f(((color & 0xff0000) >> 16) / 255.0f + whiteness, ((color & 0xff00) >> 8) / 255.0f + whiteness, (color & 0xff) / 255.0f + whiteness);
}
public void setColor(int color) {
vc = new Vector3f(((color & 0xff0000) >> 16) / 255.0f + radi, ((color & 0xff00) >> 8) / 255.0f + radi, (color & 0xff) / 255.0f + radi);
}
public void shadows(Vector2f[][] foregrounds, List<Entity> entities, int width, int height) {
glColorMask(false, false, false, false);
glStencilFunc(GL_ALWAYS, 1, 1);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
Vector2f lightpos = new Vector2f(x, y);
int x0 = xOffset >> 6;
int x1 = (xOffset >> 6) + 16;
int y0 = yOffset >> 6;
int y1 = (yOffset >> 6) + 10;
for (int y = y0 - 20; y < y1 + 20; y++) {
for (int x = x0 - 20; x < x1 + 20; x++) {
if (x < 0 || x >= width || y < 0 || y >= height) continue;
Vector2f[] vertices = foregrounds[x + y * width];
for (int i = 0; i < vertices.length; i++) {
Vector2f current = vertices[i];
if (current == null) break;
Vector2f next = vertices[(i + 1) % vertices.length];
Vector2f edge = Vector2f.sub(next, current, null);
Vector2f normal = new Vector2f(edge.y, -edge.x);
Vector2f dir = Vector2f.sub(current, lightpos, null);
if (Vector2f.dot(normal, dir) > 0) {
Vector2f point0 = Vector2f.add(current, (Vector2f) Vector2f.sub(current, lightpos, null).scale(960.0f), null);
Vector2f point1 = Vector2f.add(next, (Vector2f) Vector2f.sub(next, lightpos, null).scale(960.0f), null);
float z = 0.5f;
// TODO: Turn into VAO!
glBegin(GL_QUADS);
{
glVertex3f(current.x, current.y, z);
glVertex3f(point0.x, point0.y, z);
glVertex3f(point1.x, point1.y, z);
glVertex3f(next.x, next.y, z);
}
glEnd();
}
}
}
}
for (int j = 0; j < entities.size(); j++) {
Entity e = entities.get(j);
Vector2f[] vertices = new Vector2f[] {
new Vector2f(e.getX(), e.getY()), //
new Vector2f(e.getX() + 64.0f, e.getY()), //
new Vector2f(e.getX() + 64.0f, e.getY() + 64.0f), //
new Vector2f(e.getX(), e.getY() + 64.0f) //
};
for (int i = 0; i < vertices.length; i++) {
Vector2f current = vertices[i];
if (current == null) break;
Vector2f next = vertices[(i + 1) % vertices.length];
Vector2f edge = Vector2f.sub(next, current, null);
Vector2f normal = new Vector2f(edge.y, -edge.x);
Vector2f dir = Vector2f.sub(current, lightpos, null);
if (Vector2f.dot(normal, dir) > 0) {
Vector2f point0 = Vector2f.add(current, (Vector2f) Vector2f.sub(current, lightpos, null).scale(960.0f), null);
Vector2f point1 = Vector2f.add(next, (Vector2f) Vector2f.sub(next, lightpos, null).scale(960.0f), null);
float z = 0.5f;
// TODO: Turn into VAO!
glBegin(GL_QUADS);
{
glVertex3f(current.x, current.y, z);
glVertex3f(point0.x, point0.y, z);
glVertex3f(point1.x, point1.y, z);
glVertex3f(next.x, next.y, z);
}
glEnd();
}
}
}
glColorMask(true, true, true, true);
glStencilFunc(GL_EQUAL, 0, 1);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
}
public void setOffset(int xo, int yo) {
this.xOffset = xo;
this.yOffset = yo;
}
public void render(int shader) {
glUseProgram(shader);
glColorMask(true, true, true, true);
bindUniforms(shader);
glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE);
// TODO: Turn into VAO!
glBegin(GL_QUADS);
glVertex3f(0 + xOffset, 0 + yOffset, 0.0f);
glVertex3f(960 + xOffset, 0 + yOffset, 0.0f);
glVertex3f(960 + xOffset, 540 + yOffset, 0.0f);
glVertex3f(0 + xOffset, 540 + yOffset, 0.0f);
glEnd();
glDisable(GL_BLEND);
glUseProgram(0);
glClear(GL_STENCIL_BUFFER_BIT);
}
public int getXOffset() {
return xOffset;
}
public int getYOffset() {
return yOffset;
}
}