Compare commits

...

6 Commits

Author SHA1 Message Date
austin
f7887fc875 work towards saving framebuffers as screenshots
Some checks failed
studiorailgun/Renderer/pipeline/head There was a failure building this commit
2024-07-04 16:32:43 -04:00
austin
0db8734f44 opengl error checking fixes 2024-07-03 16:41:05 -04:00
austin
29299a7781 add saving framebuffers 2024-07-03 14:55:24 -04:00
austin
14d423d533 script engine bugfix, hitbox subtypes 2024-07-02 17:07:16 -04:00
austin
e5a187ce19 script engine work 2024-07-02 16:14:05 -04:00
austin
df4fe45dd5 transvoxel position checking work 2024-06-30 13:38:41 -04:00
67 changed files with 1977 additions and 515 deletions

6
.gitignore vendored
View File

@ -33,6 +33,9 @@
/saves/random_sp_world
/saves/defaultLevel*
#screenshots
/assets/Screenshots
#debug
/netmonitor
@ -45,3 +48,6 @@
#imgui local layout
/imgui.ini
#script engine related
/assets/Scripts/compiler/typescript.js

View File

@ -4,5 +4,7 @@
"**/.git/objects/**": true,
"**/node_modules/**": true
},
"java.jdt.ls.vmargs": "-XX:+UseParallelGC -XX:GCTimeRatio=4 -XX:AdaptiveSizePolicyWeight=90 -Dsun.zip.disableMemoryMapping=true -Xmx2G -Xms100m -Xlog:disable"
"java.jdt.ls.vmargs": "-XX:+UseParallelGC -XX:GCTimeRatio=4 -XX:AdaptiveSizePolicyWeight=90 -Dsun.zip.disableMemoryMapping=true -Xmx2G -Xms100m -Xlog:disable",
"javascript.preferences.importModuleSpecifier": "non-relative",
"typescript.preferences.importModuleSpecifier": "non-relative"
}

View File

@ -16,6 +16,11 @@
"Green Grass"
],
"texture" : "/Textures/Ground/GrassTileable256.png"
},
{
"id" : 3,
"name" : "baguette",
"texture" : "/Textures/Ground/baguette256.png"
}
]
}

View File

@ -0,0 +1,119 @@
/**
* The map of all source files to their content and compiled value
*/
let COMPILER_fileMap = { }
/**
* The compiled program
*/
let COMPILER_emitted_value = ''
/**
* Registers a file with the compiler
* @param {*} fileName The file's name
* @param {*} content The content of the file
*/
const COMPILER_registerFile = (fileName, content) => {
let normalizedFilePath = FILE_RESOLUTION_getFilePath(fileName,false)
loggerScripts.INFO('REGISTER FILE ' + normalizedFilePath)
COMPILER_fileMap[normalizedFilePath] = {
content: content,
compiled: ts.createSourceFile(
normalizedFilePath, content, ts.ScriptTarget.Latest
)
}
}
/**
* The callback invoked when the compiler host tries to read a file
* @param {*} fileName The name of the file
* @param {*} languageVersion The language version
* @returns The file if it exists, null otherwise
*/
const COMPILER_getSourceFile = (fileName, languageVersion) => {
if(!!COMPILER_fileMap[fileName]){
return COMPILER_fileMap[fileName].compiled
} else {
return null
}
}
/**
* Constructs the compiler host
* https://www.typescriptlang.org/tsconfig/#compilerOptions
*/
const COMPILER_customCompilerHost = {
getSourceFile: COMPILER_getSourceFile,
writeFile: (fileName, data) => {
let normalizedFilePath = FILE_RESOLUTION_getFilePath(fileName)
loggerScripts.INFO("EMIT FILE " + normalizedFilePath)
let finalData =
"let exports = { }\n" +
data + "\n" +
"return exports"
// COMPILER_emitted_value = data
COMPILER_fileMap[normalizedFilePath] = {
content: data, //to be eval'd from top level
moduleContent: finalData, //to be eval'd from require()
}
},
getDefaultLibFileName: () => "lib.d.ts",
useCaseSensitiveFileNames: () => false,
getCanonicalFileName: filename => filename,
getCurrentDirectory: () => "",
getNewLine: () => "\n",
getDirectories: () => [],
fileExists: () => true,
readFile: () => ""
}
/**
* Instructs Typescript to emit the final compiled value
*/
const COMPILER_run = () => {
loggerScripts.INFO('COMPILE ALL REGISTERED FILES')
const compilerOptions = { }
const COMPILER_program = ts.createProgram(
Object.keys(COMPILER_fileMap), compilerOptions, COMPILER_customCompilerHost
)
COMPILER_program.emit()
}
/**
* Loads a file
* @param {*} fileName The name of the file to load (preferably already has .ts at the end)
*/
const COMPILER_runFile = (fileName) => {
let normalizedFilePath = FILE_RESOLUTION_getFilePath(fileName)
if(!!COMPILER_fileMap[normalizedFilePath]){
loggerScripts.INFO('RUN FILE ' + normalizedFilePath)
eval(COMPILER_fileMap[normalizedFilePath].content)
} else {
const message = 'FAILED TO RESOLVE FILE ' + normalizedFilePath
loggerScripts.WARNING(message)
throw new Error(message)
}
}
/**
* Loads a file
* @param {*} fileName The name of the file to load (preferably already has .ts at the end)
*/
const COMPILER_printSource = (fileName) => {
let normalizedFilePath = FILE_RESOLUTION_getFilePath(fileName)
if(!!COMPILER_fileMap[normalizedFilePath]){
loggerScripts.INFO('FILE CONTENT ' + normalizedFilePath)
} else {
const message = 'FAILED TO RESOLVE FILE ' + normalizedFilePath
loggerScripts.WARNING(message)
loggerScripts.WARNING('file map content:')
loggerScripts.WARNING(OBject.keys(COMPILER_fileMap) + "")
throw new Error(message)
}
}

View File

@ -0,0 +1,23 @@
/**
* Normalizes a file path
* @param {*} rawFilePath The raw file path
* @returns The normalized file path
*/
const FILE_RESOLUTION_getFilePath = (rawFilePath, isJavascript = true) => {
let fileName = rawFilePath
if(isJavascript && fileName.includes('.ts')){
fileName = fileName.replace('.ts','.js')
}
if(fileName.startsWith('/Scripts')){
fileName = fileName.replace('/Scripts','')
}
if(fileName.startsWith('Scripts/')){
fileName = fileName.replace('Scripts/','/')
}
if(isJavascript && !fileName.endsWith(".js")){
fileName = fileName + ".js"
}
return fileName
}

View File

@ -0,0 +1 @@
wget -O typescript.js https://unpkg.com/typescript@latest/lib/typescript.js

View File

@ -0,0 +1,21 @@
/**
* The host context that contains the core engine functions
*/
let HOST_ACCESS = {
classes: { }, //the classes available to the script engine
singletons: { }, //the singletons available to the script engine
}
//fake require
REQUIRE_CACHE["/compiler/host_access.js"] = {
exports: {
'HOST_ACCESS': HOST_ACCESS,
'loggerScripts': loggerScripts,
},
exportedValues: [
'HOST_ACCESS',
'loggerScripts'
],
}

View File

@ -0,0 +1,43 @@
/**
* Caches loaded modules
*/
let REQUIRE_CACHE = { }
/**
* Used if the module is directly executed instead of being require'd for some reason
*/
let exports = { }
/**
* Imports a module
* @param {*} path The path of the module
* @param {*} cwd The current working directory
*/
const require = (path) => {
loggerScripts.DEBUG('Require path ' + path)
let normalizedFilePath = FILE_RESOLUTION_getFilePath(path)
if(!!REQUIRE_CACHE[normalizedFilePath]){
return REQUIRE_CACHE[normalizedFilePath].exports
} else if(!!COMPILER_fileMap[normalizedFilePath]?.content) {
const code = COMPILER_fileMap[normalizedFilePath].moduleContent
let exports = new Function(code)()
//create module object
const module = {
exports: exports,
exportedValues: Object.keys(exports),
}
REQUIRE_CACHE[normalizedFilePath] = module
loggerScripts.INFO("[require] CREATE MODULE " + normalizedFilePath)
return module.exports
} else {
const errorMsg = "FAILED TO REQUIRE FILE " + normalizedFilePath
loggerScripts.WARNING(errorMsg)
loggerScripts.WARNING('Module value:')
loggerScripts.WARNING(Object.keys(REQUIRE_CACHE?.[normalizedFilePath]) + '')
loggerScripts.WARNING('Require cache contents:')
loggerScripts.WARNING(Object.keys(REQUIRE_CACHE) + '')
throw new Error(errorMsg)
}
}

View File

@ -0,0 +1,11 @@
import { Host } from '/engine/engine-interface'
import { loggerScripts } from '/compiler/host_access'
let host: Host
/**
* Called when the script engine first initializes
*/
export const ENGINE_onInit = () => {
loggerScripts.INFO('Script Engine Init')
}

View File

@ -0,0 +1,9 @@
/**
* The host context that contains all core engine functions
*/
export interface Host {
classes: any, //the host's view of the scripting engine
singletons: any, //the singletons available to the script engine
}

View File

@ -1 +0,0 @@
console.log("test")

View File

@ -1,3 +1,3 @@
#maven.buildNumber.plugin properties file
#Wed Jun 19 19:19:09 EDT 2024
buildNumber=138
#Wed Jul 03 15:06:42 EDT 2024
buildNumber=149

View File

@ -5,3 +5,4 @@
- @subpage largelocationideas
- @subpage macrolocationideas
- @subpage smalllocations
- @subpage minidungeons

View File

@ -0,0 +1,4 @@
@page minidungeons Mini Dungeons
In certain levels, you can find premade characters that can join your party.

View File

@ -17,11 +17,11 @@ Audio FX for everything
= Coding =
Sub menu on title screen that allows changing control mappings
- Automatically generate based on the controls arrays in controls handler
Redo hitboxes to have capsules and also chaining between frames (but not between swinging the camera around)
- Introduce block hitbox (blockbox) type
- Sour spot, sweet spot for damage hitboxes and hurtboxes
Review combat code
- Damage calculation
- Particle generation
- Revive tree
Enemy AI
better scaffolding for scriptig engine with hooks for equipping items, spawning entities, pausing/resuming play, etc
Ability for private realms to have time start/stop based on the player's feedback <-- sync this up to tutorial ui via script
Scene Message Service
- Can send arbitrary events and messages

View File

@ -406,6 +406,21 @@ Audio
- Sword Hit Metal
- Sword Hit Flesh
(07/02/2024)
better scaffolding for scripting engine with hooks for equipping items, spawning entities, pausing/resuming play, etc
Redo hitboxes to have capsules and also chaining between frames (but not between swinging the camera around)
- Introduce block hitbox (blockbox) type
- Sour spot, sweet spot for damage hitboxes and hurtboxes
(07/03/2024)
Clean up framebuffer class
- Comment everything
- Error checking
Overhaul opengl error checking generally (as in, actually use it)
- Add all over the place to help debugging graphics issues
- Handle uniforms being sent to shaders that don't have the uniform defined
Extracting pixels from framebuffers
# TODO
@ -413,8 +428,10 @@ Audio
BIG BIG BIG BIG IMMEDIATE TO DO:
always enforce opengl interface across all opengl calls jesus christ the bone uniform bug was impossible
Unit Testing
- Capture image from opengl to pixel-check
- Ability to click through the ui via scripts
- Add ui tests
Goof off today requirements:
@ -429,6 +446,9 @@ Transvoxel implementation
- Ability to get terrain at point for interactions with game world eg placing grass/water collision
Fix not all grass tiles update when updating a nearby voxel (ie it doesn't go into negative coordinates to scan for foliage updates)
Refactor menu clases under electrosphere.client package
Allow texture map to bind multiple model paths to a single set of mesh->textures
@ -460,9 +480,6 @@ Data Cleanup
Clean up Material class
- fix storing textures in the mat class ( pain :c )
Clean up framebuffer class
- Comment everything
Overhaul of 'attach' semantics
- Having different types of attach tree propagation
- Ability to turn on/off combinations of models at will (already exists, but needs review)

20
pom.xml
View File

@ -13,6 +13,7 @@
<joml.version>1.9.19</joml.version>
<recast.version>1.5.7</recast.version>
<imgui.version>1.86.11</imgui.version>
<graalvm.version>23.1.3</graalvm.version>
</properties>
<!-- Used for build number plugin because it LITERALLY WONT LET YOU NOT HAVE SCM-->
@ -173,18 +174,21 @@
<!--GraalVM-->
<!--License: GPLv2 w/ classpath exception-->
<!--apparently maybe classpath exception allows use in eg game engine??-->
<!-- https://mvnrepository.com/artifact/org.graalvm.js/js -->
<dependency>
<groupId>org.graalvm.js</groupId>
<artifactId>js</artifactId>
<version>22.1.0.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.graalvm.js/js-scriptengine -->
<dependency>
<groupId>org.graalvm.js</groupId>
<artifactId>js-scriptengine</artifactId>
<version>22.1.0.1</version>
<version>${graalvm.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.graalvm.polyglot/js-community -->
<dependency>
<groupId>org.graalvm.polyglot</groupId>
<artifactId>js-community</artifactId>
<version>${graalvm.version}</version>
<type>pom</type>
<scope>runtime</scope>
</dependency>
<!--steamworks4j-->
<!--License: MIT-->
@ -326,6 +330,8 @@
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>electrosphere.engine.Main</mainClass>
</transformer>
<transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer">
</transformer>
</transformers>
</configuration>
</execution>

View File

@ -491,6 +491,182 @@ public class DrawCellManager {
}
/**
transvoxel algorithm spacing management
want to specify a radius and have it be a circle so we're not wasting resolution on far off corners
To benefit from the LOD, should have a series of for loops
First loop iterates over (-largest radius) -> (largest radius) at an interval of the width of the lowest level of detail chunk
We check all 8 corners of the chunk to see if they all fall within the largest lod concentric circle
There are a few cases to consider
- All fall outside the largest LOD radius (ignore)
- All but one fall outside thel argest LOD radius (ignore)
- All fall within the largest LOD circle (make LOD chunk)
- One is within the next LOD radius, others are within the current LOD radius (ignore for this pass)
- All are within a lower LOD radius (ignore)
Once we're done with the largest LOD radius, we go to a higher resolution radius and iterate for smaller bounds
In a middle LOD level, if all corners are outside, but the lower resolution didn't
already pick it up, still need to generate a chunk at the current resolution
Detection of this case is tricky
We could snap the currently considered position to the nearest low-resolution chunk and then bounds check that low resolution chunk for every
higher resolution position we're considering
This is probably a bad idea
We could recurse every time a chunk doesn't work for the current level of detail, then evaluate it for a higher level of detail at this closer value
*/
//the number of corners to consider for a valid chunk
static final int NUM_CORNERS_TO_CONSIDER = 8;
//offsets to get from current position to the actual corner to consider
int[] cornerOffsetsX = new int[]{0,1,0,1,0,1,0,1,};
int[] cornerOffsetsY = new int[]{0,0,0,0,1,1,1,1,};
int[] cornerOffsetsZ = new int[]{0,0,1,1,0,0,1,1,};
/**
* Recursive function that does chunk validity checking
* @param playerChunkPos
* @param minPoint
* @param maxPoint
* @param currentLOD
*/
public void assesChunkPositionsAtLOD(
Vector3i playerChunkPos,
Vector3i minPoint,
Vector3i maxPoint,
int currentLOD
){
Vector3i currentChunkPositionConsidered = new Vector3i(playerChunkPos); // The chunk position we're currently considering
double currentRadius = lodLevelRadiusTable[currentLOD];
double nextRadius = 0;
int increment = 1;
if(currentLOD > 0){
//only works when the LOD is greater than 0. When it's 0, there is no lower bound on chunk positions to generate
nextRadius = lodLevelRadiusTable[currentLOD-1];
increment = (int)Math.pow(2,currentLOD);
}
//iterate
for(int x = minPoint.x; x < maxPoint.x; x = x + increment){
for(int y = minPoint.y; y < maxPoint.x; y = y + increment){
for(int z = minPoint.z; z < maxPoint.x; z = z + increment){
//we have 8 corners to consider
//need to identify which case the current position is
int positionCase = 0;
for(int j = 0; j < NUM_CORNERS_TO_CONSIDER; j++){
currentChunkPositionConsidered.set(
x + cornerOffsetsX[j] * increment,
y + cornerOffsetsY[j] * increment,
z + cornerOffsetsZ[j] * increment
);
//figure out the case of this corner
double distance = currentChunkPositionConsidered.distance(playerChunkPos);
if(distance > currentRadius){
positionCase = 1;
break;
} else if(distance <= nextRadius){
positionCase = 2;
break;
}
}
switch(positionCase){
case 0: {
//fully within current band, generate chunk
} break;
case 1: {
//partially outside bound, ignore
} break;
case 2: {
//partially inside higher resolution bound, recurse
assesChunkPositionsAtLOD(
playerChunkPos,
new Vector3i(x,y,z),
new Vector3i(x+increment,y+increment,z+increment),
currentLOD
);
} break;
}
}
}
}
}
/**
* Assess all LOD chunk levels
*/
public void assesLODChunks(){
//pre-existing values
Vector3d playerPosition = EntityUtils.getPosition(Globals.playerEntity);
Vector3i playerChunkPosition = Globals.clientWorldData.convertRealToChunkSpace(playerPosition);
//variables used while iterating across chunk positions
double currentRadius = 0; //the current radius is in units of chunks, even though it's a double (it's discrete, not real)
double nextRadius = 0; //the next radius is in units of chunks, even though it's a double (it's discrete, not real)
int increment = 1; //the increment is in units of chunks, not real
//the offsets from the player's position to
//the nearest possible spot we could place a chunk of the current LOD at (in units of chunks)
Vector3i lowerOffsets = new Vector3i(0,0,0);
Vector3i currentChunkPositionConsidered = new Vector3i(playerChunkPosition); // The chunk position we're currently considering
//actual logic to search for valid chunks
for(int i = NUMBER_OF_LOD_LEVELS - 1; i >= 0; i--){
currentRadius = lodLevelRadiusTable[i];
nextRadius = 0;
increment = 1;
if(i > 0){
//only works when the LOD is greater than 0. When it's 0, there is no lower bound on chunk positions to generate
nextRadius = lodLevelRadiusTable[i-1];
increment = (int)Math.pow(2,i);
}
//calculate offsets to get from player's current chunk position to the lower resolution grid for the current LOD
lowerOffsets.x = playerChunkPosition.x % ((int)increment);
lowerOffsets.y = playerChunkPosition.y % ((int)increment);
lowerOffsets.z = playerChunkPosition.z % ((int)increment);
//iterate
for(int x = -(int)currentRadius - lowerOffsets.x; x < currentRadius; x = x + increment){
for(int y = -(int)currentRadius - lowerOffsets.y; y < currentRadius; y = y + increment){
for(int z = -(int)currentRadius - lowerOffsets.z; z < currentRadius; z = z + increment){
//we have 8 corners to consider
//need to identify which case the current position is
int positionCase = 0;
for(int j = 0; j < NUM_CORNERS_TO_CONSIDER; j++){
currentChunkPositionConsidered.set(
x + cornerOffsetsX[j] * increment,
y + cornerOffsetsY[j] * increment,
z + cornerOffsetsZ[j] * increment
);
//figure out the case of this corner
double distance = currentChunkPositionConsidered.distance(playerChunkPosition);
if(distance > currentRadius){
positionCase = 1;
break;
} else if(distance <= nextRadius){
positionCase = 2;
break;
}
}
switch(positionCase){
case 0: {
//fully within current band, generate chunk
} break;
case 1: {
//partially outside bound, ignore
} break;
case 2: {
//partially inside higher resolution bound, recurse
} break;
}
}
}
}
}
}
}

View File

@ -18,6 +18,9 @@ public class Control {
ControlType type;
boolean state;
int keyValue;
String name;
String description;
boolean rebindable;
ControlMethod onPress;
ControlMethod onRelease;
ControlMethod onRepeat;
@ -52,10 +55,13 @@ public class Control {
this.state = state;
}
public Control(ControlType type, int keyValue) {
public Control(ControlType type, int keyValue, boolean rebindable, String name, String description) {
this.type = type;
this.keyValue = keyValue;
this.state = false;
this.rebindable = rebindable;
this.name = name;
this.description = description;
}
public void setOnPress(ControlMethod method){
@ -134,6 +140,18 @@ public class Control {
repeatTimeout = timeout;
}
public boolean isRebindable(){
return rebindable;
}
public String getName(){
return name;
}
public String getDescription(){
return description;
}
public interface ControlMethod {
public void execute();

View File

@ -26,6 +26,7 @@ import static org.lwjgl.glfw.GLFW.GLFW_KEY_ESCAPE;
import static org.lwjgl.glfw.GLFW.GLFW_KEY_F;
import static org.lwjgl.glfw.GLFW.GLFW_KEY_F2;
import static org.lwjgl.glfw.GLFW.GLFW_KEY_F24;
import static org.lwjgl.glfw.GLFW.GLFW_KEY_F4;
import static org.lwjgl.glfw.GLFW.GLFW_KEY_G;
import static org.lwjgl.glfw.GLFW.GLFW_KEY_H;
import static org.lwjgl.glfw.GLFW.GLFW_KEY_I;
@ -99,6 +100,7 @@ import electrosphere.menu.WindowUtils;
import electrosphere.menu.debug.ImGuiWindowMacros;
import electrosphere.menu.ingame.MenuGeneratorsInGame;
import electrosphere.menu.ingame.MenuGeneratorsInventory;
import electrosphere.renderer.RenderingEngine;
import electrosphere.renderer.ui.elements.Window;
import electrosphere.renderer.ui.events.ClickEvent;
import electrosphere.renderer.ui.events.KeyboardEvent;
@ -112,6 +114,7 @@ import electrosphere.renderer.ui.events.ScrollEvent;
*/
public class ControlHandler {
//main game
public static final String INPUT_CODE_CAMERA_ROTATION = "cameraRotation";
public static final String DATA_STRING_INPUT_CODE_MOVEMENT_FORWARD = "moveForward";
public static final String DATA_STRING_INPUT_CODE_MOVEMENT_BACKWARD = "moveBackward";
@ -134,6 +137,8 @@ public class ControlHandler {
public static final String INPUT_CODE_PLACE_TERRAIN = "placeTerrain";
public static final String INPUT_CODE_REMOVE_TERRAIN = "removeTerrain";
//menu navigation
public static final String DATA_STRING_INPUT_CODE_MENU_NAVIGATE_FORWARD = "menuNavigateForward";
public static final String DATA_STRING_INPUT_CODE_MENU_NAVIGATE_BACKWARDS = "menuNavigateBackwards";
public static final String DATA_STRING_INPUT_CODE_MENU_INCREMENT = "menuIncrement";
@ -145,9 +150,11 @@ public class ControlHandler {
public static final String MENU_SCROLL = "menuScroll";
public static final String MENU_DRAG_MANIPULATE = "menuDragManipulate";
public static final String MENU_DRAG_START = "menuDragStart";
public static final String MENU_CAPTURE_SCREEN = "menuCaptureScreen";
//typing
public static final String DATA_STRING_INPUT_CODE_MENU_TYPE_BACKSPACE = "menuTypeBackspace";
public static final String DATA_STRING_INPUT_CODE_MENU_TYPE_0 = "menuType0";
public static final String DATA_STRING_INPUT_CODE_MENU_TYPE_1 = "menuType1";
@ -188,14 +195,16 @@ public class ControlHandler {
public static final String DATA_STRING_INPUT_CODE_MENU_TYPE_Z = "menuTypeZ";
public static final String INPUT_CODE_MENU_TYPE_FORWARD_SLASH = "menuTypeForwardSlash";
//inventory
public static final String INPUT_CODE_INVENTORY_CLOSE = "inventoryClose";
public static final String INPUT_CODE_INVENTORY_ITEM_MANIPULATE = "inventoryItemManipulate";
public static final String INPUT_CODE_INVENTORY_ITEM_DRAG = "inventoryDrag";
//debug
public static final String DEBUG_FRAMESTEP = "framestep";
public static final String DEBUG_OPEN_DEBUG_MENU = "openDebugMenu";
//freecam
public static final String FREECAM_UP = "freecamUp";
public static final String FREECAM_DOWN = "freecamDown";
public static final String FREECAM_FORWARD = "freecamForward";
@ -295,111 +304,112 @@ public class ControlHandler {
/*
Map the controls
*/
handler.addControl(INPUT_CODE_CAMERA_ROTATION, new Control(ControlType.MOUSE_MOVEMENT,0));
handler.addControl(DATA_STRING_INPUT_CODE_MOVEMENT_FORWARD, new Control(ControlType.KEY,GLFW_KEY_W));
handler.addControl(DATA_STRING_INPUT_CODE_MOVEMENT_BACKWARD, new Control(ControlType.KEY,GLFW_KEY_S));
handler.addControl(DATA_STRING_INPUT_CODE_MOVEMENT_LEFT, new Control(ControlType.KEY,GLFW_KEY_F24));
handler.addControl(DATA_STRING_INPUT_CODE_MOVEMENT_RIGHT, new Control(ControlType.KEY,GLFW_KEY_F24));
handler.addControl(DATA_STRING_INPUT_CODE_STRAFE_LEFT, new Control(ControlType.KEY,GLFW_KEY_A));
handler.addControl(DATA_STRING_INPUT_CODE_STRAFE_RIGHT, new Control(ControlType.KEY,GLFW_KEY_D));
handler.addControl(DATA_STRING_INPUT_CODE_MOVEMENT_JUMP, new Control(ControlType.KEY,GLFW_KEY_SPACE));
handler.addControl(DATA_STRING_INPUT_CODE_MOVEMENT_FALL, new Control(ControlType.KEY,GLFW_KEY_LEFT_CONTROL));
handler.addControl(DATA_STRING_INPUT_CODE_ATTACK_PRIMARY, new Control(ControlType.MOUSE_BUTTON,GLFW_MOUSE_BUTTON_LEFT));
handler.addControl(DATA_STRING_INPUT_CODE_IN_GAME_MAIN_MENU, new Control(ControlType.KEY,GLFW_KEY_ESCAPE));
handler.addControl(DATA_STRING_INPUT_CODE_LOCK_CROSSHAIR, new Control(ControlType.KEY,GLFW_KEY_CAPS_LOCK));
handler.addControl(INPUT_CODE_SPRINT, new Control(ControlType.KEY,GLFW_KEY_LEFT_SHIFT));
handler.addControl(INPUT_CODE_INTERACT, new Control(ControlType.KEY,GLFW_KEY_E));
handler.addControl(INPUT_CODE_DROP, new Control(ControlType.KEY,GLFW_KEY_Y));
handler.addControl(INPUT_CODE_INVENTORY_OPEN, new Control(ControlType.KEY,GLFW_KEY_I));
handler.addControl(INPUT_CODE_CHARACTER_OPEN, new Control(ControlType.KEY,GLFW_KEY_C));
handler.addControl(ITEM_SECONDARY, new Control(ControlType.MOUSE_BUTTON,GLFW_MOUSE_BUTTON_RIGHT));
handler.addControl(INPUT_CODE_CAMERA_ROTATION, new Control(ControlType.MOUSE_MOVEMENT,0,false,"",""));
handler.addControl(DATA_STRING_INPUT_CODE_MOVEMENT_FORWARD, new Control(ControlType.KEY,GLFW_KEY_W,false,"Move Foward","Moves the player forward"));
handler.addControl(DATA_STRING_INPUT_CODE_MOVEMENT_BACKWARD, new Control(ControlType.KEY,GLFW_KEY_S,false,"Move Backward","Moves the player backward"));
handler.addControl(DATA_STRING_INPUT_CODE_MOVEMENT_LEFT, new Control(ControlType.KEY,GLFW_KEY_F24,false,"Move Left","Moves the player left"));
handler.addControl(DATA_STRING_INPUT_CODE_MOVEMENT_RIGHT, new Control(ControlType.KEY,GLFW_KEY_F24,false,"Move Right","Moves the player right"));
handler.addControl(DATA_STRING_INPUT_CODE_STRAFE_LEFT, new Control(ControlType.KEY,GLFW_KEY_A,false,"Strafe Left","Strafes the player left"));
handler.addControl(DATA_STRING_INPUT_CODE_STRAFE_RIGHT, new Control(ControlType.KEY,GLFW_KEY_D,false,"Strafe Right","Strafes the player right"));
handler.addControl(DATA_STRING_INPUT_CODE_MOVEMENT_JUMP, new Control(ControlType.KEY,GLFW_KEY_SPACE,false,"Jump","Jumps"));
handler.addControl(DATA_STRING_INPUT_CODE_MOVEMENT_FALL, new Control(ControlType.KEY,GLFW_KEY_LEFT_CONTROL,false,"Fall","Lowers the camera"));
handler.addControl(DATA_STRING_INPUT_CODE_ATTACK_PRIMARY, new Control(ControlType.MOUSE_BUTTON,GLFW_MOUSE_BUTTON_LEFT,false,"Attack","Attacks"));
handler.addControl(DATA_STRING_INPUT_CODE_IN_GAME_MAIN_MENU, new Control(ControlType.KEY,GLFW_KEY_ESCAPE,false,"Main Menu","Opens the main menu while in game"));
handler.addControl(DATA_STRING_INPUT_CODE_LOCK_CROSSHAIR, new Control(ControlType.KEY,GLFW_KEY_CAPS_LOCK,false,"Lock On","Locks the camera onto the target"));
handler.addControl(INPUT_CODE_SPRINT, new Control(ControlType.KEY,GLFW_KEY_LEFT_SHIFT,false,"Sprint (hold)","Causes the player to sprint"));
handler.addControl(INPUT_CODE_INTERACT, new Control(ControlType.KEY,GLFW_KEY_E,false,"Interact","Interacts with whatever is targeted currently"));
handler.addControl(INPUT_CODE_DROP, new Control(ControlType.KEY,GLFW_KEY_Y,false,"Drop","Drops the currently equipped item"));
handler.addControl(INPUT_CODE_INVENTORY_OPEN, new Control(ControlType.KEY,GLFW_KEY_I,false,"Inventory","Opens the player's inventory"));
handler.addControl(INPUT_CODE_CHARACTER_OPEN, new Control(ControlType.KEY,GLFW_KEY_C,false,"Equip Menu","Opens the player's equipment menu"));
handler.addControl(ITEM_SECONDARY, new Control(ControlType.MOUSE_BUTTON,GLFW_MOUSE_BUTTON_RIGHT,false,"Secondary","Uses the secondary equipped item"));
/*
Map the menu navigation controls
*/
handler.addControl(DATA_STRING_INPUT_CODE_MENU_NAVIGATE_FORWARD, new Control(ControlType.KEY,GLFW_KEY_DOWN));
handler.addControl(DATA_STRING_INPUT_CODE_MENU_NAVIGATE_BACKWARDS, new Control(ControlType.KEY,GLFW_KEY_UP));
handler.addControl(DATA_STRING_INPUT_CODE_MENU_INCREMENT, new Control(ControlType.KEY,GLFW_KEY_RIGHT));
handler.addControl(DATA_STRING_INPUT_CODE_MENU_DECREMENT, new Control(ControlType.KEY,GLFW_KEY_LEFT));
handler.addControl(DATA_STRING_INPUT_CODE_MENU_SELECT, new Control(ControlType.KEY,GLFW_KEY_ENTER));
handler.addControl(DATA_STRING_INPUT_CODE_MENU_BACKOUT, new Control(ControlType.KEY,GLFW_KEY_ESCAPE));
handler.addControl(MENU_MOUSE_MOVE, new Control(ControlType.MOUSE_MOVEMENT,0));
handler.addControl(INPUT_CODE_MENU_MOUSE_PRIMARY, new Control(ControlType.MOUSE_BUTTON,GLFW_MOUSE_BUTTON_LEFT));
handler.addControl(MENU_SCROLL, new Control(ControlType.MOUSE_SCROLL,0));
handler.addControl(MENU_DRAG_START, new Control(ControlType.MOUSE_MOVEMENT,0));
handler.addControl(MENU_DRAG_MANIPULATE, new Control(ControlType.MOUSE_BUTTON,GLFW_MOUSE_BUTTON_1));
handler.addControl(DATA_STRING_INPUT_CODE_MENU_NAVIGATE_FORWARD, new Control(ControlType.KEY,GLFW_KEY_DOWN,false,"",""));
handler.addControl(DATA_STRING_INPUT_CODE_MENU_NAVIGATE_BACKWARDS, new Control(ControlType.KEY,GLFW_KEY_UP,false,"",""));
handler.addControl(DATA_STRING_INPUT_CODE_MENU_INCREMENT, new Control(ControlType.KEY,GLFW_KEY_RIGHT,false,"",""));
handler.addControl(DATA_STRING_INPUT_CODE_MENU_DECREMENT, new Control(ControlType.KEY,GLFW_KEY_LEFT,false,"",""));
handler.addControl(DATA_STRING_INPUT_CODE_MENU_SELECT, new Control(ControlType.KEY,GLFW_KEY_ENTER,false,"",""));
handler.addControl(DATA_STRING_INPUT_CODE_MENU_BACKOUT, new Control(ControlType.KEY,GLFW_KEY_ESCAPE,false,"",""));
handler.addControl(MENU_MOUSE_MOVE, new Control(ControlType.MOUSE_MOVEMENT,0,false,"",""));
handler.addControl(INPUT_CODE_MENU_MOUSE_PRIMARY, new Control(ControlType.MOUSE_BUTTON,GLFW_MOUSE_BUTTON_LEFT,false,"",""));
handler.addControl(MENU_SCROLL, new Control(ControlType.MOUSE_SCROLL,0,false,"",""));
handler.addControl(MENU_DRAG_START, new Control(ControlType.MOUSE_MOVEMENT,0,false,"",""));
handler.addControl(MENU_CAPTURE_SCREEN, new Control(ControlType.KEY,GLFW_KEY_F4,true,"Screenshot","Takes a screenshot of the engine"));
handler.addControl(MENU_DRAG_MANIPULATE, new Control(ControlType.MOUSE_BUTTON,GLFW_MOUSE_BUTTON_1,false,"",""));
/*
Map the typing controls
*/
handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_BACKSPACE, new Control(ControlType.KEY,GLFW_KEY_BACKSPACE));
handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_0, new Control(ControlType.KEY,GLFW_KEY_0));
handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_1, new Control(ControlType.KEY,GLFW_KEY_1));
handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_2, new Control(ControlType.KEY,GLFW_KEY_2));
handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_3, new Control(ControlType.KEY,GLFW_KEY_3));
handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_4, new Control(ControlType.KEY,GLFW_KEY_4));
handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_5, new Control(ControlType.KEY,GLFW_KEY_5));
handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_6, new Control(ControlType.KEY,GLFW_KEY_6));
handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_7, new Control(ControlType.KEY,GLFW_KEY_7));
handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_8, new Control(ControlType.KEY,GLFW_KEY_8));
handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_9, new Control(ControlType.KEY,GLFW_KEY_9));
handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_PERIOD, new Control(ControlType.KEY,GLFW_KEY_PERIOD));
handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_A, new Control(ControlType.KEY,GLFW_KEY_A));
handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_B, new Control(ControlType.KEY,GLFW_KEY_B));
handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_C, new Control(ControlType.KEY,GLFW_KEY_C));
handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_D, new Control(ControlType.KEY,GLFW_KEY_D));
handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_E, new Control(ControlType.KEY,GLFW_KEY_E));
handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_F, new Control(ControlType.KEY,GLFW_KEY_F));
handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_G, new Control(ControlType.KEY,GLFW_KEY_G));
handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_H, new Control(ControlType.KEY,GLFW_KEY_H));
handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_I, new Control(ControlType.KEY,GLFW_KEY_I));
handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_J, new Control(ControlType.KEY,GLFW_KEY_J));
handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_K, new Control(ControlType.KEY,GLFW_KEY_K));
handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_L, new Control(ControlType.KEY,GLFW_KEY_L));
handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_M, new Control(ControlType.KEY,GLFW_KEY_M));
handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_N, new Control(ControlType.KEY,GLFW_KEY_N));
handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_O, new Control(ControlType.KEY,GLFW_KEY_O));
handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_P, new Control(ControlType.KEY,GLFW_KEY_P));
handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_Q, new Control(ControlType.KEY,GLFW_KEY_Q));
handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_R, new Control(ControlType.KEY,GLFW_KEY_R));
handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_S, new Control(ControlType.KEY,GLFW_KEY_S));
handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_T, new Control(ControlType.KEY,GLFW_KEY_T));
handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_U, new Control(ControlType.KEY,GLFW_KEY_U));
handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_V, new Control(ControlType.KEY,GLFW_KEY_V));
handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_W, new Control(ControlType.KEY,GLFW_KEY_W));
handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_X, new Control(ControlType.KEY,GLFW_KEY_X));
handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_Y, new Control(ControlType.KEY,GLFW_KEY_Y));
handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_Z, new Control(ControlType.KEY,GLFW_KEY_Z));
handler.addControl(INPUT_CODE_MENU_TYPE_FORWARD_SLASH, new Control(ControlType.KEY,GLFW_KEY_SLASH));
handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_BACKSPACE, new Control(ControlType.KEY,GLFW_KEY_BACKSPACE,false,"",""));
handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_0, new Control(ControlType.KEY,GLFW_KEY_0,false,"",""));
handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_1, new Control(ControlType.KEY,GLFW_KEY_1,false,"",""));
handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_2, new Control(ControlType.KEY,GLFW_KEY_2,false,"",""));
handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_3, new Control(ControlType.KEY,GLFW_KEY_3,false,"",""));
handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_4, new Control(ControlType.KEY,GLFW_KEY_4,false,"",""));
handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_5, new Control(ControlType.KEY,GLFW_KEY_5,false,"",""));
handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_6, new Control(ControlType.KEY,GLFW_KEY_6,false,"",""));
handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_7, new Control(ControlType.KEY,GLFW_KEY_7,false,"",""));
handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_8, new Control(ControlType.KEY,GLFW_KEY_8,false,"",""));
handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_9, new Control(ControlType.KEY,GLFW_KEY_9,false,"",""));
handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_PERIOD, new Control(ControlType.KEY,GLFW_KEY_PERIOD,false,"",""));
handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_A, new Control(ControlType.KEY,GLFW_KEY_A,false,"",""));
handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_B, new Control(ControlType.KEY,GLFW_KEY_B,false,"",""));
handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_C, new Control(ControlType.KEY,GLFW_KEY_C,false,"",""));
handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_D, new Control(ControlType.KEY,GLFW_KEY_D,false,"",""));
handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_E, new Control(ControlType.KEY,GLFW_KEY_E,false,"",""));
handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_F, new Control(ControlType.KEY,GLFW_KEY_F,false,"",""));
handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_G, new Control(ControlType.KEY,GLFW_KEY_G,false,"",""));
handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_H, new Control(ControlType.KEY,GLFW_KEY_H,false,"",""));
handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_I, new Control(ControlType.KEY,GLFW_KEY_I,false,"",""));
handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_J, new Control(ControlType.KEY,GLFW_KEY_J,false,"",""));
handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_K, new Control(ControlType.KEY,GLFW_KEY_K,false,"",""));
handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_L, new Control(ControlType.KEY,GLFW_KEY_L,false,"",""));
handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_M, new Control(ControlType.KEY,GLFW_KEY_M,false,"",""));
handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_N, new Control(ControlType.KEY,GLFW_KEY_N,false,"",""));
handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_O, new Control(ControlType.KEY,GLFW_KEY_O,false,"",""));
handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_P, new Control(ControlType.KEY,GLFW_KEY_P,false,"",""));
handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_Q, new Control(ControlType.KEY,GLFW_KEY_Q,false,"",""));
handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_R, new Control(ControlType.KEY,GLFW_KEY_R,false,"",""));
handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_S, new Control(ControlType.KEY,GLFW_KEY_S,false,"",""));
handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_T, new Control(ControlType.KEY,GLFW_KEY_T,false,"",""));
handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_U, new Control(ControlType.KEY,GLFW_KEY_U,false,"",""));
handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_V, new Control(ControlType.KEY,GLFW_KEY_V,false,"",""));
handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_W, new Control(ControlType.KEY,GLFW_KEY_W,false,"",""));
handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_X, new Control(ControlType.KEY,GLFW_KEY_X,false,"",""));
handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_Y, new Control(ControlType.KEY,GLFW_KEY_Y,false,"",""));
handler.addControl(DATA_STRING_INPUT_CODE_MENU_TYPE_Z, new Control(ControlType.KEY,GLFW_KEY_Z,false,"",""));
handler.addControl(INPUT_CODE_MENU_TYPE_FORWARD_SLASH, new Control(ControlType.KEY,GLFW_KEY_SLASH,false,"",""));
/*
Inventory controls
*/
handler.addControl(INPUT_CODE_INVENTORY_CLOSE, new Control(ControlType.KEY,GLFW_KEY_I));
handler.addControl(INPUT_CODE_INVENTORY_ITEM_MANIPULATE, new Control(ControlType.MOUSE_BUTTON,GLFW_MOUSE_BUTTON_1));
handler.addControl(INPUT_CODE_INVENTORY_ITEM_DRAG, new Control(ControlType.MOUSE_MOVEMENT,0));
handler.addControl(INPUT_CODE_INVENTORY_CLOSE, new Control(ControlType.KEY,GLFW_KEY_I,false,"",""));
handler.addControl(INPUT_CODE_INVENTORY_ITEM_MANIPULATE, new Control(ControlType.MOUSE_BUTTON,GLFW_MOUSE_BUTTON_1,false,"",""));
handler.addControl(INPUT_CODE_INVENTORY_ITEM_DRAG, new Control(ControlType.MOUSE_MOVEMENT,0,false,"",""));
/**
Terrain controls
*/
handler.addControl(INPUT_CODE_PLACE_TERRAIN, new Control(ControlType.KEY,GLFW_KEY_T));
handler.addControl(INPUT_CODE_REMOVE_TERRAIN, new Control(ControlType.KEY,GLFW_KEY_Y));
handler.addControl(INPUT_CODE_PLACE_TERRAIN, new Control(ControlType.KEY,GLFW_KEY_T,false,"Place Terrain","Places terrain"));
handler.addControl(INPUT_CODE_REMOVE_TERRAIN, new Control(ControlType.KEY,GLFW_KEY_Y,false,"Remove Terrain","Removes terrain"));
/*
framestep controls
*/
handler.addControl(DEBUG_FRAMESTEP, new Control(ControlType.KEY, GLFW_KEY_P));
handler.addControl(DEBUG_FRAMESTEP, new Control(ControlType.KEY, GLFW_KEY_P,false,"Framesetp","Steps the engine forward one frame"));
/*
* Free camera
*/
handler.addControl(FREECAM_UP, new Control(ControlType.KEY,GLFW_KEY_SPACE));
handler.addControl(FREECAM_DOWN, new Control(ControlType.KEY,GLFW_KEY_LEFT_CONTROL));
handler.addControl(FREECAM_FORWARD, new Control(ControlType.KEY,GLFW_KEY_W));
handler.addControl(FREECAM_BACKWARD, new Control(ControlType.KEY,GLFW_KEY_S));
handler.addControl(FREECAM_LEFT, new Control(ControlType.KEY,GLFW_KEY_A));
handler.addControl(FREECAM_RIGHT, new Control(ControlType.KEY,GLFW_KEY_D));
handler.addControl(FREECAM_MOUSE, new Control(ControlType.MOUSE_MOVEMENT,0));
handler.addControl(FREECAM_UP, new Control(ControlType.KEY,GLFW_KEY_SPACE,false,"Up","Moves the camera up"));
handler.addControl(FREECAM_DOWN, new Control(ControlType.KEY,GLFW_KEY_LEFT_CONTROL,false,"Down","Moves the camera down"));
handler.addControl(FREECAM_FORWARD, new Control(ControlType.KEY,GLFW_KEY_W,false,"Forward","Moves the camera forward"));
handler.addControl(FREECAM_BACKWARD, new Control(ControlType.KEY,GLFW_KEY_S,false,"Backward","Moves the camera backward"));
handler.addControl(FREECAM_LEFT, new Control(ControlType.KEY,GLFW_KEY_A,false,"Left","Moves the camera left"));
handler.addControl(FREECAM_RIGHT, new Control(ControlType.KEY,GLFW_KEY_D,false,"Right","Moves the camera right"));
handler.addControl(FREECAM_MOUSE, new Control(ControlType.MOUSE_MOVEMENT,0,false,"",""));
/*
@ -410,8 +420,8 @@ public class ControlHandler {
/*
Debug controls
*/
handler.addControl(DATA_STRING_INPUT_CODE_DEBUG_SPAWN_ITEM, new Control(ControlType.KEY,GLFW_KEY_Q));
handler.addControl(DEBUG_OPEN_DEBUG_MENU, new Control(ControlType.KEY, GLFW_KEY_F2));
handler.addControl(DATA_STRING_INPUT_CODE_DEBUG_SPAWN_ITEM, new Control(ControlType.KEY,GLFW_KEY_Q,false,"",""));
handler.addControl(DEBUG_OPEN_DEBUG_MENU, new Control(ControlType.KEY, GLFW_KEY_F2,false,"Debug Menu","Opens the debug menu"));
/*
return
@ -946,7 +956,9 @@ public class ControlHandler {
Globals.elementManager.focusFirstElement();
Globals.controlHandler.hintUpdateControlState(ControlsState.IN_GAME_MAIN_MENU);
//play sound effect
Globals.virtualAudioSourceManager.createVirtualAudioSource("/Audio/openMenu.ogg", VirtualAudioSourceType.UI, false);
if(Globals.virtualAudioSourceManager != null){
Globals.virtualAudioSourceManager.createVirtualAudioSource("/Audio/openMenu.ogg", VirtualAudioSourceType.UI, false);
}
}});
controls.get(DATA_STRING_INPUT_CODE_IN_GAME_MAIN_MENU).setRepeatTimeout(0.5f * Main.targetFrameRate);
@ -967,7 +979,9 @@ public class ControlHandler {
//controls
Globals.controlHandler.hintUpdateControlState(ControlsState.INVENTORY);
//play sound effect
Globals.virtualAudioSourceManager.createVirtualAudioSource("/Audio/openMenu.ogg", VirtualAudioSourceType.UI, false);
if(Globals.virtualAudioSourceManager != null){
Globals.virtualAudioSourceManager.createVirtualAudioSource("/Audio/openMenu.ogg", VirtualAudioSourceType.UI, false);
}
//
Globals.openInventoriesCount++;
} else if(InventoryUtils.hasNaturalInventory(Globals.playerEntity) && Globals.elementManager.getWindow(WindowUtils.getInventoryWindowID(InventoryUtils.getNaturalInventory(Globals.playerEntity).getId())) != null){
@ -992,7 +1006,9 @@ public class ControlHandler {
//controls
Globals.controlHandler.hintUpdateControlState(ControlsState.INVENTORY);
//play sound effect
Globals.virtualAudioSourceManager.createVirtualAudioSource("/Audio/openMenu.ogg", VirtualAudioSourceType.UI, false);
if(Globals.virtualAudioSourceManager != null){
Globals.virtualAudioSourceManager.createVirtualAudioSource("/Audio/openMenu.ogg", VirtualAudioSourceType.UI, false);
}
//
Globals.openInventoriesCount++;
} else if(InventoryUtils.hasEquipInventory(Globals.playerEntity) && Globals.elementManager.getWindow(WindowStrings.WINDOW_CHARACTER) != null){
@ -1095,7 +1111,9 @@ public class ControlHandler {
LoggerInterface.loggerEngine.INFO("open debug menu");
ImGuiWindowMacros.toggleMainDebugMenu();
//play sound effect
Globals.virtualAudioSourceManager.createVirtualAudioSource("/Audio/openMenu.ogg", VirtualAudioSourceType.UI, false);
if(Globals.virtualAudioSourceManager != null){
Globals.virtualAudioSourceManager.createVirtualAudioSource("/Audio/openMenu.ogg", VirtualAudioSourceType.UI, false);
}
}});
controls.get(DEBUG_OPEN_DEBUG_MENU).setRepeatTimeout(0.5f * Main.targetFrameRate);
}
@ -1172,6 +1190,14 @@ public class ControlHandler {
}
}});
/**
Screenshots
*/
menuNavigationControlList.add(controls.get(MENU_CAPTURE_SCREEN));
controls.get(MENU_CAPTURE_SCREEN).setOnPress(new Control.ControlMethod() {public void execute(){
RenderingEngine.screenFramebuffer.getPixels(Globals.renderingEngine.getOpenGLState());
}});
@ -1424,6 +1450,14 @@ public class ControlHandler {
}});
}
/**
* Gets the main controls list
* @return The main controls
*/
public List<Control> getMainControlsList(){
return mainGameControlList;
}
/**
* Checks a list of controls to see if the corresponding key/mouse event is firing this frame

View File

@ -140,6 +140,8 @@ public class Globals {
public static ClientNetworking clientConnection;
public static boolean RUN_DEMO = false;
public static boolean RUN_CLIENT = true;
public static boolean RUN_HIDDEN = false; //glfw session will be created with hidden window
public static boolean RUN_AUDIO = false;
public static int clientCharacterID;
//
@ -444,7 +446,6 @@ public class Globals {
elementManager = new ElementManager();
//script engine
scriptEngine = new ScriptEngine();
scriptEngine.init();
//ai manager
aiManager = new AIManager();
//realm & data cell manager

View File

@ -76,6 +76,9 @@ public class Main {
//init global variables
Globals.initGlobals();
//init scripting engine
Globals.scriptEngine.init();
//controls
if(Globals.RUN_CLIENT){
initControlHandler();
@ -179,7 +182,7 @@ public class Main {
// }
//create the audio context
if(Globals.RUN_CLIENT && !Globals.HEADLESS){
if(Globals.RUN_CLIENT && !Globals.HEADLESS && Globals.RUN_AUDIO){
Globals.virtualAudioSourceManager = new VirtualAudioSourceManager();
Globals.audioEngine = new AudioEngine();
Globals.audioEngine.init();
@ -425,7 +428,7 @@ public class Main {
}
}
//shut down audio engine
if(!Globals.HEADLESS && Globals.RUN_CLIENT){
if(!Globals.HEADLESS && Globals.RUN_CLIENT && Globals.RUN_AUDIO){
Globals.audioEngine.shutdown();
}
//if netmonitor is running, close

View File

@ -62,7 +62,9 @@ public class InitialAssetLoading implements Runnable {
int offY = iterator / VoxelTextureAtlas.ELEMENTS_PER_ROW;
try {
BufferedImage newType = ImageIO.read(FileUtils.getAssetFile(type.getTexture()));
graphics.drawImage(newType, iterator * VoxelTextureAtlas.ATLAS_ELEMENT_DIM * offX, VoxelTextureAtlas.ATLAS_DIM - VoxelTextureAtlas.ATLAS_ELEMENT_DIM - iterator * VoxelTextureAtlas.ATLAS_ELEMENT_DIM * offY, null);
int drawX = VoxelTextureAtlas.ATLAS_ELEMENT_DIM * offX;
int drawY = VoxelTextureAtlas.ATLAS_DIM - VoxelTextureAtlas.ATLAS_ELEMENT_DIM - VoxelTextureAtlas.ATLAS_ELEMENT_DIM * offY;
graphics.drawImage(newType, drawX, drawY, null);
} catch (IOException e) {
LoggerInterface.loggerRenderer.ERROR("Texture atlas failed to find texture " + type.getTexture(), e);
}

View File

@ -56,10 +56,11 @@ public class SceneLoader {
}
}
//load scripts
for(String scriptPath : file.getScriptPaths()){
Globals.scriptEngine.loadScript(scriptPath);
}
Globals.scriptEngine.runScript(file.getInitScriptPath());
//TODO: integrate scripts for client side of scenes
// for(String scriptPath : file.getScriptPaths()){
// Globals.scriptEngine.loadScript(scriptPath);
// }
// Globals.scriptEngine.runScript(file.getInitScriptPath());
return rVal;
}

View File

@ -41,6 +41,15 @@ public class HitboxCollectionState {
BLOCK, // blocks a hit from another entity
}
/**
* The subtype of hitbox
*/
public enum HitboxSubtype {
SWEET, //extra damage
REGULAR, //regular damage
SOUR, //less damage
}
//the parent entity of the hitbox state
Entity parent;
@ -86,6 +95,9 @@ public class HitboxCollectionState {
DGeom geom = null;
HitboxType type = HitboxType.HIT;
HitboxShapeType shapeType = HitboxShapeType.SPHERE;
//
//Get the type as an enum
//
switch(hitboxDataRaw.getType()){
case HitboxData.HITBOX_TYPE_HIT: {
type = HitboxType.HIT;
@ -113,11 +125,34 @@ public class HitboxCollectionState {
geom = CollisionBodyCreation.createCapsuleShape(manager.getCollisionEngine(), hitboxDataRaw.getRadius(), hitboxDataRaw.getLength(), Collidable.TYPE_OBJECT_BIT);
} break;
}
//
//Get the subtype as an enum
//
HitboxSubtype subType;
String subTypeRaw = hitboxDataRaw.getSubType();
if(subTypeRaw == null){
subTypeRaw = HitboxData.HITBOX_SUBTYPE_REUGLAR;
}
switch(subTypeRaw){
case HitboxData.HITBOX_SUBTYPE_SWEET: {
subType = HitboxSubtype.SWEET;
} break;
case HitboxData.HITBOX_SUBTYPE_REUGLAR: {
subType = HitboxSubtype.REGULAR;
} break;
case HitboxData.HITBOX_SUBTYPE_SOUR: {
subType = HitboxSubtype.SOUR;
} break;
default: {
subType = HitboxSubtype.REGULAR;
} break;
}
if(hitboxDataRaw.getBone() != null){
rVal.hitboxGeomMap.put(hitboxDataRaw.getBone(),geom);
}
rVal.geoms.add(geom);
rVal.geomStateMap.put(geom,new HitboxState(hitboxDataRaw.getBone(), hitboxDataRaw, type, shapeType, true));
rVal.geomStateMap.put(geom,new HitboxState(hitboxDataRaw.getBone(), hitboxDataRaw, type, subType, shapeType, true));
}
//create body with all the shapes
@ -310,7 +345,7 @@ public class HitboxCollectionState {
worldPosition = worldPosition.rotate(rotation);
worldPosition.add(new Vector3f((float)parentPos.x,(float)parentPos.y,(float)parentPos.z));
double length = shapeStatus.getHitboxData().getRadius();
double radius = shapeStatus.getHitboxData().getRadius();
// double radius = shapeStatus.getHitboxData().getRadius();
if(previousWorldPos != null){
//called all subsequent updates to hitbox position
@ -461,6 +496,9 @@ public class HitboxCollectionState {
//the type of hitbox
HitboxType type;
//the subtype
HitboxSubtype subType;
//the type of geometry
HitboxShapeType shapeType;
@ -481,13 +519,15 @@ public class HitboxCollectionState {
* @param boneName The name of the bone the hitbox is attached to, if any
* @param data the hitbox data object
* @param type The type of hitbox
* @param subType The subtype of hitbox
* @param shapeType The type of shape the hitbox is
* @param isActive if the hitbox is active or not
*/
public HitboxState(String boneName, HitboxData data, HitboxType type, HitboxShapeType shapeType, boolean isActive){
public HitboxState(String boneName, HitboxData data, HitboxType type, HitboxSubtype subType, HitboxShapeType shapeType, boolean isActive){
this.boneName = boneName;
this.data = data;
this.type = type;
this.subType = subType;
this.shapeType = shapeType;
this.isActive = isActive;
}
@ -540,6 +580,22 @@ public class HitboxCollectionState {
this.type = type;
}
/**
* Gets the subtype of the hitbox
* @return The subtype
*/
public HitboxSubtype getSubType(){
return subType;
}
/**
* Sets the subtype of the hitbox
* @param subType The subtype
*/
public void setSubType(HitboxSubtype subType){
this.subType = subType;
}
/**
* Gets whether the hitbox is active or not
* @return true if active, false otherwise

View File

@ -21,12 +21,23 @@ public class HitboxData {
//a block sphere that is connected to its previous position by a capsule. The capsule is used for collision checks
public static final String HITBOX_TYPE_BLOCK_CONNECTED = "block_connected";
//a hitbox with extra effect (ie more damage)
public static final String HITBOX_SUBTYPE_SWEET = "sweet";
//a hitbox with normal effect
public static final String HITBOX_SUBTYPE_REUGLAR = "regular";
//a hitbox with less effect (ie reduced damange)
public static final String HITBOX_SUBTYPE_SOUR = "sour";
//used for debugging -- to show whether a hitbox is colliding with it or not
public static final String HITBOX_TYPE_STATIC_CAPSULE = "static_capsule";
//the type of hitbox
String type;
//the subtype of hitbox (ie, sweetspot, sour spot, critical spot, armor spot, etc)
String subType;
//the bone it is attached to
String bone;
@ -53,6 +64,14 @@ public class HitboxData {
return type;
}
/**
* Gets the subtype of the hitbox
* @return the subtype of hitbox
*/
public String getSubType() {
return subType;
}
/**
* Gets the type of bone
* @return the type of bone
@ -101,10 +120,26 @@ public class HitboxData {
this.bone = bone;
}
/**
* Sets the type of the hitbox
* @param type the type
*/
public void setType(String type) {
this.type = type;
}
/**
* Sets the subtype of the hitbox
* @param subType the subtype
*/
public void setSubType(String subType) {
this.subType = subType;
}
/**
* Sets the radius of the hitbox
* @param radius The radius
*/
public void setRadius(float radius) {
this.radius = radius;
}

View File

@ -1,5 +1,7 @@
package electrosphere.logger;
import org.graalvm.polyglot.HostAccess.Export;
/**
* A channel for logging messages
*/
@ -44,6 +46,7 @@ public class Logger {
* This should be used for debugging messages that are executed on a given condition that won't necessarily be every loop (ie all network messages)
* @param message The message to report
*/
@Export
public void DEBUG(String message){
if(level == LogLevel.LOOP_DEBUG || level == LogLevel.DEBUG){
System.out.println(message);
@ -56,6 +59,7 @@ public class Logger {
* This should be used for messages that would have interest to someone running a server (ie specific network messages, account creation, etc)
* @param message The message to report
*/
@Export
public void INFO(String message){
if(level == LogLevel.LOOP_DEBUG || level == LogLevel.DEBUG || level == LogLevel.INFO){
System.out.println(message);
@ -68,6 +72,7 @@ public class Logger {
* This should be used for reporting events that happen in the engine that are concerning but don't mean the engine has failed to execute (ie a texture failed to load)
* @param message The message to report
*/
@Export
public void WARNING(String message){
if(level == LogLevel.LOOP_DEBUG || level == LogLevel.DEBUG || level == LogLevel.INFO || level == LogLevel.WARNING){
System.out.println(message);
@ -83,6 +88,17 @@ public class Logger {
public void ERROR(String message, Exception e){
if(level == LogLevel.LOOP_DEBUG || level == LogLevel.DEBUG || level == LogLevel.INFO || level == LogLevel.WARNING || level == LogLevel.ERROR){
System.err.println(message);
ERROR(e);
}
}
/**
* Logs an error message.
* This should be used every time we throw any kind of error in the engine
* @param e The exception to report
*/
public void ERROR(Exception e){
if(level == LogLevel.LOOP_DEBUG || level == LogLevel.DEBUG || level == LogLevel.INFO || level == LogLevel.WARNING || level == LogLevel.ERROR){
e.printStackTrace();
}
}

View File

@ -20,6 +20,7 @@ public class LoggerInterface {
public static Logger loggerDB;
public static Logger loggerAudio;
public static Logger loggerUI;
public static Logger loggerScripts;
/**
* Initializes all logic objects
@ -35,6 +36,7 @@ public class LoggerInterface {
loggerDB = new Logger(LogLevel.WARNING);
loggerAudio = new Logger(LogLevel.WARNING);
loggerUI = new Logger(LogLevel.WARNING);
loggerScripts = new Logger(LogLevel.WARNING);
loggerStartup.INFO("Initialized loggers");
}
}

View File

@ -16,6 +16,7 @@ import electrosphere.entity.types.camera.CameraEntityUtils;
import electrosphere.entity.types.creature.CreatureUtils;
import electrosphere.game.data.creature.type.CreatureType;
import electrosphere.game.data.creature.type.visualattribute.VisualAttribute;
import electrosphere.menu.mainmenu.MenuGeneratorsKeybind;
import electrosphere.menu.mainmenu.MenuGeneratorsTitleMenu;
import electrosphere.net.NetUtils;
import electrosphere.renderer.RenderingEngine;
@ -34,6 +35,7 @@ import electrosphere.renderer.ui.elements.Slider;
import electrosphere.renderer.ui.elements.TextInput;
import electrosphere.renderer.ui.elements.Window;
import electrosphere.renderer.ui.elementtypes.ClickableElement;
import electrosphere.renderer.ui.elementtypes.ClickableElement.ClickEventCallback;
import electrosphere.renderer.ui.elementtypes.Element;
import electrosphere.renderer.ui.elementtypes.NavigableElement.NavigationEventCallback;
import electrosphere.renderer.ui.elementtypes.ValueElement.ValueChangeEventCallback;
@ -353,6 +355,13 @@ public class MenuGenerators {
return false;
}});
//button to open rebind controls window
Button rebindControlsButton = Button.createButton("Controls", new ClickEventCallback() {public boolean execute(ClickEvent event) {
WindowUtils.replaceMainMenuContents(MenuGeneratorsKeybind.createControlsRebindMenu());
return false;
}});
rVal.addChild(rebindControlsButton);
return rVal;
}

View File

@ -156,7 +156,7 @@ public class WindowUtils {
}
static void initLoadingWindow(){
Window loadingWindow = new Window(0, 0, Globals.WINDOW_WIDTH, Globals.WINDOW_HEIGHT,false);
Window loadingWindow = new Window(Globals.renderingEngine.getOpenGLState(), 0, 0, Globals.WINDOW_WIDTH, Globals.WINDOW_HEIGHT,false);
Label loadingLabel = new Label(1.0f);
loadingLabel.setText("LOADING");
loadingWindow.addChild(loadingLabel);
@ -166,7 +166,7 @@ public class WindowUtils {
}
static void initMainMenuWindow(){
Window mainMenuWindow = new Window(0, 0, Globals.WINDOW_WIDTH, Globals.WINDOW_HEIGHT,false);
Window mainMenuWindow = new Window(Globals.renderingEngine.getOpenGLState(), 0, 0, Globals.WINDOW_WIDTH, Globals.WINDOW_HEIGHT,false);
Globals.elementManager.registerWindow(WindowStrings.WINDOW_MENU_MAIN, mainMenuWindow);
WindowUtils.replaceMainMenuContents(MenuGeneratorsTitleMenu.createTitleMenu());
}
@ -176,7 +176,7 @@ public class WindowUtils {
}
static void initItemDragContainerWindow(){
Window itemDragContainerWindow = new Window(0,0,Globals.WINDOW_WIDTH,Globals.WINDOW_HEIGHT,false);
Window itemDragContainerWindow = new Window(Globals.renderingEngine.getOpenGLState(), 0,0,Globals.WINDOW_WIDTH,Globals.WINDOW_HEIGHT,false);
Globals.elementManager.registerWindow(WindowStrings.WINDOW_ITEM_DRAG_CONTAINER, itemDragContainerWindow);
}

View File

@ -43,7 +43,7 @@ public class MenuGeneratorsInGame {
// int screenTop = Globals.WINDOW_HEIGHT - 150;
int width = 500;
int height = 500;
Window rVal = new Window(0,0,width,height,true);
Window rVal = new Window(Globals.renderingEngine.getOpenGLState(),0,0,width,height,true);
// int screenLeft = (Globals.WINDOW_WIDTH - width)/2;
Div div = new Div();
rVal.addChild(div);
@ -143,7 +143,7 @@ public class MenuGeneratorsInGame {
int width = 500;
int height = 500;
float fontSize = 1.0f;
Window rVal = new Window(0,0,width,height,true);
Window rVal = new Window(Globals.renderingEngine.getOpenGLState(),0,0,width,height,true);
// int screenLeft = (Globals.WINDOW_WIDTH - width)/2;
// Div div = new Div();
// div.setPositionX(0);
@ -340,14 +340,14 @@ public class MenuGeneratorsInGame {
int width = 500;
int height = 500;
float fontSize = 0.4f;
Window rVal = new Window(0,0,width,height,true);
Window rVal = new Window(Globals.renderingEngine.getOpenGLState(),0,0,width,height,true);
// int screenLeft = (Globals.WINDOW_WIDTH - width)/2;
// Div div = new Div();
// div.setPositionX(0);
// div.setPositionY(0);
// div.setWidth(500);
// div.setHeight(500);
ScrollableContainer scrollable = new ScrollableContainer(0, 0, width, height);
ScrollableContainer scrollable = new ScrollableContainer(Globals.renderingEngine.getOpenGLState(), 0, 0, width, height);
rVal.addChild(scrollable);
// scrollable.addChild(div);
rVal.setOnNavigationCallback(new NavigationEventCallback() {public boolean execute(NavigationEvent event){

View File

@ -34,7 +34,7 @@ public class MenuGeneratorsInventory {
int width = 500;
int height = 500;
Window rVal = new Window(0,0,width,height,true);
Window rVal = new Window(Globals.renderingEngine.getOpenGLState(),0,0,width,height,true);
rVal.setParentAlignItem(Yoga.YGAlignCenter);
rVal.setParentJustifyContent(Yoga.YGJustifyCenter);
@ -53,7 +53,9 @@ public class MenuGeneratorsInventory {
Globals.controlHandler.hintUpdateControlState(ControlsState.MAIN_GAME);
}
//play sound effect
Globals.virtualAudioSourceManager.createVirtualAudioSource("/Audio/closeMenu.ogg", VirtualAudioSourceType.UI, false);
if(Globals.virtualAudioSourceManager != null){
Globals.virtualAudioSourceManager.createVirtualAudioSource("/Audio/closeMenu.ogg", VirtualAudioSourceType.UI, false);
}
return false;
}});
@ -136,7 +138,9 @@ public class MenuGeneratorsInventory {
container.removeChild(panel);
WindowUtils.pushItemIconToItemWindow(panel);
//play sound effect
Globals.virtualAudioSourceManager.createVirtualAudioSource("/Audio/inventoryGrabItem.ogg", VirtualAudioSourceType.UI, false);
if(Globals.virtualAudioSourceManager != null){
Globals.virtualAudioSourceManager.createVirtualAudioSource("/Audio/inventoryGrabItem.ogg", VirtualAudioSourceType.UI, false);
}
return false;
}});
panel.setOnDrag(new DragEventCallback() {public boolean execute(DragEvent event){
@ -179,7 +183,9 @@ public class MenuGeneratorsInventory {
//re-render inventory
WindowUtils.replaceWindow(WindowUtils.getInventoryWindowID(inventory.getId()), MenuGeneratorsInventory.createNaturalInventoryMenu(inventory));
//play sound effect
Globals.virtualAudioSourceManager.createVirtualAudioSource("/Audio/inventorySlotItem.ogg", VirtualAudioSourceType.UI, false);
if(Globals.virtualAudioSourceManager != null){
Globals.virtualAudioSourceManager.createVirtualAudioSource("/Audio/inventorySlotItem.ogg", VirtualAudioSourceType.UI, false);
}
}
//now the fun begins :)
//if transfer item
@ -211,7 +217,7 @@ public class MenuGeneratorsInventory {
int width = 500;
int height = 500;
// int screenLeft = (Globals.WINDOW_WIDTH - width)/2;
Window rVal = new Window(0,0,width,height,true);
Window rVal = new Window(Globals.renderingEngine.getOpenGLState(),0,0,width,height,true);
Div div = new Div();
rVal.addChild(div);
@ -225,7 +231,9 @@ public class MenuGeneratorsInventory {
Globals.controlHandler.hintUpdateControlState(ControlsState.MAIN_GAME);
}
//play sound effect
Globals.virtualAudioSourceManager.createVirtualAudioSource("/Audio/closeMenu.ogg", VirtualAudioSourceType.UI, false);
if(Globals.virtualAudioSourceManager != null){
Globals.virtualAudioSourceManager.createVirtualAudioSource("/Audio/closeMenu.ogg", VirtualAudioSourceType.UI, false);
}
return false;
}});
@ -304,7 +312,9 @@ public class MenuGeneratorsInventory {
container.removeChild(panel);
WindowUtils.pushItemIconToItemWindow(panel);
//play sound effect
Globals.virtualAudioSourceManager.createVirtualAudioSource("/Audio/inventoryGrabItem.ogg", VirtualAudioSourceType.UI, false);
if(Globals.virtualAudioSourceManager != null){
Globals.virtualAudioSourceManager.createVirtualAudioSource("/Audio/inventoryGrabItem.ogg", VirtualAudioSourceType.UI, false);
}
return false;
}});
panel.setOnDrag(new DragEventCallback() {public boolean execute(DragEvent event){
@ -340,7 +350,9 @@ public class MenuGeneratorsInventory {
ClientEquipState equipState = ClientEquipState.getEquipState(Globals.playerEntity);
equipState.commandAttemptEquip(item,inventory.getEquipPointFromSlot(slots.get(itemId)));
//play sound effect
Globals.virtualAudioSourceManager.createVirtualAudioSource("/Audio/inventorySlotItem.ogg", VirtualAudioSourceType.UI, false);
if(Globals.virtualAudioSourceManager != null){
Globals.virtualAudioSourceManager.createVirtualAudioSource("/Audio/inventorySlotItem.ogg", VirtualAudioSourceType.UI, false);
}
}
//update ui
Globals.dragSourceInventory = null;
@ -391,7 +403,7 @@ public class MenuGeneratorsInventory {
}
public static Element worldItemDropCaptureWindow(){
Window rVal = new Window(0,0,Globals.WINDOW_WIDTH,Globals.WINDOW_HEIGHT,true);
Window rVal = new Window(Globals.renderingEngine.getOpenGLState(),0,0,Globals.WINDOW_WIDTH,Globals.WINDOW_HEIGHT,true);
Div div = new Div();
div.setOnDragRelease(new DragEventCallback() {public boolean execute(DragEvent event){
if(Globals.draggedItem != null){

View File

@ -62,7 +62,7 @@ public class MenuGeneratorsLevelEditor {
*/
public static Window createLevelEditorSidePanel(){
//setup window
mainSidePanel = new Window(0,0,SIDE_PANEL_WIDTH,Globals.WINDOW_HEIGHT,true);
mainSidePanel = new Window(Globals.renderingEngine.getOpenGLState(),0,0,SIDE_PANEL_WIDTH,Globals.WINDOW_HEIGHT,true);
mainSidePanel.setParentAlignContent(Yoga.YGAlignFlexEnd);
mainSidePanel.setParentJustifyContent(Yoga.YGJustifyFlexEnd);
mainSidePanel.setParentAlignItem(Yoga.YGAlignFlexEnd);

View File

@ -54,7 +54,7 @@ public class MenuGeneratorsTerrainEditing {
*/
public static Window createVoxelTypeSelectionPanel(){
//setup window
rVal = new Window(0,0,WINDOW_WIDTH,WINDOW_HEIGHT,true);
rVal = new Window(Globals.renderingEngine.getOpenGLState(),0,0,WINDOW_WIDTH,WINDOW_HEIGHT,true);
rVal.setParentAlignContent(Yoga.YGAlignCenter);
rVal.setParentJustifyContent(Yoga.YGJustifyCenter);
rVal.setParentAlignItem(Yoga.YGAlignCenter);

View File

@ -25,7 +25,7 @@ public class MenuGeneratorsDebug {
static final int X_OFFSET = 1000;
public static Window createTopLevelDebugMenu(){
Window rVal = new Window(X_OFFSET,100,800,800,true);
Window rVal = new Window(Globals.renderingEngine.getOpenGLState(),X_OFFSET,100,800,800,true);
//label (title)
Label titleLabel = new Label(1.0f);
@ -50,7 +50,7 @@ public class MenuGeneratorsDebug {
}
public static Element createDebugUIMenu(){
ScrollableContainer rVal = new ScrollableContainer(0, 0, 800, 800);
ScrollableContainer rVal = new ScrollableContainer(Globals.renderingEngine.getOpenGLState(), 0, 0, 800, 800);
rVal.addChild(WidgetUtils.createLabelButton("Toggle UI Outline",100,150,1.0f,new ClickableElement.ClickEventCallback(){public boolean execute(ClickEvent event){
DebugRendering.toggleOutlineMask();
return false;
@ -59,7 +59,7 @@ public class MenuGeneratorsDebug {
}
public static Element createListUIElements(){
ScrollableContainer rVal = new ScrollableContainer(0, 0, 800, 800);
ScrollableContainer rVal = new ScrollableContainer(Globals.renderingEngine.getOpenGLState(), 0, 0, 800, 800);
int verticalOffset = 0;
int horizontalOffset = 0;
List<Element> elementsToAdd = new LinkedList<Element>();

View File

@ -0,0 +1,88 @@
package electrosphere.menu.mainmenu;
import org.lwjgl.util.yoga.Yoga;
import electrosphere.controls.Control;
import electrosphere.engine.Globals;
import electrosphere.menu.WindowUtils;
import electrosphere.renderer.ui.elements.Button;
import electrosphere.renderer.ui.elements.Div;
import electrosphere.renderer.ui.elements.FormElement;
import electrosphere.renderer.ui.elements.Label;
import electrosphere.renderer.ui.elements.VirtualScrollable;
import electrosphere.renderer.ui.elementtypes.ClickableElement;
import electrosphere.renderer.ui.elementtypes.ClickableElement.ClickEventCallback;
import electrosphere.renderer.ui.elementtypes.Element;
import electrosphere.renderer.ui.events.ClickEvent;
/**
* A menu for rebinding controls
*/
public class MenuGeneratorsKeybind {
//tracks whether the menu has been used to rebind a control or not
static boolean modifiedControls = false;
/**
* The controls rebind window
* @return the window element
*/
public static Element createControlsRebindMenu(){
FormElement rVal = new FormElement();
rVal.setAlignItems(Yoga.YGAlignCenter);
//header buttons
Div headerButtons = new Div();
headerButtons.setFlexDirection(Yoga.YGFlexDirectionRow);
Button backButton = Button.createButton("Back", new ClickableElement.ClickEventCallback(){public boolean execute(ClickEvent event){
WindowUtils.replaceMainMenuContents(MenuGeneratorsTitleMenu.createTitleMenu());
return false;
}});
headerButtons.addChild(backButton);
Button saveButton = Button.createButton("Save", new ClickableElement.ClickEventCallback(){public boolean execute(ClickEvent event){
WindowUtils.replaceMainMenuContents(MenuGeneratorsTitleMenu.createTitleMenu());
return false;
}});
saveButton.setVisible(false);
headerButtons.addChild(saveButton);
Button cancelButton = Button.createButton("Cancel", new ClickableElement.ClickEventCallback(){public boolean execute(ClickEvent event){
WindowUtils.replaceMainMenuContents(MenuGeneratorsTitleMenu.createTitleMenu());
return false;
}});
cancelButton.setVisible(false);
headerButtons.addChild(cancelButton);
rVal.addChild(headerButtons);
//
//Generate keybind controls
VirtualScrollable virtualScrollable = new VirtualScrollable(300, 700);
virtualScrollable.setAlignItems(Yoga.YGAlignFlexStart);
//add a ton of children
for(Control control : Globals.controlHandler.getMainControlsList()){
if(control.isRebindable()){
Div rebindItem = new Div();
rebindItem.setFlexDirection(Yoga.YGFlexDirectionRow);
Label controlNameLabel = Label.createLabel(control.getName());
rebindItem.addChild(controlNameLabel);
Button testButton = Button.createButton(control.getKeyValue() + "", new ClickEventCallback() {public boolean execute(ClickEvent event) {
System.out.println("Start rebind");
return false;
}});
rebindItem.addChild(testButton);
virtualScrollable.addChild(rebindItem);
}
}
rVal.addChild(virtualScrollable);
return rVal;
}
}

View File

@ -97,7 +97,7 @@ public class MenuGeneratorsMultiplayer {
//create actor panel
Actor characterActor = ActorUtils.createActorFromModelPath(selectedRaceType.getModelPath());
ActorPanel actorPanel = new ActorPanel(1200, 100, 500, 500, characterActor);
ActorPanel actorPanel = new ActorPanel(Globals.renderingEngine.getOpenGLState(), 1200, 100, 500, 500, characterActor);
actorPanel.setAnimation(Animation.ANIMATION_IDLE_1);
actorPanel.setPosition(new Vector3f(0,-0.5f,-0.6f));
// actorPanel.setRotation(new Quaternionf().rotateLocalY(0));
@ -206,7 +206,7 @@ public class MenuGeneratorsMultiplayer {
Div rVal = new Div();
rVal.setFlexDirection(Yoga.YGFlexDirectionRow);
ScrollableContainer scrollable = new ScrollableContainer(0, 0, width, height);
ScrollableContainer scrollable = new ScrollableContainer(Globals.renderingEngine.getOpenGLState(), 0, 0, width, height);
for(Element newControl : controlsToAdd){
scrollable.addChild(newControl);
}

View File

@ -37,7 +37,7 @@ public class MenuGeneratorsUITesting {
}});
rVal.addChild(backButton);
ActorPanel actorPanel = new ActorPanel(500, 100, 500, 500, ActorUtils.createActorFromModelPath("Models/deer1.fbx"));
ActorPanel actorPanel = new ActorPanel(Globals.renderingEngine.getOpenGLState(), 500, 100, 500, 500, ActorUtils.createActorFromModelPath("Models/deer1.fbx"));
if(Globals.playerCamera == null){
Globals.playerCamera = CameraEntityUtils.spawnBasicCameraEntity(new Vector3f(0,0,0), new Vector3f(-1,0,0));
}

View File

@ -29,7 +29,7 @@ public class TutorialMenus {
windowEl = (Window)Globals.elementManager.getWindow(WindowStrings.TUTORIAL_POPUP);
} else {
//create the window
windowEl = new Window(50,50,500,500,true);
windowEl = new Window(Globals.renderingEngine.getOpenGLState(),50,50,500,500,true);
windowEl.setParentAlignContent(Yoga.YGAlignCenter);
windowEl.setParentJustifyContent(Yoga.YGJustifyCenter);
windowEl.setFlexDirection(Yoga.YGFlexDirectionColumn);

View File

@ -15,6 +15,9 @@ import electrosphere.renderer.shader.ShaderProgram;
*/
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);
@ -41,6 +44,22 @@ public class OpenGLState {
//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
@ -54,6 +73,14 @@ public class OpenGLState {
}
}
/**
* 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
@ -131,6 +158,14 @@ public class OpenGLState {
}
}
/**
* 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
@ -161,4 +196,12 @@ public class OpenGLState {
return this.activeShader == program;
}
/**
* Gets MAX_TEXTURE_WIDTH
* @return MAX_TEXTURE_WIDTH
*/
public int getMAX_TEXTURE_WIDTH(){
return MAX_TEXTURE_WIDTH;
}
}

View File

@ -229,6 +229,10 @@ public class RenderingEngine {
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glslVersion = "#version 410";
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
//headless option
if(Globals.RUN_HIDDEN){
glfwWindowHint(GLFW.GLFW_VISIBLE, GLFW.GLFW_FALSE);
}
// glfwWindowHint(GLFW_TRANSPARENT_FRAMEBUFFER, GLFW_TRUE); Allows you to make the background transparent
// glfwWindowHint(GLFW_OPACITY, 23);
//Creates the window reference object
@ -286,6 +290,9 @@ public class RenderingEngine {
//Creates the OpenGL capabilities for the program.
GL.createCapabilities();
//get environment constraints
openGLState.storeCurrentEnvironmentContraints();
//init imgui pipeline
imGuiPipeline = new ImGuiPipeline(Globals.window, glslVersion);
@ -314,10 +321,10 @@ public class RenderingEngine {
// screenTextureShaders = ShaderProgram.loadSpecificShader("/Shaders/screentexture/drawDepthBuffer/drawDepthBuffer.vs", "/Shaders/screentexture/drawDepthBuffer/drawDepthBuffer.fs");
//generate framebuffers
screenTextureColor = FramebufferUtils.generateScreenTextureColor(Globals.userSettings.getRenderResolutionX(), Globals.userSettings.getRenderResolutionY());
screenTextureDepth = FramebufferUtils.generateScreenTextureDepth(Globals.userSettings.getRenderResolutionX(), Globals.userSettings.getRenderResolutionY());
screenFramebuffer = FramebufferUtils.generateScreenTextureFramebuffer(Globals.userSettings.getRenderResolutionX(), Globals.userSettings.getRenderResolutionY(), screenTextureColor, screenTextureDepth);
glBindFramebuffer(GL_FRAMEBUFFER, GL_DEFAULT_FRAMEBUFFER);
screenTextureColor = FramebufferUtils.generateScreenTextureColor(openGLState, Globals.userSettings.getRenderResolutionX(), Globals.userSettings.getRenderResolutionY());
screenTextureDepth = FramebufferUtils.generateScreenTextureDepth(openGLState, Globals.userSettings.getRenderResolutionX(), Globals.userSettings.getRenderResolutionY());
screenFramebuffer = FramebufferUtils.generateScreenTextureFramebuffer(openGLState, Globals.userSettings.getRenderResolutionX(), Globals.userSettings.getRenderResolutionY(), screenTextureColor, screenTextureDepth);
openGLState.glBindFramebuffer(GL_FRAMEBUFFER, GL_DEFAULT_FRAMEBUFFER);
glBindRenderbuffer(GL_RENDERBUFFER, GL_DEFAULT_RENDERBUFFER);
//
@ -330,7 +337,7 @@ public class RenderingEngine {
//
lightDepthShaderProgram = ShaderProgram.loadSpecificShader("/Shaders/lightDepth/lightDepth.vs", "/Shaders/lightDepth/lightDepth.fs");
Globals.depthMapShaderProgramLoc = lightDepthShaderProgram.getShaderId();
lightDepthBuffer = FramebufferUtils.generateDepthBuffer();
lightDepthBuffer = FramebufferUtils.generateDepthBuffer(openGLState);
Globals.shadowMapTextureLoc = lightDepthBuffer.getTexturePointer();
// glEnable(GL_CULL_FACE); // enabled for shadow mapping
@ -338,10 +345,10 @@ public class RenderingEngine {
//create volume depth framebuffer/shader for volumetric rendering
//
volumeDepthShaderProgram = ShaderProgram.loadSpecificShader("/Shaders/volumeBuffer/volumetric.vs", "/Shaders/volumeBuffer/volumetric.fs");
volumeDepthBackfaceTexture = FramebufferUtils.generateDepthBufferTexture(Globals.userSettings.getRenderResolutionX(), Globals.userSettings.getRenderResolutionY());
volumeDepthBackfaceFramebuffer = FramebufferUtils.generateDepthBuffer(Globals.userSettings.getRenderResolutionX(), Globals.userSettings.getRenderResolutionY(), volumeDepthBackfaceTexture);
volumeDepthFrontfaceTexture = FramebufferUtils.generateDepthBufferTexture(Globals.userSettings.getRenderResolutionX(), Globals.userSettings.getRenderResolutionY());
volumeDepthFrontfaceFramebuffer = FramebufferUtils.generateDepthBuffer(Globals.userSettings.getRenderResolutionX(), Globals.userSettings.getRenderResolutionY(), volumeDepthFrontfaceTexture);
volumeDepthBackfaceTexture = FramebufferUtils.generateDepthBufferTexture(openGLState, Globals.userSettings.getRenderResolutionX(), Globals.userSettings.getRenderResolutionY());
volumeDepthBackfaceFramebuffer = FramebufferUtils.generateDepthBuffer(openGLState, Globals.userSettings.getRenderResolutionX(), Globals.userSettings.getRenderResolutionY(), volumeDepthBackfaceTexture);
volumeDepthFrontfaceTexture = FramebufferUtils.generateDepthBufferTexture(openGLState, Globals.userSettings.getRenderResolutionX(), Globals.userSettings.getRenderResolutionY());
volumeDepthFrontfaceFramebuffer = FramebufferUtils.generateDepthBuffer(openGLState, Globals.userSettings.getRenderResolutionX(), Globals.userSettings.getRenderResolutionY(), volumeDepthFrontfaceTexture);
//
//Game normals
@ -351,19 +358,19 @@ public class RenderingEngine {
static Framebuffer gameImageNormalsFramebuffer;
static ShaderProgram renderNormalsShader;
*/
gameImageNormalsTexture = FramebufferUtils.generateScreenTextureColor(Globals.userSettings.getRenderResolutionX(), Globals.userSettings.getRenderResolutionY());
Texture gameImageNormalsDepthTexture = FramebufferUtils.generateScreenTextureDepth(Globals.userSettings.getRenderResolutionX(), Globals.userSettings.getRenderResolutionY());
gameImageNormalsFramebuffer = FramebufferUtils.generateScreenTextureFramebuffer(Globals.userSettings.getRenderResolutionX(), Globals.userSettings.getRenderResolutionY(), gameImageNormalsTexture, gameImageNormalsDepthTexture);
gameImageNormalsTexture = FramebufferUtils.generateScreenTextureColor(openGLState, Globals.userSettings.getRenderResolutionX(), Globals.userSettings.getRenderResolutionY());
Texture gameImageNormalsDepthTexture = FramebufferUtils.generateScreenTextureDepth(openGLState, Globals.userSettings.getRenderResolutionX(), Globals.userSettings.getRenderResolutionY());
gameImageNormalsFramebuffer = FramebufferUtils.generateScreenTextureFramebuffer(openGLState, Globals.userSettings.getRenderResolutionX(), Globals.userSettings.getRenderResolutionY(), gameImageNormalsTexture, gameImageNormalsDepthTexture);
renderNormalsShader = ShaderProgram.loadSpecificShader("Shaders/anime/renderNormals.vs", "Shaders/anime/renderNormals.fs");
//
//Transparency framebuffers
//
transparencyAccumulatorClear = new float[]{0.0f, 0.0f, 0.0f, 0.0f};
transparencyAccumulatorTexture = FramebufferUtils.generateOITAccumulatorTexture(Globals.userSettings.getRenderResolutionX(), Globals.userSettings.getRenderResolutionY());
transparencyAccumulatorTexture = FramebufferUtils.generateOITAccumulatorTexture(openGLState, Globals.userSettings.getRenderResolutionX(), Globals.userSettings.getRenderResolutionY());
transparencyRevealageClear = new float[]{1.0f, 1.0f, 1.0f, 1.0f};
transparencyRevealageTexture = FramebufferUtils.generateOITRevealageTexture(Globals.userSettings.getRenderResolutionX(), Globals.userSettings.getRenderResolutionY());
transparencyBuffer = FramebufferUtils.generateOITFramebuffer(Globals.userSettings.getRenderResolutionX(), Globals.userSettings.getRenderResolutionY(), transparencyAccumulatorTexture, transparencyRevealageTexture, screenTextureDepth);
transparencyRevealageTexture = FramebufferUtils.generateOITRevealageTexture(openGLState, Globals.userSettings.getRenderResolutionX(), Globals.userSettings.getRenderResolutionY());
transparencyBuffer = FramebufferUtils.generateOITFramebuffer(openGLState, Globals.userSettings.getRenderResolutionX(), Globals.userSettings.getRenderResolutionY(), transparencyAccumulatorTexture, transparencyRevealageTexture, screenTextureDepth);
oitCompositeProgram = ShaderProgram.loadSpecificShader("Shaders/oit/composite.vs", "Shaders/oit/composite.fs");
//projection matrices
@ -377,8 +384,8 @@ public class RenderingEngine {
static Framebuffer normalsOutlineFrambuffer;
static ShaderProgram normalsOutlineShader;
*/
normalsOutlineTexture = FramebufferUtils.generateScreenTextureColorAlpha(Globals.userSettings.getRenderResolutionX(), Globals.userSettings.getRenderResolutionY());
normalsOutlineFrambuffer = FramebufferUtils.generateScreenTextureFramebuffer(Globals.userSettings.getRenderResolutionX(), Globals.userSettings.getRenderResolutionY(), normalsOutlineTexture);
normalsOutlineTexture = FramebufferUtils.generateScreenTextureColorAlpha(openGLState, Globals.userSettings.getRenderResolutionX(), Globals.userSettings.getRenderResolutionY());
normalsOutlineFrambuffer = FramebufferUtils.generateScreenTextureFramebuffer(openGLState, Globals.userSettings.getRenderResolutionX(), Globals.userSettings.getRenderResolutionY(), normalsOutlineTexture);
// normalsOutlineShader = ShaderProgram.loadSpecificShader("Shaders/anime/outlineNormals.vs", "Shaders/anime/outlineNormals.fs");
Globals.assetManager.addShaderToQueue("Shaders/anime/outlineNormals.vs", "Shaders/anime/outlineNormals.fs");
@ -416,7 +423,7 @@ public class RenderingEngine {
//
//Init pipelines
//
firstPersonItemsPipeline.init();
firstPersonItemsPipeline.init(Globals.renderingEngine.getOpenGLState());
compositePipeline.setFirstPersonPipeline(firstPersonItemsPipeline);
//
@ -455,6 +462,7 @@ public class RenderingEngine {
//Update light buffer
lightManager.updateData();
checkError();
//Render content to the game framebuffer
@ -464,18 +472,24 @@ public class RenderingEngine {
} else {
mainContentNoOITPipeline.render(openGLState, renderPipelineState);
}
checkError();
debugContentPipeline.render(openGLState, renderPipelineState);
checkError();
normalsForOutlinePipeline.render(openGLState, renderPipelineState);
checkError();
firstPersonItemsPipeline.render(openGLState, renderPipelineState);
checkError();
postProcessingPipeline.render(openGLState, renderPipelineState);
checkError();
compositePipeline.render(openGLState, renderPipelineState);
checkError();
}
//bind default FBO
glBindFramebuffer(GL_FRAMEBUFFER,0);
openGLState.glBindFramebuffer(GL_FRAMEBUFFER,0);
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
@ -483,10 +497,12 @@ public class RenderingEngine {
//Render the game framebuffer texture to a quad
if(Globals.RENDER_FLAG_RENDER_SCREEN_FRAMEBUFFER){
renderScreenPipeline.render(openGLState, renderPipelineState);
checkError();
}
//render ui
uiPipeline.render(openGLState, renderPipelineState);
checkError();
//Render boundaries of ui elements
if(Globals.RENDER_FLAG_RENDER_UI_BOUNDS){
@ -497,6 +513,7 @@ public class RenderingEngine {
* Render imgui
*/
imGuiPipeline.render(openGLState, renderPipelineState);
checkError();
//check for errors
@ -506,6 +523,7 @@ public class RenderingEngine {
LoggerInterface.loggerRenderer.DEBUG_LOOP("Swap buffers");
glfwSwapBuffers(Globals.window);
glfwPollEvents();
checkError();
}
/**
@ -516,7 +534,7 @@ public class RenderingEngine {
}
public void bindFramebuffer(int framebufferPointer){
glBindFramebuffer(GL_FRAMEBUFFER, framebufferPointer);
openGLState.glBindFramebuffer(GL_FRAMEBUFFER, framebufferPointer);
}
public void setTitleBarDimensions(){
@ -615,40 +633,61 @@ public class RenderingEngine {
* Checks for any errors currently caught by OpenGL.
* Refer: https://docs.gl/gl4/glGetError
*/
private static void checkError(){
int error = GL11.glGetError();
String errorInEnglish = "";
switch(error){
case GL11.GL_NO_ERROR: {
errorInEnglish = "";
} break;
case GL11.GL_INVALID_ENUM: {
errorInEnglish = "An unacceptable value is specified for an enumerated argument. The offending command is ignored and has no other side effect than to set the error flag.";
} break;
case GL11.GL_INVALID_VALUE: {
errorInEnglish = "A numeric argument is out of range. The offending command is ignored and has no other side effect than to set the error flag.";
} break;
case GL11.GL_INVALID_OPERATION: {
errorInEnglish = "The specified operation is not allowed in the current state. The offending command is ignored and has no other side effect than to set the error flag.";
} break;
case GL30.GL_INVALID_FRAMEBUFFER_OPERATION: {
errorInEnglish = "The framebuffer object is not complete. The offending command is ignored and has no other side effect than to set the error flag. ";
} break;
case GL11.GL_OUT_OF_MEMORY: {
errorInEnglish = "There is not enough memory left to execute the command. The state of the GL is undefined, except for the state of the error flags, after this error is recorded. ";
} break;
case GL11.GL_STACK_UNDERFLOW: {
errorInEnglish = "An attempt has been made to perform an operation that would cause an internal stack to underflow. ";
} break;
case GL11.GL_STACK_OVERFLOW: {
errorInEnglish = "An attempt has been made to perform an operation that would cause an internal stack to overflow. ";
} break;
default: {
errorInEnglish = "Un-enum'd error " + error;
} break;
public void checkError(){
int error = this.getError();
if(error != GL11.GL_NO_ERROR){
LoggerInterface.loggerRenderer.ERROR("checkError - " + getErrorInEnglish(error), new IllegalStateException("OpenGL Error"));
}
if(!errorInEnglish.equals("")){
LoggerInterface.loggerRenderer.ERROR(errorInEnglish, new Exception(errorInEnglish));
}
/**
* Gets the current error code
* @return The error code
*/
public int getError(){
int lastCode = GL11.glGetError();
int currentCode = lastCode;
while((currentCode = GL11.glGetError()) != GL11.GL_NO_ERROR){
lastCode = currentCode;
}
return lastCode;
}
/**
* Checks for any errors currently caught by OpenGL.
* Refer: https://docs.gl/gl4/glGetError
* @param errorCode The error code
* @return The message
*/
public static String getErrorInEnglish(int errorCode){
switch(errorCode){
case GL11.GL_NO_ERROR: {
return null;
}
case GL11.GL_INVALID_ENUM: {
return "An unacceptable value is specified for an enumerated argument. The offending command is ignored and has no other side effect than to set the error flag.";
}
case GL11.GL_INVALID_VALUE: {
return "A numeric argument is out of range. The offending command is ignored and has no other side effect than to set the error flag.";
}
case GL11.GL_INVALID_OPERATION: {
return "The specified operation is not allowed in the current state. The offending command is ignored and has no other side effect than to set the error flag.";
}
case GL30.GL_INVALID_FRAMEBUFFER_OPERATION: {
return "The framebuffer object is not complete. The offending command is ignored and has no other side effect than to set the error flag. ";
}
case GL11.GL_OUT_OF_MEMORY: {
return "There is not enough memory left to execute the command. The state of the GL is undefined, except for the state of the error flags, after this error is recorded. ";
}
case GL11.GL_STACK_UNDERFLOW: {
return "An attempt has been made to perform an operation that would cause an internal stack to underflow. ";
}
case GL11.GL_STACK_OVERFLOW: {
return "An attempt has been made to perform an operation that would cause an internal stack to overflow. ";
}
default: {
return "Un-enum'd error or no error. Code: " + errorCode;
}
}
}

View File

@ -1,57 +1,128 @@
package electrosphere.renderer.framebuffer;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import electrosphere.engine.Globals;
import electrosphere.logger.LoggerInterface;
import electrosphere.renderer.OpenGLState;
import electrosphere.renderer.RenderingEngine;
import electrosphere.renderer.texture.Texture;
import electrosphere.util.FileUtils;
import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import org.lwjgl.opengl.GL30;
import static org.lwjgl.opengl.GL30.GL_FRAMEBUFFER;
import static org.lwjgl.opengl.GL30.GL_DRAW_FRAMEBUFFER;
import javax.imageio.ImageIO;
import org.lwjgl.opengl.GL40;
import org.lwjgl.system.MemoryUtil;
import static org.lwjgl.opengl.GL11.GL_TEXTURE_2D;
import static org.lwjgl.opengl.GL30.*;
import static org.lwjgl.opengl.GL30.glBindFramebuffer;
import static org.lwjgl.opengl.GL30.glCheckFramebufferStatus;
import static org.lwjgl.opengl.GL30.glDeleteFramebuffers;
import static org.lwjgl.opengl.GL30.glGenFramebuffers;
import static org.lwjgl.opengl.GL45.glCheckNamedFramebufferStatus;
/**
*
* @author amaterasu
* Framebuffer object
*/
public class Framebuffer {
//the pointer to the framebuffer
int framebufferPointer;
//gets the texture pointer to the framebuffer's content
int texturePointer;
//the mipmap level
int mipMap = -1;
//the map of attachment point to texture object
Map<Integer,Texture> attachTextureMap = new HashMap<Integer,Texture>();
/**
* Creates a framebuffer
*/
public Framebuffer(){
framebufferPointer = glGenFramebuffers();
}
public void setTexturePointer(int texturePointer){
/**
* Sets the texture attached to the framebuffer
* @param texture The texture attached to the framebuffer
*/
public void setTexture(Texture texture){
setTexture(texture.getTexturePointer());
}
/**
* Sets the texture attached to the framebuffer
* @param texturePointer The texture attached to the framebuffer
*/
public void setTexture(int texturePointer){
this.texturePointer = texturePointer;
}
/**
* Gets the texture associated with the framebuffer
* @return The texture's pointer
*/
public int getTexturePointer(){
return texturePointer;
}
public void bind(){
glBindFramebuffer(GL_FRAMEBUFFER, framebufferPointer);
/**
* Binds the framebuffer
*/
public void bind(OpenGLState openGLState){
openGLState.glBindFramebuffer(GL_FRAMEBUFFER, framebufferPointer);
}
/**
* Checks if the framebuffer compiled correctly
* @return true if compiled correctly, false otherwise
*/
public boolean isComplete(){
bind();
return glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE;
return glCheckNamedFramebufferStatus(framebufferPointer,GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE;
}
/**
* Checks if the framebuffer has an error
* @return true if error, false otherwise
*/
public boolean isError(){
return glCheckNamedFramebufferStatus(framebufferPointer,GL_FRAMEBUFFER) == 0;
}
public void checkStatus(){
if(isError()){
LoggerInterface.loggerRenderer.WARNING("Framebuffer [error] - " + RenderingEngine.getErrorInEnglish(Globals.renderingEngine.getError()));
} else if(!isComplete()){
LoggerInterface.loggerRenderer.WARNING("Framebuffer [glError] - " + RenderingEngine.getErrorInEnglish(Globals.renderingEngine.getError()));
LoggerInterface.loggerRenderer.WARNING("Framebuffer [status] - " + getStatus());
LoggerInterface.loggerRenderer.ERROR("Failed to build framebuffer", new IllegalStateException("Framebuffer failed to build."));
}
}
/**
* Gets the framebuffer's pointer
* @return The framebuffer's pointer
*/
public int getFramebufferPointer(){
return framebufferPointer;
}
/**
* Frees the framebuffer
*/
public void free(){
glDeleteFramebuffers(framebufferPointer);
}
/**
* Blocks the thread until the framebuffer has compiled
*/
public void blockUntilCompiled(){
int status = -1;
while((status = glCheckFramebufferStatus(framebufferPointer)) != GL_FRAMEBUFFER_UNDEFINED){
while(glCheckNamedFramebufferStatus(framebufferPointer,GL_FRAMEBUFFER) != GL_FRAMEBUFFER_UNDEFINED){
try {
TimeUnit.MILLISECONDS.sleep(1);
} catch (InterruptedException ex) {
@ -59,4 +130,202 @@ public class Framebuffer {
}
}
}
/**
* Gets the status of the framebuffer
* @return The status
*/
public String getStatus(){
switch(glCheckNamedFramebufferStatus(framebufferPointer,GL_FRAMEBUFFER)){
case GL_FRAMEBUFFER_UNDEFINED: {
return "The specified framebuffer is the default read or draw framebuffer, but the default framebuffer does not exist.";
}
case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: {
return "Any of the framebuffer attachment points are framebuffer incomplete.";
}
case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: {
return "The framebuffer does not have at least one image attached to it.";
}
case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER: {
return "The value of GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE is GL_NONE for any color attachment point(s) named by GL_DRAW_BUFFERi.";
}
case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER: {
return "GL_READ_BUFFER is not GL_NONE and the value of GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE is GL_NONE for the color attachment point named by GL_READ_BUFFER.";
}
case GL_FRAMEBUFFER_UNSUPPORTED: {
return "The combination of internal formats of the attached images violates an implementation-dependent set of restrictions.";
}
case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE: {
return "The value of GL_RENDERBUFFER_SAMPLES is not the same for all attached renderbuffers; if the value of GL_TEXTURE_SAMPLES is the not same for all attached textures; or, if the attached images are a mix of renderbuffers and textures, the value of GL_RENDERBUFFER_SAMPLES does not match the value of GL_TEXTURE_SAMPLES.";
}
case 0: {
return RenderingEngine.getErrorInEnglish(Globals.renderingEngine.getError());
}
}
return "Unknown framebuffer status";
}
/**
* Sets the mipmap level
* @param mipMap The mipmap level
*/
public void setMipMapLevel(int mipMap){
this.mipMap = mipMap;
}
/**
* Sets the color attachment
* @param texturePointer The color attachment's pointer
*/
public void attachTexture(OpenGLState openGLState, int texturePointer){
attachTexture(openGLState,texturePointer,0);
}
/**
* Sets the color attachment
* @param texturePointer The color attachment's pointer
* @param attachmentNum The number of the color attachment
*/
public void attachTexture(OpenGLState openGLState, int texturePointer, int attachmentNum){
if(this.mipMap < 0){
LoggerInterface.loggerRenderer.ERROR(new IllegalStateException("Trying to attach a texture to a framebuffer where mipmap hasn't been set."));
}
this.texturePointer = texturePointer;
openGLState.glBindFramebuffer(GL_FRAMEBUFFER, framebufferPointer);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + attachmentNum, GL_TEXTURE_2D, this.texturePointer, this.mipMap);
}
/**
* Attaches a color texture to the default texture unit
* @param texture
*/
public void attachTexture(OpenGLState openGLState, Texture texture){
attachTexture(openGLState, texture, 0);
}
/**
* Attaches a texture to the framebuffer
* @param texture The texture
* @param attachmentNum The texture unit to attach to
*/
public void attachTexture(OpenGLState openGLState, Texture texture, int attachmentNum){
this.attachTextureMap.put(attachmentNum,texture);
attachTexture(openGLState, texture.getTexturePointer(), attachmentNum);
}
/**
* Sets the depth attachment for the framebuffer
* @param texturePointer The depth attachment's pointer
*/
public void setDepthAttachment(OpenGLState openGLState, int texturePointer){
openGLState.glBindFramebuffer(GL_FRAMEBUFFER, framebufferPointer);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, texturePointer, this.mipMap);
openGLState.glBindFramebuffer(GL_FRAMEBUFFER, 0);
checkStatus();
}
/**
* Gets the pixels currently stored in this framebuffer
*/
public BufferedImage getPixels(OpenGLState openGLState){
BufferedImage rVal = null;
bind(openGLState);
GL40.glReadBuffer(GL40.GL_COLOR_ATTACHMENT0);
int offsetX = 0;
int offsetY = 0;
int width = openGLState.getViewport().x;
int height = openGLState.getViewport().y;
int pixelFormat = GL40.GL_RGBA;
int type = GL40.GL_UNSIGNED_INT;
if(attachTextureMap.containsKey(0)){
Texture texture = attachTextureMap.get(0);
pixelFormat = texture.getFormat();
type = texture.getDataType();
width = texture.getWidth();
height = texture.getHeight();
} else {
throw new IllegalStateException("Tried to get pixels from a framebuffer that does not have a texture attached to attachment point 0.");
}
//get pixel data
try {
int bytesPerPixel = pixelFormatToBytes(pixelFormat,type);
int bufferSize = width * height * bytesPerPixel;
ByteBuffer buffer = MemoryUtil.memAlloc(bufferSize);
openGLState.glViewport(width, height);
GL40.glReadPixels(offsetX, offsetY, width, height, pixelFormat, type, buffer);
Globals.renderingEngine.checkError();
//convert to a buffered images
rVal = new BufferedImage(width,height,BufferedImage.TYPE_INT_ARGB);
for(int x = 0; x < width; x++){
for(int y = 0; y < height; y++){
int i = (x + (width * y)) * bytesPerPixel;
int red = buffer.get(i) & 0xFF;
int green = buffer.get(i + 1) & 0xFF;
int blue = buffer.get(i + 2) & 0xFF;
if(red != 0 || green != 0 || blue != 0){
System.out.println(x + " " + y);
System.out.println(red + " " + green + " " + blue);
}
int alpha = 255;
if(pixelFormat == GL40.GL_RGBA){
alpha = buffer.get(i + 3) & 0xFF;
}
rVal.setRGB(x, height - (y + 1), (alpha << 24) | (red << 16) | (green << 8) | blue);
}
}
//write the buffered image out
try {
File outputFile = FileUtils.getAssetFile("Screenshots/" + System.currentTimeMillis() + ".png");
if(!outputFile.getParentFile().exists()){
outputFile.getParentFile().mkdirs();
}
if(!outputFile.exists()){
outputFile.createNewFile();
}
ImageIO.write(rVal,"png",outputFile);
} catch (IOException e) {
LoggerInterface.loggerRenderer.ERROR(e);
}
//memory management
MemoryUtil.memFree(buffer);
} catch (OutOfMemoryError e){
LoggerInterface.loggerRenderer.ERROR(new IllegalStateException(e.getMessage()));
}
return rVal;
}
/**
* Gets the number of bytes per pixel based on the format and type of pixel
* @param format The format of the pixels
* @param type The datatype of as single component of the pixel
* @return The number of bytes
*/
private static int pixelFormatToBytes(int format, int type){
int multiplier = 1;
switch(format){
case GL40.GL_RGBA: {
multiplier = 4;
} break;
case GL40.GL_RGB: {
multiplier = 3;
} break;
default: {
LoggerInterface.loggerRenderer.WARNING("Trying to export framebuffer that has image of unsupported pixel format");
} break;
}
int bytesPerComponent = 1;
switch(type){
case GL40.GL_UNSIGNED_INT: {
bytesPerComponent = 4;
} break;
case GL40.GL_UNSIGNED_BYTE: {
bytesPerComponent = 1;
} break;
default: {
LoggerInterface.loggerRenderer.WARNING("Trying to export framebuffer that has image of unsupported datatype");
} break;
}
return multiplier * bytesPerComponent;
}
}

View File

@ -1,13 +1,10 @@
package electrosphere.renderer.framebuffer;
import electrosphere.engine.Globals;
import electrosphere.logger.LoggerInterface;
import electrosphere.renderer.OpenGLState;
import electrosphere.renderer.texture.Texture;
import java.nio.IntBuffer;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.lwjgl.BufferUtils;
@ -16,96 +13,72 @@ import static org.lwjgl.opengl.GL11.GL_FLOAT;
import static org.lwjgl.opengl.GL11.GL_LINEAR;
import static org.lwjgl.opengl.GL11.GL_NEAREST;
import static org.lwjgl.opengl.GL11.GL_NONE;
import static org.lwjgl.opengl.GL11.GL_REPEAT;
import static org.lwjgl.opengl.GL11.GL_RED;
import static org.lwjgl.opengl.GL11.GL_RGB;
import static org.lwjgl.opengl.GL11.GL_RGBA;
import static org.lwjgl.opengl.GL11.GL_TEXTURE_2D;
import static org.lwjgl.opengl.GL11.GL_TEXTURE_BORDER_COLOR;
import static org.lwjgl.opengl.GL11.GL_TEXTURE_MAG_FILTER;
import static org.lwjgl.opengl.GL11.GL_TEXTURE_MIN_FILTER;
import static org.lwjgl.opengl.GL11.GL_SHORT;
import static org.lwjgl.opengl.GL11.GL_TEXTURE_WRAP_S;
import static org.lwjgl.opengl.GL11.GL_TEXTURE_WRAP_T;
import static org.lwjgl.opengl.GL11.GL_UNSIGNED_BYTE;
import static org.lwjgl.opengl.GL11.glBindTexture;
import static org.lwjgl.opengl.GL11.glDrawBuffer;
import static org.lwjgl.opengl.GL11.glGenTextures;
import static org.lwjgl.opengl.GL11.glReadBuffer;
import static org.lwjgl.opengl.GL11.glTexImage2D;
import static org.lwjgl.opengl.GL11.glTexParameterfv;
import static org.lwjgl.opengl.GL11.glTexParameteri;
import static org.lwjgl.opengl.GL12.GL_CLAMP_TO_EDGE;
import static org.lwjgl.opengl.GL13.GL_CLAMP_TO_BORDER;
import static org.lwjgl.opengl.GL20.glDrawBuffers;
import static org.lwjgl.opengl.GL30.GL_COLOR_ATTACHMENT0;
import static org.lwjgl.opengl.GL30.GL_COLOR_ATTACHMENT1;
import static org.lwjgl.opengl.GL30.GL_DEPTH24_STENCIL8;
import static org.lwjgl.opengl.GL30.GL_DEPTH_ATTACHMENT;
import static org.lwjgl.opengl.GL30.GL_DEPTH_STENCIL_ATTACHMENT;
import static org.lwjgl.opengl.GL30.GL_FRAMEBUFFER;
import static org.lwjgl.opengl.GL30.GL_FRAMEBUFFER_COMPLETE;
import static org.lwjgl.opengl.GL30.GL_RENDERBUFFER;
import static org.lwjgl.opengl.GL30.GL_RGBA16F;
import static org.lwjgl.opengl.GL30.GL_HALF_FLOAT;
import static org.lwjgl.opengl.GL30.GL_R8;
import static org.lwjgl.opengl.GL30.GL_RED;
import static org.lwjgl.opengl.GL30.glBindFramebuffer;
import static org.lwjgl.opengl.GL30.glBindRenderbuffer;
import static org.lwjgl.opengl.GL30.glCheckFramebufferStatus;
import static org.lwjgl.opengl.GL30.glFramebufferRenderbuffer;
import static org.lwjgl.opengl.GL30.glFramebufferTexture2D;
import static org.lwjgl.opengl.GL30.glGenRenderbuffers;
import static org.lwjgl.opengl.GL30.glRenderbufferStorage;
import static org.lwjgl.system.MemoryUtil.NULL;
import static org.lwjgl.opengl.GL45.glNamedFramebufferDrawBuffer;
import static org.lwjgl.opengl.GL45.glNamedFramebufferDrawBuffers;
import static org.lwjgl.opengl.GL45.glNamedFramebufferReadBuffer;
/**
* Utilities for framebuffer creation
*/
public class FramebufferUtils {
public static Texture generateScreenTextureColor(int width, int height){
int texturePtr = glGenTextures();
glBindTexture(GL_TEXTURE_2D,texturePtr);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
public static Texture generateScreenTextureColor(OpenGLState openGLState, int width, int height){
Texture texture = new Texture();
texture.glTexImage2D(openGLState, width, height, GL_RGB, GL_UNSIGNED_BYTE);
texture.setMinFilter(GL_LINEAR);
texture.setMagFilter(GL_LINEAR);
//these make sure the texture actually clamps to the borders of the quad
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
Texture texture = new Texture(texturePtr);
texture.setWrap(GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
texture.setWrap(GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
texture.checkStatus(openGLState);
return texture;
}
public static Texture generateScreenTextureColorAlpha(int width, int height){
int texturePtr = glGenTextures();
glBindTexture(GL_TEXTURE_2D,texturePtr);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
public static Texture generateScreenTextureColorAlpha(OpenGLState openGLState, int width, int height){
Texture texture = new Texture();
texture.glTexImage2D(openGLState, width, height, GL_RGBA, GL_UNSIGNED_BYTE);
texture.setMinFilter(GL_LINEAR);
texture.setMagFilter(GL_LINEAR);
//these make sure the texture actually clamps to the borders of the quad
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
Texture texture = new Texture(texturePtr);
texture.setWrap(GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
texture.setWrap(GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
texture.checkStatus(openGLState);
return texture;
}
public static Texture generateScreenTextureDepth(int width, int height){
int texturePtr = glGenTextures();
glBindTexture(GL_TEXTURE_2D,texturePtr);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, width, height, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
Texture texture = new Texture(texturePtr);
public static Texture generateScreenTextureDepth(OpenGLState openGLState, int width, int height){
Texture texture = new Texture();
texture.glTexImage2D(openGLState, width, height, GL_DEPTH_COMPONENT, GL_FLOAT);
texture.checkStatus(openGLState);
return texture;
}
public static Framebuffer generateScreenTextureFramebuffer(int width, int height, Texture colorTexture, Texture depthTexture){
public static Framebuffer generateScreenTextureFramebuffer(OpenGLState openGLState, int width, int height, Texture colorTexture, Texture depthTexture){
Framebuffer buffer = new Framebuffer();
buffer.bind();
//texture
// int texture = glGenTextures();
// glBindTexture(GL_TEXTURE_2D,texture);
@ -115,22 +88,17 @@ public class FramebufferUtils {
// //these make sure the texture actually clamps to the borders of the quad
// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
buffer.setTexturePointer(colorTexture.getTexturePointer());
//bind texture to fbo
int mipMapLevel = 0;
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture.getTexturePointer(), mipMapLevel);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTexture.getTexturePointer(), mipMapLevel);
buffer.setMipMapLevel(0);
buffer.attachTexture(openGLState,colorTexture);
buffer.setDepthAttachment(openGLState,depthTexture.getTexturePointer());
//check make sure compiled
if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE){
System.out.println("Framebuffer is not complete!");
}
glBindFramebuffer(GL_FRAMEBUFFER, 0);
buffer.checkStatus();
return buffer;
}
public static Framebuffer generateScreenTextureFramebuffer(int width, int height, Texture colorTexture){
public static Framebuffer generateScreenTextureFramebuffer(OpenGLState openGLState, int width, int height, Texture colorTexture){
Framebuffer buffer = new Framebuffer();
buffer.bind();
//texture
// int texture = glGenTextures();
// glBindTexture(GL_TEXTURE_2D,texture);
@ -140,34 +108,29 @@ public class FramebufferUtils {
// //these make sure the texture actually clamps to the borders of the quad
// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
buffer.setTexturePointer(colorTexture.getTexturePointer());
//bind texture to fbo
int mipMapLevel = 0;
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture.getTexturePointer(), mipMapLevel);
buffer.setMipMapLevel(0);
buffer.attachTexture(openGLState,colorTexture.getTexturePointer());
//check make sure compiled
if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE){
System.out.println("Framebuffer is not complete!");
}
glBindFramebuffer(GL_FRAMEBUFFER, 0);
buffer.checkStatus();
return buffer;
}
public static Framebuffer generateScreensizeTextureFramebuffer(){
public static Framebuffer generateScreensizeTextureFramebuffer(OpenGLState openGLState){
Framebuffer buffer = new Framebuffer();
buffer.bind();
buffer.bind(openGLState);
//texture
int texture = glGenTextures();
glBindTexture(GL_TEXTURE_2D,texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, Globals.WINDOW_WIDTH, Globals.WINDOW_HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
Texture texture = new Texture();
texture.glTexImage2D(openGLState, Globals.WINDOW_WIDTH, Globals.WINDOW_HEIGHT, GL_RGB, GL_UNSIGNED_BYTE);
texture.setMinFilter(GL_LINEAR);
texture.setMagFilter(GL_LINEAR);
//these make sure the texture actually clamps to the borders of the quad
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
buffer.setTexturePointer(texture);
texture.setWrap(GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
texture.setWrap(GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
texture.checkStatus(openGLState);
//bind texture to fbo
int mipMapLevel = 0;
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, mipMapLevel);
buffer.setMipMapLevel(0);
buffer.attachTexture(openGLState,texture);
//renderbuffer
int renderBuffer = glGenRenderbuffers();
glBindRenderbuffer(GL_RENDERBUFFER, renderBuffer);
@ -175,28 +138,25 @@ public class FramebufferUtils {
//bind rbo to fbo
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, renderBuffer);
//check make sure compiled
if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE){
System.out.println("Framebuffer is not complete!");
}
buffer.checkStatus();
return buffer;
}
public static Framebuffer generateTextureFramebuffer(int width, int height){
public static Framebuffer generateTextureFramebuffer(OpenGLState openGLState, int width, int height){
Framebuffer buffer = new Framebuffer();
buffer.bind();
buffer.bind(openGLState);
//texture
int texture = glGenTextures();
glBindTexture(GL_TEXTURE_2D,texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
Texture texture = new Texture();
texture.glTexImage2D(openGLState, width, height, GL_RGBA, GL_UNSIGNED_BYTE);
texture.setMinFilter(GL_LINEAR);
texture.setMagFilter(GL_LINEAR);
//these make sure the texture actually clamps to the borders of the quad
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
buffer.setTexturePointer(texture);
texture.setWrap(GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
texture.setWrap(GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
texture.checkStatus(openGLState);
//bind texture to fbo
int mipMapLevel = 0;
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, mipMapLevel);
buffer.setMipMapLevel(0);
buffer.attachTexture(openGLState,texture);
//renderbuffer
int renderBuffer = glGenRenderbuffers();
glBindRenderbuffer(GL_RENDERBUFFER, renderBuffer);
@ -204,9 +164,7 @@ public class FramebufferUtils {
//bind rbo to fbo
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, renderBuffer);
//check make sure compiled
if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE){
System.out.println("Framebuffer is not complete!");
}
buffer.checkStatus();
return buffer;
}
@ -214,10 +172,11 @@ public class FramebufferUtils {
public static Renderbuffer generateScreensizeStencilDepthRenderbuffer(){
public static Renderbuffer generateScreensizeStencilDepthRenderbuffer(OpenGLState openGLState){
Renderbuffer buffer = new Renderbuffer();
buffer.bind();
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, Globals.WINDOW_WIDTH, Globals.WINDOW_HEIGHT);
Globals.renderingEngine.checkError();
return buffer;
}
@ -225,121 +184,93 @@ public class FramebufferUtils {
static int depthMapWidth = 4096;
static int depthMapHeight = 4096;
public static Framebuffer generateDepthBuffer(){
public static Framebuffer generateDepthBuffer(OpenGLState openGLState){
Framebuffer buffer = new Framebuffer();
buffer.bind();
buffer.bind(openGLState);
//texture
int texture = glGenTextures();
glBindTexture(GL_TEXTURE_2D,texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, depthMapWidth, depthMapHeight, 0, GL_DEPTH_COMPONENT, GL_FLOAT , NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
float borderColor[] = { 1.0f, 1.0f, 1.0f, 1.0f };
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor);
buffer.setTexturePointer(texture);
Texture texture = new Texture();
texture.glTexImage2D(openGLState, depthMapWidth, depthMapHeight, GL_DEPTH_COMPONENT, GL_FLOAT);
texture.setMinFilter(GL_NEAREST);
texture.setMagFilter(GL_NEAREST);
texture.setWrap(GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
texture.setWrap(GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
texture.setBorderColor(new float[]{ 1.0f, 1.0f, 1.0f, 1.0f });
texture.checkStatus(openGLState);
//bind texture to fbo
int mipMapLevel = 0;
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, texture, mipMapLevel);
glDrawBuffer(GL_NONE);
glReadBuffer(GL_NONE);
buffer.setMipMapLevel(0);
buffer.setDepthAttachment(openGLState,texture.getTexturePointer());
glNamedFramebufferDrawBuffer(buffer.getFramebufferPointer(), GL_NONE);
glNamedFramebufferReadBuffer(buffer.getFramebufferPointer(), GL_NONE);
//check make sure compiled
if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE){
System.out.println("Framebuffer is not complete!");
}
buffer.checkStatus();
return buffer;
}
public static Texture generateDepthBufferTexture(int width, int height){
int texturePtr = glGenTextures();
glBindTexture(GL_TEXTURE_2D,texturePtr);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, width, height, 0, GL_DEPTH_COMPONENT, GL_FLOAT , NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
float borderColor[] = { 1.0f, 1.0f, 1.0f, 1.0f };
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor);
Texture texture = new Texture(texturePtr);
public static Texture generateDepthBufferTexture(OpenGLState openGLState, int width, int height){
Texture texture = new Texture();
texture.glTexImage2D(openGLState, width, height, GL_DEPTH_COMPONENT, GL_SHORT);
texture.setMinFilter(GL_NEAREST);
texture.setMagFilter(GL_NEAREST);
texture.setWrap(GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
texture.setWrap(GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
texture.setBorderColor(new float[]{ 1.0f, 1.0f, 1.0f, 1.0f });
texture.checkStatus(openGLState);
return texture;
}
public static Framebuffer generateDepthBuffer(int width, int height, Texture texture){
public static Framebuffer generateDepthBuffer(OpenGLState openGLState, int width, int height, Texture texture){
Framebuffer buffer = new Framebuffer();
buffer.bind();
//texture
buffer.setTexturePointer(texture.getTexturePointer());
buffer.bind(openGLState);
//bind texture to fbo
int mipMapLevel = 0;
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, texture.getTexturePointer(), mipMapLevel);
glDrawBuffer(GL_NONE);
glReadBuffer(GL_NONE);
buffer.setMipMapLevel(0);
buffer.setDepthAttachment(openGLState,texture.getTexturePointer());
glNamedFramebufferDrawBuffer(buffer.getFramebufferPointer(), GL_NONE);
glNamedFramebufferReadBuffer(buffer.getFramebufferPointer(), GL_NONE);
//check make sure compiled
if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE){
System.out.println("Framebuffer is not complete!");
}
buffer.checkStatus();
return buffer;
}
public static Texture generateOITAccumulatorTexture(int width, int height){
int texturePtr = glGenTextures();
glBindTexture(GL_TEXTURE_2D,texturePtr);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, width, height, 0, GL_RGBA, GL_HALF_FLOAT, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glBindTexture(GL_TEXTURE_2D, 0);
Texture texture = new Texture(texturePtr);
public static Texture generateOITAccumulatorTexture(OpenGLState openGLState, int width, int height){
Texture texture = new Texture();
texture.setMinFilter(GL_LINEAR);
texture.setMagFilter(GL_LINEAR);
texture.glTexImage2D(openGLState, width, height, GL_RGBA, GL_HALF_FLOAT);
texture.checkStatus(openGLState);
return texture;
}
public static Texture generateOITRevealageTexture(int width, int height){
int texturePtr = glGenTextures();
glBindTexture(GL_TEXTURE_2D,texturePtr);
glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, width, height, 0, GL_RED, GL_FLOAT, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glBindTexture(GL_TEXTURE_2D, 0);
Texture texture = new Texture(texturePtr);
public static Texture generateOITRevealageTexture(OpenGLState openGLState, int width, int height){
Texture texture = new Texture();
texture.setMinFilter(GL_LINEAR);
texture.setMagFilter(GL_LINEAR);
texture.glTexImage2D(openGLState, width, height, GL_RED, GL_FLOAT);
texture.checkStatus(openGLState);
return texture;
}
public static Framebuffer generateOITFramebuffer(int width, int height, Texture accumulatorTex, Texture revealageTex, Texture depthTexture){
public static Framebuffer generateOITFramebuffer(OpenGLState openGLState, int width, int height, Texture accumulatorTex, Texture revealageTex, Texture depthTexture){
Framebuffer buffer = new Framebuffer();
buffer.bind();
buffer.bind(openGLState);
//texture
buffer.setTexturePointer(accumulatorTex.getTexturePointer());
//bind texture to fbo
int mipMapLevel = 0;
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, accumulatorTex.getTexturePointer(), mipMapLevel);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, revealageTex.getTexturePointer(), mipMapLevel);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTexture.getTexturePointer(), mipMapLevel);
buffer.setMipMapLevel(0);
buffer.attachTexture(openGLState,accumulatorTex.getTexturePointer(),0);
buffer.attachTexture(openGLState,revealageTex.getTexturePointer(),1);
buffer.setDepthAttachment(openGLState,depthTexture.getTexturePointer());
// const GLenum transparentDrawBuffers[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 };
// glDrawBuffers(2, transparentDrawBuffers);
@ -347,13 +278,10 @@ public class FramebufferUtils {
drawBuffers.put(GL_COLOR_ATTACHMENT0);
drawBuffers.put(GL_COLOR_ATTACHMENT1);
drawBuffers.flip();
glDrawBuffers(drawBuffers);
glNamedFramebufferDrawBuffers(buffer.getFramebufferPointer(),drawBuffers);
//check make sure compiled
if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE){
System.out.println("Framebuffer is not complete!");
}
glBindFramebuffer(GL_FRAMEBUFFER, 0);
buffer.checkStatus();
return buffer;
}

View File

@ -12,6 +12,8 @@ import org.lwjgl.opengl.GL31;
import electrosphere.engine.Globals;
import electrosphere.entity.types.camera.CameraEntityUtils;
import electrosphere.logger.LoggerInterface;
import electrosphere.renderer.shader.ShaderProgram;
/**
* Manages the light sources in the engine
@ -155,11 +157,16 @@ public class LightManager {
public void bindBuffer(int shaderIndex){
//get position of lights object in shader
int bufferIndex = GL31.glGetUniformBlockIndex(shaderIndex, "Lights");
//bind that position to the slot '2'
GL31.glUniformBlockBinding(shaderIndex, bufferIndex, BIND_POINT);
//bind our buffer to slot '2' as well
GL31.glBindBufferBase(GL_UNIFORM_BUFFER, BIND_POINT, uboIndex);
if(bufferIndex == ShaderProgram.INVALID_UNIFORM_NAME){
LoggerInterface.loggerRenderer.INFO("Tried to buffer light manager to shader that does not have it active.");
} else {
//bind that position to the slot '2'
GL31.glUniformBlockBinding(shaderIndex, bufferIndex, BIND_POINT);
//bind our buffer to slot '2' as well
GL31.glBindBufferBase(GL_UNIFORM_BUFFER, BIND_POINT, uboIndex);
}
//alternatively if want to use range, do glBindBufferRange(GL_UNIFORM_BUFFER, 2, uboExampleBlock, 0, 152);
Globals.renderingEngine.checkError();
}
/**

View File

@ -5,11 +5,7 @@ import electrosphere.renderer.OpenGLState;
import electrosphere.renderer.texture.Texture;
import org.lwjgl.assimp.AIMaterial;
import static org.lwjgl.opengl.GL11.GL_TEXTURE_2D;
import static org.lwjgl.opengl.GL11.glBindTexture;
import static org.lwjgl.opengl.GL13.GL_TEXTURE0;
import static org.lwjgl.opengl.GL13.glActiveTexture;
import static org.lwjgl.opengl.GL20.glGetUniformLocation;
import static org.lwjgl.opengl.GL20.glUniform1i;
/**
*
@ -91,16 +87,17 @@ public class Material {
Texture diffuseTexture = Globals.assetManager.fetchTexture(diffuse);
if(diffuseTexture != null){
diffuseTexture.bind(openGLState,0);
glUniform1i(glGetUniformLocation(Globals.renderingEngine.getOpenGLState().getActiveShader().getShaderId(), "material.diffuse"), 0);
openGLState.getActiveShader().setUniform(openGLState, "material.diffuse", 0);
}
Texture specularTexture = Globals.assetManager.fetchTexture(specular);
if(specularTexture != null){
specularTexture.bind(openGLState,1);
glUniform1i(glGetUniformLocation(Globals.renderingEngine.getOpenGLState().getActiveShader().getShaderId(), "material.specular"), 1);
openGLState.getActiveShader().setUniform(openGLState, "material.specular", 1);
}
} else {
openGLState.glBindTextureUnit(GL_TEXTURE0, texturePointer, GL_TEXTURE_2D);
}
Globals.renderingEngine.checkError();
}
public void apply_material(OpenGLState openGLState, int diffuse_channel, int specular_channel){
Texture diffuseTexture = Globals.assetManager.fetchTexture(diffuse);
@ -111,6 +108,7 @@ public class Material {
if(specularTexture != null){
specularTexture.bind(openGLState,specular_channel);
}
Globals.renderingEngine.checkError();
}
public boolean isTransparent(){

View File

@ -4,7 +4,6 @@ import electrosphere.engine.Globals;
import electrosphere.entity.types.camera.CameraEntityUtils;
import electrosphere.renderer.OpenGLState;
import electrosphere.renderer.RenderPipelineState;
import electrosphere.renderer.RenderPipelineState.SelectedShaderEnum;
import electrosphere.renderer.actor.ActorTextureMask;
import electrosphere.renderer.actor.instance.InstanceData;
import electrosphere.renderer.buffer.HomogenousInstancedArray;
@ -28,8 +27,6 @@ import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL15;
import org.lwjgl.opengl.GL20;
import static org.lwjgl.opengl.GL11.GL_FLOAT;
import static org.lwjgl.opengl.GL11.GL_INT;
import static org.lwjgl.opengl.GL11.GL_TEXTURE_2D;
@ -50,7 +47,6 @@ import static org.lwjgl.opengl.GL20.glUniformMatrix4fv;
import static org.lwjgl.opengl.GL20.glVertexAttribPointer;
import static org.lwjgl.opengl.GL30.glBindVertexArray;
import static org.lwjgl.opengl.GL30.glGenVertexArrays;
import static org.lwjgl.opengl.GL40.*;
import org.lwjgl.opengl.GL45;
import org.lwjgl.system.MemoryStack;
@ -365,6 +361,7 @@ public class Mesh {
selectedProgram = shader;
}
openGLState.setActiveShader(renderPipelineState, selectedProgram);
Globals.renderingEngine.checkError();
}
if(renderPipelineState.getUseLight()){
@ -376,20 +373,23 @@ public class Mesh {
LightManager lightManager = Globals.renderingEngine.getLightManager();
lightManager.bindBuffer(openGLState.getActiveShader().getShaderId());
}
Globals.renderingEngine.checkError();
}
if(renderPipelineState.getUseMaterial() && textureMask == null){
Globals.renderingEngine.checkError();
if(material == null){
Globals.materialDefault.apply_material(openGLState,0,1);
GL20.glUniform1i(glGetUniformLocation(openGLState.getActiveShader().getShaderId(), "hasTransparency"), 0);
openGLState.getActiveShader().setUniform(openGLState, "hasTransparency", 0);
} else {
material.apply_material(openGLState);
if(material.hasTransparency){
GL20.glUniform1i(glGetUniformLocation(openGLState.getActiveShader().getShaderId(), "hasTransparency"), 1);
openGLState.getActiveShader().setUniform(openGLState, "hasTransparency", 1);
} else {
GL20.glUniform1i(glGetUniformLocation(openGLState.getActiveShader().getShaderId(), "hasTransparency"), 0);
openGLState.getActiveShader().setUniform(openGLState, "hasTransparency", 0);
}
}
Globals.renderingEngine.checkError();
}
@ -415,12 +415,14 @@ public class Mesh {
// glUniform1i(glGetUniformLocation(Globals.renderingEngine.getActiveShader().shaderProgram, "groundTextures[" + j + "]"),6+j);
// }
// glActiveTexture(GL_TEXTURE0);
Globals.renderingEngine.checkError();
}
if(renderPipelineState.getUseShadowMap()){
openGLState.glActiveTexture(GL_TEXTURE3);
openGLState.glBindTexture(GL_TEXTURE_2D, Globals.shadowMapTextureLoc);
glUniform1i(glGetUniformLocation(openGLState.getActiveShader().getShaderId(), "shadowMap"), 3);
Globals.renderingEngine.checkError();
}
@ -462,6 +464,7 @@ public class Mesh {
} else {
glUniform1i(glGetUniformLocation(openGLState.getActiveShader().getShaderId(), "hasBones"), 0);
}
Globals.renderingEngine.checkError();
if(renderPipelineState.getBufferStandardUniforms()){
@ -477,10 +480,12 @@ public class Mesh {
glUniform1i(glGetUniformLocation(openGLState.getActiveShader().getShaderId(), "frame"), (int)Globals.timekeeper.getNumberOfRenderFramesElapsed());
glUniform1f(glGetUniformLocation(openGLState.getActiveShader().getShaderId(), "time"), (float)Globals.timekeeper.getCurrentRendererTime());
}
Globals.renderingEngine.checkError();
}
if(renderPipelineState.getBufferNonStandardUniforms()){
bufferAllUniforms(openGLState);
Globals.renderingEngine.checkError();
}
if(renderPipelineState.getInstanced()){
@ -490,6 +495,7 @@ public class Mesh {
Map<ShaderAttribute,HomogenousInstancedArray> glBufferMap = instanceData.getGlBufferMap();
bufferInstanceData(renderPipelineState, buffers, glBufferMap);
renderPipelineState.setInstanceCount(instanceData.getDrawCount());
Globals.renderingEngine.checkError();
}
}
@ -503,6 +509,7 @@ public class Mesh {
GL11.glDrawArrays(GL_TRIANGLES, 0, elementCount);
}
}
Globals.renderingEngine.checkError();
glBindVertexArray(0);
}

View File

@ -23,7 +23,7 @@ public class CompositePipeline implements RenderPipeline {
GL40.glEnable(GL40.GL_BLEND);
GL40.glBlendFunc(GL40.GL_SRC_ALPHA, GL40.GL_ONE_MINUS_SRC_ALPHA);
RenderingEngine.screenFramebuffer.bind();
RenderingEngine.screenFramebuffer.bind(openGLState);
GL40.glBindVertexArray(RenderingEngine.screenTextureVAO);

View File

@ -41,7 +41,7 @@ public class DebugContentPipeline implements RenderPipeline {
Globals.profiler.beginCpuSample("DebugContentPipeline.render");
//bind screen fbo
RenderingEngine.screenFramebuffer.bind();
RenderingEngine.screenFramebuffer.bind(openGLState);
openGLState.glDepthTest(true);
openGLState.glDepthFunc(GL40.GL_LESS);
GL40.glDepthMask(true);

View File

@ -35,8 +35,8 @@ public class FirstPersonItemsPipeline implements RenderPipeline {
/**
* Initializes the pipeline
*/
public void init(){
this.firstPersonFramebuffer = FramebufferUtils.generateTextureFramebuffer(Globals.WINDOW_WIDTH, Globals.WINDOW_HEIGHT);
public void init(OpenGLState openGLState){
this.firstPersonFramebuffer = FramebufferUtils.generateTextureFramebuffer(openGLState, Globals.WINDOW_WIDTH, Globals.WINDOW_HEIGHT);
}
@Override
@ -48,7 +48,7 @@ public class FirstPersonItemsPipeline implements RenderPipeline {
}
//setup opengl state
this.firstPersonFramebuffer.bind();
this.firstPersonFramebuffer.bind(openGLState);
renderPipelineState.setUseBones(true);
renderPipelineState.setUseLight(false);
renderPipelineState.setUseMaterial(true);

View File

@ -41,6 +41,9 @@ public class ImGuiPipeline implements RenderPipeline {
public ImGuiPipeline(long windowId, String glslVersion){
//init imgui (must happen after gl.createCapabilities)
imGuiContext = ImGui.createContext();
if(!imGuiContext.isValidPtr()){
throw new IllegalStateException("Imgui failed to initialize.");
}
ImPlot.createContext();
imGuiGlfw.init(Globals.window,true);
imGuiGl13.init(glslVersion);

View File

@ -25,7 +25,7 @@ public class MainContentNoOITPipeline implements RenderPipeline {
Globals.profiler.beginCpuSample("MainContentNoOITPipeline.render");
//bind screen fbo
RenderingEngine.screenFramebuffer.bind();
RenderingEngine.screenFramebuffer.bind(openGLState);
openGLState.glDepthTest(true);
openGLState.glDepthFunc(GL40.GL_LESS);
GL40.glDepthMask(true);

View File

@ -34,7 +34,7 @@ public class MainContentPipeline implements RenderPipeline {
Matrix4d modelTransformMatrix = new Matrix4d();
//bind screen fbo
RenderingEngine.screenFramebuffer.bind();
RenderingEngine.screenFramebuffer.bind(openGLState);
openGLState.glDepthTest(true);
openGLState.glDepthFunc(GL40.GL_LESS);
GL40.glDepthMask(true);
@ -131,7 +131,7 @@ public class MainContentPipeline implements RenderPipeline {
GL40.glBlendFunci(1, GL40.GL_ZERO, GL40.GL_ONE_MINUS_SRC_COLOR);
GL40.glBlendEquation(GL40.GL_FUNC_ADD);
RenderingEngine.transparencyBuffer.bind();
RenderingEngine.transparencyBuffer.bind(openGLState);
GL40.glClearBufferfv(GL40.GL_COLOR,0,RenderingEngine.transparencyAccumulatorClear);
GL40.glClearBufferfv(GL40.GL_COLOR,1,RenderingEngine.transparencyRevealageClear);

View File

@ -28,7 +28,7 @@ public class NormalsForOutlinePipeline implements RenderPipeline {
*/
//bind screen fbo
RenderingEngine.gameImageNormalsFramebuffer.bind();
RenderingEngine.gameImageNormalsFramebuffer.bind(openGLState);
openGLState.glDepthTest(true);
GL40.glDisable(GL40.GL_BLEND);
GL40.glBlendFunc(GL40.GL_SRC_ALPHA, GL40.GL_ONE_MINUS_SRC_ALPHA);

View File

@ -20,7 +20,7 @@ public class PostProcessingPipeline implements RenderPipeline {
// Outline normals
//
RenderingEngine.normalsOutlineFrambuffer.bind();
RenderingEngine.normalsOutlineFrambuffer.bind(openGLState);
ShaderProgram program = Globals.assetManager.fetchShader("Shaders/anime/outlineNormals.vs", null, "Shaders/anime/outlineNormals.fs");
if(program != null){
openGLState.setActiveShader(renderPipelineState, program);

View File

@ -34,7 +34,7 @@ public class ShadowMapPipeline implements RenderPipeline {
openGLState.setActiveShader(renderPipelineState, RenderingEngine.lightDepthShaderProgram);
RenderingEngine.lightDepthBuffer.bind();
RenderingEngine.lightDepthBuffer.bind(openGLState);
GL40.glClear(GL40.GL_DEPTH_BUFFER_BIT);
openGLState.glActiveTexture(GL40.GL_TEXTURE0);

View File

@ -38,7 +38,7 @@ public class VolumeBufferPipeline implements RenderPipeline {
openGLState.setActiveShader(renderPipelineState, RenderingEngine.volumeDepthShaderProgram);
RenderingEngine.volumeDepthBackfaceFramebuffer.bind();
RenderingEngine.volumeDepthBackfaceFramebuffer.bind(openGLState);
GL40.glClear(GL40.GL_DEPTH_BUFFER_BIT);
openGLState.glActiveTexture(GL40.GL_TEXTURE0);
// glBindTexture(GL_TEXTURE_2D, woodTexture);
@ -137,7 +137,7 @@ public class VolumeBufferPipeline implements RenderPipeline {
openGLState.setActiveShader(renderPipelineState, RenderingEngine.volumeDepthShaderProgram);
RenderingEngine.volumeDepthFrontfaceFramebuffer.bind();
RenderingEngine.volumeDepthFrontfaceFramebuffer.bind(openGLState);
GL40.glClear(GL40.GL_DEPTH_BUFFER_BIT);
openGLState.glActiveTexture(GL40.GL_TEXTURE0);
// glBindTexture(GL_TEXTURE_2D, woodTexture);

View File

@ -38,6 +38,7 @@ import org.lwjgl.opengl.GL40;
import electrosphere.engine.Globals;
import electrosphere.logger.LoggerInterface;
import electrosphere.renderer.OpenGLState;
import electrosphere.util.FileUtils;
/**
@ -763,6 +764,23 @@ public class ShaderProgram {
}
}
//returned if the uniform isn't found
public static final int INVALID_UNIFORM_NAME = -1;
/**
* Tries to set a uniform
* @param uniformName The name of the uniform
* @param value The value to set the uniform to
*/
public void setUniform(OpenGLState openGLState, String uniformName, Object value){
int uniformLocation = glGetUniformLocation(this.getShaderId(), uniformName);
if(uniformLocation == INVALID_UNIFORM_NAME){
LoggerInterface.loggerRenderer.INFO("Searched for uniform in a shader that does not contain it. Uniform name: \"" + uniformName + "\"");
} else {
setUniform(uniformLocation, value);
}
}
/**
* Gets the id of the shader

View File

@ -1,64 +1,84 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package electrosphere.renderer.texture;
import electrosphere.engine.Globals;
import electrosphere.engine.Main;
import electrosphere.logger.LoggerInterface;
import electrosphere.renderer.OpenGLState;
import electrosphere.renderer.RenderingEngine;
import electrosphere.util.FileUtils;
import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.GL40;
import org.lwjgl.system.MemoryUtil;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL12.GL_CLAMP_TO_EDGE;
import static org.lwjgl.opengl.GL13.GL_TEXTURE0;
import static org.lwjgl.opengl.GL14.*;
import static org.lwjgl.opengl.GL30.*;
/**
*
* @author amaterasu
* A opengl in texture
*/
public class Texture {
int texturePointer;
int width;
int height;
//the pointer for the texture
int texturePointer = -1;
//the width of the texture
int width = -1;
//the height of the texture
int height = -1;
//whether the texture has transparency or not
boolean hasTransparency;
//the path to the texture
String path = "";
//the border color
float[] borderColor = null;
//the min and max filter
int minFilter = -1;
int maxFilter = -1;
private Texture(){
//the pixel format (ie RGB, ARGB, etc)
int pixelFormat = -1;
}
//the data type of a single component of a pixel (IE UNSIGNED_INT, BYTE, etc)
int datatype = -1;
/**
* Constructs a texture from a pointer
* @param pointer the pointer
*/
public Texture(int pointer){
this.texturePointer = pointer;
}
/**
* Creates a texture with a new opengl texture object
*/
public Texture(){
this.texturePointer = glGenTextures();
}
/**
* Creates an in engine texture object from a java bufferedimage object
* @param bufferedImage The java bufferedimage object
*/
public Texture(BufferedImage bufferedImage){
texturePointer = glGenTextures();
this.texturePointer = glGenTextures();
//bind the new texture
glBindTexture(GL_TEXTURE_2D, texturePointer);
//how are we gonna wrap the texture??
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
this.setWrap(GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
this.setWrap(GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
//set the border color to black
float borderColor[] = { 0.0f, 0.0f, 0.0f, 1.0f };
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor);
this.setBorderColor(new float[]{ 0.0f, 0.0f, 0.0f, 1.0f });
//set magnification and minification operation sampling strategies
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
this.setMinFilter(GL_LINEAR);
this.setMagFilter(GL_LINEAR);
//load the image here
ByteBuffer data;
width = 1;
@ -101,30 +121,42 @@ public class Texture {
}
//buffer the texture information
if(hasTransparency){
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
this.pixelFormat = GL_RGBA;
this.datatype = GL_UNSIGNED_BYTE;
this.glTexImage2D(width, height, GL_RGBA, GL_UNSIGNED_BYTE, data);
} else {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
this.pixelFormat = GL_RGB;
this.datatype = GL_UNSIGNED_BYTE;
this.glTexImage2D(width, height, GL_RGB, GL_UNSIGNED_BYTE, data);
}
glGenerateMipmap(GL_TEXTURE_2D);
//check build status
String errorMessage = RenderingEngine.getErrorInEnglish(Globals.renderingEngine.getError());
if(errorMessage != null){
LoggerInterface.loggerRenderer.ERROR(new IllegalStateException("Texture Constructor[from bufferedimage]: " + errorMessage));
}
glBindTexture(GL_TEXTURE_2D, 0);
}
/**
* Creates a texture from an existing file
* @param path The path to the image file
*/
public Texture(String path){
this.path = path;
if(!Globals.HEADLESS){
//generate the texture object on gpu
texturePointer = glGenTextures();
this.texturePointer = glGenTextures();
//bind the new texture
glBindTexture(GL_TEXTURE_2D, texturePointer);
//how are we gonna wrap the texture??
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
this.setWrap(GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
this.setWrap(GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
//set the border color to black
float borderColor[] = { 0.0f, 0.0f, 0.0f, 1.0f };
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor);
this.setBorderColor(new float[]{ 0.0f, 0.0f, 0.0f, 1.0f });
//set magnification and minification operation sampling strategies
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
this.setMinFilter(GL_LINEAR);
this.setMagFilter(GL_LINEAR);
//load the image here
ByteBuffer data;
width = 1;
@ -192,13 +224,22 @@ public class Texture {
}
//buffer the texture information
if(hasTransparency){
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
this.pixelFormat = GL_RGBA;
this.datatype = GL_UNSIGNED_BYTE;
this.glTexImage2D(width, height, GL_RGBA, GL_UNSIGNED_BYTE, data);
} else {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
this.pixelFormat = GL_RGB;
this.datatype = GL_UNSIGNED_BYTE;
this.glTexImage2D(width, height, GL_RGB, GL_UNSIGNED_BYTE, data);
}
glGenerateMipmap(GL_TEXTURE_2D);
//OPTIONAL free the original image data now that it's on the gpu
// System.gc();
//check build status
String errorMessage = RenderingEngine.getErrorInEnglish(Globals.renderingEngine.getError());
if(errorMessage != null){
LoggerInterface.loggerRenderer.ERROR(new IllegalStateException("Texture Constructor[from bufferedimage]: " + errorMessage));
}
}
}
@ -211,43 +252,257 @@ public class Texture {
public Texture(ByteBuffer buffer, int width, int height){
if(!Globals.HEADLESS){
//generate the texture object on gpu
texturePointer = glGenTextures();
this.texturePointer = glGenTextures();
//bind the new texture
glBindTexture(GL_TEXTURE_2D, texturePointer);
//how are we gonna wrap the texture??
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
this.setWrap(GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
this.setWrap(GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
//disable mipmap
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
this.setMinFilter(GL_LINEAR);
//call if width != height so opengl figures out how to unpack it properly
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
//GL_RED = 32bit r value
//buffer the texture information
glTexImage2D(GL_TEXTURE_2D, 0, GL_R32F, width, height, 0, GL_RED, GL_FLOAT, buffer);
this.pixelFormat = GL_RED;
this.datatype = GL_FLOAT;
GL40.glTexImage2D(GL_TEXTURE_2D, 0, GL_R32F, width, height, 0, GL_RED, GL_FLOAT, buffer);
//check build status
String errorMessage = RenderingEngine.getErrorInEnglish(Globals.renderingEngine.getError());
if(errorMessage != null){
LoggerInterface.loggerRenderer.ERROR(new IllegalStateException("Texture Constructor[from bytebuffer]: " + errorMessage));
}
}
}
/**
* Binds the texture to unit 0
* @param openGLState The opengl state
*/
public void bind(OpenGLState openGLState){
if(texturePointer == -1){
LoggerInterface.loggerRenderer.ERROR(new IllegalStateException("Tring to bind a texture object that has not been initialized yet"));
}
if(texturePointer == 0){
LoggerInterface.loggerRenderer.ERROR(new IllegalStateException("Trying to bind texture object that has texturepointer of 0"));
}
// openGLState.glActiveTexture(GL_TEXTURE0);
// openGLState.glBindTexture(GL_TEXTURE_2D, texturePointer);
openGLState.glBindTextureUnit(GL_TEXTURE0,texturePointer,GL_TEXTURE_2D);
openGLState.glBindTextureUnit(GL_TEXTURE0,this.texturePointer,GL_TEXTURE_2D);
}
/**
* Binds the texture
* @param openGLState The opengl state
* @param attrib_val The texture unit number
*/
public void bind(OpenGLState openGLState, int attrib_val){
openGLState.glBindTextureUnit(GL_TEXTURE0 + attrib_val,texturePointer,GL_TEXTURE_2D);
if(texturePointer == -1){
LoggerInterface.loggerRenderer.ERROR(new IllegalStateException("Tring to bind a texture object that has not been initialized yet"));
}
if(texturePointer == 0){
LoggerInterface.loggerRenderer.ERROR(new IllegalStateException("Trying to bind texture object that has texturepointer of 0"));
}
openGLState.glBindTextureUnit(GL_TEXTURE0 + attrib_val,this.texturePointer,GL_TEXTURE_2D);
// openGLState.glActiveTexture(GL_TEXTURE0 + attrib_val);
// openGLState.glBindTexture(GL_TEXTURE_2D, texturePointer);
}
/**
* Checks if the texture has transparency or not
* @return true if transparent, false otherwise
*/
public boolean isTransparent(){
return hasTransparency;
}
/**
* Gets the path of the texture
* @return The path
*/
public String getPath(){
return path;
}
/**
* Gets the pointer of the texture
* @return The pointer
*/
public int getTexturePointer(){
return texturePointer;
}
/**
* Sets the wrap strategy of the texture
* @param wrapDir The direction to wrap
* @param wrapType The type of wrapping to perform
*/
public void setWrap(int wrapDir, int wrapType){
//TODO: store wrap type for the direction in this object
glBindTexture(GL_TEXTURE_2D,texturePointer);
glTexParameteri(GL_TEXTURE_2D, wrapDir, wrapType);
}
/**
* Sets the border color
* @param borderColor The color (must be 4 floats)
*/
public void setBorderColor(float borderColor[]){
this.borderColor = borderColor;
glBindTexture(GL_TEXTURE_2D,texturePointer);
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor);
}
/**
* Sets the min filter
* @param minFilter The min filter
*/
public void setMinFilter(int minFilter){
this.minFilter = minFilter;
glBindTexture(GL_TEXTURE_2D,texturePointer);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter);
}
/**
* Sets the max filter
* @param maxFilter The max filter
*/
public void setMagFilter(int maxFilter){
this.maxFilter = maxFilter;
glBindTexture(GL_TEXTURE_2D,texturePointer);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, maxFilter);
}
/**
* Specifies a 2d image
* @param width The width of the image
* @param height The height of the image
* @param format The format of the pixels (ie GL_RGB, GL_RGBA, etc)
* @param datatype The data type of a single component of a pixel (ie GL_BYTE, GL_UNSIGNED_INT, etc)
*/
public void glTexImage2D(OpenGLState openGLState, int width, int height, int format, int datatype){
//store provided values
this.width = width;
this.height = height;
this.pixelFormat = format;
this.datatype = datatype;
//static values going into call
int level = 0;
int border = 0; //this must be 0 according to docs
openGLState.glBindTexture(GL_TEXTURE_2D,texturePointer);
GL40.glTexImage2D(GL_TEXTURE_2D, level, format, width, height, border, format, datatype, MemoryUtil.NULL);
}
/**
* Specifies a 2d image
* @param width The width of the image
* @param height The height of the image
* @param format The format of the pixels (ie GL_RGB, GL_RGBA, etc)
* @param datatype The data type of a single component of a pixel (ie GL_BYTE, GL_UNSIGNED_INT, etc)
* @param data The data to populate the image with
*/
public void glTexImage2D(int width, int height, int format, int datatype, ByteBuffer data){
//store provided values
this.width = width;
this.height = height;
this.pixelFormat = format;
this.datatype = datatype;
//static values going into call
int level = 0;
int border = 0; //this must be 0 according to docs
glBindTexture(GL_TEXTURE_2D,texturePointer);
GL40.glTexImage2D(GL_TEXTURE_2D, level, format, width, height, border, format, datatype, data);
}
/**
* Gets the width of the texture
* @return The width
*/
public int getWidth(){
if(pixelFormat == -1){
throw new IllegalStateException(
"The width of the texture you are trying to query from has not been set yet." +
" The texture was likely constructed by passing the opengl texture pointer into the texture object."
);
}
return width;
}
/**
* Gets the height of the texture
* @return The height
*/
public int getHeight(){
if(pixelFormat == -1){
throw new IllegalStateException(
"The height of the texture you are trying to query from has not been set yet." +
" The texture was likely constructed by passing the opengl texture pointer into the texture object."
);
}
return height;
}
/**
* Gets the format of the pixels
* @return The format of the pixels (ie GL_RGBA, GL_RGB, etc)
*/
public int getFormat(){
if(pixelFormat == -1){
throw new IllegalStateException(
"The pixel format of the texture you are trying to query from has not been set yet." +
" The texture was likely constructed by passing the opengl texture pointer into the texture object."
);
}
return pixelFormat;
}
/**
* Gets the datatype of the pixels
* @return The datatype (IE GL_FLOAT, GL_BYTE, etc)
*/
public int getDataType(){
if(datatype == -1){
throw new IllegalStateException(
"The datatype of the texture you are trying to query from has not been set yet." +
" The texture was likely constructed by passing the opengl texture pointer into the texture object."
);
}
return datatype;
}
/**
* Gets for errors with the texture
* @param state The opengl state
*/
public void checkStatus(OpenGLState state){
this.bind(state);
int errorCode = Globals.renderingEngine.getError();
if(errorCode != GL40.GL_NO_ERROR){
switch(errorCode){
case GL40.GL_INVALID_VALUE: {
if(this.width < 0){
LoggerInterface.loggerRenderer.ERROR("Texture has width less than 0", new IllegalStateException("Texture has width less than 0"));
}
if(this.width > state.getMAX_TEXTURE_WIDTH()){
LoggerInterface.loggerRenderer.ERROR("Texture is greater width than environment allows", new IllegalStateException("Texture is greater width than environment allows"));
}
} break;
}
}
}
@Override
public String toString(){
String rVal = "" +
"Texture[" +
"path=\"" + path + "\", " +
"texturePointer=\"" + texturePointer + "\", " +
"width=\"" + width + "\", " +
"height=\"" + height + "\", " +
"]"
;
return rVal;
}
}

View File

@ -125,7 +125,7 @@ public class WidgetUtils {
int x = Globals.WINDOW_WIDTH - width;
int y = Globals.WINDOW_HEIGHT - height;
// Window rVal = new Window(x, 10, 100, 20);
Window rVal = new Window(x,y,width,height,true);
Window rVal = new Window(Globals.renderingEngine.getOpenGLState(),x,y,width,height,true);
// Window rVal = new Window(100,100,100,100);
// System.out.println(x + " " + y + " " + width + " " + height);
// LayoutSchemeListScrollable rVal = new LayoutSchemeListScrollable(x, y, width, height, true);

View File

@ -55,9 +55,9 @@ public class ActorPanel extends StandardElement implements DrawableElement, Drag
static final Vector3f windowDrawDebugColor = new Vector3f(0.0f,0.0f,1.0f);
public ActorPanel(int x, int y, int width, int height, Actor actor){
public ActorPanel(OpenGLState openGLState, int x, int y, int width, int height, Actor actor){
super();
elementBuffer = FramebufferUtils.generateTextureFramebuffer(width, height);
elementBuffer = FramebufferUtils.generateTextureFramebuffer(openGLState, width, height);
customMat.setTexturePointer(elementBuffer.getTexturePointer());
this.actor = actor;
this.internalPositionX = x;
@ -81,7 +81,7 @@ public class ActorPanel extends StandardElement implements DrawableElement, Drag
int parentHeight
) {
elementBuffer.bind();
elementBuffer.bind(openGLState);
// Globals.renderingEngine.setViewportSize(width, height);
RenderingEngine.setFOV(FOV);
@ -134,7 +134,7 @@ public class ActorPanel extends StandardElement implements DrawableElement, Drag
//this call binds the screen as the "texture" we're rendering to
//have to call before actually rendering
glBindFramebuffer(GL_FRAMEBUFFER, parentFramebufferPointer);
openGLState.glBindFramebuffer(GL_FRAMEBUFFER, parentFramebufferPointer);
//set viewport
openGLState.glViewport(parentWidth, parentHeight);

View File

@ -149,7 +149,7 @@ public class Button extends StandardContainerElement implements DrawableElement,
//this call binds the screen as the "texture" we're rendering to
//have to call before actually rendering
GL30.glBindFramebuffer(GL30.GL_FRAMEBUFFER, parentFramebufferPointer);
openGLState.glBindFramebuffer(GL30.GL_FRAMEBUFFER, parentFramebufferPointer);
openGLState.glViewport(parentWidth, parentHeight);
//error if assets are null

View File

@ -151,7 +151,7 @@ public class ImagePanel extends StandardElement implements DrawableElement, Drag
//this call binds the screen as the "texture" we're rendering to
//have to call before actually rendering
glBindFramebuffer(GL_FRAMEBUFFER, parentFramebufferPointer);
openGLState.glBindFramebuffer(GL_FRAMEBUFFER, parentFramebufferPointer);
openGLState.glViewport(parentWidth, parentHeight);
if(planeModel != null){

View File

@ -33,9 +33,9 @@ public class ScrollableContainer extends StandardContainerElement implements Dra
Vector3f texScale = new Vector3f(1,1,0);
public ScrollableContainer(int positionX, int positionY, int width, int height){
public ScrollableContainer(OpenGLState openGLState, int positionX, int positionY, int width, int height){
super();
widgetBuffer = FramebufferUtils.generateTextureFramebuffer(width, height);
widgetBuffer = FramebufferUtils.generateTextureFramebuffer(openGLState, width, height);
// widgetBuffer = FramebufferUtils.generateScreensizeTextureFramebuffer();
customMat.setTexturePointer(widgetBuffer.getTexturePointer());
// customMat.setTexturePointer(Globals.assetManager.fetchTexture("Textures/Testing1.png").getTexturePointer());
@ -149,7 +149,7 @@ public class ScrollableContainer extends StandardContainerElement implements Dra
Texture windowFrame = Globals.assetManager.fetchTexture("Textures/ui/uiFrame1.png");
widgetBuffer.bind();
widgetBuffer.bind(openGLState);
openGLState.glViewport(width, height);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
@ -163,7 +163,7 @@ public class ScrollableContainer extends StandardContainerElement implements Dra
}
//this call binds the screen as the "texture" we're rendering to
//have to call before actually rendering
glBindFramebuffer(GL_FRAMEBUFFER, parentFramebufferPointer);
openGLState.glBindFramebuffer(GL_FRAMEBUFFER, parentFramebufferPointer);
openGLState.glViewport(parentWidth, parentHeight);
//render background of window

View File

@ -159,7 +159,7 @@ public class TextInput extends StandardContainerElement implements DrawableEleme
//this call binds the screen as the "texture" we're rendering to
//have to call before actually rendering
GL30.glBindFramebuffer(GL30.GL_FRAMEBUFFER, parentFramebufferPointer);
openGLState.glBindFramebuffer(GL30.GL_FRAMEBUFFER, parentFramebufferPointer);
openGLState.glViewport(parentWidth, parentHeight);
//error if assets are null

View File

@ -5,7 +5,6 @@ import static org.lwjgl.opengl.GL11.GL_DEPTH_BUFFER_BIT;
import static org.lwjgl.opengl.GL11.glClear;
import static org.lwjgl.opengl.GL11.glClearColor;
import static org.lwjgl.opengl.GL30.GL_FRAMEBUFFER;
import static org.lwjgl.opengl.GL30.glBindFramebuffer;
import java.util.LinkedList;
import java.util.List;
@ -67,8 +66,8 @@ public class Window implements DrawableElement, ContainerElement, NavigableEleme
* @param width
* @param height
*/
public Window(int positionX, int positionY, int width, int height, boolean showDecorations){
widgetBuffer = FramebufferUtils.generateTextureFramebuffer(width, height);
public Window(OpenGLState openGLState, int positionX, int positionY, int width, int height, boolean showDecorations){
widgetBuffer = FramebufferUtils.generateTextureFramebuffer(openGLState, width, height);
customMat.setTexturePointer(widgetBuffer.getTexturePointer());
float ndcWidth = (float)width/Globals.WINDOW_WIDTH;
float ndcHeight = (float)height/Globals.WINDOW_HEIGHT;
@ -108,7 +107,7 @@ public class Window implements DrawableElement, ContainerElement, NavigableEleme
boxPosition = new Vector3f(ndcX,ndcY,0);
boxDimensions = new Vector3f(ndcWidth,ndcHeight,0);
widgetBuffer.bind();
widgetBuffer.bind(openGLState);
openGLState.glViewport(width, height);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
@ -126,7 +125,7 @@ public class Window implements DrawableElement, ContainerElement, NavigableEleme
}
//this call binds the screen as the "texture" we're rendering to
//have to call before actually rendering
glBindFramebuffer(GL_FRAMEBUFFER, parentFramebufferPointer);
openGLState.glBindFramebuffer(GL_FRAMEBUFFER, parentFramebufferPointer);
openGLState.glViewport(parentWidth, parentHeight);
//error if assets are null

View File

@ -7,11 +7,15 @@ import java.util.Map;
import org.graalvm.polyglot.Context;
import org.graalvm.polyglot.Engine;
import org.graalvm.polyglot.PolyglotException;
import org.graalvm.polyglot.Source;
import org.graalvm.polyglot.Source.Builder;
import org.graalvm.polyglot.Value;
import electrosphere.engine.Globals;
import electrosphere.logger.LoggerInterface;
import electrosphere.util.FileUtils;
import electrosphere.util.MathUtils;
/**
* Interface for executing scripts in the game engine
@ -21,11 +25,44 @@ public class ScriptEngine {
//the graal context
Context context;
//used to build source objects
Builder builder;
//the map of script filepaths to parsed, in-memory scripts
Map<String,Source> sourceMap;
//the javascript object that stores values
Value jsBindingsObject;
Value topLevelValue;
//the object that contains all host values accessible to javascript land
Value hostObject;
//The files that are loaded on init to bootstrap the script engine
static final String[] filesToLoadOnInit = new String[]{
//polyfills
"Scripts/compiler/require_polyfill.js",
//main typescript engine
"Scripts/compiler/typescript.js",
//compiler and utilities
"Scripts/compiler/file_resolution.js",
"Scripts/compiler/compiler.js",
"Scripts/compiler/host_access.js",
};
//The classes that will be provided to the scripting engine
//https://stackoverflow.com/a/65942034
static final Object[][] staticClasses = new Object[][]{
{"mathUtils",MathUtils.class},
};
//singletons from the host that are provided to the javascript context
static final Object[][] hostSingletops = new Object[][]{
{"timekeeper",Globals.timekeeper},
{"currentPlayer",Globals.clientPlayer},
{"loggerScripts",LoggerInterface.loggerScripts},
};
/**
* Initializes the engine
@ -36,11 +73,41 @@ public class ScriptEngine {
//create engine with flag to disable warning
Engine engine = Engine.newBuilder().option("engine.WarnInterpreterOnly", "false").build();
//create context
context = Context.newBuilder("js").engine(engine).build();
//read scripts into source map
readScriptsDirectory("/src/main/sql", FileUtils.getAssetFile("/src/main/sql"));
context = Context.newBuilder("js")
.allowNativeAccess(false)
.engine(engine)
.build();
//save the js bindings object
jsBindingsObject = context.getBindings("js");
topLevelValue = context.getBindings("js");
//put host members into environment
putTopLevelValue("loggerScripts",LoggerInterface.loggerScripts);
//load all files required to start the engine
for(String fileToLoad : filesToLoadOnInit){
loadDependency(fileToLoad);
}
//define host members
defineHostMembers();
//register engine files
registerScriptDirectory("Scripts/engine",FileUtils.getAssetFile("Scripts/engine"));
//compile
compile();
//run script for engine init
requireModule("/Scripts/engine/engine-init.ts");
invokeModuleFunction("/Scripts/engine/engine-init.ts","ENGINE_onInit");
//call the engine initialization function
// invokeFunction("ENGINE_onInit");
//read scripts into source map
// readScriptsDirectory("/src/main/sql", FileUtils.getAssetFile("/src/main/sql"));
//create bindings
// try {
// String content = FileUtils.getAssetFileAsString("/Scripts/test.js");
@ -59,7 +126,7 @@ public class ScriptEngine {
* @param value The value that is stored at that variable
*/
public void putTopLevelValue(String valueName, Object value){
jsBindingsObject.putMember(valueName, value);
topLevelValue.putMember(valueName, value);
}
/**
@ -68,7 +135,16 @@ public class ScriptEngine {
* @return The value of the variable
*/
public Value getTopLevelValue(String valueName){
return jsBindingsObject.getMember(valueName);
return topLevelValue.getMember(valueName);
}
/**
* Removes a top level member from the javascript context
* @param valueName The name of the top level member
* @return true if successfully removed, false otherwise
*/
public boolean removeTopLevelValue(String valueName){
return topLevelValue.removeMember(valueName);
}
/**
@ -76,17 +152,18 @@ public class ScriptEngine {
* @param path The
* @param directory
*/
void readScriptsDirectory(String path, File directory){
void registerScriptDirectory(String path, File directory){
if(directory.exists() && directory.isDirectory()){
File[] children = directory.listFiles();
for(File childFile : children){
String qualifiedName = path + "/" + childFile.getName();
if(childFile.isDirectory()){
readScriptsDirectory(qualifiedName,childFile);
registerScriptDirectory(qualifiedName,childFile);
} else {
//add to source map
String content = FileUtils.readFileToString(childFile);
sourceMap.put(qualifiedName,Source.create("js",content));
registerFile(qualifiedName);
// String content = FileUtils.readFileToString(childFile);
// sourceMap.put(qualifiedName,Source.create("js",content));
}
}
}
@ -96,15 +173,22 @@ public class ScriptEngine {
* Loads a script from disk
* @param path The path to the script file
*/
public void loadScript(String path){
public void loadDependency(String path){
String content;
Source source = null;
try {
content = FileUtils.getAssetFileAsString(path);
sourceMap.put(path,Source.create("js",content));
source = Source.create("js",content);
sourceMap.put(path,source);
context.eval(source);
} catch (IOException e) {
// TODO Auto-generated catch block
LoggerInterface.loggerScripts.ERROR("FAILED TO LOAD SCRIPT", e);
} catch (PolyglotException e){
if(source != null){
LoggerInterface.loggerScripts.WARNING("Source language: " + source.getLanguage());
}
LoggerInterface.loggerScripts.ERROR("Script error", e);
e.printStackTrace();
LoggerInterface.loggerGameLogic.ERROR("FAILED TO LOAD SCRIPT", e);
}
}
@ -113,12 +197,95 @@ public class ScriptEngine {
* @param path The filepath of the script
*/
public void runScript(String path){
Source source = sourceMap.get(path);
if(source != null){
context.eval(source);
invokeFunction("COMPILER_runFile", path);
}
/**
* Prints the content of a file
* @param path The filepath of the script
*/
public void printScriptSource(String path){
invokeFunction("COMPILER_printSource", path);
}
/**
* Registers a file with the scripting engine to be compiled into the full binary
* @param path The path to the script file
*/
private void registerFile(String path){
String content;
try {
content = FileUtils.getAssetFileAsString(path);
sourceMap.put(path,Source.create("js",content));
invokeFunction("COMPILER_registerFile",path,content);
} catch (IOException e) {
LoggerInterface.loggerScripts.ERROR("FAILED TO LOAD SCRIPT", e);
}
}
/**
* Compiles the project
*/
private void compile(){
invokeFunction("COMPILER_run");
Value compiledCode = topLevelValue.getMember("COMPILER_emitted_value");
context.eval("js",compiledCode.asString());
}
/**
* Calls a function defined in the global scope with the arguments provided
* @param functionName The function name
* @param args The arguments
*/
public Value invokeFunction(String functionName, Object... args){
Value function = topLevelValue.getMember(functionName);
if(function != null){
return function.execute(args);
} else {
LoggerInterface.loggerScripts.WARNING("Failed to invoke function " + functionName);
}
return null;
}
/**
* Invokes a function defined in a file
* @param filePath The file the function is defined in
* @param functionName The function's name
* @param args The args to pass into the function
*/
public void invokeModuleFunction(String filePath, String functionName, Object ... args){
Value filePathRaw = invokeFunction("FILE_RESOLUTION_getFilePath",filePath);
Value requireCache = topLevelValue.getMember("REQUIRE_CACHE");
Value module = requireCache.getMember(filePathRaw.asString());
Value exports = module.getMember("exports");
Value function = exports.getMember(functionName);
if(function != null && function.canExecute()){
function.execute(args);
} else {
LoggerInterface.loggerScripts.WARNING("Failed to invoke function " + functionName);
}
}
/**
* Requires a module into the global space
* @param filePath The filepath of the module
*/
public void requireModule(String filePath){
invokeFunction("require", filePath);
}
/**
* Defines host members within javascript context
*/
private void defineHostMembers(){
hostObject = topLevelValue.getMember("HOST_ACCESS");
//give guest access to static classes
Value classes = hostObject.getMember("classes");
for(Object[] currentClass : staticClasses){
classes.putMember((String)currentClass[0], currentClass[1]);
}
}
}

9
tsconfig.json Normal file
View File

@ -0,0 +1,9 @@
{
"compilerOptions": {
"paths" : {
"/*" : [
"./assets/Scripts/*"
],
}
}
}