[SOLVED] Weird OpenGL Blending Issue

So I’m working on implementing a basic 2D forward rendering system right now with lighting, but there is a slight problem that I can’t wrap my head around. All of the articles that I have read about blending point me right where I am now. In forward rendering, you need to sum up all of the fragment shading calculations to get your final scene with blending, but somehow blending is just not working for me. I apologize if this problem is extremely simple ahead of time as I haven’t really worked with blending in OpenGL until just now.

I have included what I think to be the relevant code. If you need to see any more of the code, or details, just let me know.

Core class:


package gel.engine.core;

import gel.engine.graphics.RenderingEngine;

import static org.lwjgl.opengl.GL11.*;
import gel.engine.input.Input;
import gel.engine.window.Window;

public abstract class Core
{

	private static Core instance;

	protected boolean running;
	protected int targetFps;
	protected int targetUps;
	protected ProfileTimer profileTimer;
	protected Window window;
	protected Input input;
	protected RenderingEngine renderingEngine;

	public Core()
	{
		if (instance == null)
		{

			instance = this;

			this.running = false;
			this.targetFps = -1;
			this.targetUps = 60;

			window = new Window();

		} else
		{
			throw new IllegalStateException("Can not make more than one instance of Core");
		}
	}

	public static Core getInstance()
	{
		return instance;
	}

	public static boolean created()
	{
		return (instance == null);
	}

	public boolean isRunning()
	{
		return running;
	}

	public int getTargetFps()
	{
		return targetFps;
	}

	public int getTargetUps()
	{
		return targetUps;
	}

	public ProfileTimer getProfileTimer()
	{
		return profileTimer;
	}

	public Window getWindow()
	{
		return window;
	}

	public Input getInput()
	{
		return input;
	}

	public RenderingEngine getRenderingEngine()
	{
		return renderingEngine;
	}

	public void setTargetFps(int target)
	{
		if (!running)
		{
			this.targetFps = target;
		}
	}

	public void setTargetUps(int target)
	{
		if (!running)
		{
			this.targetUps = target;
		}
	}

	public void start()
	{
		run();
	}

	public void stop()
	{
		running = false;
	}

	private void run()
	{

		// initialize the engine
		initEngine();

		running = true;

		long lastSecond = System.nanoTime();
		long thisFrame = System.nanoTime();
		long lastFrame = System.nanoTime();
		double updateTime = 1e9f / targetUps;
		double renderTime = 1e9f / targetFps;
		double accumulativeUpdateTime = 0;
		double accumulativeFrameTime = 0;
		long sleepTime = 0;
		int updateCount = 0;
		int frameCount = 0;

		while (running)
		{

			// Get the delta between this frame and last frame
			thisFrame = System.nanoTime();
			profileTimer.updateDelta(thisFrame, lastFrame);
			lastFrame = thisFrame;

			// Accumulate the delta in the update and render accumulate variables.
			accumulativeUpdateTime += profileTimer.getDelta();
			accumulativeFrameTime += profileTimer.getDelta();

			// Update and take into account any missed frames.
			if (targetUps != -1)
			{
				while (accumulativeUpdateTime >= updateTime)
				{
					updateGame();
					updateCount++;
					accumulativeUpdateTime -= updateTime;
				}
			} else
			{
				updateGame();
				updateCount++;
				accumulativeUpdateTime = 0;
			}

			// Render if possible.
			if (targetFps != -1)
			{
				if (accumulativeFrameTime >= renderTime)
				{
					renderGame();
					frameCount++;
					accumulativeFrameTime = 0;
				} else
				{

					// Calculate sleep time and sleep for that amount.

					sleepTime = Math.round((renderTime - accumulativeFrameTime) / (1024 * 1024));

					try
					{
						Thread.sleep(sleepTime);
					} catch (InterruptedException e)
					{
						e.printStackTrace();
					}

				}
			} else
			{
				renderGame();
				frameCount++;
				accumulativeFrameTime = 0;
			}

			// Check if a second has passed, and if so, update fps and ups.
			if (System.nanoTime() - lastSecond >= 1e9)
			{
				profileTimer.updateFps(frameCount);
				profileTimer.updateUps(updateCount);
				frameCount = 0;
				updateCount = 0;
				lastSecond = System.nanoTime();
			}

			// Check if the game needs to stop.
			if (window.isCloseRequested())
			{
				stop();
			}

		}

		// Unload the game content.
		unloadGame();

	}

	private void initEngine()
	{

		// create gl context and initialize rendering engine

		window.create();

		renderingEngine = new RenderingEngine();
		profileTimer = new ProfileTimer();
		input = new Input();
		input.create();

		// load game content
		loadGame();
	}

	private void loadGame()
	{
		load();
	}

	private void updateGame()
	{
		input.update();
		update();
	}

	private void renderGame()
	{
		glClear(GL_COLOR_BUFFER_BIT);
		renderingEngine.update();
		render();
		window.update();
		
	}

	private void unloadGame()
	{
		unload();
	}

	public abstract void load();

	public abstract void update();

	public abstract void render();

	public abstract void unload();

}

RenderingEngine Class:


package gel.engine.graphics;

import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL11.glDisable;
import gel.engine.core.Core;
import gel.engine.graphics.lighting.AmbientLight;
import gel.engine.graphics.lighting.PointLight;
import gel.engine.graphics.matrix.RotationMatrix;
import gel.engine.graphics.matrix.ScaleMatrix;
import gel.engine.graphics.matrix.TransformationMatrix;
import gel.engine.graphics.matrix.TranslationMatrix;
import gel.engine.math.Vector2f;

public class RenderingEngine
{

	public static final String UNIFORM_MODEL_MATRIX = "modelMatrix";
	public static final String UNIFORM_VIEW_MATRIX = "viewMatrix";
	public static final String UNIFORM_PROJECTION_MATRIX = "projectionMatrix";

	public static final String UNIFORM_AMBIENTCOLOR = "ambientColor";

	private static RenderingEngine instance;

	private VertexArray vertexArray;
	private OrthographicCamera camera;
	private ShaderProgram ambientShader;
	private ShaderProgram pointLightShader;

	private AmbientLight ambient;

	public RenderingEngine()
	{
		if (instance == null)
		{
			instance = this;

			vertexArray = new VertexArray();
			camera = new OrthographicCamera(0, Core.getInstance().getWindow().getWidth(), 0, Core.getInstance().getWindow().getHeight(), 1, -1);

			ambientShader = new ShaderProgram();
			ambientShader.createAndCompileVertexShader("res\\shaders\\ambientShader.vs");
			ambientShader.createAndCompileFragmentShader("res\\shaders\\ambientShader.fs");
			ambientShader.linkProgram();

			pointLightShader = new ShaderProgram();
			pointLightShader.createAndCompileVertexShader("res\\shaders\\pointLightShader.vs");
			pointLightShader.createAndCompileFragmentShader("res\\shaders\\pointLightShader.fs");
			pointLightShader.linkProgram();

			ambient = new AmbientLight(new Color(255, 255, 255));

		} else
		{
			throw new IllegalStateException("Can not make more than one instance of RenderingEngine");
		}
	}

	public static RenderingEngine getInstance()
	{
		return instance;
	}

	public OrthographicCamera getCamera()
	{
		return camera;
	}

	public AmbientLight getAmbientLight()
	{
		return ambient;
	}

	public void update()
	{
		camera.update();

		ambientShader.setMatrix4f(UNIFORM_VIEW_MATRIX, camera.getViewMatrix().getMatrix());
		ambientShader.setMatrix4f(UNIFORM_PROJECTION_MATRIX, camera.getProjectionMatrix().getMatrix());

		pointLightShader.setMatrix4f(UNIFORM_VIEW_MATRIX, camera.getViewMatrix().getMatrix());
		pointLightShader.setMatrix4f(UNIFORM_PROJECTION_MATRIX, camera.getProjectionMatrix().getMatrix());

	}

	// update uniforms for rendering passes

	public void renderTexture(Texture t, float x, float y, float rotation)
	{
		if (x + t.getWidth() >= 0 && x < Core.getInstance().getWindow().getWidth() + t.getWidth() && y + t.getHeight() >= 0 && y < Core.getInstance().getWindow().getHeight() + t.getHeight())
		{
			ambientShader.bind();
			vertexArray.clear();
			
			vertexArray.addVertex(new Vertex(new Vector2f(-t.getWidth() / 2, -t.getHeight() / 2), new Color(0), new Vector2f(1, 1)));
			vertexArray.addVertex(new Vertex(new Vector2f(-t.getWidth() / 2, t.getHeight() / 2), new Color(0), new Vector2f(1, 0)));
			vertexArray.addVertex(new Vertex(new Vector2f(t.getWidth() / 2, t.getHeight() / 2), new Color(0), new Vector2f(0, 0)));
			vertexArray.addVertex(new Vertex(new Vector2f(t.getWidth() / 2, -t.getHeight() / 2), new Color(0), new Vector2f(0, 1)));
			
			ambientShader.setMatrix4f(UNIFORM_MODEL_MATRIX, new TransformationMatrix(new TranslationMatrix(x + t.getWidth() / 2, y + t.getHeight() / 2), new RotationMatrix(rotation), new ScaleMatrix(1, 1)).getMatrix());
			ambientShader.setVector3f(UNIFORM_AMBIENTCOLOR, ambient.getColor().toVector3f());
			
			vertexArray.render();
		}
	}

	public void renderPointLight(PointLight light)
	{
		glEnable(GL_BLEND);
		glBlendFunc(GL_ONE, GL_ONE);
		if (light.getPosition().getX() + light.getRadius() >= 0 && light.getPosition().getX() < Core.getInstance().getWindow().getWidth() && light.getPosition().getY() + light.getRadius() >= 0 && light.getPosition().getY() < Core.getInstance().getWindow().getHeight())
		{
			pointLightShader.bind();
			vertexArray.clear();
			vertexArray.addVertex(new Vertex(new Vector2f(-light.getRadius(), -light.getRadius())));
			vertexArray.addVertex(new Vertex(new Vector2f(-light.getRadius(), light.getRadius())));
			vertexArray.addVertex(new Vertex(new Vector2f(light.getRadius(), light.getRadius())));
			vertexArray.addVertex(new Vertex(new Vector2f(light.getRadius(), -light.getRadius())));
			pointLightShader.setMatrix4f(UNIFORM_MODEL_MATRIX, new TransformationMatrix(new TranslationMatrix(light.getPosition().getX(), light.getPosition().getY()), new RotationMatrix(0), new ScaleMatrix(1, 1)).getMatrix());
			pointLightShader.setVector2f("pos", light.getPosition());
			pointLightShader.setVector3f("color", light.getColor().toVector3f());
			pointLightShader.setFloat("radius", light.getRadius());
			pointLightShader.setFloat("constant", light.getConstAtten());
			pointLightShader.setFloat("linear", light.getLinearAtten());
			pointLightShader.setFloat("quadratic", light.getQuadAtten());
			vertexArray.render();
		}
		glDisable(GL_BLEND);
	}

}


Game class(Subclass of Core):


package game;

import static org.lwjgl.opengl.GL11.*;
import gel.engine.core.Core;
import gel.engine.graphics.Bitmap;
import gel.engine.graphics.Color;
import gel.engine.graphics.Texture;
import gel.engine.graphics.lighting.PointLight;
import gel.engine.math.Vector2f;

public class Game extends Core
{

	private Texture grass;
	private PointLight light;

	public static void main(String[] args)
	{
		Game g = new Game();
		g.getWindow().setTitle("Gel Engine");
		g.getWindow().setSize(16 * 60, 9 * 60);
		g.getWindow().setResizable(false);
		g.start();
	}

	@Override
	public void load()
	{
		grass = new Texture(new Bitmap("res\\grass.png"));
		light = new PointLight(new Vector2f(400, 400), new Color(255, 127, 0), 200, 0, 0, 0.01f); // pos, color, range, const, linear, quadratic attenuation
	}

	@Override
	public void update()
	{

	}

	@Override
	public void render()
	{
		renderingEngine.renderTexture(grass, 400, 400, 0);
		renderingEngine.renderPointLight(light);
	}

	@Override
	public void unload()
	{

	}

}


Texture and Ambient Vertex Shader:


#version 110

uniform mat4 modelMatrix;
uniform mat4 viewMatrix;
uniform mat4 projectionMatrix;

void main()
{
	gl_Position = projectionMatrix * viewMatrix * modelMatrix * gl_Vertex;
	gl_TexCoord[0] = gl_MultiTexCoord0;
}

Ambient Fragment Shader:


#version 110

uniform sampler2D textureSampler;
uniform vec3 ambientColor;

void main()
{
	gl_FragColor = vec4(ambientColor, 1.0) * texture2D(textureSampler, gl_TexCoord[0].st);
}

Point light fragment shader:


#version 110

uniform vec2 pos;
uniform vec3 color;
uniform float radius;
uniform float constant;
uniform float linear;
uniform float quadratic;

void main()
{

	float dist = distance(gl_FragCoord.xy, pos);
	float atten = 1.0 / (quadratic * dist * dist + linear * dist + constant);
	gl_FragColor = vec4(atten, atten, atten, 1.0) * vec4(color, 1.0);
}

With this code, this is the current scene that I get:

If I comment out rendering the texture in the render() method in the Game class, I get the same results. Could blending be getting ignored or something alike?

If I comment out where I render the point light in the render() method of the Game class I get the actual texture rendered, like so:

Out of those results, I would expect to get the grass texture additively blended in with the light, but that is obviously not so. If anyone who has a solution to this issue, it would be greatly appreciated.