Renderer/src/main/java/electrosphere/renderer/OpenGLState.java
2024-07-03 14:55:24 -04:00

208 lines
6.1 KiB
Java

package electrosphere.renderer;
import java.util.HashMap;
import java.util.Map;
import org.joml.Vector2i;
import org.lwjgl.opengl.GL40;
import electrosphere.renderer.shader.ShaderProgram;
/**
* Encapsulates the state of opengl.
* The main function of this class is to sit between any consuming classes and opengl.
* It can then deduplicate calls based on the state that is already set.
*/
public class OpenGLState {
//the max texture allowed by the current environment
int MAX_TEXTURE_WIDTH = 0;
//the current viewport dimensions
private Vector2i viewport = new Vector2i(0,0);
//whether depth test is enabled or not
boolean depthTest = false;
//the current depth function
int depthFunction = -1;
//the currently bound texture
int boundTexturePointer = 0;
int boundTextureType = 0;
//the currently active texture
int activeTexture = 0;
//the currently bound framebuffer
int framebufferType = 0;
int framebufferPointer = 0;
//active shader
ShaderProgram activeShader = null;
//map of texture units and their corresponding texture pointers
Map<Integer,Integer> unitToPointerMap = new HashMap<Integer,Integer>();
/**
* Gets the constraints of the current environment (ie how large can the max texture be)
*/
public void storeCurrentEnvironmentContraints(){
//the array used to store values fetched from opengl
int[] intFetchArray = new int[1];
//get max texture size
GL40.glGetIntegerv(GL40.GL_MAX_TEXTURE_SIZE, intFetchArray);
MAX_TEXTURE_WIDTH = intFetchArray[0];
}
/**
* Sets the viewport
* @param x the width
* @param y the height
*/
public void glViewport(int x, int y){
if(x != viewport.x || y != viewport.y){
viewport.x = x;
viewport.y = y;
GL40.glViewport(0, 0, viewport.x, viewport.y);
}
}
/**
* Gets the viewport's dimensions
* @return The viewport's dimensions
*/
public Vector2i getViewport(){
return viewport;
}
/**
* Sets the depth test
* @param depthTest the depth test state
*/
public void glDepthTest(boolean depthTest){
// if(this.depthTest != depthTest){
this.depthTest = depthTest;
if(this.depthTest){
GL40.glEnable(GL40.GL_DEPTH_TEST);
} else {
GL40.glDisable(GL40.GL_DEPTH_TEST);
}
// }
}
/**
* Sets the depth function
* @param depthFunction The depth function
*/
public void glDepthFunc(int depthFunction){
if(this.depthFunction != depthFunction){
this.depthFunction = depthFunction;
GL40.glDepthFunc(this.depthFunction);
}
}
/**
* Sets the active texture
* @param texture The active texture
*/
public void glActiveTexture(int texture){
if(this.activeTexture != texture){
this.activeTexture = texture;
GL40.glActiveTexture(this.activeTexture);
}
}
/**
* Binds a texture
* @param textureType The type of texture
* @param textureValue The texture pointer
*/
public void glBindTexture(int textureType, int texturePointer){
if(this.boundTexturePointer != texturePointer || this.boundTextureType != textureType){
this.boundTextureType = textureType;
this.boundTexturePointer = texturePointer;
GL40.glBindTexture(this.boundTextureType,this.boundTexturePointer);
}
}
/**
* Binds a texture to a given texture unit if the texture hasn't already been bound to that unit
* @param textureUnit The texture unit
* @param texturePointer The texture pointer
* @param textureType the type of texture (2d, 3d, etc)
*/
public void glBindTextureUnit(int textureUnit, int texturePointer, int textureType){
if(!unitToPointerMap.containsKey(textureUnit) || unitToPointerMap.get(textureUnit)!=texturePointer){
unitToPointerMap.put(textureUnit,texturePointer);
GL40.glActiveTexture(textureUnit);
GL40.glBindTexture(textureType,texturePointer);
}
}
/**
* Binds a framebuffer
* @param framebufferType the type of framebuffer (vanilla, renderbuffer, etc)
* @param framebufferPointer the pointer to the framebuffer
*/
public void glBindFramebuffer(int framebufferType, int framebufferPointer){
if(this.framebufferType != framebufferType || this.framebufferPointer != framebufferPointer){
this.framebufferType = framebufferType;
this.framebufferPointer = framebufferPointer;
GL40.glBindFramebuffer(this.framebufferType,this.framebufferPointer);
}
}
/**
* Gets the currently bound framebuffer's pointer
* @return The pointer
*/
public int getBoundFramebuffer(){
return this.framebufferPointer;
}
/**
* Sets the currently active shader program for the renderer
* @param renderPipelineState The render pipeline state object
* @param program The shader program to bind
*/
public void setActiveShader(RenderPipelineState renderPipelineState, ShaderProgram program){
if(program != activeShader){
activeShader = program;
GL40.glUseProgram(activeShader.getShaderId());
renderPipelineState.setCurrentShaderPointer(activeShader.getShaderId());
}
}
/**
* Gets the active shader program
* @return The active shader
*/
public ShaderProgram getActiveShader(){
return activeShader;
}
/**
* Checks whether the provided shader program is the active shader program
* @param program The program to check
* @return true if the provided program is the active program, false otherwise
*/
public boolean isCurrentShader(ShaderProgram program){
return this.activeShader == program;
}
/**
* Gets MAX_TEXTURE_WIDTH
* @return MAX_TEXTURE_WIDTH
*/
public int getMAX_TEXTURE_WIDTH(){
return MAX_TEXTURE_WIDTH;
}
}