package com.thecherno.ld29.level.tile;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL13.*;
import static org.lwjgl.opengl.GL15.*;
import static org.lwjgl.opengl.GL20.*;
import static org.lwjgl.opengl.GL30.*;
import java.util.List;
import com.thecherno.ld29.graphics.Light;
import com.thecherno.ld29.graphics.Shader;
import com.thecherno.ld29.input.Keyboard;
import com.thecherno.ld29.resources.Texture;
import com.thecherno.ld29.util.Buffer;
public class Tile {
public static final byte GROUND = 0x0;
public static final byte GRASS = 0x2;
public static final byte DIRT = 0x3;
public static final float SIZE = 64.0f;
// vao = entire array
// vbo = vertex buffer
// vio = index buffer
// vto = texCoord buffer
protected int vao, vbo, vio, vto;
protected Shader shader;
protected int texture;
protected float waterLevel = 0.0f;
private float time = 0.0f;
protected float[] vertices = new float[] {
0.0f, 0.0f, 0.0f,//
SIZE, 0.0f, 0.0f, //
SIZE, SIZE, 0.0f,//
0, SIZE, 0.0f //
};
protected byte[] indices = new byte[] {
0, 1, 2, //
2, 3, 0 //
};
protected byte[] texCoords = new byte[] {
0, 0,//
1, 0,//
1, 1, //
1, 1, //
0, 1, //
0, 0 //
};
public Tile() {
texture = Texture.GROUND;
createShader(Shader.TILE);
compile();
}
public Tile(int texture) {
this.texture = texture;
createShader(Shader.TILE);
compile();
}
protected void compile() {
vao = glGenVertexArrays();
glBindVertexArray(vao);
{
vbo = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, vbo);
{
glBufferData(GL_ARRAY_BUFFER, Buffer.createFloatBuffer(vertices), GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, 0);
}
glBindBuffer(GL_ARRAY_BUFFER, 0);
vio = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, vio);
{
glBufferData(GL_ARRAY_BUFFER, Buffer.createByteBuffer(indices), GL_STATIC_DRAW);
}
glBindBuffer(GL_ARRAY_BUFFER, 0);
vto = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, vto);
{
glBufferData(GL_ARRAY_BUFFER, Buffer.createByteBuffer(texCoords), GL_STATIC_DRAW);
glVertexAttribPointer(1, 3, GL_UNSIGNED_BYTE, false, 0, 1);
}
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
glBindVertexArray(0);
}
protected void createShader(Shader shader) {
this.shader = shader;
glActiveTexture(GL_TEXTURE1);
shader.bind();
int uniform = glGetUniformLocation(shader.getID(), "texture");
glUniform1i(uniform, 1);
glActiveTexture(GL_TEXTURE2);
uniform = glGetUniformLocation(shader.getID(), "waterTexture");
glUniform1i(uniform, 2);
shader.release();
}
public void render(int x, int y, float water) {
setWaterLevel(water);
glPushMatrix();
shader.bind();
glBindVertexArray(vao);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
{
glTranslatef(x, y, 0);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, texture);
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, Texture.WATER);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vio);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindTexture(GL_TEXTURE_2D, 0);
}
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(0);
glBindVertexArray(0);
shader.release();
glPopMatrix();
}
public void update() {
time += 0.005f;
shader.bind();
int uniform = shader.getUniform("time");
shader.setUniformf(uniform, time);
shader.release();
}
public void bindUniforms(Light light) {
shader.bind();
light.bindUniforms(shader.getID());
shader.setUniform1f("waterLevel", waterLevel);
shader.release();
}
public void bindUniforms(List<Light> lights) {
if (lights.size() > 10) {
System.err.println("Too many lights!");
return;
}
float[] positions = new float[10 * 2];
float[] colors = new float[10 * 3];
float[] intensities = new float[10];
for (int i = 0; i < lights.size() * 2; i += 2) {
positions[i] = lights.get(i >> 1).x - lights.get(i >> 1).getXOffset();
positions[i + 1] = 540.0f - lights.get(i >> 1).y + lights.get(i >> 1).getYOffset();
}
for (int i = 0; i < lights.size(); i++) {
intensities[i] = lights.get(i).intensity;
}
for (int i = 0; i < lights.size() * 3; i += 3) {
colors[i] = lights.get(i / 3).vc.x;
colors[i + 1] = lights.get(i / 3).vc.y;
colors[i + 2] = lights.get(i / 3).vc.z;
}
shader.bind();
int uniform = glGetUniformLocation(shader.getID(), "lightPosition");
glUniform2(uniform, Buffer.createFloatBuffer(positions));
uniform = glGetUniformLocation(shader.getID(), "lightColor");
glUniform3(uniform, Buffer.createFloatBuffer(colors));
uniform = glGetUniformLocation(shader.getID(), "lightIntensity");
glUniform1(uniform, Buffer.createFloatBuffer(intensities));
shader.release();
}
public void setWaterLevel(float waterLevel) {
this.waterLevel = waterLevel;
}
public boolean solid() {
return false;
}
public void increaseWaterLevel(float amount) {
this.waterLevel += amount;
}
}