package me.hammerle.snuviengine.api; import java.nio.FloatBuffer; import org.lwjgl.BufferUtils; import static org.lwjgl.opengl.GL11.*; import static org.lwjgl.opengl.GL14.*; import static org.lwjgl.opengl.GL20.*; public final class Renderer { private float width; private float height; private int scale; private final FontRenderer fontRenderer = new FontRenderer(); private final ColorRenderer colorRenderer = new ColorRenderer(); private final DirectTextureRenderer textureRenderer = new DirectTextureRenderer(); // uniform stuff private final int unifViewMatrix; private final int unifModelMatrix; private final MatrixStack modelMatrix = new MatrixStack(20); private final int unifAmbientLight; private final int[][] unifLight = new int[32][3]; private final UniformBoolean useTexture; private final UniformBoolean useColor; private final UniformBoolean useLight; private final UniformBoolean useMixColor; private final int unifMixColorLoc; private final float[] unifMixColor = new float[]{0.0f, 0.0f, 0.0f, 0.0f}; protected Renderer(int program, int width, int height, WindowView windowView) { glUseProgram(program); unifViewMatrix = glGetUniformLocation(program, "viewMatrix"); setSize(width, height, windowView); unifModelMatrix = glGetUniformLocation(program, "modelMatrix"); updateMatrix(); unifAmbientLight = glGetUniformLocation(program, "ambientLight"); setAmbientLight(1.0f, 1.0f, 1.0f); for(int index = 0; index < unifLight.length; index++) { unifLight[index][0] = glGetUniformLocation(program, String.format("lights[%d].color", index)); unifLight[index][1] = glGetUniformLocation(program, String.format("lights[%d].pos", index)); unifLight[index][2] = glGetUniformLocation(program, String.format("lights[%d].strength", index)); setLightColor(index, 0.0f, 0.0f, 0.0f); setLightLocation(index, 0.0f, 0.0f); setLightStrength(index, 0.0f); } useTexture = new UniformBoolean(program, "useTexture", false); useColor = new UniformBoolean(program, "useColor", false); useLight = new UniformBoolean(program, "useLight", false); useMixColor = new UniformBoolean(program, "useMixColor", false); unifMixColorLoc = glGetUniformLocation(program, "mixColor"); setMixColor(0.0f, 0.0f, 0.0f, 0.0f); } public FontRenderer getFontRenderer() { return fontRenderer; } public ColorRenderer getColorRenderer() { return colorRenderer; } public DirectTextureRenderer getTextureRenderer() { return textureRenderer; } private void updateViewMatrix() { FloatBuffer buffer = BufferUtils.createFloatBuffer(16); addToBuffer(buffer, 2.0f / width, 0.0f, 0.0f, 0.0f); addToBuffer(buffer, 0.0f, -2.0f / height, 0.0f, 0.0f); addToBuffer(buffer, 0.0f, 0.0f, -1.0f / height, 0.0f); addToBuffer(buffer, -1.0f, 1.0f, 0.5f, 1.0f); buffer.flip(); glUniformMatrix4fv(unifViewMatrix, false, buffer); } private void addToBuffer(FloatBuffer buffer, float a, float b, float c, float d) { buffer.put(a); buffer.put(b); buffer.put(c); buffer.put(d); } protected void setSize(int width, int height, WindowView windowView) { scale = windowView.getScale(width, height); fontRenderer.setScale(windowView.getFontScale(width, height)); this.width = width / scale; this.height = height / scale; updateViewMatrix(); } public int getViewScale() { return scale; } public float getViewWidth() { return width; } public float getViewHeight() { return height; } public void updateMatrix() { glUniformMatrix4fv(unifModelMatrix, false, modelMatrix.getData()); } public void pushMatrix() { modelMatrix.push(); } public void popMatrix() { modelMatrix.pop(); } public void translate(float tx, float ty) { modelMatrix.translate(tx, ty); } public void translateTo(float tx, float ty) { modelMatrix.translateTo(tx, ty); } public void scale(float sx, float sy) { modelMatrix.scale(sx, sy); } public void rotate(float angle) { modelMatrix.rotate(angle); } public void setAmbientLight(float r, float g, float b) { glUniform3f(unifAmbientLight, r, g, b); } private boolean isValidLightIndex(int index) { return index >= 0 && index < unifLight.length; } public void setLightColor(int index, float r, float g, float b) { if(isValidLightIndex(index)) { glUniform3f(unifLight[index][0], r, g, b); } } public void setLightLocation(int index, float x, float y) { if(isValidLightIndex(index)) { glUniform2f(unifLight[index][1], x, y); } } public void setLightStrength(int index, float strength) { if(isValidLightIndex(index)) { glUniform1f(unifLight[index][2], strength); } } public void setTextureEnabled(boolean use) { useTexture.set(use); } public void setColorEnabled(boolean use) { useColor.set(use); } public void setMixColorEnabled(boolean use) { useMixColor.set(use); } public void setMixColor(float r, float g, float b, float a) { unifMixColor[0] = r; unifMixColor[1] = g; unifMixColor[2] = b; unifMixColor[3] = a; glUniform4fv(unifMixColorLoc, unifMixColor); } public void setLightEnabled(boolean use) { useLight.set(use); } public void enableDepthTest() { glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LEQUAL); } public void disableDepthTest() { glDisable(GL_DEPTH_TEST); } public void enableBlending() { glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBlendEquation(GL_FUNC_ADD); } public void disableBlending() { glDisable(GL_BLEND); } public float round(float f) { return ((int) (f * scale)) / (float) scale; } }