Part of the Khronos Group
OpenGL.org

The Industry's Foundation for High Performance Graphics

from games to virtual reality, mobile phones to supercomputers

Results 1 to 6 of 6

Thread: Poor Performance with Point Light rendering in a Deferred Rendering pipeline?

  1. #1
    Intern Contributor
    Join Date
    Jan 2018
    Posts
    51

    Poor Performance with Point Light rendering in a Deferred Rendering pipeline?

    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:
    Code :
    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<<"\n OpenGL reports an ERROR!";
    		// if (communism == GL_INVALID_ENUM)
    			// std::cout<<"\n Invalid enum.";
    		// if (communism == GL_INVALID_OPERATION)
    			// std::cout<<"\n Invalid operation.";
    		// if (communism == GL_INVALID_FRAMEBUFFER_OPERATION)
    			// std::cout <<"\n Invalid Framebuffer Operation.";
    		// if (communism == GL_OUT_OF_MEMORY)
    		// {
    			// std::cout <<"\n 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:
    Code :
    #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:
    Code :
    #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);
    }
    Last edited by Geklmin; 05-19-2018 at 06:17 AM. Reason: Hitler told me to

  2. #2
    Senior Member OpenGL Guru Dark Photon's Avatar
    Join Date
    Oct 2004
    Location
    Druidia
    Posts
    4,478
    Whatever you read, you misinterpreted it. To maximize the number of light sources you can process, you want to minimize the fill per light. To do so, you typically apply multiple lights per primitive, and (as best a you efficiently can) avoid applying lights to pixels they cannot influence.
    Last edited by Dark Photon; 05-18-2018 at 07:07 PM.

  3. #3
    Intern Contributor
    Join Date
    Jan 2018
    Posts
    51
    yes but you said it would be faster than using a for loop over all lights in the scene in one pass

  4. #4
    Intern Contributor
    Join Date
    Jan 2018
    Posts
    51

    lots of lights in one shader is FAST!!! (Dark photon was wrong!)

    For the first time in his life, Dark photon was wrong about something.
    This fragment shader which takes in 100 point lights and renders them in a for loop (WITH dynamic uniform indexing... using an iterator to index a uniform) is A BAJILLION TIMES FASTER than the one that renders one at a time (below)
    Code :
    #version 330
     
    #define MAX_LIGHTS 100
    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.
     
    struct PointLight {
    	vec3 pos;
    	vec3 color;
    	float range;
    	float dropoff;
    };
     
    uniform PointLight LightArray[MAX_LIGHTS]; //MAX_LIGHTS
    //NOTE: I feared a for loop might be slow because of what I saw here, but apparently technology has advanced since the 2006. My GTX 960 can do it fine!
    /*
    https://stackoverflow.com/questions/16039515/glsl-for-loop-array-index#26480937
    */
     
    uniform sampler2D tex1; //Unit 0
    uniform sampler2D tex2;
    uniform sampler2D tex3;
    uniform sampler2D tex4; //Unit 3
    uniform vec3 camerapos;
    uniform int numlights; //How many lights do we have?
    //far and near clip planes
    /* DOES NOT work!
    vec3 calculate_world_position(vec2 texture_coordinate, float depth_from_depth_buffer)
    {
        vec4 clip_space_position = vec4(texture_coordinate * 2.0 - vec2(1.0), 2.0 * depth_from_depth_buffer - 1.0, 1.0);
     
        //vec4 position = inverse_projection_matrix * clip_space_position; // Use this for view space
        vec4 position = inverse_view_projection_matrix * clip_space_position; // Use this for world space
     
        return(position.xyz / position.w);
    }
    */
     
    //Another thing that should work
     
    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 unit_surface_normal_world = tex2_value.xyz;
    	float specular_dampening = tex2_value.w;
    	float specular_reflectivity = tex1_value.w;
    	float diffusivity = tex4_value.x;
    	vec3 frag_to_camera = camerapos - world_pos;
    	vec3 unit_frag_to_camera = normalize(frag_to_camera);
     
    	vec3 betterdiffuse;
    	vec3 finalSpecular;
    	//Our main for loop.
    	for (int i = 0; i < numlights && i < MAX_LIGHTS; i++){
    		vec3 frag_to_light = LightArray[i].pos - world_pos;
    		vec3 unit_frag_to_light = normalize(frag_to_light);
    		vec3 lightDir = -unit_frag_to_light;
     
    		//DIFFUSE LIGHTING CALCULATION
    		float nDotl = dot(unit_surface_normal_world, unit_frag_to_light);
    		float lightdist = length(frag_to_light); //Can never be negative
    		nDotl = max(nDotl * pow(max(1-(lightdist/LightArray[i].range),0.0), LightArray[i].dropoff),0.0);
    		betterdiffuse += nDotl * LightArray[i].color * 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);
     
    		finalSpecular += specDampFactor * specular_reflectivity * LightArray[i].color * pow(max(1-(lightdist/LightArray[i].range),0.0), LightArray[i].dropoff);
    	}
     
    	fColor[0] = vec4(betterdiffuse,1.0);
    	fColor[1] = vec4(finalSpecular,1.0);
    }

    Code :
     #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;
    /* DOES NOT work!
    vec3 calculate_world_position(vec2 texture_coordinate, float depth_from_depth_buffer)
    {
        vec4 clip_space_position = vec4(texture_coordinate * 2.0 - vec2(1.0), 2.0 * depth_from_depth_buffer - 1.0, 1.0);
     
        //vec4 position = inverse_projection_matrix * clip_space_position; // Use this for view space
        vec4 position = inverse_view_projection_matrix * clip_space_position; // Use this for world space
     
        return(position.xyz / position.w);
    }
    */
     
    //Another thing that should work
     
    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 unit_surface_normal_world = tex2_value.xyz;
    	float specular_dampening = tex2_value.w;
    	float specular_reflectivity = tex1_value.w;
    	float diffusivity = tex4_value.x; 
    	//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 = dot(unit_surface_normal_world, unit_frag_to_light);
    	float lightdist = length(frag_to_light); //Can never be negative
    	nDotl = max(nDotl * pow(max(1-(lightdist/range),0.0), dropoff),0.0);
    	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 = finalSpecular * pow(max(1-(lightdist/range),0.0), dropoff);
     
    	fColor[0] = vec4(betterdiffuse,1.0);
    	fColor[1] = vec4(finalSpecular,1.0);
    }

    I still love you Dark Photon <3 no hate~~~

  5. #5
    Senior Member OpenGL Lord
    Join Date
    May 2009
    Posts
    6,031
    For the first time in his life, Dark photon was wrong about something.
    I've looked over his posting history for the last week or so, and I've seen nothing about this. Perhaps you could provide a link to this supposed statement, so that we can verify your claims.

  6. #6
    Junior Member Newbie
    Join Date
    May 2018
    Posts
    13
    Code :
    /* DOES NOT work!
    vec3 calculate_world_position(vec2 texture_coordinate, float depth_from_depth_buffer)
    {
        vec4 clip_space_position = vec4(texture_coordinate * 2.0 - vec2(1.0), 2.0 * depth_from_depth_buffer - 1.0, 1.0);
     
        //vec4 position = inverse_projection_matrix * clip_space_position; // Use this for view space
        vec4 position = inverse_view_projection_matrix * clip_space_position; // Use this for world space
     
        return(position.xyz / position.w);
    }
    */

    There is nothing wrong with this code, except from the naming: What you call "clip_space_position" are actually NDC coordinates. So please stop confusing people with your wrong information.

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •