I am rendering the scene in a deferred rendering pipeline with the G-buffer pass using 32 bit floating point accuracy and the lighting pass using 16 bit floating point accuracy RGBA rendertargets.
Because Dark Photon said it would be more efficient (ALL HAIL DARK PHOTON), I am rendering an entire screenquad for every point light in the scene.
I seem to dip below 60 FPS after 20-25 point lights at 1080p. I was told that I would get hundreds of point lights, so I am quite disappointed.
at 1/4 of the number of pixels (1/4 of the resolution) my code runs a lot faster, allowing me nearly 60 point lights without dipping below 60 FPS
C++ Rendering Function:
void GkScene::drawPipeline(){ //Approaches spaghetti levels of unreadability
//Used for error checking
GLenum communism;
/* Error Check code. Paste where you need it.
// communism = glGetError(); //Ensure there are no errors listed before we start.
// if (communism != GL_NO_ERROR) //if communism has made an error (which is pretty typical)
// {
// std::cout<<"
OpenGL reports an ERROR!";
// if (communism == GL_INVALID_ENUM)
// std::cout<<"
Invalid enum.";
// if (communism == GL_INVALID_OPERATION)
// std::cout<<"
Invalid operation.";
// if (communism == GL_INVALID_FRAMEBUFFER_OPERATION)
// std::cout <<"
Invalid Framebuffer Operation.";
// if (communism == GL_OUT_OF_MEMORY)
// {
// std::cout <<"
Out of memory. You've really done it now. I'm so angry, i'm going to close the program. ARE YOU HAPPY NOW, DAVE?!?!";
// std::abort();
// }
// }
*/
/*
FUNCTION STRUCTURE:
* Initial Opaque Pass
* SkyboxShader pass
* InitialOpaquePassShader pass
* SHADOWED LIGHT DEPTH PASSES
* LIGHT PASSES
* SHADOWLESS LIGHTING PASSES
* Point Light Passes
* SHADOWED LIGHTING PASSES
* FINAL OPAQUE PASS
* TRANSPARENCY
* TOSCREEN/TOTARGET
*/
if (!SceneCamera || !InitialOpaqueShader || !ShowTextureShader || !InitialOpaqueUniforms || !FinalOpaqueShader){ //if one is not good
return; //gtfo
}
//Setup Camera mat4s so that we can send in the addresses.
InitialOpaqueCameraMatrix = SceneCamera->GetViewProjection();
InitialOpaqueCameraViewMatrix = SceneCamera->GetViewMatrix();
InitialOpaqueCameraProjectionMatrix = SceneCamera->GetProjection();
//In case we need it...
InverseViewProjectionMatrix = glm::inverse(InitialOpaqueCameraMatrix); //Inverse of the Viewprojection Matrix.
InverseProjectionMatrix = glm::inverse(InitialOpaqueCameraProjectionMatrix);//Matrix that undoes perspective transformation
InverseViewMatrix = glm::inverse(InitialOpaqueCameraViewMatrix);
/*
=========================
BEGIN INITIAL OPAQUE PASS
=========================
*/
FboArray[OPAQUE_INITIAL]->BindRenderTarget(); //Bind this FBO as the Render Target. We render the skybox here too...
FBO::clearTexture(0.0,0.0,0.2,0.0);//Clears the Opaque Initial target. The screen isn't cleared for a long time.
//Skybox code culled to conserve space on OpenGL Forums
/*
INITIAL OPAQUE PASS- NON SKYBOX
*/
InitialOpaqueShader->Bind(); //Bind the shader!
//Runs whenever the window is resized or a shader is reassigned, so that we only need to get uniform locations once. It's not optimized fully yet...
if(HasntRunYet){
// screensize.x = width;
// screensize.y = height;
HasntRunYet = false;
InitialOpaqueUniforms[INITOPAQUE_DIFFUSE] = InitialOpaqueShader->GetUniformLocation("diffuse"); //Literal texture unit
InitialOpaqueUniforms[INITOPAQUE_WORLD2CAMERA] = InitialOpaqueShader->GetUniformLocation("World2Camera"); //World --> NDC
InitialOpaqueUniforms[INITOPAQUE_MODEL2WORLD] = InitialOpaqueShader->GetUniformLocation("Model2World"); //Model --> World
InitialOpaqueUniforms[INITOPAQUE_AMBIENT] = InitialOpaqueShader->GetUniformLocation("ambient"); //Ambient component of the material
InitialOpaqueUniforms[INITOPAQUE_SPECREFLECTIVITY] = InitialOpaqueShader->GetUniformLocation("specreflectivity"); //Specular reflectivity
InitialOpaqueUniforms[INITOPAQUE_SPECDAMP] = InitialOpaqueShader->GetUniformLocation("specdamp"); //Specular dampening
InitialOpaqueUniforms[INITOPAQUE_EMISSIVITY] = InitialOpaqueShader->GetUniformLocation("emissivity"); //emissivity... currently unused
InitialOpaqueUniforms[INITOPAQUE_DIFFUSIVITY] = InitialOpaqueShader->GetUniformLocation("diffusivity"); //Diffusivity... currently unused
InitialOpaqueUniforms[INITOPAQUE_RENDERFLAGS] = InitialOpaqueShader->GetUniformLocation("renderflags");
InitialOpaqueUniforms[INITOPAQUE_WORLDAROUNDME] = InitialOpaqueShader->GetUniformLocation("worldaroundme");
InitialOpaqueUniforms[INITOPAQUE_ENABLE_CUBEMAP_REFLECTIONS] = InitialOpaqueShader->GetUniformLocation("enableCubeMapReflections");
InitialOpaqueUniforms[INITOPAQUE_CAMERAPOS] = InitialOpaqueShader->GetUniformLocation("CameraPos");
InitialOpaqueUniforms[INITOPAQUE_JANEAR] = InitialOpaqueShader->GetUniformLocation("janear");
InitialOpaqueUniforms[INITOPAQUE_JAFAR] = InitialOpaqueShader->GetUniformLocation("jafar");
InitialOpaqueShader->setUniform1f("windowsize_x", (width
* Initial_Opaque_Pass_Approximation_Factor
));
InitialOpaqueShader->setUniform1f("windowsize_y", (height
* Initial_Opaque_Pass_Approximation_Factor
));
}
glUniform3f(InitialOpaqueUniforms[INITOPAQUE_CAMERAPOS], SceneCamera->pos.x, SceneCamera->pos.y, SceneCamera->pos.z);
glUniform1f(InitialOpaqueUniforms[INITOPAQUE_JAFAR], SceneCamera->jafar); //Needed for depth.
glUniform1f(InitialOpaqueUniforms[INITOPAQUE_JANEAR], SceneCamera->janear); //Needed for depth.
glUniform1f(InitialOpaqueUniforms[INITOPAQUE_ENABLE_CUBEMAP_REFLECTIONS], 1.0f);
Texture::SetActiveUnit(0);
//InitialOpaqueShader->setUniform1i("diffuse", 0);//Texture unit 0 is reserved for the textures of objects.
glUniform1i(InitialOpaqueUniforms[INITOPAQUE_DIFFUSE],0);
if(SkyBoxCubemap)
{
Texture::SetActiveUnit(1);
SkyBoxCubemap->Bind(1); //Bind to 1
}
//Do this regardless of the presence of Skyboxcubemap
glUniform1i(InitialOpaqueUniforms[INITOPAQUE_WORLDAROUNDME], 1);//Cubemap unit 1 is reserved for the cubemap representing the world around the object, for reflections.
glUniformMatrix4fv(InitialOpaqueUniforms[INITOPAQUE_WORLD2CAMERA], 1, GL_FALSE, &InitialOpaqueCameraMatrix[0][0]);
/*
Actually Render the objects to the screen
*/
//Now that we have the shader stuff set up, let's get to rendering!
glEnableVertexAttribArray(0); //Position
glEnableVertexAttribArray(1); //Texture
glEnableVertexAttribArray(2); //Normal
glEnableVertexAttribArray(3); //Color
if (Meshes.size() > 0) //if there are any
for (size_t i = 0; i < Meshes.size(); i++) //for all of them
if (Meshes[i]) //don't call methods on nullptrs
{
unsigned int flagerinos = Meshes[i]->getFlags(); //Set flags
glUniform1ui(InitialOpaqueUniforms[INITOPAQUE_RENDERFLAGS], flagerinos); //Set flags on GPU
Meshes[i]->DrawInstancesPhong(
InitialOpaqueUniforms[INITOPAQUE_MODEL2WORLD], //Model->World transformation matrix
InitialOpaqueUniforms[INITOPAQUE_AMBIENT], //Ambient material component
InitialOpaqueUniforms[INITOPAQUE_SPECREFLECTIVITY], //Specular reflective material component
InitialOpaqueUniforms[INITOPAQUE_SPECDAMP], //Specular dampening material component
InitialOpaqueUniforms[INITOPAQUE_DIFFUSIVITY], //Diffusivity. Reaction to diffuse light.
InitialOpaqueUniforms[INITOPAQUE_EMISSIVITY], //Emissivity material component
InitialOpaqueUniforms[INITOPAQUE_ENABLE_CUBEMAP_REFLECTIONS],
false //Yes, we're using textures.
);
}
//glDisableVertexAttribArray(0); //Position. We use this for the screenquadding, so we shouldn't disable it.
glDisableVertexAttribArray(1); //Texture
glDisableVertexAttribArray(2); //Normal
glDisableVertexAttribArray(3); //Color
//Note to self: Insert shadowed light depth passes here.
/*
===============================
* SHADOWLESS LIGHTING PASSES *
===============================
*/
//Setup for lights
glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE);
glDisable(GL_DEPTH_TEST); //Disable depth testing, we don't need it.
FboArray[LIGHT_ACCUMULATOR]->BindRenderTarget();
FBO::clearTexture(0.0,0.0,0.0,0.0);
/*
Point Lights
*/
if (SimplePointLights.size() > 0)
{
//Prep
PointLightShader->Bind();
if (!haveInitializedPointlightUniforms){
PointlightUniforms[POINTLIGHT_WORLD2CAMERA] = PointLightShader->GetUniformLocation("World2Camera");
PointlightUniforms[POINTLIGHT_TEX1] = PointLightShader->GetUniformLocation("tex1");
PointlightUniforms[POINTLIGHT_TEX2] = PointLightShader->GetUniformLocation("tex2");
PointlightUniforms[POINTLIGHT_TEX3] = PointLightShader->GetUniformLocation("tex3");
PointlightUniforms[POINTLIGHT_TEX4] = PointLightShader->GetUniformLocation("tex4");
PointlightUniforms[POINTLIGHT_POS] = PointLightShader->GetUniformLocation("lightpos");
PointlightUniforms[POINTLIGHT_COLOR] = PointLightShader->GetUniformLocation("lightcolor");
PointlightUniforms[POINTLIGHT_RANGE] = PointLightShader->GetUniformLocation("range");
PointlightUniforms[POINTLIGHT_DROPOFF] = PointLightShader->GetUniformLocation("dropoff");
PointlightUniforms[POINTLIGHT_JAFAR] = PointLightShader->GetUniformLocation("jafar");
PointlightUniforms[POINTLIGHT_JANEAR] = PointLightShader->GetUniformLocation("janear");
PointlightUniforms[POINTLIGHT_CAMERAPOS] = PointLightShader->GetUniformLocation("camerapos");
}
glUniform1i(PointlightUniforms[POINTLIGHT_TEX1], 0);
glUniform1i(PointlightUniforms[POINTLIGHT_TEX2], 1);
glUniform1i(PointlightUniforms[POINTLIGHT_TEX3], 2);
glUniform1i(PointlightUniforms[POINTLIGHT_TEX4], 3);
FboArray[OPAQUE_INITIAL]->BindasTexture(0,0);
FboArray[OPAQUE_INITIAL]->BindasTexture(1,1);
FboArray[OPAQUE_INITIAL]->BindasTexture(2,2);
FboArray[OPAQUE_INITIAL]->BindasTexture(3,3);
glUniform3f(PointlightUniforms[POINTLIGHT_CAMERAPOS], SceneCamera->pos.x, SceneCamera->pos.y, SceneCamera->pos.z);
glUniform1f(PointlightUniforms[POINTLIGHT_JAFAR], SceneCamera->jafar);
glUniform1f(PointlightUniforms[POINTLIGHT_JANEAR], SceneCamera->janear);
//Now do the point lights
if (SimplePointLights.size() > 0)
for (size_t i = 0; i < SimplePointLights.size(); i++) //LOOK HERE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! POINT LIGHT RENDERING HERE!!!!!!!!!!!!!!!!!!!!!!!!!!
{
SimplePointLights[i]->bindToUniformLight(PointlightUniforms[POINTLIGHT_POS], PointlightUniforms[POINTLIGHT_COLOR], PointlightUniforms[POINTLIGHT_RANGE], PointlightUniforms[POINTLIGHT_DROPOFF]);
ScreenquadtoFBO(PointLightShader);
}
}//Eof Point Lights.
//DONE WITH SHADOWLESS LIGHTS
/*
===================
* SHADOWED LIGHTS *
===================
*/
//(No code yet)
glEnable(GL_DEPTH_TEST); //We want it back!
glDisable(GL_BLEND);
//Final Opaque
if(FinalOpaqueShader) {
FboArray[OPAQUE_FINAL]->BindRenderTarget();
FBO::clearTexture(0.0,0.0,0.0,0.0);
FinalOpaqueShader->Bind();
//Grab uniform locations
if (!haveInitializedFinalOpaqueUniforms)
{
/*
enum{
FINALOPAQUE_INITOPAQUE1_TEX, //Holds the albedo
//Data buffers
FINALOPAQUE_INITOPAQUE2_TEX,
FINALOPAQUE_INITOPAQUE3_TEX,
FINALOPAQUE_INITOPAQUE4_TEX,
//Light Accumulator Textures
FINALOPAQUE_LIGHTACCUM1_TEX, //Diffuse
FINALOPAQUE_LIGHTACCUM2_TEX, //Specular
FINALOPAQUE_NUM_FINALOPAQUE_SHADER_UNIFORMS
};
GLuint FinalOpaqueUniforms[FINALOPAQUE_NUM_FINALOPAQUE_SHADER_UNIFORMS];
*/
FinalOpaqueUniforms[FINALOPAQUE_INITOPAQUE1_TEX] = FinalOpaqueShader->GetUniformLocation("initopaque1");
FinalOpaqueUniforms[FINALOPAQUE_INITOPAQUE2_TEX] = FinalOpaqueShader->GetUniformLocation("initopaque2");
FinalOpaqueUniforms[FINALOPAQUE_INITOPAQUE3_TEX] = FinalOpaqueShader->GetUniformLocation("initopaque3");
FinalOpaqueUniforms[FINALOPAQUE_INITOPAQUE4_TEX] = FinalOpaqueShader->GetUniformLocation("initopaque4");
FinalOpaqueUniforms[FINALOPAQUE_LIGHTACCUM1_TEX] = FinalOpaqueShader->GetUniformLocation("lightaccum1");
FinalOpaqueUniforms[FINALOPAQUE_LIGHTACCUM2_TEX] = FinalOpaqueShader->GetUniformLocation("lightaccum2");
haveInitializedFinalOpaqueUniforms = true;
}
//Bind Uniform values
glUniform1i(FinalOpaqueUniforms[FINALOPAQUE_INITOPAQUE1_TEX], 0);
glUniform1i(FinalOpaqueUniforms[FINALOPAQUE_INITOPAQUE2_TEX], 1);
glUniform1i(FinalOpaqueUniforms[FINALOPAQUE_INITOPAQUE3_TEX], 2);
glUniform1i(FinalOpaqueUniforms[FINALOPAQUE_INITOPAQUE4_TEX], 3);
glUniform1i(FinalOpaqueUniforms[FINALOPAQUE_LIGHTACCUM1_TEX], 4);
glUniform1i(FinalOpaqueUniforms[FINALOPAQUE_LIGHTACCUM2_TEX], 5);
//Bind Textures. Remember: Unit, Whichone
FboArray[OPAQUE_INITIAL]->BindasTexture(0,0);
FboArray[OPAQUE_INITIAL]->BindasTexture(1,1);
FboArray[OPAQUE_INITIAL]->BindasTexture(2,2);
FboArray[OPAQUE_INITIAL]->BindasTexture(3,3);
FboArray[LIGHT_ACCUMULATOR]->BindasTexture(4,0);
FboArray[LIGHT_ACCUMULATOR]->BindasTexture(5,1);
ScreenquadtoFBO(FinalOpaqueShader);
}
//Transparency Render
//Screenquad the results to the screen.
FBO::unBindRenderTarget(width, height);
FBO::clearTexture(0.0,0.0,0.0,0.0);
ShowTextureShader->Bind();
ShowTextureShader->setUniform1i("diffuse", 0);//NOTE TO SELF: Avoid glGetUniformLocation repeats
FboArray[OPAQUE_FINAL]->BindasTexture(0,0); //See FINALOPAQUE.fs
ScreenquadtoScreen(ShowTextureShader);
//Beautiful, isn't it?
} //eof drawPipeline
G Buffer Fragment Shader:
#version 330
// #extension GL_ARB_conservative_depth : enable
// out vec4 fColor[2];
// INITIAL_OPAQUE.FS
// (C) GEKLMIN 2018
// layout (depth_greater) out float gl_FragDepth;
// ^ should probably re-enable that later
//List of flags. Some of these are no longer implemented, they caused too much of a performance problem. I do not recommend you enable them.
const uint GK_RENDER = uint(1); // Do we render it? This is perhaps the most important flag.
const uint GK_TEXTURED = uint(2); // Do we texture it? if disabled, only the texture will be used. if both this and colored are disabled, the object will be black.
const uint GK_COLORED = uint(4);// Do we color it? if disabled, only the texture will be used. if both this and textured are disabled, the object will be black.
const uint GK_FLAT_NORMAL = uint(8); // Do we use flat normals? If this is set, then the normals output to the fragment shader in the initial opaque pass will use the flat layout qualifier.
const uint GK_FLAT_COLOR = uint(16); // Do we render flat colors? the final, provoking vertex will be used as the color for the entire triangle.
const uint GK_COLOR_IS_BASE = uint(32); //Use the color as the primary. Uses texture as primary if disabled.
const uint GK_TINT = uint(64); //Does secondary add to primary?
const uint GK_DARKEN = uint(128);//Does secondary subtract from primary?
const uint GK_AVERAGE = uint(256);//Do secondary and primary just get averaged?
const uint GK_COLOR_INVERSE = uint(512);//Do we use the inverse of the color?
const uint GK_TEXTURE_INVERSE = uint(1024);//Do we use the inverse of the texture color? DOES NOT invert alpha.
const uint GK_TEXTURE_ALPHA_MULTIPLY = uint(2048);//Do we multiply the color from the texture by the alpha before doing whatever it is we're doing? I do not recommend enabling this and alpha culling, especially if you're trying to create a texture-on-a-flat-color-model effect (Think sega saturn models)
const uint GK_ENABLE_ALPHA_CULLING = uint(4096); //Do we use the texture alpha to cull alpha fragments
const uint GK_TEXTURE_ALPHA_REPLACE_PRIMARY_COLOR = uint(8192); //if the alpha from the texture is <0.5 then the secondary color will replace the primary color.
//Utility functions
// vec4 when_eq(vec4 x, vec4 y) {
// return 1.0 - abs(sign(x - y));
// }
// vec4 when_neq(vec4 x, vec4 y) {
// return abs(sign(x - y));
// }
// vec4 when_gt(vec4 x, vec4 y) {
// return max(sign(x - y), 0.0);
// }
// vec4 when_lt(vec4 x, vec4 y) {
// return max(sign(y - x), 0.0);
// }
// vec4 when_ge(vec4 x, vec4 y) {
// return 1.0 - when_lt(x, y);
// }
// vec4 when_le(vec4 x, vec4 y) {
// return 1.0 - when_gt(x, y);
// }
uniform sampler2D diffuse; //This is actually the texture unit. limit 32. This one happens to be for the literal object's texture.
uniform samplerCube worldaroundme; //This is the cubemap we use for reflections.
in vec2 texcoord;
in vec3 normout;
flat in vec3 flatnormout;
flat in vec3 Flat_Vert_Color;
in vec3 Smooth_Vert_Color;
in vec4 ND_out;
in vec2 window_size;
in vec3 vert_to_camera;
in float ourdepth;
//Logic from the vertex level
in float isFlatNormal;
in float isTextured;
in float isColored;
in float isFlatColor;
in float ColorisBase;
in float AlphaReplaces;
in float isTinted;
in float isDarkened;
in float isAveraged;
in float isNotAnyofThose;
in vec3 worldout;
uniform float ambient;
uniform float specreflectivity;
uniform float specdamp;
uniform float emissivity;
uniform float jafar;
uniform float janear;
uniform float enableCubeMapReflections;
uniform float diffusivity;
uniform vec3 CameraPos; //Camera position in world space
vec2 bettertexcoord;
vec4 texture_value;
vec3 color_value;
vec3 primary_color;
vec3 secondary_color;
vec3 finalcolor = vec3(0,0,0); //default value. Does it work?
uniform uint renderflags;
void main()
{
bettertexcoord = vec2(texcoord.x, -texcoord.y); //Looks like blender
vec3 UnitNormal;
vec3 usefulNormal;
UnitNormal = ((normalize(flatnormout) + vec3(1.0,1.0,1.0)) * 0.5)* float((renderflags & GK_FLAT_NORMAL) > uint(0))+ ((normalize(normout) + vec3(1.0,1.0,1.0)) * 0.5) * (1-float((renderflags & GK_FLAT_NORMAL) > uint(0)));
// if (UnitNormal.x > 1 || UnitNormal.y > 1 || UnitNormal.z > 1)
// UnitNormal = vec3(1.0);
usefulNormal = normalize(flatnormout) * float((renderflags & GK_FLAT_NORMAL) > uint(0)) + normalize(normout) * (1-float((renderflags & GK_FLAT_NORMAL) > uint(0)));
texture_value = (texture2D(diffuse, bettertexcoord)) * float((renderflags & GK_TEXTURED) > uint(0)) + vec4(0.0,0.2,0.0,1.0) * (1-float((renderflags & GK_TEXTURED) > uint(0)));
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//UNCOMMENT THIS LINE IF YOU WANT ALPHA CULLING! It will slow down your application, be weary!
// if ((renderflags & GK_ENABLE_ALPHA_CULLING) > uint(0))
// if (texture_value.w == 0)
// discard;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
float flat_color = float((renderflags & GK_FLAT_COLOR) > uint(0));
float colored_at_all = float((renderflags & GK_COLORED) > uint(0));
color_value = flat_color * colored_at_all * Flat_Vert_Color + (1-flat_color) * colored_at_all * Smooth_Vert_Color + (1-flat_color) * (1-colored_at_all) * vec3(0,0,0);
//primary_color and secondary_color stuff
float colorbase = float((renderflags & GK_COLOR_IS_BASE) > uint(0));
primary_color = colorbase * color_value + (1-colorbase) * texture_value.xyz;
secondary_color = (1-colorbase) * color_value + colorbase * texture_value.xyz;
float alphareplace = float((renderflags & GK_TEXTURE_ALPHA_REPLACE_PRIMARY_COLOR) > uint(0));
primary_color = primary_color * (1-alphareplace) + (primary_color * (1-texture_value.w)) + (texture_value.xyz * texture_value.w) * alphareplace;
//EQUATION TIME!
//This will be hell to break up. Maybe the compiler will do it for me?
// if ((renderflags & GK_TINT) > uint(0))
// finalcolor = primary_color + secondary_color;
// else if ((renderflags & GK_DARKEN) > uint(0))
// finalcolor = primary_color - secondary_color;
// else if ((renderflags & GK_AVERAGE) > uint(0))
// finalcolor = vec3(
// (primary_color.x + secondary_color.x)/2.0,
// (primary_color.y + secondary_color.y)/2.0,
// (primary_color.z + secondary_color.z)/2.0);
// else
// finalcolor = primary_color;
//Floating point logic tables?!?!
float isTint = float((renderflags & GK_TINT) > uint(0)); // 1 if true, 0 if false
float isNotTint = 1-isTint;//swaps with the other value
float isDarken = float((renderflags & GK_DARKEN) > uint(0));
float isNotDarken = 1-isDarken;
float isAverage = float((renderflags & GK_AVERAGE) > uint(0));
float isNotAverage = 1-isAverage;
//it is none of those if:
//* More than one of them is true
//* All of them are false
float isNoneofThose = isTint * isDarken * isAverage + isNotTint * isAverage * isDarken + isTint * isNotAverage * isDarken + isTint * isAverage * isNotDarken + isNotTint * isNotAverage * isNotDarken;
float isNotNoneofThose = 1-isNoneofThose;
//Calc finalcolor;
finalcolor = (primary_color + secondary_color) * isTint * isNotNoneofThose + (primary_color - secondary_color) * isDarken * isNotNoneofThose + vec3((primary_color.x + secondary_color.x)/2.0,(primary_color.y + secondary_color.y)/2.0,(primary_color.z + secondary_color.z)/2.0) * isAverage * isNotNoneofThose + primary_color * isNoneofThose;
// (diffuse component * texture) + specular
// gl_FragData[0] = mix(vec4(finalcolor,specreflectivity),vec4(texture(worldaroundme,reflect(-vert_to_camera, usefulNormal)).xyz, specreflectivity),specreflectivity/2.0); //Lol
vec4 cubemapData = texture(worldaroundme,reflect(-vert_to_camera, usefulNormal));
gl_FragData[0] = vec4(finalcolor,specreflectivity);
float adjustedspecdamp = specdamp/128.0;
gl_FragData[1] = vec4(UnitNormal,adjustedspecdamp); //Normals. Specular dampening goes as high as 128 in OpenGL Immediate Mode, so it has to be allowed up there. Note that we are using 32 bit floating-point accuracy, so dividing will not seriously reduce our abilities with regards to specdamp
vec3 adjusted_world = worldout - CameraPos;
gl_FragData[2] = vec4(adjusted_world.x/jafar + 0.5 , adjusted_world.y/jafar + 0.5, adjusted_world.z/jafar + 0.5, emissivity/2.0 + 0.5);
gl_FragData[3] = vec4(diffusivity, cubemapData.xyz * enableCubeMapReflections * specreflectivity * adjustedspecdamp); //Not using ambient.
}
PointLight Fragment Shader:
#version 330
out vec4 fColor[2];
in vec2 texcoord;
in vec2 ScreenPosition;
// uniform sampler2D diffuse; //This is actually the texture unit. limit 32. This one happens to be for the literal object's texture.
uniform sampler2D tex1; //Unit 0
uniform sampler2D tex2;
uniform sampler2D tex3;
uniform sampler2D tex4; //Unit 3
uniform vec3 lightpos;
uniform vec3 lightcolor;
uniform vec3 camerapos;
uniform float range;
uniform float dropoff;
//far and near clip planes
uniform float jafar;
uniform float janear;
void main()
{
//Grab the values from the initial opaque pass buffers
vec4 tex1_value = texture2D(tex1, texcoord);
vec4 tex2_value = texture2D(tex2, texcoord);
vec4 tex3_value = texture2D(tex3, texcoord);
vec4 tex4_value = texture2D(tex4, texcoord);
vec3 world_pos = (tex3_value.xyz - vec3(0.5)) * jafar + camerapos;
vec3 surface_normal_world = (tex2_value.xyz * 2) - vec3(1);
vec3 unit_surface_normal_world = normalize(surface_normal_world);
float specular_dampening = tex2_value.w * 128.0;
float specular_reflectivity = tex1_value.w;
float diffusivity = tex4_value.x;
surface_normal_world = normalize(surface_normal_world);
//PHONG calculations begin!
vec3 frag_to_camera = camerapos - world_pos;
vec3 frag_to_light = lightpos - world_pos;
vec3 unit_frag_to_camera = normalize(frag_to_camera);
vec3 unit_frag_to_light = normalize(frag_to_light);
vec3 lightDir = -unit_frag_to_light;
//DIFFUSE LIGHTING CALCULATION
float nDotl = max(dot(unit_surface_normal_world, unit_frag_to_light), 0);
float lightdist = length(frag_to_light); //Can never be negative
nDotl = float(range > 0) * max(nDotl * pow(max(1-(lightdist/range),0.0), dropoff),0.0) + float(range <= 0) * nDotl;
vec3 betterdiffuse = nDotl * lightcolor * diffusivity;
//SPECULAR LIGHTING CALCULATION
vec3 reflectedLightDir = reflect(lightDir,unit_surface_normal_world);
float specFactor = max(
dot(reflectedLightDir, unit_frag_to_camera),
0.0
);
float specDampFactor = pow(specFactor,specular_dampening);
vec3 finalSpecular = specDampFactor * specular_reflectivity * lightcolor;
finalSpecular = float(range > 0) * finalSpecular * max(1-(lightdist/range),0.0) + float(range <= 0) * finalSpecular;
//The skybox has to have a diffuse of 1.
fColor[0] = vec4(betterdiffuse,1.0);
fColor[1] = vec4(finalSpecular,1.0);
}