Good first pass at anime outline shader

This commit is contained in:
austin 2022-03-25 16:09:18 -04:00
parent 4cf3a0e2d4
commit e729c53e3c
20 changed files with 451 additions and 95 deletions

View File

@ -56,7 +56,8 @@
"GRAVITY", "GRAVITY",
"TARGETABLE", "TARGETABLE",
"CAN_EQUIP", "CAN_EQUIP",
"INVENTORY" "INVENTORY",
"OUTLINE"
], ],
"visualAttributes" : [], "visualAttributes" : [],
"movementSystems" : [ "movementSystems" : [

View File

@ -30,7 +30,8 @@
"GRAVITY", "GRAVITY",
"BLENDER_TRANSFORM", "BLENDER_TRANSFORM",
"MELEE", "MELEE",
"TARGETABLE" "TARGETABLE",
"OUTLINE"
], ],
"equipClass" : "weapon", "equipClass" : "weapon",
"idleAnim" : "Sword|Idle", "idleAnim" : "Sword|Idle",
@ -55,7 +56,8 @@
"tokens" : [ "tokens" : [
"GRAVITY", "GRAVITY",
"RANGED", "RANGED",
"TARGETABLE" "TARGETABLE",
"OUTLINE"
], ],
"equipClass" : "weapon", "equipClass" : "weapon",
"collidable": { "collidable": {

View File

@ -0,0 +1,30 @@
#version 420 core
// shader outputs
layout (location = 0) out vec4 frag;
// color accumulation buffer
layout (binding = 0) uniform sampler2D texture;
void main(){
// fragment coordination
ivec2 coords = ivec2(gl_FragCoord.xy);
// fragment color
vec4 color = texelFetch(texture, coords, 0);
float val = color.r;
// if(color.r < 0.5){z
// discard;
// }
vec4 outColor = vec4(0);
if(val == 1){
outColor = vec4(0,0,0,1);
// outColor.a = 1;
}
frag = outColor;
}

View File

@ -0,0 +1,8 @@
#version 420 core
// shader inputs
layout (location = 0) in vec3 position;
void main(){
gl_Position = vec4(position, 1.0f);
}

View File

@ -0,0 +1,134 @@
#version 330 core
out vec4 FragColor;
in vec2 TexCoords;
uniform sampler2D screenTexture;
const float offset = 1.0 / 2000.0;
int posToIndex(int x, int y);
float calculateAveragedEdge(int x, int y, vec3 sT[25]);
void main(){
vec2 offsets[25] = vec2[25](
vec2(-2 * offset, 2 * offset),
vec2(-2 * offset, 1 * offset),
vec2(-2 * offset, 0 * offset),
vec2(-2 * offset, -1 * offset),
vec2(-2 * offset, -2 * offset),
vec2(-1 * offset, 2 * offset),
vec2(-1 * offset, 1 * offset),
vec2(-1 * offset, 0 * offset),
vec2(-1 * offset, -1 * offset),
vec2(-1 * offset, -2 * offset),
vec2( 0 * offset, 2 * offset),
vec2( 0 * offset, 1 * offset),
vec2( 0 * offset, 0 * offset),
vec2( 0 * offset, -1 * offset),
vec2( 0 * offset, -2 * offset),
vec2( 1 * offset, 2 * offset),
vec2( 1 * offset, 1 * offset),
vec2( 1 * offset, 0 * offset),
vec2( 1 * offset, -1 * offset),
vec2( 1 * offset, -2 * offset),
vec2( 2 * offset, 2 * offset),
vec2( 2 * offset, 1 * offset),
vec2( 2 * offset, 0 * offset),
vec2( 2 * offset, -1 * offset),
vec2( 2 * offset, -2 * offset)
);
// vec2 offsets[9] = vec2[](
// vec2(-offset, offset), // top-left
// vec2( 0.0f, offset), // top-center
// vec2( offset, offset), // top-right
// vec2(-offset, 0.0f), // center-left
// vec2( 0.0f, 0.0f), // center-center
// vec2( offset, 0.0f), // center-right
// vec2(-offset, -offset), // bottom-left
// vec2( 0.0f, -offset), // bottom-center
// vec2( offset, -offset) // bottom-right
// );
// float kernel[9] = float[](
// -1, -1, -1,
// -1, 9, -1,
// -1, -1, -1
// );
vec3 sT[25];
for(int x = 0; x < 5; x++){
for(int y = 0; y < 5; y++){
sT[x * 5 + y] = texture(screenTexture, TexCoords.st + offsets[x * 5 + y]).xyz;
}
}
// vec3 Gx = (-sT[0] + sT[2]) + 2 * (-sT[3] + sT[5]) + (-sT[6] + sT[8]);
// vec3 Gy = (sT[0] + 2 * sT[1] + sT[2]) - (sT[6] + 2 * sT[7] + sT[8]);
// vec3 G = sqrt(Gx * Gx + Gy * Gy);
// float averaged = (G.x + G.y + G.z)/3.0;
float vals[9];
for(int x = 0; x < 3; x++){
for(int y = 0; y < 3; y++){
vals[x * 3 + y] = calculateAveragedEdge(x,y,sT);
}
}
float rVal = 0;
float cutoff1 = 0.6;
float cutoff2 = 0.1;
float cutoff3 = 0.5;
float surroundAvg = (vals[0] + vals[2] + vals[6] + vals[8])/4.0;
if(
//center
vals[4] > cutoff1 &&
surroundAvg > cutoff3
// //plus
// vals[1] > cutoff2 &&
// vals[3] > cutoff2 &&
// vals[5] > cutoff2 &&
// vals[7] > cutoff2 //&&
// // //diag
// vals[0] < cutoff3 &&
// vals[2] < cutoff3 &&
// vals[6] < cutoff3 &&
// vals[8] < cutoff3
){
rVal = min(vals[4],1.0);
}
// rVal = calculateAveragedEdge(1,1,sT);
// if(rVal < 0.8){
// rVal = 0;
// }
// vec3 col = vec3(0.0);
// for(int i = 0; i < 9; i++){
// col += sampleTex[i] * kernel[i];
// }
FragColor = vec4(rVal,rVal,rVal,1);
}
float calculateAveragedEdge(int x, int y, vec3 sT[25]){
//compute sobel kernel
vec3 Gx =
(-sT[posToIndex(x,y) + 0] + sT[posToIndex(x,y) + 2]) +
2 * (-sT[posToIndex(x,y) + 5] + sT[posToIndex(x,y) + 7]) +
(-sT[posToIndex(x,y) + 10] + sT[posToIndex(x,y)+ 12]);
vec3 Gy =
(sT[posToIndex(x,y) + 0] + 2 * sT[posToIndex(x,y) + 1] + sT[posToIndex(x,y) + 2]) -
(sT[posToIndex(x,y) + 10] + 2 * sT[posToIndex(x,y)+ 11] + sT[posToIndex(x,y) + 12]);
vec3 G = sqrt(Gx * Gx + Gy * Gy);
//compute laplacian kernel
vec3 L = sT[posToIndex(x,y) + 1] + sT[posToIndex(x,y) + 5] - 4 * sT[posToIndex(x,y) + 6] + sT[posToIndex(x,y) + 7] + sT[posToIndex(x,y) + 11];
float averaged = abs(G.x + G.y + G.z)/3.0;
return averaged;
}
int posToIndex(int x, int y){
return x * 5 + y;
}

View File

@ -0,0 +1,10 @@
#version 330 core
layout (location = 0) in vec2 aPos;
layout (location = 1) in vec2 aTexCoords;
out vec2 TexCoords;
void main(){
gl_Position = vec4(aPos.x, aPos.y, 0.0, 1.0);
TexCoords = aTexCoords;
}

View File

@ -0,0 +1,45 @@
#version 330 core
out vec4 FragColor;
in vec2 TexCoords;
uniform sampler2D screenTexture;
const float offset = 1.0 / 500.0;
void main(){
vec2 offsets[9] = vec2[](
vec2(-offset, offset), // top-left
vec2( 0.0f, offset), // top-center
vec2( offset, offset), // top-right
vec2(-offset, 0.0f), // center-left
vec2( 0.0f, 0.0f), // center-center
vec2( offset, 0.0f), // center-right
vec2(-offset, -offset), // bottom-left
vec2( 0.0f, -offset), // bottom-center
vec2( offset, -offset) // bottom-right
);
// float kernel[9] = float[](
// -1, -1, -1,
// -1, 9, -1,
// -1, -1, -1
// );
vec3 sT[9];
for(int i = 0; i < 9; i++)
{
sT[i] = vec3(texture(screenTexture, TexCoords.st + offsets[i]));
}
vec3 Gx = (-sT[0] + sT[2]) + 2 * (-sT[3] + sT[5]) + (-sT[6] + sT[8]);
vec3 Gy = (sT[0] + 2 * sT[1] + sT[2]) - (sT[6] + 2 * sT[7] + sT[8]);
vec3 G = sqrt(Gx * Gx + Gy * Gy);
// vec3 col = vec3(0.0);
// for(int i = 0; i < 9; i++){
// col += sampleTex[i] * kernel[i];
// }
FragColor = vec4(G,1);
}

View File

@ -0,0 +1,10 @@
#version 330 core
layout (location = 0) in vec2 aPos;
layout (location = 1) in vec2 aTexCoords;
out vec2 TexCoords;
void main(){
gl_Position = vec4(aPos.x, aPos.y, 0.0, 1.0);
TexCoords = aTexCoords;
}

View File

@ -1,6 +1,6 @@
#version 330 core #version 330 core
out vec4 FragColor; out vec3 FragColor;
in vec3 FragPos; in vec3 FragPos;
@ -8,8 +8,10 @@ in vec3 Normal;
void main(){ void main(){
vec3 norm = normalize(Normal); vec3 norm = normalize(Normal) / 2.0;
norm = vec3(norm.x + 0.5,norm.y + 0.5,norm.z + 0.5);
// float dist = gl_FragDepth;
FragColor = vec4(norm,1.0); FragColor = norm;
} }

View File

@ -34,19 +34,22 @@ out vec3 FragPos;
void main() { void main() {
//calculate bone transform
mat4 BoneTransform = (bones[int(aIndex[0])] * aWeights[0]);
BoneTransform = BoneTransform + (bones[int(aIndex[1])] * aWeights[1]);
BoneTransform = BoneTransform + (bones[int(aIndex[2])] * aWeights[2]);
BoneTransform = BoneTransform + (bones[int(aIndex[3])] * aWeights[3]);
//apply bone transform to position vectors //apply bone transform to position vectors
vec4 FinalVertex = BoneTransform * vec4(aPos, 1.0); vec4 FinalVertex = vec4(aPos, 1.0);
vec4 FinalNormal = BoneTransform * vec4(aNormal, 1.0); vec4 FinalNormal = vec4(aNormal, 1.0);
if(hasBones==1){
//calculate bone transform
mat4 BoneTransform = (bones[int(aIndex[0])] * aWeights[0]);
BoneTransform = BoneTransform + (bones[int(aIndex[1])] * aWeights[1]);
BoneTransform = BoneTransform + (bones[int(aIndex[2])] * aWeights[2]);
BoneTransform = BoneTransform + (bones[int(aIndex[3])] * aWeights[3]);
//apply bone transform to position vectors
FinalVertex = BoneTransform * vec4(aPos, 1.0);
FinalNormal = BoneTransform * vec4(aNormal, 1.0);
}
//make sure the W component is 1.0 //make sure the W component is 1.0
FinalVertex = vec4(FinalVertex.xyz, 1.0); FinalVertex = vec4(FinalVertex.xyz, 1.0);

View File

@ -13,19 +13,16 @@ layout (binding = 1) uniform sampler2D reveal;
const float EPSILON = 0.00001f; const float EPSILON = 0.00001f;
// caluclate floating point numbers equality accurately // caluclate floating point numbers equality accurately
bool isApproximatelyEqual(float a, float b) bool isApproximatelyEqual(float a, float b){
{
return abs(a - b) <= (abs(a) < abs(b) ? abs(b) : abs(a)) * EPSILON; return abs(a - b) <= (abs(a) < abs(b) ? abs(b) : abs(a)) * EPSILON;
} }
// get the max value between three values // get the max value between three values
float max3(vec3 v) float max3(vec3 v) {
{
return max(max(v.x, v.y), v.z); return max(max(v.x, v.y), v.z);
} }
void main() void main(){
{
// fragment coordination // fragment coordination
ivec2 coords = ivec2(gl_FragCoord.xy); ivec2 coords = ivec2(gl_FragCoord.xy);

View File

@ -3,7 +3,6 @@
// shader inputs // shader inputs
layout (location = 0) in vec3 position; layout (location = 0) in vec3 position;
void main() void main(){
{
gl_Position = vec4(position, 1.0f); gl_Position = vec4(position, 1.0f);
} }

View File

@ -750,6 +750,7 @@ public class LoadingThread extends Thread {
Entity shrine = EntityUtils.spawnDrawableEntity("Models/shrine2.fbx"); Entity shrine = EntityUtils.spawnDrawableEntity("Models/shrine2.fbx");
EntityUtils.getPosition(shrine).set(15,0,15); EntityUtils.getPosition(shrine).set(15,0,15);
EntityUtils.getRotation(shrine).rotationX((float)-Math.PI/2.0f); EntityUtils.getRotation(shrine).rotationX((float)-Math.PI/2.0f);
shrine.putData(EntityDataStrings.DRAW_OUTLINE, true);
// goblin = CreatureUtils.spawnBasicCreature("Goblin"); // goblin = CreatureUtils.spawnBasicCreature("Goblin");

View File

@ -20,6 +20,7 @@ public class EntityDataStrings {
public static final String DRAW_TRANSPARENT_PASS = "drawTransparentPass"; public static final String DRAW_TRANSPARENT_PASS = "drawTransparentPass";
public static final String DRAW_CAST_SHADOW = "castShadow"; public static final String DRAW_CAST_SHADOW = "castShadow";
public static final String DRAW_VOLUMETRIC = "drawVolumetric"; public static final String DRAW_VOLUMETRIC = "drawVolumetric";
public static final String DRAW_OUTLINE = "drawOutline";
/* /*

View File

@ -202,6 +202,9 @@ public class CreatureUtils {
case "INVENTORY": case "INVENTORY":
rVal.putData(EntityDataStrings.NATURAL_INVENTORY,UnrelationalInventoryState.createUnrelationalInventory(10)); rVal.putData(EntityDataStrings.NATURAL_INVENTORY,UnrelationalInventoryState.createUnrelationalInventory(10));
break; break;
case "OUTLINE":
rVal.putData(EntityDataStrings.DRAW_OUTLINE, true);
break;
} }
} }
//variants //variants

View File

@ -109,6 +109,9 @@ public class ItemUtils {
case "TARGETABLE": case "TARGETABLE":
Globals.entityManager.registerTargetableEntity(rVal); Globals.entityManager.registerTargetableEntity(rVal);
break; break;
case "OUTLINE":
rVal.putData(EntityDataStrings.DRAW_OUTLINE, true);
break;
} }
} }
if(item.getEquipWhitelist() != null){ if(item.getEquipWhitelist() != null){

View File

@ -73,82 +73,82 @@ public class TerrainGen {
public static int current_Region_X = 0; public static int current_Region_X = 0;
public static int current_Region_Y = 0; public static int current_Region_Y = 0;
public static void main(String args[]){ // public static void main(String args[]){
TerrainGenerator tergen = new TerrainGenerator(); // TerrainGenerator tergen = new TerrainGenerator();
tergen.set_Dimension(DIMENSION); // tergen.set_Dimension(DIMENSION);
tergen.set_Lifespan(15000); // tergen.set_Lifespan(15000);
tergen.run(); // tergen.run();
elevation = tergen.get_Terrain(); // elevation = tergen.get_Terrain();
elevation = interpolate_Elevation_Raws(elevation); // elevation = interpolate_Elevation_Raws(elevation);
DIMENSION = DIMENSION * 2; // DIMENSION = DIMENSION * 2;
elevation = compression_filter(elevation); // elevation = compression_filter(elevation);
elevation = three_halves_filter(elevation); // elevation = three_halves_filter(elevation);
elevation = smooth_Terrain_Further(elevation); // elevation = smooth_Terrain_Further(elevation);
elevation = small_Kernel_Sharpen(elevation); // elevation = small_Kernel_Sharpen(elevation);
elevation = smooth_Terrain_Further(elevation); // elevation = smooth_Terrain_Further(elevation);
elevation = three_halves_filter(elevation); // elevation = three_halves_filter(elevation);
elevation = small_Kernel_Smooth(elevation); // elevation = small_Kernel_Smooth(elevation);
elevation = small_Kernel_Sharpen(elevation); // elevation = small_Kernel_Sharpen(elevation);
elevation = smooth_Terrain_Further(elevation); // elevation = smooth_Terrain_Further(elevation);
elevation = smooth_Terrain_Further(elevation); // elevation = smooth_Terrain_Further(elevation);
elevation = land_exponential_filter(elevation); // elevation = land_exponential_filter(elevation);
elevation = land_exponential_filter(elevation); // elevation = land_exponential_filter(elevation);
elevation = land_exponential_filter(elevation); // elevation = land_exponential_filter(elevation);
elevation = land_exponential_filter(elevation); // elevation = land_exponential_filter(elevation);
mountainParsed = new int[DIMENSION][DIMENSION]; // mountainParsed = new int[DIMENSION][DIMENSION];
oceanParsed = new int[DIMENSION][DIMENSION]; // oceanParsed = new int[DIMENSION][DIMENSION];
continentIdField = new int[DIMENSION][DIMENSION]; // continentIdField = new int[DIMENSION][DIMENSION];
mountainParsed = parse_Mountainscapes(elevation); // mountainParsed = parse_Mountainscapes(elevation);
oceanParsed = parse_Oceans(elevation); // oceanParsed = parse_Oceans(elevation);
wind_field = map_Wind_Field(); // wind_field = map_Wind_Field();
precipitationChart = calculate_Rain_Shadows(elevation,oceanParsed,wind_field); // precipitationChart = calculate_Rain_Shadows(elevation,oceanParsed,wind_field);
temperatureChart = generate_Temperature_Chart(); // temperatureChart = generate_Temperature_Chart();
climateCategory = infer_Climate_Category(); // climateCategory = infer_Climate_Category();
determine_Continents(); // determine_Continents();
fill_Continents(); // fill_Continents();
//for display tbh // //for display tbh
anchor_To_Real_Region(); // anchor_To_Real_Region();
display_toggle = 0; // display_toggle = 0;
create_Frame(); // create_Frame();
while(true){ // while(true){
if(brightness_increasing){ // if(brightness_increasing){
if(brightness < 100){ // if(brightness < 100){
brightness++; // brightness++;
} else { // } else {
} // }
} else { // } else {
if(brightness > 0){ // if(brightness > 0){
brightness--; // brightness--;
} else { // } else {
brightness_increasing = true; // brightness_increasing = true;
display_toggle++; // display_toggle++;
if(display_toggle > 1){ // if(display_toggle > 1){
display_toggle = 0; // display_toggle = 0;
} // }
} // }
} // }
frame.repaint(); // frame.repaint();
Utilities.sleep(10); // Utilities.sleep(10);
} // }
} // }
public TerrainModel generateModel(){ public TerrainModel generateModel(){
TerrainModel rVal; TerrainModel rVal;

View File

@ -852,10 +852,10 @@ public class Mesh {
incrementer++; incrementer++;
} }
} else { } else {
glUniform1i(Globals.renderingEngine.getActiveShader().shaderVertexHasBonesLoc, 0); glUniform1i(glGetUniformLocation(Globals.renderingEngine.getActiveShader().shaderProgram, "hasBones"), 0);
} }
} else { } else {
glUniform1i(Globals.renderingEngine.getActiveShader().shaderVertexHasBonesLoc, 0); glUniform1i(glGetUniformLocation(Globals.renderingEngine.getActiveShader().shaderProgram, "hasBones"), 0);
} }

View File

@ -177,6 +177,18 @@ public class RenderingEngine {
// static Framebuffer volumeVerticalBackfaceBuffer; // static Framebuffer volumeVerticalBackfaceBuffer;
// static Texture volumeVerticalFrontfaceTexture; // static Texture volumeVerticalFrontfaceTexture;
// static Framebuffer volumeVerticalFrontfaceBuffer; // static Framebuffer volumeVerticalFrontfaceBuffer;
/*
Post processing effects (ie kernels) textures, framebuffers, shaders
*/
static Texture normalsOutlineTexture;
static Framebuffer normalsOutlineFrambuffer;
static ShaderProgram normalsOutlineShader;
/*
compositing functions
*/
static ShaderProgram compositeAnimeOutline;
// public static boolean renderHitboxes = false; // public static boolean renderHitboxes = false;
// public static boolean renderPhysics = false; // public static boolean renderPhysics = false;
@ -187,7 +199,7 @@ public class RenderingEngine {
ShaderProgram activeProgram; ShaderProgram activeProgram;
static int outputFramebuffer = 0; static int outputFramebuffer = 6;
public void createOpenglContext(){ public void createOpenglContext(){
@ -312,7 +324,8 @@ public class RenderingEngine {
static ShaderProgram renderNormalsShader; static ShaderProgram renderNormalsShader;
*/ */
gameImageNormalsTexture = FramebufferUtils.generateScreenTextureColor(Globals.WINDOW_WIDTH, Globals.WINDOW_HEIGHT); gameImageNormalsTexture = FramebufferUtils.generateScreenTextureColor(Globals.WINDOW_WIDTH, Globals.WINDOW_HEIGHT);
gameImageNormalsFramebuffer = FramebufferUtils.generateScreenTextureFramebuffer(Globals.WINDOW_WIDTH, Globals.WINDOW_HEIGHT, gameImageNormalsTexture); Texture gameImageNormalsDepthTexture = FramebufferUtils.generateScreenTextureDepth(Globals.WINDOW_WIDTH, Globals.WINDOW_HEIGHT);
gameImageNormalsFramebuffer = FramebufferUtils.generateScreenTextureFramebuffer(Globals.WINDOW_WIDTH, Globals.WINDOW_HEIGHT, gameImageNormalsTexture, gameImageNormalsDepthTexture);
renderNormalsShader = ShaderProgram.loadSpecificShader("Shaders/anime/renderNormals.vs", "Shaders/anime/renderNormals.fs"); renderNormalsShader = ShaderProgram.loadSpecificShader("Shaders/anime/renderNormals.vs", "Shaders/anime/renderNormals.fs");
// //
@ -328,6 +341,24 @@ public class RenderingEngine {
//projection matrices //projection matrices
nearVolumeProjectionMatrix.setPerspective((float)(Globals.verticalFOV * Math.PI /180.0f), (float)Globals.WINDOW_WIDTH / (float)Globals.WINDOW_HEIGHT, 0.1f, 100); nearVolumeProjectionMatrix.setPerspective((float)(Globals.verticalFOV * Math.PI /180.0f), (float)Globals.WINDOW_WIDTH / (float)Globals.WINDOW_HEIGHT, 0.1f, 100);
//
//Postprocessing textures and buffers
//
/*
static Texture normalsOutlineTexture;
static Framebuffer normalsOutlineFrambuffer;
static ShaderProgram normalsOutlineShader;
*/
normalsOutlineTexture = FramebufferUtils.generateScreenTextureColorAlpha(Globals.WINDOW_WIDTH, Globals.WINDOW_HEIGHT);
normalsOutlineFrambuffer = FramebufferUtils.generateScreenTextureFramebuffer(Globals.WINDOW_WIDTH, Globals.WINDOW_HEIGHT, normalsOutlineTexture);
// normalsOutlineShader = ShaderProgram.loadSpecificShader("Shaders/anime/outlineNormals.vs", "Shaders/anime/outlineNormals.fs");
Globals.assetManager.addShaderToQueue("Shaders/anime/outlineNormals.vs", "Shaders/anime/outlineNormals.fs");
//
//Compositing shaders
//
compositeAnimeOutline = ShaderProgram.loadSpecificShader("Shaders/anime/compositeAnimeOutline.vs", "Shaders/anime/compositeAnimeOutline.fs");
//instantiate light manager //instantiate light manager
lightManager = new LightManager(); lightManager = new LightManager();
@ -432,7 +463,8 @@ public class RenderingEngine {
if(Globals.RENDER_FLAG_RENDER_SCREEN_FRAMEBUFFER_CONTENT){ if(Globals.RENDER_FLAG_RENDER_SCREEN_FRAMEBUFFER_CONTENT){
renderGameContent(); renderGameContent();
renderDebugContent(); renderDebugContent();
renderNormals(); renderNormalsForOutline();
applyKernelsAndPostprocessing();
compositeGameImage(); compositeGameImage();
} }
@ -822,7 +854,7 @@ public class RenderingEngine {
} }
} }
static void renderNormals(){ static void renderNormalsForOutline(){
/* /*
gameImageNormalsTexture; gameImageNormalsTexture;
@ -833,8 +865,11 @@ public class RenderingEngine {
//bind screen fbo //bind screen fbo
gameImageNormalsFramebuffer.bind(); gameImageNormalsFramebuffer.bind();
glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);
glDisable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDepthFunc(GL_LESS); glDepthFunc(GL_LESS);
glDepthMask(true); glDepthMask(true);
glViewport(0, 0, Globals.WINDOW_WIDTH, Globals.WINDOW_HEIGHT); glViewport(0, 0, Globals.WINDOW_WIDTH, Globals.WINDOW_HEIGHT);
/// ///
@ -855,6 +890,7 @@ public class RenderingEngine {
if( if(
(boolean)currentEntity.getData(EntityDataStrings.DATA_STRING_DRAW) && (boolean)currentEntity.getData(EntityDataStrings.DATA_STRING_DRAW) &&
currentEntity.getData(EntityDataStrings.DRAW_SOLID_PASS) != null && currentEntity.getData(EntityDataStrings.DRAW_SOLID_PASS) != null &&
currentEntity.getData(EntityDataStrings.DRAW_OUTLINE) != null &&
drawPoint(cameraPos,new Vector3f((float)position.x,(float)position.y,(float)position.z)) drawPoint(cameraPos,new Vector3f((float)position.x,(float)position.y,(float)position.z))
){ ){
//fetch actor //fetch actor
@ -874,9 +910,41 @@ public class RenderingEngine {
} }
} }
static void applyKernelsAndPostprocessing(){
//
// Outline normals
//
glDepthFunc(GL_ALWAYS);
glDepthMask(false);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
normalsOutlineFrambuffer.bind();
ShaderProgram program = Globals.assetManager.fetchShader("Shaders/anime/outlineNormals.vs", null, "Shaders/anime/outlineNormals.fs");
if(program != null){
Globals.renderingEngine.setActiveShader(program);
glBindVertexArray(screenTextureVAO);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, 0);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, 0);
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, 0);
glActiveTexture(GL_TEXTURE3);
glBindTexture(GL_TEXTURE_2D, 0);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, gameImageNormalsTexture.getTexturePointer());
glDrawArrays(GL_TRIANGLES, 0, 6);
glBindVertexArray(0);
}
}
static void compositeGameImage(){ static void compositeGameImage(){
// //
// Pass Three: Composite transparency on top of solids //Setup to render screen textures & bind screen framebuffer
// //
glDepthFunc(GL_ALWAYS); glDepthFunc(GL_ALWAYS);
// glDepthMask(false); // glDepthMask(false);
@ -884,10 +952,33 @@ public class RenderingEngine {
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
screenFramebuffer.bind(); screenFramebuffer.bind();
Globals.renderingEngine.setActiveShader(oitCompositeProgram);
glBindVertexArray(screenTextureVAO); glBindVertexArray(screenTextureVAO);
//
//Draw anime outline
//
Globals.renderingEngine.setActiveShader(compositeAnimeOutline);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, 0);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, 0);
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, 0);
glActiveTexture(GL_TEXTURE3);
glBindTexture(GL_TEXTURE_2D, 0);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, normalsOutlineTexture.getTexturePointer());
glDrawArrays(GL_TRIANGLES, 0, 6);
//
//Composite transparency on top of solids
//
Globals.renderingEngine.setActiveShader(oitCompositeProgram);
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, 0); glBindTexture(GL_TEXTURE_2D, 0);
glActiveTexture(GL_TEXTURE1); glActiveTexture(GL_TEXTURE1);
@ -903,6 +994,9 @@ public class RenderingEngine {
glDrawArrays(GL_TRIANGLES, 0, 6); glDrawArrays(GL_TRIANGLES, 0, 6);
glBindVertexArray(0); glBindVertexArray(0);
} }
static void renderScreenFramebuffer(){ static void renderScreenFramebuffer(){
@ -948,9 +1042,7 @@ public class RenderingEngine {
} else if(outputFramebuffer == 5){ } else if(outputFramebuffer == 5){
glBindTexture(GL_TEXTURE_2D, gameImageNormalsTexture.getTexturePointer()); glBindTexture(GL_TEXTURE_2D, gameImageNormalsTexture.getTexturePointer());
} else if(outputFramebuffer == 6){ } else if(outputFramebuffer == 6){
Globals.renderingEngine.setActiveShader(drawChannel); glBindTexture(GL_TEXTURE_2D, normalsOutlineTexture.getTexturePointer());
glUniform1f(glGetUniformLocation(Globals.renderingEngine.getActiveShader().shaderProgram, "channel"),0);
glBindTexture(GL_TEXTURE_2D, transparencyRevealageTexture.getTexturePointer());
} else if(outputFramebuffer == 7){ } else if(outputFramebuffer == 7){
Globals.renderingEngine.setActiveShader(drawChannel); Globals.renderingEngine.setActiveShader(drawChannel);
glUniform1f(glGetUniformLocation(Globals.renderingEngine.getActiveShader().shaderProgram, "channel"),4); glUniform1f(glGetUniformLocation(Globals.renderingEngine.getActiveShader().shaderProgram, "channel"),4);

View File

@ -78,6 +78,21 @@ public class FramebufferUtils {
return texture; 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);
//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);
return texture;
}
public static Texture generateScreenTextureDepth(int width, int height){ public static Texture generateScreenTextureDepth(int width, int height){
int texturePtr = glGenTextures(); int texturePtr = glGenTextures();
glBindTexture(GL_TEXTURE_2D,texturePtr); glBindTexture(GL_TEXTURE_2D,texturePtr);