Renderer/src/main/java/electrosphere/renderer/OpenGLState.java
austin df3010f38a
Some checks failed
studiorailgun/Renderer/pipeline/head There was a failure building this commit
framebuffer bug hunt work
2024-09-06 01:32:25 -04:00

292 lines
9.3 KiB
Java

package electrosphere.renderer;
import java.util.HashMap;
import java.util.Map;
import org.joml.Vector2i;
import org.lwjgl.opengl.GL40;
import electrosphere.engine.Globals;
import electrosphere.logger.LoggerInterface;
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 {
//tracks whether caching should be used or not (to deduplicate opengl calls)
private static final boolean DISABLE_CACHING = false;
//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;
//whether to blend or nit
boolean blendTest = false;
//the current blend func
//map is (texture unit) -> [sfactor,dfactor]
Map<Integer,int[]> blendFuncMap = new HashMap<Integer,int[]>();
//the key that contains the value of glBlendFunc (which would affect all buffers)
static final int ALL_BUFFERS_KEY = -1;
//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(DISABLE_CACHING || 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(DISABLE_CACHING || 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(DISABLE_CACHING || this.activeTexture != texture){
this.activeTexture = texture;
GL40.glActiveTexture(this.activeTexture);
Globals.renderingEngine.checkError();
}
}
/**
* Binds a texture
* @param textureType The type of texture
* @param textureValue The texture pointer
*/
public void glBindTexture(int textureType, int texturePointer){
this.glBindTextureUnit(this.activeTexture, texturePointer, textureType);
}
/**
* 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(DISABLE_CACHING || !unitToPointerMap.containsKey(textureUnit) || unitToPointerMap.get(textureUnit)!=texturePointer){
unitToPointerMap.put(textureUnit,texturePointer);
this.glActiveTexture(textureUnit);
GL40.glBindTexture(textureType,texturePointer);
Globals.renderingEngine.checkError();
}
}
/**
* 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 glBindTextureUnitForce(int textureUnit, int texturePointer, int textureType){
unitToPointerMap.put(textureUnit,texturePointer);
this.activeTexture = textureUnit;
GL40.glActiveTexture(this.activeTexture);
Globals.renderingEngine.checkError();
GL40.glBindTexture(textureType,texturePointer);
Globals.renderingEngine.checkError();
}
/**
* 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(DISABLE_CACHING || this.framebufferType != framebufferType || this.framebufferPointer != framebufferPointer){
this.framebufferType = framebufferType;
this.framebufferPointer = framebufferPointer;
GL40.glBindFramebuffer(this.framebufferType,this.framebufferPointer);
Globals.renderingEngine.checkError();
}
}
/**
* 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(DISABLE_CACHING || program != activeShader){
activeShader = program;
GL40.glUseProgram(activeShader.getShaderId());
int glErrorCode = Globals.renderingEngine.getError();
if(glErrorCode != 0){
LoggerInterface.loggerRenderer.DEBUG_LOOP(RenderingEngine.getErrorInEnglish(glErrorCode));
}
Globals.renderingEngine.checkError();
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;
}
/**
*
* @param sfactor
* @param dfactor
*/
public void glBlendFunc(int sfactor, int dfactor){
GL40.glBlendFunc(sfactor, dfactor);
//set all other keys
for(int keyCurrent : this.blendFuncMap.keySet()){
if(keyCurrent != ALL_BUFFERS_KEY){
int[] funcs = this.blendFuncMap.get(keyCurrent);
funcs[0] = sfactor;
funcs[1] = dfactor;
}
}
}
/**
* Sets the blend function for opengl
* @param drawBufferIndex The draw buffer index that will have this function set
* @param sfactor The source factor
* @param dfactor The destination factor
*/
public void glBlendFunci(int drawBufferIndex, int sfactor, int dfactor){
if(!DISABLE_CACHING && this.blendFuncMap.containsKey(drawBufferIndex)){
int[] funcs = this.blendFuncMap.get(drawBufferIndex);
int sFactorCurr = funcs[0];
int dFactorCurr = funcs[1];
if(sfactor != sFactorCurr || dfactor != dFactorCurr){
funcs[0] = sfactor;
funcs[1] = dfactor;
this.blendFuncMap.put(drawBufferIndex,funcs);
GL40.glBlendFunci(drawBufferIndex, sfactor, dfactor);
}
} else {
int[] funcs = new int[]{
sfactor, dfactor
};
this.blendFuncMap.put(drawBufferIndex,funcs);
GL40.glBlendFunci(drawBufferIndex, sfactor, dfactor);
}
}
public void glBlend(boolean blend){
// if(this.blendTest != blend){
this.blendTest = blend;
if(this.blendTest){
GL40.glEnable(GL40.GL_BLEND);
} else {
GL40.glDisable(GL40.GL_BLEND);
}
// }
}
}