function gadget:GetInfo()
  return {
    name      = "Smoke POPS",
    desc      = "Powerful Open-source Particle System 1.0",
    author    = "Argh",
    date      = "September 18th, 2009",
    license   = "GNU GPL, v2 or later",
    layer     = 50, --way late
    enabled   = true--  loaded by default?
  }
end

popsList = {}


if (gadgetHandler:IsSyncedCode()) then
--------------------------------------------------------------SAFETY CODE, REMOVE AT OWN PERIL
function gadget:Initialize()
	gadgetHandler:RegisterGlobal("popsList", popsList)
end

local ran = 0
function gadget:GameFrame(f)
	Spring.Echo(ran)
	if ran < 1 then
		
		for x = 1,4096,1 do
			SendToUnsynced("pops_event",0.999999,0.999999,0.99999,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)
			SendToUnsynced("pops_slow_event",0.999999,0.999999,0.99999,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)
		end
		ran = 1
	end
	if ran < 33 then
		SendToUnsynced("build_texture_atlas",0)
		ran = ran + 1
	end
	if ran >= 32 then
		SendToUnsynced("freeze_texture_atlas",0)
	end
	if ran >= 33 then
		gadgetHandler:RemoveCallIn("GameFrame")
	end
end
else
--------------------------------------------------------------ALL CODE PAST HERE IS UNSYNCED!

--------------------------------------------------------------------------------------CONFIG VARIABLES
local drawScreen     = false
local drawReflection = false

local runShader = 0

-- total particles = pXcount * pYcount
local pXcount = 64
local pYcount = 64

--------------------------------------------------------------------------------------TEXTURE ATLAS
local textureAtlas = {
[1] = "smoke1.tga",
[2] = "smoke2.tga",
[3] = "smoke3.tga",
[4] = "smoke4.tga",
[5] = "randdots.tga",
[6] = "randdots2.tga",
[7] = "genericexplosion.tga",
[8] = "circularthingy.tga",

[9] = "explosion001.tga",
[10] = "explosion002.tga",
[11] = "explosion003.tga",
[12] = "explosion004.tga",
[13] = "explosion005.tga",
[14] = "explosion006.tga",
[15] = "explosion007.tga",
[16] = "explosion008.tga",

[17] = "gas.tga",
[18] = "sakflowerexplo.tga",
[19] = "sakmildexplo.tga",
[20] = "sakexplo.tga",
[21] = "sakcloudexplo.tga",
[22] = "sakempexplo.tga",
[23] = "sakfireball.tga",
[24] = "sakflame.tga",

[25] = "static_explosion001.tga",
[26] = "circularthingy.tga",
[27] = "circularthingy.tga",
[28] = "circularthingy.tga",
[29] = "circularthingy.tga",
[30] = "circularthingy.tga",
[31] = "circularthingy.tga",
[32] = "circularthingy.tga",

[33] = "chunklet001.tga",
[34] = "chunklet002.tga",
[35] = "chunklet003.tga",
[36] = "chunklet004.tga",
[37] = "chunklet005.tga",
[38] = "chunklet006.tga",
[39] = "chunklet007.tga",
[40] = "chunklet008.tga",

[41] = "debris001.tga",
[42] = "debris002.tga",
[43] = "debris003.tga",
[44] = "debris004.tga",
[45] = "debris005.tga",
[46] = "debris006.tga",
[47] = "debris007.tga",
[48] = "debris008.tga",

[49] = "circularthingy.tga",
[50] = "circularthingy.tga",
[51] = "circularthingy.tga",
[52] = "circularthingy.tga",
[53] = "circularthingy.tga",
[54] = "circularthingy.tga",
[55] = "circularthingy.tga",
[56] = "circularthingy.tga",

[57] = "bloodblast.tga",
[58] = "plasmaflame.tga",
[59] = "circularthingy.tga",
[60] = "circularthingy.tga",
[61] = "circularthingy.tga",
[62] = "circularthingy.tga",
[63] = "circularthingy.tga",
[64] = "dynamicfake.tga",
}


--------------------------------------------------------------------------------------GL SPEEDUPS
local glColor = gl.Color
local glCulling = gl.Culling
local glBlending = gl.Blending
local glActiveFBO = gl.ActiveFBO
local glTexture = gl.Texture
local glTexRect = gl.TexRect
local glRect = gl.Rect
local glUniform = gl.Uniform
local glUseShader = gl.UseShader
local glDepthTest = gl.DepthTest

local glCallList = gl.CallList
local glResetState = gl.ResetState
local GL_SRC_ALPHA = GL.SRC_ALPHA
local GL_ONE = GL.ONE
local GL_LEQUAL = GL.LEQUAL
local GL_ONE_MINUS_SRC_ALPHA = GL.ONE_MINUS_SRC_ALPHA
local glCulling = gl.Culling
local GL_BACK = GL.BACK

--------------------------------------------------------------------------------------LOS STUFF, MAP SIZE
local Ally = Spring.GetLocalAllyTeamID()
local IsPosInLos = Spring.IsPosInLos
local MaxSizeX = Game.mapSizeX
local MaxSizeZ = Game.mapSizeZ
if MaxSizeX > MaxSizeZ then MaxSizeZ = MaxSizeX end --Fix for non-square maps
if MaxSizeZ > MaxSizeX then MaxSizeX = MaxSizeZ end

--------------------------------------------------------------------------------------NON-STANDARD GL CONSTANTS
--------------------------------------------------------------------------------------DON'T REMOVE UNLESS YOU KNOW WHAT YOU'RE DOING
local GL_RGBA32F_ARB = 0x8814

local GL_COLOR_ATTACHMENT0_EXT = 0x8CE0
local GL_COLOR_ATTACHMENT1_EXT = 0x8CE1
local GL_COLOR_ATTACHMENT2_EXT = 0x8CE2
local GL_COLOR_ATTACHMENT3_EXT = 0x8CE3

--------------------------------------------------------------------------------------LOCALIZED VARIABLES
--------------------------------------------------------------------------------------THESE ARE INTERNAL AND YOU PROBABLY SHOULD LEAVE ALONE
local posTex, velTex, dragTex, otherTex, losTex, myAtlasTex, myCopyTex
local posTex2, velTex2, dragTex2, otherTex2
local colorTex1, colorTex2, colorTex3, colorTex4, colorTex5, colorTex6, colorTex7, colorTex8
local fbo, fbo1, fbo2, fbo3, fbo4, fbo5, fbo6, fbo7, fbo8

local startTimer = Spring.GetTimer()
local diffTime = 0
local dt = 0
local oldTime = 0

local buildIt = 0

local currentParticles = 0
local currentColorParticles = 0
local currentRow = 0
local currentColumn = 0
local math_random = math.random
local math_floor = math.floor
local dpX = 1 / (2 * pXcount)
local dpY = 1 / (2 * pYcount)
local distScale = 1000000
local particleList = {}
local slowParticleList ={}

--------------------------------------------------------------------------------------COMMUNICATION FUNCTION AND QUEUE HANDLER
local function BuildParticleTable(_,posX,posY,posZ,gravity,velX,velY,velZ,size,drag,sizeGrowth,myVelocity,startTime, finishTime,myRand,myType, myCone, color1R, color1G, color1B, color1A, color2R, color2G, color2B, color2A, color3R, color3G, color3B, color3A, color4R, color4G, color4B, color4A)
		startTime = diffTime / distScale
		finishTime = (diffTime + finishTime) / distScale

		particleList[#particleList+1] = {posX = posX,posY = posY,posZ = posZ,gravity = gravity,velX = velX,velY = velY,velZ = velZ,size = size,drag = drag,sizeGrowth = sizeGrowth,myVelocity = myVelocity,startTime = startTime, finishTime = finishTime,myRand = myRand,myType = myType, myCone = myCone, color1R = color1R, color1G = color1G, color1B = color1B, color1A = color1A, color2R = color2R, color2G = color2G, color2B = color2B, color2A = color2A, color3R = color3R, color3G = color3G, color3B = color3B, color3A = color3A, color4R = color4R, color4G = color4G, color4B = color4B, color4A = color4A}
end

local function BuildSlowParticleTable(_,posX,posY,posZ,gravity,velX,velY,velZ,size,drag,sizeGrowth,myVelocity,startTime, finishTime,myRand,myType, myCone, color1R, color1G, color1B, color1A, color2R, color2G, color2B, color2A, color3R, color3G, color3B, color3A, color4R, color4G, color4B, color4A)
		startTime = diffTime / distScale
		finishTime = (diffTime + finishTime) / distScale

		slowParticleList[#slowParticleList+1] = {posX = posX,posY = posY,posZ = posZ,gravity = gravity,velX = velX,velY = velY,velZ = velZ,size = size,drag = drag,sizeGrowth = sizeGrowth,myVelocity = myVelocity,startTime = startTime, finishTime = finishTime,myRand = myRand,myType = myType, myCone = myCone, color1R = color1R, color1G = color1G, color1B = color1B, color1A = color1A, color2R = color2R, color2G = color2G, color2B = color2B, color2A = color2A, color3R = color3R, color3G = color3G, color3B = color3B, color3A = color3A, color4R = color4R, color4G = color4G, color4B = color4B, color4A = color4A}
end

local function BuildIt()
	buildIt = 1
end

local function StopIt()
	buildIt = 0
end

local function BuildTextureAtlas()
Spring.Echo("building atlas")
glActiveFBO(fbo5, true, function()  -- START FBO
	glCulling(GL.BACK)
	glBlending(false)
	glUseShader(pops_atlas_shader)
	local texX,texY = 0,0
	local currentLoc = 0
	for i,k in ipairs (textureAtlas) do
		currentLoc = i
		glTexture(0,'bitmaps/projectiletextures/'..k)

		if currentLoc == 1 then
			glTexRect(1/8 - 7/8,1/8 + 7/8,-1/8 - 7/8, -1/8 + 7/8)
		end

		if currentLoc == 2 then
			glTexRect(1/8 - 5/8,1/8 + 7/8,-1/8 - 5/8, -1/8 + 7/8)
		end

		if currentLoc == 3 then
			glTexRect(1/8 - 3/8,1/8 + 7/8,-1/8 - 3/8, -1/8 + 7/8)
		end

		if currentLoc == 4 then
			glTexRect(1/8 - 1/8,1/8 + 7/8,-1/8 - 1/8, -1/8 + 7/8)
		end

		if currentLoc == 5 then
			glTexRect(1/8 + 1/8,1/8 + 7/8,-1/8 + 1/8, -1/8 + 7/8)
		end

		if currentLoc == 6 then
			glTexRect(1/8 + 3/8,1/8 + 7/8,-1/8 + 3/8, -1/8 + 7/8)
		end

		if currentLoc == 7 then
			glTexRect(1/8 + 5/8,1/8 + 7/8,-1/8 + 5/8, -1/8 + 7/8)
		end

		if currentLoc == 8 then
			glTexRect(1/8 + 7/8,1/8 + 7/8,-1/8 + 7/8, -1/8 + 7/8)
		end

------------------------------------------------------------------------------------------------------------------
		if currentLoc == 9 then
			glTexRect(1/8 - 7/8,1/8 + 5/8,-1/8 - 7/8, -1/8 + 5/8)
		end

		if currentLoc == 10 then
			glTexRect(1/8 - 5/8,1/8 + 5/8,-1/8 - 5/8, -1/8 + 5/8)
		end

		if currentLoc == 11 then
			glTexRect(1/8 - 3/8,1/8 + 5/8,-1/8 - 3/8, -1/8 + 5/8)
		end

		if currentLoc == 12 then
			glTexRect(1/8 - 1/8,1/8 + 5/8,-1/8 - 1/8, -1/8 + 5/8)
		end

		if currentLoc == 13 then
			glTexRect(1/8 + 1/8,1/8 + 5/8,-1/8 + 1/8, -1/8 + 5/8)
		end

		if currentLoc == 14 then
			glTexRect(1/8 + 3/8,1/8 + 5/8,-1/8 + 3/8, -1/8 + 5/8)
		end

		if currentLoc == 15 then
			glTexRect(1/8 + 5/8,1/8 + 5/8,-1/8 + 5/8, -1/8 + 5/8)
		end

		if currentLoc == 16 then
			glTexRect(1/8 + 7/8,1/8 + 5/8,-1/8 + 7/8, -1/8 + 5/8)
		end

------------------------------------------------------------------------------------------------------------------
		if currentLoc == 17 then
			glTexRect(1/8 - 7/8,1/8 + 3/8,-1/8 - 7/8, -1/8 + 3/8)
		end

		if currentLoc == 18 then
			glTexRect(1/8 - 5/8,1/8 + 3/8,-1/8 - 5/8, -1/8 + 3/8)
		end

		if currentLoc == 19 then
			glTexRect(1/8 - 3/8,1/8 + 3/8,-1/8 - 3/8, -1/8 + 3/8)
		end

		if currentLoc == 20 then
			glTexRect(1/8 - 1/8,1/8 + 3/8,-1/8 - 1/8, -1/8 + 3/8)
		end

		if currentLoc == 21 then
			glTexRect(1/8 + 1/8,1/8 + 3/8,-1/8 + 1/8, -1/8 + 3/8)
		end

		if currentLoc == 22 then
			glTexRect(1/8 + 3/8,1/8 + 3/8,-1/8 + 3/8, -1/8 + 3/8)
		end

		if currentLoc == 23 then
			glTexRect(1/8 + 5/8,1/8 + 3/8,-1/8 + 5/8, -1/8 + 3/8)
		end

		if currentLoc == 24 then
			glTexRect(1/8 + 7/8,1/8 + 3/8,-1/8 + 7/8, -1/8 + 3/8)
		end
------------------------------------------------------------------------------------------------------------------
		if currentLoc == 25 then
			glTexRect(1/8 - 7/8,1/8 + 1/8,-1/8 - 7/8, -1/8 + 1/8)
		end

		if currentLoc == 26 then
			glTexRect(1/8 - 5/8,1/8 + 1/8,-1/8 - 5/8, -1/8 + 1/8)
		end

		if currentLoc == 27 then
			glTexRect(1/8 - 3/8,1/8 + 1/8,-1/8 - 3/8, -1/8 + 1/8)
		end

		if currentLoc == 28 then
			glTexRect(1/8 - 1/8,1/8 + 1/8,-1/8 - 1/8, -1/8 + 1/8)
		end

		if currentLoc == 29 then
			glTexRect(1/8 + 1/8,1/8 + 1/8,-1/8 + 1/8, -1/8 + 1/8)
		end

		if currentLoc == 30 then
			glTexRect(1/8 + 3/8,1/8 + 1/8,-1/8 + 3/8, -1/8 + 1/8)
		end

		if currentLoc == 31 then
			glTexRect(1/8 + 5/8,1/8 + 1/8,-1/8 + 5/8, -1/8 + 1/8)
		end

		if currentLoc == 32 then
			glTexRect(1/8 + 7/8,1/8 + 1/8,-1/8 + 7/8, -1/8 + 1/8)
		end
------------------------------------------------------------------------------------------------------------------
		if currentLoc == 33 then
			glTexRect(1/8 - 7/8,1/8 - 1/8,-1/8 - 7/8, -1/8 - 1/8)
		end

		if currentLoc == 34 then
			glTexRect(1/8 - 5/8,1/8 - 1/8,-1/8 - 5/8, -1/8 - 1/8)
		end

		if currentLoc == 35 then
			glTexRect(1/8 - 3/8,1/8 - 1/8,-1/8 - 3/8, -1/8 - 1/8)
		end

		if currentLoc == 36 then
			glTexRect(1/8 - 1/8,1/8 - 1/8,-1/8 - 1/8, -1/8 - 1/8)
		end

		if currentLoc == 37 then
			glTexRect(1/8 + 1/8,1/8 - 1/8,-1/8 + 1/8, -1/8 - 1/8)
		end

		if currentLoc == 38 then
			glTexRect(1/8 + 3/8,1/8 - 1/8,-1/8 + 3/8, -1/8 - 1/8)
		end

		if currentLoc == 39 then
			glTexRect(1/8 + 5/8,1/8 - 1/8,-1/8 + 5/8, -1/8 - 1/8)
		end

		if currentLoc == 40 then
			glTexRect(1/8 + 7/8,1/8 - 1/8,-1/8 + 7/8, -1/8 - 1/8)
		end

------------------------------------------------------------------------------------------------------------------
		if currentLoc == 41 then
			glTexRect(1/8 - 7/8,1/8 - 3/8,-1/8 - 7/8, -1/8 - 3/8)
		end

		if currentLoc == 42 then
			glTexRect(1/8 - 5/8,1/8 - 3/8,-1/8 - 5/8, -1/8 - 3/8)
		end

		if currentLoc == 43 then
			glTexRect(1/8 - 3/8,1/8 - 3/8,-1/8 - 3/8, -1/8 - 3/8)
		end

		if currentLoc == 44 then
			glTexRect(1/8 - 1/8,1/8 - 3/8,-1/8 - 1/8, -1/8 - 3/8)
		end

		if currentLoc == 45 then
			glTexRect(1/8 + 1/8,1/8 - 3/8,-1/8 + 1/8, -1/8 - 3/8)
		end

		if currentLoc == 46 then
			glTexRect(1/8 + 3/8,1/8 - 3/8,-1/8 + 3/8, -1/8 - 3/8)
		end

		if currentLoc == 47 then
			glTexRect(1/8 + 5/8,1/8 - 3/8,-1/8 + 5/8, -1/8 - 3/8)
		end

		if currentLoc == 48 then
			glTexRect(1/8 + 7/8,1/8 - 3/8,-1/8 + 7/8, -1/8 - 3/8)
		end

------------------------------------------------------------------------------------------------------------------
		if currentLoc == 49 then
			glTexRect(1/8 - 7/8,1/8 - 5/8,-1/8 - 7/8, -1/8 - 5/8)
		end

		if currentLoc == 50 then
			glTexRect(1/8 - 5/8,1/8 - 5/8,-1/8 - 5/8, -1/8 - 5/8)
		end

		if currentLoc == 51 then
			glTexRect(1/8 - 3/8,1/8 - 5/8,-1/8 - 3/8, -1/8 - 5/8)
		end

		if currentLoc == 52 then
			glTexRect(1/8 - 1/8,1/8 - 5/8,-1/8 - 1/8, -1/8 - 5/8)
		end

		if currentLoc == 53 then
			glTexRect(1/8 + 1/8,1/8 - 5/8,-1/8 + 1/8, -1/8 - 5/8)
		end

		if currentLoc == 54 then
			glTexRect(1/8 + 3/8,1/8 - 5/8,-1/8 + 3/8, -1/8 - 5/8)
		end

		if currentLoc == 55 then
			glTexRect(1/8 + 5/8,1/8 - 5/8,-1/8 + 5/8, -1/8 - 5/8)
		end

		if currentLoc == 56 then
			glTexRect(1/8 + 7/8,1/8 - 5/8,-1/8 + 7/8, -1/8 - 5/8)
		end

------------------------------------------------------------------------------------------------------------------
		if currentLoc == 57 then
			glTexRect(1/8 - 7/8,1/8 - 7/8,-1/8 - 7/8, -1/8 - 7/8)
		end

		if currentLoc == 58 then
			glTexRect(1/8 - 5/8,1/8 - 7/8,-1/8 - 5/8, -1/8 - 7/8)
		end

		if currentLoc == 59 then
			glTexRect(1/8 - 3/8,1/8 - 7/8,-1/8 - 3/8, -1/8 - 7/8)
		end

		if currentLoc == 60 then
			glTexRect(1/8 - 1/8,1/8 - 7/8,-1/8 - 1/8, -1/8 - 7/8)
		end

		if currentLoc == 61 then
			glTexRect(1/8 + 1/8,1/8 - 7/8,-1/8 + 1/8, -1/8 - 7/8)
		end

		if currentLoc == 62 then
			glTexRect(1/8 + 3/8,1/8 - 7/8,-1/8 + 3/8, -1/8 - 7/8)
		end

		if currentLoc == 63 then
			glTexRect(1/8 + 5/8,1/8 - 7/8,-1/8 + 5/8, -1/8 - 7/8)
		end

		if currentLoc == 64 then
			glTexRect(1/8 + 7/8,1/8 - 7/8,-1/8 + 7/8, -1/8 - 7/8)
		end

	end -- END CREATION CYCLE
	glUseShader(0)
end) -- END FBO
end

--------------------------------------------------------------------------------------QUAD LIST
local function createPOPSboardList()
POPSboardList = gl.CreateList(function()
	    gl.BeginEnd(GL.QUADS, function()
		for x = 0,pXcount -1,1 do
			for y = 0, pXcount -1,1 do
				gl.MultiTexCoord(1,(x - 0.5) / pXcount,(y - 0.5) / pXcount)
				gl.Vertex(1,1,0)
				gl.Vertex(-1,1,0)
				gl.Vertex(-1,-1,0)
				gl.Vertex(1,-1,0)
			end
		end
	end)	
end)
end

--------------------------------------------------------------------------------------A USEFUL STRING UTILITY FUNCTION (THANKS, TREPAN)
local function FloatStr(x)
	return string.format('%.1f', x)
end

--------------------------------------------------------------------------------------BEGIN SETUP
function gadget:Initialize()
	local check = createPOPSboardList()
	if check == false then Spring.Echo("Display List Failed!") runShader = 0 else Spring.Echo("Display List Built!") end


  -- compatibility check
	if not gl.CreateShader or
		not gl.CreateFBO() then
		Spring.Echo('POPS will not run with your hardware')
		runShader = 0
		return 
	end

--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------------FINAL SHADER
pops_shader = gl.CreateShader({

    vertex = [[
     		uniform sampler2D posTex;
      		uniform sampler2D dragTex;
		uniform sampler2D otherTex;
		varying vec2 losPos;

		uniform float shaderTime;
		varying float timePercent;
		const float mapSize = ]] .. FloatStr(MaxSizeX) .. [[;


		void main(void)
		{
			float dScale = 1000000.0;
//	GET POSITION OF COLORMAP, ETC.
			gl_TexCoord[1].st = gl_MultiTexCoord1.st;
			float texType = texture2D(otherTex,gl_TexCoord[1].st).y * dScale;

//	UNPACK POSITION AND TIME
			vec4 posData = vec4(texture2D(posTex, gl_TexCoord[1].st));  // Get Color Data from sectors
			vec4 timeData = vec4(texture2D(dragTex, gl_TexCoord[1].st)); // get time data

			timePercent = ((shaderTime / dScale) - timeData.b) / (timeData.g - timeData.b);

			if (timePercent > 1.0)
			{
				gl_Position = vec4(100000.0,100000.0,100000.0,1.0);
				return;
			}

//	CONVERT FLOATING-POINT VALUES TO WORLDSPACE
			if (posData.r > 0.5)
			{
				posData.r = float((posData.r - 0.5) * (dScale * -1.0));
			} else {

				posData.r = float(posData.r * dScale);
			}

			if (posData.g > 0.5)
			{
				posData.g = float((posData.g - 0.5) * (dScale * -1.0));
			} else {
				posData.g = float(posData.g * dScale);
			}

			if (posData.b > 0.5)
			{
				posData.b = float((posData.b - 0.5) * (dScale * -1.0));
			} else {
				posData.b = float(posData.b * dScale);
			}

//	GET SIZE
			float size = float(posData.w * dScale);

//	DETERMINE TEXTURE COORDINATES IN ATLAS

			vec2 rowColumn;
			rowColumn.x = mod(texType -1.0,8.0);

			if (texType < 9.0)
			{
				rowColumn.y = 7.0;
			}

			if (texType < 17.0 && texType > 8.0)
			{
				rowColumn.y = 6.0;
			}

			if (texType < 25.0 && texType > 16.0)
			{
				rowColumn.y = 5.0;
			}

			if (texType < 33.0 && texType > 24.0)
			{
				rowColumn.y = 4.0;
			}

			if (texType < 41.0 && texType > 32.0)
			{
				rowColumn.y = 3.0;
			}

			if (texType < 49.0 && texType > 40.0)
			{
				rowColumn.y = 2.0;
			}

			if (texType < 57.0 && texType > 48.0)
			{
				rowColumn.y = 1.0;
			}

			if (texType > 56.0)
			{
				rowColumn.y = 0.0;
			}

			if (gl_Vertex.x < 0)
			{
				gl_TexCoord[0].s = rowColumn.x / 8.0;
			} else {
				gl_TexCoord[0].s = (rowColumn.x + 1.0) / 8.0;
			}

			if (gl_Vertex.y < 0)
			{
				gl_TexCoord[0].t = rowColumn.y / 8.0;
			} else {
				gl_TexCoord[0].t = (rowColumn.y + 1.0) / 8.0;
			}


//	BILLBOARD, USING POSDATA AS BASIS	

			vec4 wpos = vec4(posData.rgb, 1.0);
			vec4 epos = gl_ModelViewMatrix * wpos;
			epos.xy += gl_Vertex.xy * size * 2.0; 
			gl_Position = gl_ProjectionMatrix * epos;

//	WE HAVE REAL WORLDSPACE POSITION, MATCH TO LOS
			losPos = vec2(posData.x/mapSize,posData.z/mapSize);
			if (losPos.x < 0.0)
			{
				losPos.x = 0.01;
			}
			if (losPos.y > 1.0)
			{
				losPos.y = 0.99;
			}
		}
	]],
	fragment = [[

		uniform sampler2D losTex;
		//uniform sampler2D otherTex;

		uniform sampler2D texOne;

		uniform sampler2D colorTexOne;
		uniform sampler2D colorTexTwo;
		uniform sampler2D colorTexThree;
		uniform sampler2D colorTexFour;

		varying vec2 losPos;
		varying float timePercent;

		const float dScale = 1000000.0;
		
		void main()
		{
//	SET MAIN TEXTURE COORDINATES
			vec2 hC = gl_TexCoord[0].st;

//	SET LOS STATE
			vec4 losState = vec4(texture2D(losTex,losPos));

			if (losState.r < 0.5)
			{	
				gl_FragColor = vec4(0.0,0.0,0.0,0.0);
			} else {
//	SET TEXTURE TYPE			

//	SET FINAL COLOR MIX
			vec4 colorMix;
				if (timePercent >= 0.66)
				{
					float finalTimePercent = timePercent / 1.0;
					colorMix = mix(texture2D(colorTexTwo,gl_TexCoord[1].st),texture2D(colorTexOne,gl_TexCoord[1].st),finalTimePercent); 

				}
				if (timePercent >= 0.33 && timePercent < 0.666666)
				{
					float finalTimePercent = timePercent / 0.666666;
					colorMix = mix(texture2D(colorTexThree,gl_TexCoord[1].st),texture2D(colorTexTwo,gl_TexCoord[1].st),finalTimePercent); 
				}
				if (timePercent < 0.333333)
				{
					float finalTimePercent = timePercent /  0.333333;
					colorMix = mix(texture2D(colorTexFour,gl_TexCoord[1].st),texture2D(colorTexThree,gl_TexCoord[1].st),finalTimePercent); 
				}

			gl_FragColor = vec4(texture2D(texOne,hC)) * colorMix; 
			}	
		}
		]],
	uniformInt = {

		texOne = 7,

		posTex = 8,
		losTex = 9,
		dragTex = 10,
		otherTex = 11,

		colorTexOne = 12,
		colorTexTwo = 13,
		colorTexThree = 14,
		colorTexFour = 15,
		},
	uniform = {
		shaderTime = 0,
    		},
  	})

--------------------------------------------------------------------------------------PHYSICS SHADER
pops_physics_shader = gl.CreateShader({
    vertex = [[
		void main(void)
		{
			gl_TexCoord[0].xy = gl_MultiTexCoord0.xy;	
			gl_Position = gl_Vertex;
		}
	]],
	fragment = [[
		#extension GL_ARB_draw_buffers : enable
		uniform vec2 time;
      		uniform sampler2D posTex;
      		uniform sampler2D velTex;
      		uniform sampler2D dragTex;
      		uniform sampler2D otherTex;
		const float dScale = 1000000.0;

		void main()
		{
			vec2 texCoord = gl_TexCoord[0].xy;

//	GET TIME AND OTHER DATA
			vec4 otherData = vec4(texture2D(otherTex, texCoord));

//	GET DRAG AND GROWTH
			vec4 dragData = vec4(texture2D(dragTex, texCoord));

//	TIME FINISH
			dragData.b = float(dragData.b * dScale);

//	PASSED FINISH TIME?  SEND THE PARTICLE FAR, FAR AWAY
		if (time.x  > dragData.b)
		{
			gl_FragData[0] = vec4(0.49999,0.49999,0.49999,0.0000001); 
			return;
		} else {

//	GET POSITIONS
			vec4 posData = vec4(texture2D(posTex, texCoord));

//	GET VELOCITIES
			vec4 velData = vec4(texture2D(velTex, texCoord));

//	GET GRAVITY + / -
			if (velData.w > 0.5)
			{
				velData.w = (velData.w - 0.5) * -1.0;
			}

//	GET VELOCITY
			dragData.r = dragData.r * dScale;
			if (velData.r < 0.5)
			{
				velData.r = float(max(velData.r -(velData.r * dragData.r * time.y), 0.0));
			} else {
				velData.r = velData.r - 0.5;
				velData.r = float(max(velData.r -(velData.r * dragData.r * time.y), 0.0));
				velData.r = velData.r + 0.5;
			}
			if (velData.g < 0.5)
			{
				velData.g = float(max(velData.g -(velData.g * dragData.r  * time.y), 0.0));
				velData.g = velData.g - (velData.w * time.y); // GRAVITY
				if (velData.g < 0.0)
				{
					velData.g = velData.g * -1.0;
					velData.g = velData.g + 0.5;
				}
			} else {
				velData.g = velData.g - 0.5;
				velData.g = float(max(velData.g -(velData.g * dragData.r * time.y), 0.0));
				velData.g = velData.g + (velData.w * time.y); // GRAVITY
				velData.g = velData.g + 0.5;
			}
			if (velData.b < 0.5)
			{
				velData.b = float(max(velData.b -(velData.b * dragData.r * time.y), 0.0));
			} else {
				velData.b = velData.b - 0.5;
				velData.b = float(max(velData.b -(velData.b * dragData.r * time.y), 0.0));
				velData.b = velData.b + 0.5;
			}

//	GET FINAL POSITIONS		
			if (posData.r < 0.5 && velData.r < 0.5)
			{
				posData.r = posData.r + (velData.r * time.y);
			}
			if (posData.r < 0.5 && velData.r > 0.5)
			{
					posData.r = posData.r - ((velData.r - 0.5) * time.y);
			}
			if (posData.r > 0.5 && velData.r < 0.5)
			{
					posData.r = posData.r - ((velData.r - 0.5) * time.y);
			}
			if (posData.r > 0.5 && velData.r > 0.5)
			{
					posData.r = posData.r + (velData.r * time.y);
			}

			if (posData.g < 0.5 && velData.g < 0.5)
			{
				posData.g = posData.g + (velData.g * time.y);
			}
			if (posData.g < 0.5 && velData.g > 0.5)
			{
					posData.g = posData.g - ((velData.g - 0.5) * time.y);
			}
			if (posData.g > 0.5 && velData.g < 0.5)
			{
					posData.g = posData.g - ((velData.g - 0.5) * time.y);
			}
			if (posData.g > 0.5 && velData.g > 0.5)
			{
					posData.g = posData.g + (velData.g * time.y);
			}

			if (posData.b < 0.5 && velData.b < 0.5)
			{
				posData.b = posData.b + (velData.b * time.y);
			}
			if (posData.b < 0.5 && velData.b > 0.5)
			{
					posData.b = posData.b - ((velData.b - 0.5) * time.y);
			}
			if (posData.b > 0.5 && velData.b < 0.5)
			{
					posData.b = posData.b - ((velData.b - 0.5) * time.y);
			}
			if (posData.b > 0.5 && velData.b > 0.5)
			{
					posData.b = posData.b + (velData.b * time.y);
			}

//	GET SIZE GROWTH			
			if (dragData.w < 0.5)
			{
				posData.w = posData.w + (dragData.w);
			} else {
				posData.w = posData.w - (dragData.w - 0.5);
			}

//	RENDER TO TEXTURE
			gl_FragData[0] = vec4(posData.r,posData.g,posData.b,posData.w);
			gl_FragData[1] =  vec4(velData.r,velData.g,velData.b,velData.w);

		} // FINISH IF-THEN LOOP
		}
		]],
	uniformInt = {
		posTex = 1,
		velTex = 2,
		dragTex = 3,
		otherTex = 4,
		},
	uniform = {
		time   = {0,0},
    		},
  	})

--------------------------------------------------------------------------------------CREATION SHADER
pops_quad_shader = gl.CreateShader({
    vertex = [[
		void main(void)
		{
			gl_TexCoord[0].xy = gl_MultiTexCoord0.xy;	
			gl_Position = gl_Vertex;
		}
	]],
	fragment = [[
		#extension GL_ARB_draw_buffers : enable
		uniform vec4 PosValues;
		uniform vec4 VelValues;
		uniform vec4 DragValues;
		uniform vec4 OtherValues;
		uniform float Create;

		const float PI = 3.14159265358979323846;
		const float dScale = 1000000.0;
		const float twoPI = 3.14159265358979323846 * 2.0;
		const float PIdiv = 3.14159265358979323846 / 180.0;
		void main()
		{

		if (Create > 0.5)
		{
			
//	PERFORM CONIC
        			float startCone = OtherValues.w;  // need to send via Uniform
			float startVel = OtherValues.x;  //need to send via Uniform

			vec3 up = vec3(VelValues.xyz);
			vec3 right = vec3(cross(up,vec3(up.y,up.z,-up.x)));
			vec3 forward = vec3(cross(up,right));

			float az = OtherValues.z* twoPI;
			float ay = float(startCone + OtherValues.z) * PIdiv;

			vec3 coneVec = vec3(cos(ay), cos(az)*sin(ay),  sin(az)*sin(ay));

//	CONVERT VELOCITY RESULT
			vec3 vel = vec3(up.x*coneVec.x - right.x*coneVec.y + forward.x*coneVec.z, up.y*coneVec.x - right.y*coneVec.y + forward.y*coneVec.z, up.z*coneVec.x - right.z*coneVec.y + forward.z*coneVec.z);
			vel = vel * startVel;

//	ROTATE THE MATRIX			
			mat3 emitMatrix;
			float xz = up.x * up.z;
			float xy = up.x * up.y;
			float yz = up.y * up.z;
			emitMatrix[0].xyz = vec3(up.x*up.x,  xy-up.z, xz+up.y);
			emitMatrix[1].xyz = vec3(xy+up.z, up.y*up.y,  yz-up.x);
			emitMatrix[2].xyz = vec3(xz-up.y, yz+up.x, up.z*up.z);

//	FINAL VELOCITY
			vel = vec3(emitMatrix[0].x * vel.x + emitMatrix[0].y * vel.y + emitMatrix[0].z * vel.z, emitMatrix[1].x * vel.x + emitMatrix[1].y * vel.y + emitMatrix[1].z * vel.z, emitMatrix[2].x * vel.x + emitMatrix[2].y * vel.y + emitMatrix[2].z * vel.z);

			if (vel.x < 0.0)
			{
				vel.x = ((vel.x * -1.0) / dScale) + 0.5;
			} else {
				vel.x = vel.x / dScale;
			}

			if (vel.y < 0.0)
			{
				vel.y = ((vel.y * -1.0) / dScale) + 0.5;
			} else {
				vel.y = vel.y / dScale;
			}

			if (vel.z < 0.0)
			{
				vel.z = ((vel.z * -1.0) / dScale) + 0.5;
			} else {
				vel.z = vel.z / dScale;
			}
			
//	RENDER TO PHYSICS TEXTURES
			gl_FragData[0] = PosValues;
			gl_FragData[1] = vec4(vel,VelValues.w);
			gl_FragData[2] = DragValues;
			gl_FragData[3] = OtherValues;
			} else {
//	RENDER TO COLOR TEXTURES
				gl_FragData[0] = PosValues;
				gl_FragData[1] = VelValues;
				gl_FragData[2] = DragValues;
				gl_FragData[3] = OtherValues;
			}
		}
		]],
	uniform = {
		PosValues   = {0,0,0,0},
		VelValues   = {0,0,0,0},
		DragValues   = {0,0,0,0},
		OtherValues   = {0,0,0,0},
		Create = 0,
    		},
  	})

--------------------------------------------------------------------------------------ATLAS SHADER
pops_atlas_shader = gl.CreateShader({
    vertex = [[
		void main(void)
		{	
			gl_TexCoord[0].xy = gl_MultiTexCoord0.xy;
			gl_Position = gl_Vertex;
		}
	]],
	fragment = [[
      		uniform sampler2D TextureOne;
		void main()
		{
//	RENDER TO TEXTURES
			gl_FragData[0] = texture2D(TextureOne,gl_TexCoord[0].xy);
		}
		]],
	uniformInt = {
		TextureOne = 0,
		},
  	})

--------------------------------------------------------------------------------------LOS SHADER
pops_los_shader = gl.CreateShader({
    vertex = [[
		void main(void)
		{	
			gl_TexCoord[0].xy = gl_MultiTexCoord0.xy;
			gl_Position = gl_Vertex;
		}
	]],
	fragment = [[
		#extension GL_ARB_draw_buffers : enable
		uniform vec4 losValues;

		void main()
		{
//	RENDER TO LOS TEXTURE
			gl_FragData[0] = losValues;
		}
		]],
	uniform = {
		losValues   = {0,0,0,0},
    		},
  	})

--------------------------------------------------------------------------------------GRACEFUL FAILURE AND DEBUGGING OUTPUT
	Spring.Echo("POPS main system shader log:"..gl.GetShaderLog())
	if (pops_shader == nil) then
		Spring.Echo("POPS Vertex Shader Failed")
		Spring.Echo(gl.GetShaderLog())
	end

	if (pops_quad_shader == nil) then
		Spring.Echo("POPS Quad Shader Failed")
		Spring.Echo(gl.GetShaderLog())
	end

	if (pops_atlas_shader == nil) then
		Spring.Echo("POPS Atlas Shader Failed")
		Spring.Echo(gl.GetShaderLog())
	end

	if (pops_physics_shader == nil) then
		Spring.Echo("POPS Physics Shader Failed")
		Spring.Echo(gl.GetShaderLog())
	end

	if (pops_los_shader == nil) then
		Spring.Echo("POPS LOS Shader Failed")
		Spring.Echo(gl.GetShaderLog())
	end

	if (pops_shader == nil or pops_quad_shader == nil or pops_physics_shader == nil or pops_los_shader == nil or pops_atlas_shader == nil) then
		--gadgetHandler:RemoveGadget()
		runShader = 0
		return	
	else
		Spring.Echo("POPS Successfully Compiled")
		runShader = 1
		Spring.Echo(gl.GetShaderLog())
	end

	Spring.Echo("P.O.P.S. runShader = "..runShader)

--------------------------------------------------------------------------------------DEFINE UNIFORMS
if runShader == 1 then
--FINAL SHADER
	shaderTimeLoc = gl.GetUniformLocation(pops_shader, 'shaderTime')

--LOS SHADER
	losValuesLoc = gl.GetUniformLocation(pops_los_shader, 'losValues')

--CREATION SHADER
	shaderPosValuesLoc = gl.GetUniformLocation(pops_quad_shader, 'PosValues')
	shaderVelocityValuesLoc = gl.GetUniformLocation(pops_quad_shader, 'VelValues')
	shaderDragValuesLoc = gl.GetUniformLocation(pops_quad_shader, 'DragValues')
	shaderOtherValuesLoc = gl.GetUniformLocation(pops_quad_shader, 'OtherValues')
	shaderCreateLoc = gl.GetUniformLocation(pops_quad_shader, 'Create')

--PHYSICS SHADER
	physicsTimeLoc = gl.GetUniformLocation(pops_physics_shader, 'time')
end

--------------------------------------------------------------------------------------DEFINE TEXTURE SPECIFICATIONS
--FLOATING-POINT TEXTURES (DO NOT USE FOR FRAGMENT COLORS)
local texSpec = {
	format = GL_RGBA32F_ARB,
	min_filter = GL.NEAREST,
	mag_filter = GL.NEAREST,
}
--STANDARD TEXTURES (RGBA) --NO FILTERING
local colorSpec = {
	min_filter = GL.NEAREST,
	mag_filter = GL.NEAREST,
}

--ATLASED TEXTURES (RGBA)
local atlasSpec = {
	min_filter = GL.LINEAR,
	mag_filter = GL.LINEAR,
}	
--------------------------------------------------------------------------------------DEFINE TEXTURES
	--tex1 = gl.CreateTexture(256,256,colorSpec)

	posTex = gl.CreateTexture(pXcount, pYcount, texSpec)
	velTex = gl.CreateTexture(pXcount, pYcount, texSpec)
	dragTex = gl.CreateTexture(pXcount, pYcount, texSpec)
	otherTex = gl.CreateTexture(pXcount, pYcount, texSpec)

	posTex2 = gl.CreateTexture(pXcount, pYcount, texSpec)
	velTex2 = gl.CreateTexture(pXcount, pYcount, texSpec)
	dragTex2 = gl.CreateTexture(pXcount, pYcount, texSpec)
	otherTex2 = gl.CreateTexture(pXcount, pYcount, texSpec)

	losTex = gl.CreateTexture(MaxSizeX/512, MaxSizeZ/512, colorSpec)

	colorTex1 = gl.CreateTexture(pXcount, pYcount, colorSpec)
	colorTex2 = gl.CreateTexture(pXcount, pYcount, colorSpec)
	colorTex3 = gl.CreateTexture(pXcount, pYcount, colorSpec)
	colorTex4 = gl.CreateTexture(pXcount, pYcount, colorSpec)

	colorTex5 = gl.CreateTexture(pXcount, pYcount, colorSpec)
	colorTex6 = gl.CreateTexture(pXcount, pYcount, colorSpec)
	colorTex7 = gl.CreateTexture(pXcount, pYcount, colorSpec)
	colorTex8 = gl.CreateTexture(pXcount, pYcount, colorSpec)

	myAtlasTex = gl.CreateTexture(1024, 1024, atlasSpec)

	if posTex == nil or losTex == nil or myAtlasTex == nil or posTex2 == nil then runShader = 0 Spring.Echo("Failed texture creation") end
--------------------------------------------------------------------------------------DEFINE FBOS
  fbo1 = gl.CreateFBO()
 fbo1.color0 = posTex
 fbo1.color1 = velTex
 fbo1.color2 = dragTex
 fbo1.color3 = otherTex
  fbo1.drawbuffers = {
    GL_COLOR_ATTACHMENT0_EXT,
    GL_COLOR_ATTACHMENT1_EXT,
    GL_COLOR_ATTACHMENT2_EXT,
    GL_COLOR_ATTACHMENT3_EXT,
  }
  fbo4 = gl.CreateFBO()
 fbo4.color0 = colorTex1
 fbo4.color1 = colorTex2
 fbo4.color2 = colorTex3
 fbo4.color3 = colorTex4
  fbo4.drawbuffers = {
    GL_COLOR_ATTACHMENT0_EXT,
    GL_COLOR_ATTACHMENT1_EXT,
    GL_COLOR_ATTACHMENT2_EXT,
    GL_COLOR_ATTACHMENT3_EXT,
  }

  fbo2 = gl.CreateFBO()
 fbo2.color0 = posTex
 fbo2.color1 = velTex
 fbo2.color2 = dragTex
 fbo2.color3 = otherTex
  fbo2.drawbuffers = {
    GL_COLOR_ATTACHMENT0_EXT,
    GL_COLOR_ATTACHMENT1_EXT,
  }
  fbo3 = gl.CreateFBO()
 fbo3.color0 = losTex
  fbo3.drawbuffers = {
    GL_COLOR_ATTACHMENT0_EXT,
  }

  fbo5 = gl.CreateFBO()
 fbo5.color0 = myAtlasTex
  fbo5.drawbuffers = {
    GL_COLOR_ATTACHMENT0_EXT,
  }

fbo6 = gl.CreateFBO()
 fbo6.color0 = posTex2
 fbo6.color1 = velTex2
 fbo6.color2 = dragTex2
 fbo6.color3 = otherTex2
  fbo6.drawbuffers = {
    GL_COLOR_ATTACHMENT0_EXT,
    GL_COLOR_ATTACHMENT1_EXT,
    GL_COLOR_ATTACHMENT2_EXT,
    GL_COLOR_ATTACHMENT3_EXT,
  }

  fbo7 = gl.CreateFBO()
 fbo7.color0 = colorTex5
 fbo7.color1 = colorTex6
 fbo7.color2 = colorTex7
 fbo7.color3 = colorTex8
  fbo7.drawbuffers = {
    GL_COLOR_ATTACHMENT0_EXT,
    GL_COLOR_ATTACHMENT1_EXT,
    GL_COLOR_ATTACHMENT2_EXT,
    GL_COLOR_ATTACHMENT3_EXT,
  }

  fbo8 = gl.CreateFBO()
 fbo8.color0 = posTex2
 fbo8.color1 = velTex2
 fbo8.color2 = dragTex2
 fbo8.color3 = otherTex2
  fbo8.drawbuffers = {
    GL_COLOR_ATTACHMENT0_EXT,
    GL_COLOR_ATTACHMENT1_EXT,
  }

	--if fbo1 == nil or fbo2 == nil or fbo3 == nil or fbo4 == nil or fbo5 == nil or fbo6 == nil or fbo7 == nil or fbo8 == nil then runShader = 0 Spring.Echo("Failed FBO creation") end
--------------------------------------------------------------------------------------EVENT HANDLER
if runShader == 1 then
gadgetHandler:AddSyncAction("pops_event", BuildParticleTable)
gadgetHandler:AddSyncAction("pops_slow_event", BuildSlowParticleTable)
gadgetHandler:AddSyncAction("build_texture_atlas", BuildIt)
gadgetHandler:AddSyncAction("freeze_texture_atlas", StopIt)
end
--------------------------------------------------------------------------------------END SETUP
end

function gadget:Shutdown()
	gl.DeleteShader(pops_shader)
	gl.DeleteShader(pops_quad_shader)
	gl.DeleteShader(pops_atlas_shader)
	gl.DeleteShader(pops_physics_shader)
	gl.DeleteShader(pops_los_shader)

	gl.DeleteTexture(posTex)
	gl.DeleteTexture(velTex)
	gl.DeleteTexture(dragTex)
	gl.DeleteTexture(otherTex)
	gl.DeleteTexture(losTex)

	gl.DeleteTexture(colorTex1)
	gl.DeleteTexture(colorTex2)
	gl.DeleteTexture(colorTex3)
	gl.DeleteTexture(colorTex4)

	gl.DeleteTexture(myAtlasTex)

	gl.DeleteFBO(fbo1)
	gl.DeleteFBO(fbo2)
	gl.DeleteFBO(fbo3)
	gl.DeleteFBO(fbo4)
	gl.DeleteFBO(fbo5)
	gl.DeleteList(POPSboardList)
end

--------------------------------------------------------------------------------------MAIN PARTICLE UPDATE SEQUENCE START
local function UpdateParticles(diffTime,dt)
--------------------------------------------------------------------------------------CREATE TEXTURE ATLAS
--------------------------------------------------------------------------------------UPDATE LOS STATE
if diffTime % 2 < 0.05 then

--Spring.Echo("Updating LOS")
glActiveFBO(fbo3, true, function()  -- START FBO
	glUseShader(pops_los_shader)

for curX = 0,MaxSizeX,512 do  -- START CREATION CYCLE
	for curZ = 0,MaxSizeZ,512 do 
		if IsPosInLos(curX,0,curZ,Ally) then
			texX = ((curX/MaxSizeX) * 2) -1
			texY = ((curZ/MaxSizeZ) * 2) -1
			glUniform(losValuesLoc,1.0,1.0,1.0,1.0)  -- Position is in LOS
			glRect(texX,texY,texX + MaxSizeX/256,texY + MaxSizeX/256) 
		else
			texX = ((curX/MaxSizeX) * 2) -1
			texY = ((curZ/MaxSizeZ) * 2) -1
			glUniform(losValuesLoc,0.0,0.0,0.0,1.0)  -- Position is not in LOS
			glRect(texX,texY,texX + MaxSizeX/256,texY + MaxSizeX/256) 
		end
	end
end  -- END CREATION CYCLE
end) -- END FBO
end -- END IF

--------------------------------------------------------------------------------------RUN PHYSICS SIMULATION
glActiveFBO(fbo2, true, function()
	glUseShader(pops_physics_shader)  -- UPDATE PHYSICS
	glTexture(1, posTex)
	glTexture(2, velTex)
	glTexture(3, dragTex)
	glTexture(4, otherTex)

	glUniform(physicsTimeLoc,diffTime,dt)

	glTexRect(-1,-1,1,1,dpX,dpY,1-dpX,1-dpY)

end)  -- END FBO

glActiveFBO(fbo8, true, function()
	glUseShader(pops_physics_shader)  -- UPDATE PHYSICS
	glTexture(1, posTex2)
	glTexture(2, velTex2)
	glTexture(3, dragTex2)
	glTexture(4, otherTex2)

	glUniform(physicsTimeLoc,diffTime,dt)

	glTexRect(-1,-1,1,1,dpX,dpY,1-dpX,1-dpY)

end)  -- END FBO

--------------------------------------------------------------------------------------ADD NEW PARTICLE STATES TO SYSTEM
if particleList[1] ~= nil  then  -- ADD NEW PARTICLES
	glUseShader(pops_quad_shader)

	glUniform(shaderCreateLoc,1.0)
glActiveFBO(fbo1, true, function()  -- START PARTICLE FBO
	for k = 1,#particleList,1 do  -- START CREATION CYCLE
		--Spring.Echo("particle found: "..k[1])
		currentParticles = currentParticles + 1
		if currentParticles > 4096 then currentParticles = 1 end

		currentRow = math_floor(((currentParticles / 4096) * pXcount) -0.00001)
		currentColumn = (currentRow * pXcount - currentParticles) / pXcount
		currentRow = currentRow / pXcount

		texX = currentRow * 2 -1
		texY = (currentColumn  * 2) + 1
	
		glUniform(shaderPosValuesLoc,particleList[k].posX,particleList[k].posY,particleList[k].posZ,particleList[k].size)
		glUniform(shaderVelocityValuesLoc,particleList[k].velX,particleList[k].velY,particleList[k].velZ,particleList[k].gravity)
		glUniform(shaderDragValuesLoc,particleList[k].drag,particleList[k].startTime,particleList[k].finishTime,particleList[k].sizeGrowth)
		glUniform(shaderOtherValuesLoc,particleList[k].myVelocity,particleList[k].myType,particleList[k].myRand,particleList[k].myCone)  --extra slot here, 1.0

		glRect(texX,texY,texX + 1/32,texY + 1/32) -- 1/32 resolves to 1 pixel on a 64 pixel map from coords -1 --> 1
	end
end) -- END FBO

--------------------------------------------------------------------------------------ADD NEW COLOR STATES TO NEW PARTICLE
	glUniform(shaderCreateLoc,0.0)
glActiveFBO(fbo4, true, function()  -- START COLOR FBO
	for k = 1,#particleList,1 do  -- START CREATION CYCLE
		--Spring.Echo("particle found: "..k[1])
		currentColorParticles = currentColorParticles + 1
		if currentColorParticles > 4096 then currentColorParticles = 1 end

		currentRow = math_floor(((currentColorParticles / 4096) * pXcount) -0.00001)
		currentColumn = (currentRow * pXcount - currentColorParticles) / pXcount
		currentRow = currentRow / pXcount

		texX = currentRow * 2 -1
		texY = (currentColumn  * 2) + 1

		glUniform(shaderPosValuesLoc,particleList[k].color1R,particleList[k].color1G,particleList[k].color1B,particleList[k].color1A) 
		glUniform(shaderVelocityValuesLoc,particleList[k].color2R,particleList[k].color2G,particleList[k].color2B,particleList[k].color2A)  
		glUniform(shaderDragValuesLoc,particleList[k].color3R,particleList[k].color3G,particleList[k].color3B,particleList[k].color3A)  
		glUniform(shaderOtherValuesLoc,particleList[k].color4R,particleList[k].color4G,particleList[k].color4B,particleList[k].color4A)

		glRect(texX,texY,texX + 1/32,texY + 1/32) -- 1/32 resolves to 1 pixel on a 64 pixel map from coords -1 --> 1
	end
end) -- END FBO
particleList = {}
end

if slowParticleList[1] ~= nil  then  -- ADD NEW PARTICLES
	glUseShader(pops_quad_shader)

	glUniform(shaderCreateLoc,1.0)
glActiveFBO(fbo6, true, function()  -- START PARTICLE FBO
	for k = 1,#slowParticleList,1 do  -- START CREATION CYCLE
		--Spring.Echo("particle found: "..k[1])
		currentParticles = currentParticles + 1
		if currentParticles > 4096 then currentParticles = 1 end

		currentRow = math_floor(((currentParticles / 4096) * pXcount) -0.00001)
		currentColumn = (currentRow * pXcount - currentParticles) / pXcount
		currentRow = currentRow / pXcount

		texX = currentRow * 2 -1
		texY = (currentColumn  * 2) + 1
	
		glUniform(shaderPosValuesLoc,slowParticleList[k].posX,slowParticleList[k].posY,slowParticleList[k].posZ,slowParticleList[k].size)
		glUniform(shaderVelocityValuesLoc,slowParticleList[k].velX,slowParticleList[k].velY,slowParticleList[k].velZ,slowParticleList[k].gravity)
		glUniform(shaderDragValuesLoc,slowParticleList[k].drag,slowParticleList[k].startTime,slowParticleList[k].finishTime,slowParticleList[k].sizeGrowth)
		glUniform(shaderOtherValuesLoc,slowParticleList[k].myVelocity,slowParticleList[k].myType,slowParticleList[k].myRand,slowParticleList[k].myCone)  --extra slot here, 1.0

		glRect(texX,texY,texX + 1/32,texY + 1/32) -- 1/32 resolves to 1 pixel on a 64 pixel map from coords -1 --> 1
	end
end) -- END FBO

--------------------------------------------------------------------------------------ADD NEW COLOR STATES TO NEW PARTICLE
	glUniform(shaderCreateLoc,0.0)
glActiveFBO(fbo7, true, function()  -- START COLOR FBO
	for k = 1,#slowParticleList,1 do  -- START CREATION CYCLE
		--Spring.Echo("particle found: "..k[1])
		currentColorParticles = currentColorParticles + 1
		if currentColorParticles > 4096 then currentColorParticles = 1 end

		currentRow = math_floor(((currentColorParticles / 4096) * pXcount) -0.00001)
		currentColumn = (currentRow * pXcount - currentColorParticles) / pXcount
		currentRow = currentRow / pXcount

		texX = currentRow * 2 -1
		texY = (currentColumn  * 2) + 1

		glUniform(shaderPosValuesLoc,slowParticleList[k].color1R,slowParticleList[k].color1G,slowParticleList[k].color1B,slowParticleList[k].color1A) 
		glUniform(shaderVelocityValuesLoc,slowParticleList[k].color2R,slowParticleList[k].color2G,slowParticleList[k].color2B,slowParticleList[k].color2A)  
		glUniform(shaderDragValuesLoc,slowParticleList[k].color3R,slowParticleList[k].color3G,slowParticleList[k].color3B,slowParticleList[k].color3A)  
		glUniform(shaderOtherValuesLoc,slowParticleList[k].color4R,slowParticleList[k].color4G,slowParticleList[k].color4B,slowParticleList[k].color4A)

		glRect(texX,texY,texX + 1/32,texY + 1/32) -- 1/32 resolves to 1 pixel on a 64 pixel map from coords -1 --> 1
	end
end) -- END FBO
slowParticleList = {}
end
end

--------------------------------------------------------------------------------------DRAW PARTICLE SYSTEM
local function DrawParticles()
	gl.PushMatrix()

	glUseShader(pops_shader)

	glTexture(12, colorTex1)
	glTexture(13, colorTex2)
	glTexture(14, colorTex3)
	glTexture(15, colorTex4)

	glTexture(7,myAtlasTex)

	glTexture(8, posTex)
	glTexture(9, losTex)
	glTexture(10, dragTex)
	glTexture(11,otherTex)

	--glCulling(GL_BACK)
	glDepthTest(GL_LEQUAL)
	--glBlending(GL_ONE,GL.SRC_ALPHA_SATURATE)  --JUST FOR BUBBLES, MAYBE CLOUDS?
	--glBlending(GL.SRC_ALPHA,GL.ONE)  --THIS WORKS, PROCEED
	glBlending(GL_ONE,GL_ONE_MINUS_SRC_ALPHA)

	glUniform(shaderTimeLoc, diffTime)

	glCallList(POPSboardList)
	-- END DRAW


	glTexture(12, colorTex5)
	glTexture(13, colorTex6)
	glTexture(14, colorTex7)
	glTexture(15, colorTex8)

	glTexture(8, posTex2)

	glTexture(10, dragTex2)
	glTexture(11,otherTex2)

	glCallList(POPSboardList)
	gl.PopMatrix()
	-- END DRAW

	glUseShader(0)
	glDepthTest(true)
	glBlending(true)
	glCulling(false)
end

--------------------------------------------------------------------------------------DRAW WORLD
function gadget:DrawWorld()
--------------------------------------------------------------------------------------UPDATE THE FBO TEXTURES NOW
	if runShader == 1 then
	local GetGameSpeed = Spring.GetGameSpeed
	local _,_,paused = GetGameSpeed()
	local texX,texY = 0,0

	if buildIt == 1 then
		BuildTextureAtlas()
	end

	if paused == false then
		dt = Spring.GetLastUpdateSeconds()
		diffTime = oldTime + dt
		oldTime = diffTime
		glCulling(false)
		glBlending(false)

		UpdateParticles(diffTime,dt)
	end
--------------------------------------------------------------------------------------DRAW THE PARTICLE SYSTEM
	DrawParticles(0)
	end
end

--------------------------------------------------------------------------------------DRAW REFLECTIONS TO CUBE
if (drawReflection) then
	if runShader == 1 then
	function gadget:DrawWorldReflection()
		DrawParticles(0)
	end
	end
end

--------------------------------------------------------------------------------------DIAGNOSTIC CODE
if (drawScreen) then
	function gadget:DrawScreen()
	gl.Blending(false)
	glTexture(posTex)
	gl.Color(1.0,1.0,1.0,1.0)
	glTexRect(88,  600, 600, 88)
	gl.Blending(true)
	end
end
--------------------------------------------------------------------------------------END OF GADGET

end