瀏覽代碼

error report on gl2d

meemknight 2 年之前
父節點
當前提交
0d4450b97e
共有 33 個文件被更改,包括 1184 次插入935 次删除
  1. 13 11
      Pika/core/pikaEditor/containersWindow/containersWindow.cpp
  2. 3 2
      Pika/core/pikaRuntime/containerManager/containerManager.cpp
  3. 2 2
      Pika/core/pikaRuntime/dllLoader/dllLoader.h
  4. 1 1
      Pika/core/pikaRuntime/pikaMain.cpp
  5. 3 0
      Pika/core/pikaRuntime/runtimeContainer/runtimeContainer.h
  6. 1 1
      Pika/core/pikaSTD/engineLibraresSupport/engineGL2DSupport.cpp
  7. 28 1
      Pika/core/pikaSTD/pikaAllocator/freeListAllocator.h
  8. 5 0
      Pika/core/pikaSTD/staticVector.h
  9. 38 10
      Pika/core/sharedRuntime/baseContainer.h
  10. 26 2
      Pika/core/sharedRuntime/globalAllocator/globalAllocator.cpp
  11. 4 0
      Pika/core/sharedRuntime/globalAllocator/globalAllocator.h
  12. 4 1
      Pika/core/sharedRuntime/windowSystemm/window.cpp
  13. 二進制
      Pika/engineResources/engineSaves/options1.bin
  14. 二進制
      Pika/engineResources/engineSaves/options2.bin
  15. 二進制
      Pika/engineResources/engineSaves/window1.bin
  16. 二進制
      Pika/engineResources/engineSaves/window2.bin
  17. 二進制
      Pika/engineResources/engineSaves/windowPos1.bin
  18. 二進制
      Pika/engineResources/engineSaves/windowPos2.bin
  19. 42 2
      Pika/gameplay/containers/mario/mario.h
  20. 2 2
      Pika/gameplay/containers/mario/marioCommon.h
  21. 0 2
      Pika/gameplay/containers/mario/marioNeuralVizualizer.h
  22. 2 2
      Pika/gameplay/containers/minecraftDungeons/mcDungeonsgameplay.h
  23. 15 5
      Pika/gameplay/dll/dllMain.cpp
  24. 2 2
      Pika/gameplay/dll/dllMain.h
  25. 1 0
      Pika/pluggins/pluggins/threeDEditor.h
  26. 2 18
      Pika/resources/logs.txt
  27. 29 0
      Pika/resources/mario/postProcess.frag
  28. 14 0
      Pika/resources/mario/postProcess.vert
  29. 1 1
      Pika/thirdparty/gl2d/CMakeLists.txt
  30. 24 133
      Pika/thirdparty/gl2d/include/gl2d/gl2d.h
  31. 124 0
      Pika/thirdparty/gl2d/include/gl2d/gl2dParticleSystem.h
  32. 155 737
      Pika/thirdparty/gl2d/src/gl2d.cpp
  33. 643 0
      Pika/thirdparty/gl2d/src/gl2dParticleSystem.cpp

+ 13 - 11
Pika/core/pikaEditor/containersWindow/containersWindow.cpp

@@ -400,6 +400,18 @@ void pika::ContainersWindow::update(pika::LogManager &logManager, bool &open, pi
 
 							ImGui::Separator();
 
+							if (ImGui::Button("Calculate memory usage"))
+							{
+								c.allocator.calculateMemoryMetrics(c.availableMemory, c.biggestBlock, c.freeBlocks);
+							}
+
+							ImGui::Text("Available memory: %" IM_PRIu64, c.availableMemory);
+							ImGui::Text("Biggest block: %" IM_PRIu64,	c.biggestBlock);
+							ImGui::Text("Free blocks: %d",				c.freeBlocks);
+
+							ImGui::Separator();
+
+
 							if (ImGui::BeginTabBar("##Tabs for play and record", ImGuiTabBarFlags_Reorderable))
 							{
 								if (ImGui::BeginTabItem(ICON_FK_CAMERA " Snapshot"))
@@ -627,17 +639,7 @@ void pika::ContainersWindow::update(pika::LogManager &logManager, bool &open, pi
 
 								ImGui::EndTabBar();
 							}
-
-							
-
-
-							
-
-							
-
-
-
-						
+					
 
 						}
 					}

+ 3 - 2
Pika/core/pikaRuntime/containerManager/containerManager.cpp

@@ -759,8 +759,7 @@ void pika::ContainerManager::reloadDll(pika::LoadedDll &loadedDll, pika::PikaWin
 	}
 
 
-
-	loadedDll.gameplayReload_(window.context);
+	loadedDll.gameplayReload_(window.context, logs);
 	
 
 
@@ -1224,6 +1223,8 @@ bool pika::checkIfSnapshotIsCompatible(pika::RuntimeContainer &info, const char
 		return false;
 	}
 
+	//todo fix this
+	//todo remake this function probably 
 	if (loadedInfo.requestedContainerInfo.bonusAllocators != info.requestedContainerInfo.bonusAllocators)
 	{
 		return false;

+ 2 - 2
Pika/core/pikaRuntime/dllLoader/dllLoader.h

@@ -13,11 +13,11 @@
 #include <unordered_map>
 #include <string>
 
-#define GAMEPLAYSTART(x) void x(pika::PikaContext &pikaContext)
+#define GAMEPLAYSTART(x) void x(pika::PikaContext &pikaContext, pika::LogManager &logs)
 typedef GAMEPLAYSTART(gameplayStart_t);
 #undef GAMEPLAYSTART
 
-#define GAMEPLAYRELOAD(x) void x(pika::PikaContext &pikaContext)
+#define GAMEPLAYRELOAD(x) void x(pika::PikaContext &pikaContext, pika::LogManager &logs)
 typedef GAMEPLAYRELOAD(gameplayReload_t);
 #undef GAMEPLAYRELOAD
 

+ 1 - 1
Pika/core/pikaRuntime/pikaMain.cpp

@@ -163,7 +163,7 @@ int main()
 
 #pragma region init dll reaml
 
-	loadedDll.gameplayStart_(window.context);
+	loadedDll.gameplayStart_(window.context, logs);
 
 	
 #pragma endregion

+ 3 - 0
Pika/core/pikaRuntime/runtimeContainer/runtimeContainer.h

@@ -38,6 +38,9 @@ struct RuntimeContainer
 	unsigned int frameCounter = 0;
 	float frameTimer = 0;
 	float currentMs = 0;
+	size_t availableMemory = 0;
+	size_t biggestBlock = 0;
+	int freeBlocks = 0;
 
 	bool lastFrameFocus = 0;
 

+ 1 - 1
Pika/core/pikaSTD/engineLibraresSupport/engineGL2DSupport.cpp

@@ -1,6 +1,6 @@
 #include "engineGL2DSupport.h"
 
-
+//todo use global allocator and test.
 ::gl2d::Texture pika::gl2d::loadTextureWithPixelPadding(const char *path, RequestedContainerInfo &info, int blockSize,
 	bool pixelated, bool useMipMaps)
 {

+ 28 - 1
Pika/core/pikaSTD/pikaAllocator/freeListAllocator.h

@@ -44,7 +44,6 @@ namespace memory
 	#endif
 	
 	
-	
 	struct FreeListAllocator
 	{
 		char* baseMemory = 0;
@@ -77,6 +76,34 @@ namespace memory
 		//I rocommand leaving this to false
 		bool returnZeroIfNoMoreMemory = false;
 	
+
+		bool operator==(const FreeListAllocator &other)
+		{
+			if (this == &other) { return true; }
+
+			char *baseMemory = 0;
+			void *originalBaseMemory = 0;
+			size_t heapSize = 0;
+			void *end = 0;
+
+			if(
+				baseMemory == other.baseMemory &&
+				originalBaseMemory == other.originalBaseMemory &&
+				heapSize == other.heapSize &&
+				end == other.end
+				)
+			{
+				return true;
+			}
+
+			return false;
+		}
+
+		bool operator!=(const FreeListAllocator &other)
+		{
+			return !(*this == other);
+		}
+
 	private:
 	
 		void* end = 0;

+ 5 - 0
Pika/core/pikaSTD/staticVector.h

@@ -120,6 +120,11 @@ namespace pika
 			return true;
 		}
 
+		bool operator!=(const StaticVector &other)
+		{
+			return !(*this == other);
+		}
+
 		T &operator[] (size_t index)
 		{
 			PIKA_PERMA_ASSERT(index < size_, "buffer overflow on acces");

+ 38 - 10
Pika/core/sharedRuntime/baseContainer.h

@@ -106,9 +106,9 @@ struct RequestedContainerInfo
 		info.containerName = {containerName.c_str()};
 		info.cmdArgs = {cmdArgs.c_str()};
 
-		pika::memory::setGlobalAllocatorToStandard();
+		pika::memory::pushCustomAllocatorsToStandard();
 		internal.containersToCreate->push_back(info);
-		pika::memory::setGlobalAllocator(mainAllocator);
+		pika::memory::popCustomAllocatorsToStandard();
 
 	}
 
@@ -192,12 +192,40 @@ struct RequestedContainerInfo
 		return readEntireFile(name, data.data(), s);
 	}
 
+	std::string readEntireFileBinaryAsAString(std::string_view name)
+	{
+		std::string rez;
+		size_t s = 0;
+		bool succeed = getFileSizeBinary(name, s);
+		if (!succeed) { return rez; }
+
+		rez.resize(s + 1);
+
+		pika::memory::pushCustomAllocatorsToStandard();
+		{
+			std::ifstream f(name, std::ios::binary);
+			if (!f.is_open())
+			{
+				succeed = false;
+			}
+			else
+			{
+				f.read((char *)rez.data(), s);
+				f.close();
+			}
+		}
+		pika::memory::popCustomAllocatorsToStandard();
+
+		if (!succeed) { return ""; }
+		return rez;
+	}
+
 	bool readEntireFileBinary(std::string_view name, void *buffer, size_t size, size_t from = 0)
 	{
 		//PIKA_DEVELOPMENT_ONLY_ASSERT(readEntireFilePointer, "read entire file pointer not assigned");
 		bool success = true;
 
-		pika::memory::setGlobalAllocatorToStandard();
+		pika::memory::pushCustomAllocatorsToStandard();
 		{
 			std::ifstream f(name, std::ios::binary);
 
@@ -212,7 +240,7 @@ struct RequestedContainerInfo
 				f.close();
 			}
 		}
-		pika::memory::setGlobalAllocator(mainAllocator);
+		pika::memory::popCustomAllocatorsToStandard();
 
 		return success;
 	}
@@ -222,7 +250,7 @@ struct RequestedContainerInfo
 		//PIKA_DEVELOPMENT_ONLY_ASSERT(readEntireFilePointer, "read entire file pointer not assigned");
 		bool success = true;
 
-		pika::memory::setGlobalAllocatorToStandard();
+		pika::memory::pushCustomAllocatorsToStandard();
 		{
 			std::ifstream f(name);
 
@@ -236,7 +264,7 @@ struct RequestedContainerInfo
 				f.close();
 			}
 		}
-		pika::memory::setGlobalAllocator(mainAllocator);
+		pika::memory::popCustomAllocatorsToStandard();
 
 		return success;
 	}
@@ -249,7 +277,7 @@ struct RequestedContainerInfo
 		size = 0;
 
 		//todo push pop allocator or use that pointer thing (and don't forget to only use explicit allocators calls or sthing)
-		pika::memory::setGlobalAllocatorToStandard();
+		pika::memory::pushCustomAllocatorsToStandard();
 		{
 			std::ifstream f(name, std::ifstream::ate | std::ifstream::binary);
 			if (!f.is_open())
@@ -262,7 +290,7 @@ struct RequestedContainerInfo
 				f.close();
 			}
 		}
-		pika::memory::setGlobalAllocator(mainAllocator);
+		pika::memory::popCustomAllocatorsToStandard();
 
 		return size;
 	}
@@ -271,7 +299,7 @@ struct RequestedContainerInfo
 	{
 		bool success = true;
 		size = 0;
-		pika::memory::setGlobalAllocatorToStandard();
+		pika::memory::pushCustomAllocatorsToStandard();
 		{
 			std::ifstream f(name, std::ifstream::ate);
 			if (!f.is_open())
@@ -284,7 +312,7 @@ struct RequestedContainerInfo
 				f.close();
 			}
 		}
-		pika::memory::setGlobalAllocator(mainAllocator);
+		pika::memory::popCustomAllocatorsToStandard();
 
 		return success;
 	}

+ 26 - 2
Pika/core/sharedRuntime/globalAllocator/globalAllocator.cpp

@@ -2,8 +2,7 @@
 #include <malloc.h>
 #include <pikaAllocator/freeListAllocator.h>
 #include <fstream>
-
-
+#include <logs/assert.h>
 
 
 void *DefaultAllocator(size_t size)
@@ -41,24 +40,49 @@ namespace pika
 {
 namespace memory
 {
+	int pushed = 0;
+
 	void setGlobalAllocatorToStandard()
 	{
+		PIKA_PERMA_ASSERT(!pushed, "Can't edit allocators while you pushed custom allocators to standard");
+
 		GlobalAllocateFunction = DefaultAllocator;
 		GlobalFree = DefaultFree;
 	}
 
 	void dissableAllocators()
 	{
+		PIKA_PERMA_ASSERT(!pushed, "Can't edit allocators while you pushed custom allocators to standard");
+
 		GlobalAllocateFunction = DisabeledAllocator;
 		GlobalFree = DisabeledFree;
 	}
 
 	void setGlobalAllocator(pika::memory::FreeListAllocator *allocator)
 	{
+		PIKA_PERMA_ASSERT(!pushed, "Can't edit allocators while you pushed custom allocators to standard");
+
 		currentCustomAllocator = allocator;
 		GlobalAllocateFunction = CustomAllocator;
 		GlobalFree = CustomFree;
 	}
+
+
+	void pushCustomAllocatorsToStandard()
+	{
+		pushed++;
+		GlobalAllocateFunction = DefaultAllocator;
+		GlobalFree = DefaultFree;
+	}
+
+	//can be pushed and popped only once
+	void popCustomAllocatorsToStandard()
+	{
+		pushed--;
+		PIKA_PERMA_ASSERT(pushed>=0, "pop underflow on popCustomAllocatorsToStandard");
+		GlobalAllocateFunction = CustomAllocator;
+		GlobalFree = CustomFree;
+	}
 }
 }
 

+ 4 - 0
Pika/core/sharedRuntime/globalAllocator/globalAllocator.h

@@ -12,5 +12,9 @@ namespace memory
 
 	void dissableAllocators();
 
+	void pushCustomAllocatorsToStandard();
+
+	void popCustomAllocatorsToStandard();
+
 }
 }

+ 4 - 1
Pika/core/sharedRuntime/windowSystemm/window.cpp

@@ -150,7 +150,10 @@ void pika::PikaWindow::update()
 
 		windowState.windowW = w;
 		windowState.windowH = h;
-
+		
+		glfwGetFramebufferSize(context.wind, &w, &h);
+		windowState.frameBufferW = w;
+		windowState.frameBufferH = h;
 	}
 
 #pragma endregion

二進制
Pika/engineResources/engineSaves/options1.bin


二進制
Pika/engineResources/engineSaves/options2.bin


二進制
Pika/engineResources/engineSaves/window1.bin


二進制
Pika/engineResources/engineSaves/window2.bin


二進制
Pika/engineResources/engineSaves/windowPos1.bin


二進制
Pika/engineResources/engineSaves/windowPos2.bin


+ 42 - 2
Pika/gameplay/containers/mario/mario.h

@@ -9,7 +9,6 @@
 #include <fileChanged.h>
 
 
-
 struct Mario: public Container
 {
 
@@ -18,6 +17,11 @@ struct Mario: public Container
 	mario::Player player;
 	
 	pika::FileChanged fileChanged;
+	gl2d::FrameBuffer fbo;
+	gl2d::ShaderProgram postProcessShader;
+	pika::FileChanged vertexChanged;
+	pika::FileChanged fragmentChanged;
+
 
 	//todo user can request imgui ids; shortcut manager context; allocators
 	static ContainerStaticInfo containerInfo()
@@ -34,6 +38,16 @@ struct Mario: public Container
 
 	std::string mapFile = PIKA_RESOURCES_PATH "/mario/map1.mario";
 
+	void loadShader(RequestedContainerInfo &requestedInfo)
+	{
+
+		auto vertData = requestedInfo.readEntireFileBinaryAsAString(PIKA_RESOURCES_PATH "mario/postProcess.vert");
+		auto fragmeData = requestedInfo.readEntireFileBinaryAsAString(PIKA_RESOURCES_PATH "mario/postProcess.frag");
+
+		postProcessShader = gl2d::createShaderProgram(vertData.c_str(), fragmeData.c_str());
+
+	}
+
 	bool create(RequestedContainerInfo &requestedInfo, pika::StaticString<256> commandLineArgument)
 	{
 		player.position.position = {1,1};
@@ -50,18 +64,34 @@ struct Mario: public Container
 
 		fileChanged.setFile(mapFile.c_str());
 
+		fbo.create(1, 1);
+
+		loadShader(requestedInfo);
+		vertexChanged.setFile(PIKA_RESOURCES_PATH "mario/postProcess.vert");
+		fragmentChanged.setFile(PIKA_RESOURCES_PATH "mario/postProcess.frag");
+
 		return rez;
 	}
 
 	bool update(pika::Input input, pika::WindowState windowState,
 		RequestedContainerInfo &requestedInfo)
 	{
+		fbo.clear();
+		fbo.resize(windowState.frameBufferW, windowState.frameBufferH);
+		//glBindFramebuffer(GL_FRAMEBUFFER, requestedInfo.requestedFBO.fbo);
+		renderer.renderer.clearScreen();
 
 		if (fileChanged.changed())
 		{
 			mario::loadMap(requestedInfo, mapFile, &simulator.map, simulator.mapSize);
 		}
 
+		if (vertexChanged.changed() || fragmentChanged.changed())
+		{
+			glDeleteShader(postProcessShader.id);
+			loadShader(requestedInfo);
+		}
+
 		{
 			int delta = 0;
 
@@ -101,7 +131,15 @@ struct Mario: public Container
 		renderer.update(input, windowState, simulator);
 		renderer.followPlayer(player, input, windowState);
 		renderer.drawPlayer(player);
-		renderer.render();
+		//renderer.render();
+
+		renderer.renderer.flushFBO(fbo);
+		renderer.renderer.pushCamera();
+		renderer.renderer.pushShader(postProcessShader);
+		renderer.renderer.renderRectangle({0,0, windowState.frameBufferW, windowState.frameBufferH}, {}, 0, fbo.texture);
+		renderer.renderer.flush();
+		renderer.renderer.popShader();
+		renderer.renderer.popCamera();
 
 		return true;
 	}
@@ -110,6 +148,8 @@ struct Mario: public Container
 	{
 		renderer.cleanup();
 		simulator.cleanup();
+		fbo.cleanup();
+		glDeleteShader(postProcessShader.id);
 	}
 
 };

+ 2 - 2
Pika/gameplay/containers/mario/marioCommon.h

@@ -177,7 +177,7 @@ struct GameplayRenderer
 
 	bool init(RequestedContainerInfo &requestedInfo)
 	{
-		renderer.create();
+		renderer.create(requestedInfo.requestedFBO.fbo);
 		//gl2d::setErrorFuncCallback() //tood
 		//pika::initShortcutApi();
 
@@ -336,7 +336,7 @@ struct NeuralNetork
 		{
 			for (int j = 0; j < visionTotal; j++)
 			{
-				if (input[j])
+				if (input[j] > 0)
 				{
 					rezult[i] += weights[i][j];
 				}

+ 0 - 2
Pika/gameplay/containers/mario/marioNeuralVizualizer.h

@@ -100,8 +100,6 @@ struct MarioNeuralVizualizer: public Container
 		mario::renderNeuralNetwork(renderer.renderer, vision, 20, network);
 		
 
-	
-
 
 		glBindFramebuffer(GL_FRAMEBUFFER, requestedInfo.requestedFBO.fbo);
 		renderer.render();

+ 2 - 2
Pika/gameplay/containers/minecraftDungeons/mcDungeonsgameplay.h

@@ -433,9 +433,9 @@ struct McDungeonsGameplay: public Container
 		font = pika::gl2d::loadFont(PIKA_RESOURCES_PATH "mcDungeons/CommodorePixeled.ttf", requestedInfo);
 
 
-		//todo close function for containers
 		//todo check out why mouse don't work in outside window
-
+		
+		//todo add a utulity for setting all this
 		renderer.setErrorCallback(&errorCallbackCustom, &requestedInfo);
 		renderer.fileOpener.userData = &requestedInfo;
 		renderer.fileOpener.readEntireFileBinaryCallback = readEntireFileBinaryCustom;

+ 15 - 5
Pika/gameplay/dll/dllMain.cpp

@@ -56,12 +56,20 @@ PIKA_API void dissableAllocators()
 	pika::memory::dissableAllocators();
 }
 
-void gl2dErrorFuncStub(const char *msg) //todo
+void gl2dErrorFunc(const char *msg, void* userData) //todo
 {
+	pika::LogManager *logManager = (pika::LogManager *)userData;
+
+	pika::memory::pushCustomAllocatorsToStandard();
+
+	if (logManager)
+		logManager->log(msg, pika::logError);
+
+	pika::memory::popCustomAllocatorsToStandard();
 }
 
 //used to initialize libraries 
-PIKA_API void gameplayStart(pika::PikaContext &pikaContext)
+PIKA_API void gameplayStart(pika::PikaContext &pikaContext, pika::LogManager &logs)
 {
 	pika::pikaImgui::setImguiAllocator(pikaContext.imguiAllocator);
 	//pika::initShortcutApi(); //todo
@@ -74,14 +82,15 @@ PIKA_API void gameplayStart(pika::PikaContext &pikaContext)
 #endif
 
 	gl2d::init();
-	gl2d::setErrorFuncCallback(gl2dErrorFuncStub);
+	gl2d::setUserDefinedData(&logs);
+	gl2d::setErrorFuncCallback(gl2dErrorFunc);
 
 #pragma endregion
 }
 
 
 //this won't be ever called in production so we can remove the code
-PIKA_API void gameplayReload(pika::PikaContext &pikaContext)
+PIKA_API void gameplayReload(pika::PikaContext &pikaContext, pika::LogManager &logs)
 {
 #ifdef PIKA_DEVELOPMENT	
 
@@ -93,7 +102,8 @@ PIKA_API void gameplayReload(pika::PikaContext &pikaContext)
 	pika::pikaImgui::setImguiContext(pikaContext);
 
 	gl2d::init();
-	gl2d::setErrorFuncCallback(gl2dErrorFuncStub);
+	gl2d::setUserDefinedData(&logs);
+	gl2d::setErrorFuncCallback(gl2dErrorFunc);
 #endif
 }
 

+ 2 - 2
Pika/gameplay/dll/dllMain.h

@@ -15,9 +15,9 @@
 #include <pikaAllocator/freeListAllocator.h>
 #include <sstream>
 
-PIKA_API void gameplayStart(pika::PikaContext &pikaContext);
+PIKA_API void gameplayStart(pika::PikaContext &pikaContext, pika::LogManager &logs);
 PIKA_API void setConsoleBuffer(std::streambuf *buf);
-PIKA_API void gameplayReload(pika::PikaContext &pikaContext);
+PIKA_API void gameplayReload(pika::PikaContext &pikaContext, pika::LogManager &logs);
 PIKA_API void getContainersInfo(std::vector<pika::ContainerInformation> &info);
 PIKA_API bool constructContainer(Container **c, pika::memory::MemoryArena *arena, const char *name);
 PIKA_API void destructContainer(Container **c, pika::memory::MemoryArena *arena);

+ 1 - 0
Pika/pluggins/pluggins/threeDEditor.h

@@ -47,6 +47,7 @@ struct ThreeDEditor: public Container
 		
 		renderer.init(1, 1, PIKA_RESOURCES_PATH "BRDFintegrationMap.png", requestedInfo.requestedFBO.fbo);
 		
+
 		const char *names[6] =
 		{PIKA_RESOURCES_PATH "/skyBoxes/ocean/right.jpg",
 			PIKA_RESOURCES_PATH "/skyBoxes/ocean/left.jpg",

+ 2 - 18
Pika/resources/logs.txt

@@ -1,18 +1,2 @@
-#2023-05-22 12:13:38: Created container: ImmageViewer
-#2023-05-22 12:13:42: Terminated container because it returned 0: ImmageViewer #1
-#2023-05-22 12:13:42: Destroyed continer: ImmageViewer #1
-#2023-05-22 12:13:45: Created container: PikaTextEditor
-#2023-05-22 12:13:49: Terminated container because it returned 0: PikaTextEditor #2
-#2023-05-22 12:13:49: Destroyed continer: PikaTextEditor #2
-#2023-05-22 12:13:54: Created container: ImmageViewer
-#2023-05-22 12:13:58: Terminated container because it returned 0: ImmageViewer #3
-#2023-05-22 12:13:58: Destroyed continer: ImmageViewer #3
-#2023-05-22 12:13:58: Created container: ImmageViewer
-#2023-05-22 12:14:00: Terminated container because it returned 0: ImmageViewer #4
-#2023-05-22 12:14:00: Destroyed continer: ImmageViewer #4
-#2023-05-22 12:14:01: Created container: ImmageViewer
-#2023-05-22 12:14:18: Terminated container because it returned 0: ImmageViewer #5
-#2023-05-22 12:14:18: Destroyed continer: ImmageViewer #5
-#2023-05-22 12:14:22: Created container: ImmageViewer
-#2023-05-22 12:14:39: Terminated container because it returned 0: ImmageViewer #6
-#2023-05-22 12:14:39: Destroyed continer: ImmageViewer #6
+#2023-05-28 21:06:07: Created container: Mario
+#2023-05-28 21:08:14: Destroyed continer: Mario #1

+ 29 - 0
Pika/resources/mario/postProcess.frag

@@ -0,0 +1,29 @@
+#version 330
+
+out vec4 color;
+in vec4 v_color;
+in vec2 v_texture;
+uniform sampler2D u_sampler;
+void main()
+{
+
+	vec2 newSamplePoint = v_texture;
+	newSamplePoint *= 2;
+	newSamplePoint -= 1;
+
+	vec2 s = sign(newSamplePoint);
+	newSamplePoint = abs(newSamplePoint);
+	newSamplePoint = 
+	mix(pow(newSamplePoint, vec2(1.2)) * abs(cos(newSamplePoint*3.141592*2.f)), newSamplePoint, 
+	min(distance(newSamplePoint, vec2(0.2,0.2))/0.2*sqrt(2.f),1));
+
+	newSamplePoint *= s;
+
+	newSamplePoint += 1;
+	newSamplePoint /= 2;
+	color = v_color * texture2D(u_sampler, newSamplePoint);
+
+	//color.rgb = vec3(length(color.rgb));
+
+	color.a = 1;
+}

+ 14 - 0
Pika/resources/mario/postProcess.vert

@@ -0,0 +1,14 @@
+#version 130
+
+in vec2 quad_positions;
+in vec4 quad_colors;
+in vec2 texturePositions;
+out vec4 v_color;
+out vec2 v_texture;
+
+void main()
+{
+	gl_Position = vec4(quad_positions, 0, 1);
+	v_color = quad_colors;
+	v_texture = texturePositions;
+}

+ 1 - 1
Pika/thirdparty/gl2d/CMakeLists.txt

@@ -2,6 +2,6 @@ cmake_minimum_required(VERSION 3.1)
 project(gl2d)
 
 add_library(gl2d)
-target_sources(gl2d PRIVATE "src/gl2d.cpp")
+target_sources(gl2d PRIVATE "src/gl2d.cpp" "src/gl2dParticleSystem.cpp")
 target_include_directories(gl2d PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include")
 target_link_libraries(gl2d PUBLIC glm glad stb_image stb_truetype)

+ 24 - 133
Pika/thirdparty/gl2d/include/gl2d/gl2d.h

@@ -1,5 +1,5 @@
 //////////////////////////////////////////////////
-//gl2d.h				1.2.5
+//gl2d.h				1.2.6
 //Copyright(c) 2020 Luta Vlad
 //https://github.com/meemknight/gl2d
 //
@@ -45,12 +45,12 @@
 #define GL2D_DEFAULT_TEXTURE_LOAD_MODE_USE_MIPMAPS true
 
 
-//version of the shading language. this is the minimum but you can go lower if you midify the shader code with minimal effort
+//version of the shading language. this is the minimum but you can go lower if you modify the shader code with minimal effort
 #define GL2D_OPNEGL_SHADER_VERSION "#version 130"
 #define GL2D_OPNEGL_SHADER_PRECISION "precision highp float;"
 
 //this is the default capacity of the renderer
-#define GL2D_Renderer2D_Max_Triangle_Capacity 42000
+#define GL2D_Renderer2D_Max_Triangle_Capacity 4200
 #define GL2D_DefaultTextureCoords (glm::vec4{ 0, 1, 1, 0 })
 
 #include <glad/glad.h>
@@ -66,7 +66,11 @@ namespace gl2d
 
 	void init();
 
-	void defaultErrorFunc(const char* msg);
+	void clearnup();
+
+	void defaultErrorFunc(const char* msg, void *userDefinedData);
+
+	void setUserDefinedData(void *data);
 
 	using errorFuncType = decltype(defaultErrorFunc);
 
@@ -77,14 +81,16 @@ namespace gl2d
 	//returns false on fail
 	bool setVsync(bool b);
 
-	namespace internal
+	struct ShaderProgram
 	{
-		struct ShaderProgram
-		{
-			GLuint id;
-			int u_sampler;
-		};
+		GLuint id;
+		int u_sampler;
+	};
 
+	ShaderProgram createShaderProgram(const char *vertex, const char *fragment);
+
+	namespace internal
+	{
 		float positionToScreenCoordsX(const float position, float w);
 		float positionToScreenCoordsY(const float position, float h);
 
@@ -157,12 +163,6 @@ namespace gl2d
 		void cleanup();
 	};
 
-	struct TextureRegion //todo add uses for this
-	{
-		Texture texture;
-		glm::vec4 textureCoords;
-	};
-
 #pragma endregion
 
 
@@ -297,11 +297,13 @@ namespace gl2d
 		Renderer2D(Renderer2D &other) = delete; 
 		Renderer2D operator=(Renderer2D &other) = delete;
 
-		void create();
+		void create(GLuint fbo = 0);
 
 		//does not clear resources allocated by user like textures, fonts and fbos
 		void clear();
 
+		GLuint defaultFBO = 0;
+
 		GLuint buffers[Renderer2DBufferType::bufferSize] = {};
 		GLuint vao = {};
 
@@ -317,9 +319,9 @@ namespace gl2d
 		int spriteTexturesCount = 0;
 
 
-		internal::ShaderProgram currentShader = {};
-		std::vector<internal::ShaderProgram> shaderPushPop;
-		void pushShader(internal::ShaderProgram s = {});
+		ShaderProgram currentShader = {};
+		std::vector<ShaderProgram> shaderPushPop;
+		void pushShader(ShaderProgram s = {});
 		void popShader();
 
 		Camera currentCamera = {};
@@ -392,9 +394,10 @@ namespace gl2d
 
 		void clearScreen(const Color4f color = Color4f{0,0,0,0});
 
-		void setShaderProgram(const internal::ShaderProgram shader);
+		void setShaderProgram(const ShaderProgram shader);
 		void setCamera(const Camera camera);
 
+		//will reset on the current stack
 		void resetCameraAndShader();
 
 		//draws to the screen
@@ -407,118 +410,6 @@ namespace gl2d
 #pragma endregion
 
 
-	///////////////////// ParticleSysyem /////////////////////
-#pragma region ParticleSysyem
-
-	struct ParticleApearence
-	{
-		glm::vec2 size = {};
-		glm::vec4 color1 = {};
-		glm::vec4 color2 = {};
-	};
-
-	enum TRANZITION_TYPES
-	{
-		none = 0,
-		linear,
-		curbe,
-		abruptCurbe,
-		wave,
-		wave2,
-		delay,
-		delay2
-	};
-
-
-	struct ParticleSettings
-	{
-		ParticleSettings* deathRattle = nullptr;
-		ParticleSettings* subemitParticle = nullptr;
-
-		int onCreateCount = 0;
-
-		glm::vec2 subemitParticleTime = {};
-
-		glm::vec2 positionX = {};
-		glm::vec2 positionY = {};
-
-		glm::vec2 particleLifeTime = {}; // move
-		glm::vec2 directionX = {};
-		glm::vec2 directionY = {};
-		glm::vec2 dragX = {};
-		glm::vec2 dragY = {};
-
-		glm::vec2 rotation = {};
-		glm::vec2 rotationSpeed = {};
-		glm::vec2 rotationDrag = {};
-
-		ParticleApearence createApearence = {};
-		ParticleApearence createEndApearence = {};
-
-		gl2d::Texture* texturePtr = 0;
-
-		int tranzitionType = TRANZITION_TYPES::linear;
-	};
-
-
-	struct ParticleSystem
-	{
-		void initParticleSystem(int size);
-		void cleanup();
-
-		void emitParticleWave(ParticleSettings* ps, glm::vec2 pos);
-
-
-		void applyMovement(float deltaTime);
-
-		void draw(Renderer2D& r);
-
-		bool postProcessing = true;
-		float pixelateFactor = 2;
-
-	private:
-
-		int size = 0;
-
-		float* posX = 0;
-		float* posY = 0;
-
-		float* directionX = 0;
-		float* directionY = 0;
-
-		float* rotation = 0;
-
-		float* sizeXY = 0;
-
-		float* dragX = 0;
-		float* dragY = 0;
-
-		float* duration = 0;
-		float* durationTotal = 0;
-
-		glm::vec4* color = 0;
-
-		float* rotationSpeed = 0;
-		float* rotationDrag = 0;
-
-		float* emitTime = 0;
-
-		char* tranzitionType = 0;
-		ParticleSettings** deathRattle = 0;
-		ParticleSettings** thisParticleSettings = 0;
-		ParticleSettings** emitParticle = 0;
-
-		gl2d::Texture** textures = 0;
-
-		std::mt19937 random{ std::random_device{}() };
-
-		gl2d::FrameBuffer fb = {};
-
-		float rand(glm::vec2 v);
-	};
-
-
-#pragma endregion
 
 
 

+ 124 - 0
Pika/thirdparty/gl2d/include/gl2d/gl2dParticleSystem.h

@@ -0,0 +1,124 @@
+#pragma once
+#include "gl2d.h"
+
+namespace gl2d
+{
+
+	///////////////////// ParticleSysyem /////////////////////
+#pragma region ParticleSysyem
+
+	void initgl2dParticleSystem();
+	
+	void cleanupgl2dParticleSystem();
+
+	struct ParticleApearence
+	{
+		glm::vec2 size = {};
+		glm::vec4 color1 = {};
+		glm::vec4 color2 = {};
+	};
+
+	enum TRANZITION_TYPES
+	{
+		none = 0,
+		linear,
+		curbe,
+		abruptCurbe,
+		wave,
+		wave2,
+		delay,
+		delay2
+	};
+
+
+	struct ParticleSettings
+	{
+		ParticleSettings *deathRattle = nullptr;
+		ParticleSettings *subemitParticle = nullptr;
+
+		int onCreateCount = 0;
+
+		glm::vec2 subemitParticleTime = {};
+
+		glm::vec2 positionX = {};
+		glm::vec2 positionY = {};
+
+		glm::vec2 particleLifeTime = {}; // move
+		glm::vec2 directionX = {};
+		glm::vec2 directionY = {};
+		glm::vec2 dragX = {};
+		glm::vec2 dragY = {};
+
+		glm::vec2 rotation = {};
+		glm::vec2 rotationSpeed = {};
+		glm::vec2 rotationDrag = {};
+
+		ParticleApearence createApearence = {};
+		ParticleApearence createEndApearence = {};
+
+		gl2d::Texture *texturePtr = 0;
+
+		int tranzitionType = TRANZITION_TYPES::linear;
+	};
+
+
+	struct ParticleSystem
+	{
+		void initParticleSystem(int size);
+		void cleanup();
+
+		void emitParticleWave(ParticleSettings *ps, glm::vec2 pos);
+
+
+		void applyMovement(float deltaTime);
+
+		void draw(gl2d::Renderer2D &r);
+
+		bool postProcessing = true;
+		float pixelateFactor = 2;
+
+	private:
+
+		int size = 0;
+
+		float *posX = 0;
+		float *posY = 0;
+
+		float *directionX = 0;
+		float *directionY = 0;
+
+		float *rotation = 0;
+
+		float *sizeXY = 0;
+
+		float *dragX = 0;
+		float *dragY = 0;
+
+		float *duration = 0;
+		float *durationTotal = 0;
+
+		glm::vec4 *color = 0;
+
+		float *rotationSpeed = 0;
+		float *rotationDrag = 0;
+
+		float *emitTime = 0;
+
+		char *tranzitionType = 0;
+		ParticleSettings **deathRattle = 0;
+		ParticleSettings **thisParticleSettings = 0;
+		ParticleSettings **emitParticle = 0;
+
+		gl2d::Texture **textures = 0;
+
+		std::mt19937 random{std::random_device{}()};
+
+		gl2d::FrameBuffer fb = {};
+
+		float rand(glm::vec2 v);
+	};
+
+
+#pragma endregion
+
+}

+ 155 - 737
Pika/thirdparty/gl2d/src/gl2d.cpp

@@ -27,7 +27,20 @@
 // push pop shaders and camera
 // added getViewRect
 // 
-//////////////////////////////////////////////////
+// 1.2.6
+// updated camera.follow
+// removed TextureRegion
+// 
+// 1.3.0
+// polished using custom shader api
+// fixed camera follow
+// moved the particle system into another file
+// added a proper cmake
+// used the proper stbi free function
+// added a default fbo support
+// added proper error reporting (with uer defined data)
+// 
+/////////////////////////////////////////////////////////
 
 
 //	todo
@@ -42,10 +55,9 @@
 //	
 //
 
-#include "gl2d/gl2d.h"
+#include <gl2d/gl2d.h>
 
 #ifdef _WIN32
-#include <gl/GL.h>
 #include <Windows.h>
 #endif
 
@@ -68,8 +80,7 @@ namespace gl2d
 {
 #pragma region shaders
 
-	static internal::ShaderProgram defaultShader = {};
-	static internal::ShaderProgram defaultParticleShader = {};
+	static ShaderProgram defaultShader = {};
 	static Camera defaultCamera{};
 	static Texture white1pxSquareTexture = {};
 
@@ -100,77 +111,21 @@ namespace gl2d
 		"    color = v_color * texture2D(u_sampler, v_texture);\n"
 		"}\n";
 
-	static const char* defaultParticleVertexShader =
-		GL2D_OPNEGL_SHADER_VERSION "\n"
-		GL2D_OPNEGL_SHADER_PRECISION "\n"
-		"in vec2 quad_positions;\n"
-		"in vec4 quad_colors;\n"
-		"in vec2 texturePositions;\n"
-		"out vec4 v_color;\n"
-		"out vec2 v_texture;\n"
-		"void main()\n"
-		"{\n"
-		"	gl_Position = vec4(quad_positions, 0, 1);\n"
-		"	v_color = quad_colors;\n"
-		"	v_texture = texturePositions;\n"
-		"}\n";
-
-	static const char* defaultParcileFragmentShader =
-		GL2D_OPNEGL_SHADER_VERSION "\n"
-		GL2D_OPNEGL_SHADER_PRECISION "\n"
-		R"(out vec4 color;
-			in vec4 v_color;
-			in vec2 v_texture;
-			uniform sampler2D u_sampler;
-			
-			vec3 rgbTohsv(vec3 c)
-			{
-				vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
-				vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));
-				vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));
-			
-				float d = q.x - min(q.w, q.y);
-				float e = 1.0e-10;
-				return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
-			}
-			
-			vec3 hsvTorgb(vec3 c)
-			{
-				vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
-				vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
-				return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
-			}
-			
-			const float cFilter = 5.f;
-			
-			void main()
-			{
-				color = v_color * texture2D(u_sampler, v_texture);
-				
-				if(color.a <0.01)discard;
-				//color.a = 1.f;
-			
-				//color.a = pow(color.a, 0.2); 
-			
-				color.rgb *= cFilter;				//
-				color.rgb = floor(color.rgb);		//remove color quality to get a retro effect
-				color.rgb /= cFilter;				//
-			
-				//color.rgb = rgbTohsv(color.rgb);
-			
-				//color.rgb = hsvTorgb(color.rgb);
-			
-			})";
-
 #pragma endregion
 
 	static errorFuncType* errorFunc = defaultErrorFunc;
 
-	void defaultErrorFunc(const char* msg)
+	void defaultErrorFunc(const char* msg, void *userDefinedData)
 	{
 		std::cerr << "gl2d error: " << msg << "\n";
 	}
 
+	void *userDefinedData = 0;
+	void setUserDefinedData(void *data)
+	{
+		userDefinedData = data;
+	}
+
 	errorFuncType* setErrorFuncCallback(errorFuncType* newFunc)
 	{
 		auto a = errorFunc;
@@ -237,7 +192,7 @@ namespace gl2d
 
 				message[l - 1] = 0;
 
-				errorFunc(message);
+				errorFunc(message, userDefinedData);
 
 				delete[] message;
 
@@ -245,52 +200,7 @@ namespace gl2d
 
 			return id;
 		}
-
-		internal::ShaderProgram createShaderProgram(const char* vertex, const char* fragment)
-		{
-			internal::ShaderProgram shader = { 0 };
-
-			const GLuint vertexId = loadShader(vertex, GL_VERTEX_SHADER);
-			const GLuint fragmentId = loadShader(fragment, GL_FRAGMENT_SHADER);
-
-			shader.id = glCreateProgram();
-			glAttachShader(shader.id, vertexId);
-			glAttachShader(shader.id, fragmentId);
-
-			glBindAttribLocation(shader.id, 0, "quad_positions");
-			glBindAttribLocation(shader.id, 1, "quad_colors");
-			glBindAttribLocation(shader.id, 2, "texturePositions");
-
-			glLinkProgram(shader.id);
-
-			glDeleteShader(vertexId);
-			glDeleteShader(fragmentId);
-
-			int info = 0;
-			glGetProgramiv(shader.id, GL_LINK_STATUS, &info);
-
-			if (info != GL_TRUE)
-			{
-				char* message = 0;
-				int   l = 0;
-
-				glGetProgramiv(shader.id, GL_INFO_LOG_LENGTH, &l);
-
-				message = new char[l];
-
-				glGetProgramInfoLog(shader.id, l, &l, message);
-
-				errorFunc(message);
-
-				delete[] message;
-			}
-
-			glValidateProgram(shader.id);
-
-			shader.u_sampler = glGetUniformLocation(shader.id, "u_sampler");
-
-			return shader;
-		}
+		
 	}
 
 #ifdef _WIN32
@@ -329,13 +239,19 @@ namespace gl2d
 		extensions.wglSwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC)wglGetProcAddress("wglSwapIntervalEXT");
 	#endif
 
-		defaultShader = internal::createShaderProgram(defaultVertexShader, defaultFragmentShader);
-		defaultParticleShader = internal::createShaderProgram(defaultParticleVertexShader, defaultParcileFragmentShader);
+		defaultShader = createShaderProgram(defaultVertexShader, defaultFragmentShader);
 		white1pxSquareTexture.create1PxSquare();
 
 		enableNecessaryGLFeatures();
 	}
 
+	void clearnup()
+	{
+		white1pxSquareTexture.cleanup();
+		glDeleteShader(defaultShader.id);
+		hasInitialized = false;
+	}
+
 	bool setVsync(bool b)
 	{
 		//add linux suport
@@ -373,6 +289,58 @@ namespace gl2d
 		return vec;
 	}
 
+
+	///////////////////// Shader /////////////////////
+#pragma region shader
+
+	ShaderProgram createShaderProgram(const char *vertex, const char *fragment)
+	{
+		ShaderProgram shader = {0};
+
+		const GLuint vertexId = internal::loadShader(vertex, GL_VERTEX_SHADER);
+		const GLuint fragmentId = internal::loadShader(fragment, GL_FRAGMENT_SHADER);
+
+		shader.id = glCreateProgram();
+		glAttachShader(shader.id, vertexId);
+		glAttachShader(shader.id, fragmentId);
+
+		glBindAttribLocation(shader.id, 0, "quad_positions");
+		glBindAttribLocation(shader.id, 1, "quad_colors");
+		glBindAttribLocation(shader.id, 2, "texturePositions");
+
+		glLinkProgram(shader.id);
+
+		glDeleteShader(vertexId);
+		glDeleteShader(fragmentId);
+
+		int info = 0;
+		glGetProgramiv(shader.id, GL_LINK_STATUS, &info);
+
+		if (info != GL_TRUE)
+		{
+			char *message = 0;
+			int   l = 0;
+
+			glGetProgramiv(shader.id, GL_INFO_LOG_LENGTH, &l);
+
+			message = new char[l];
+
+			glGetProgramInfoLog(shader.id, l, &l, message);
+
+			errorFunc(message, userDefinedData);
+
+			delete[] message;
+		}
+
+		glValidateProgram(shader.id);
+
+		shader.u_sampler = glGetUniformLocation(shader.id, "u_sampler");
+
+		return shader;
+	}
+
+#pragma endregion
+
 	///////////////////// Texture /////////////////////
 #pragma region Texture
 
@@ -484,7 +452,7 @@ namespace gl2d
 			char c[300] = {0};
 			strcat(c, "error openning: ");
 			strcat(c + strlen(c), file);
-			errorFunc(c);
+			errorFunc(c, userDefinedData);
 			return;
 		}
 
@@ -512,69 +480,70 @@ namespace gl2d
 	///////////////////// Renderer2D /////////////////////
 #pragma region Renderer2D
 
-	void gl2d::Renderer2D::flush()
+	//won't bind any fbo
+	void internalFlush(gl2d::Renderer2D &renderer)
 	{
 		enableNecessaryGLFeatures();
 
-		if (!hasInitialized) 
+		if (!hasInitialized)
 		{
-			errorFunc("Library not initialized. Have you forgotten to call gl2d::init() ?");
+			errorFunc("Library not initialized. Have you forgotten to call gl2d::init() ?", userDefinedData);
 		}
 
-		if (!vao)
+		if (!renderer.vao)
 		{
-			errorFunc("Renderer not initialized. Have you forgotten to call gl2d::Renderer2D::create() ?");
+			errorFunc("Renderer not initialized. Have you forgotten to call gl2d::Renderer2D::create() ?", userDefinedData);
 		}
 
-		if (windowH == 0 || windowW == 0)
+		if (renderer.windowH == 0 || renderer.windowW == 0)
 		{
-			spritePositionsCount = 0;
-			spriteColorsCount = 0;
-			spriteTexturesCount = 0;
-			texturePositionsCount = 0;
+			renderer.spritePositionsCount = 0;
+			renderer.spriteColorsCount = 0;
+			renderer.spriteTexturesCount = 0;
+			renderer.texturePositionsCount = 0;
 			return;
 		}
 
-		if (spriteTexturesCount == 0)
+		if(renderer.spriteTexturesCount == 0)
 		{
 			return;
 		}
 
-		glViewport(0, 0, windowW, windowH);
+		glViewport(0, 0, renderer.windowW, renderer.windowH);
 
-		glBindVertexArray(vao);
+		glBindVertexArray(renderer.vao);
 
-		glUseProgram(currentShader.id);
+		glUseProgram(renderer.currentShader.id);
 
-		glUniform1i(currentShader.u_sampler, 0);
+		glUniform1i(renderer.currentShader.u_sampler, 0);
 
-		glBindBuffer(GL_ARRAY_BUFFER, buffers[Renderer2DBufferType::quadPositions]);
-		glBufferData(GL_ARRAY_BUFFER, spritePositionsCount * sizeof(glm::vec2), spritePositions, GL_STREAM_DRAW);
+		glBindBuffer(GL_ARRAY_BUFFER, renderer.buffers[Renderer2DBufferType::quadPositions]);
+		glBufferData(GL_ARRAY_BUFFER, renderer.spritePositionsCount * sizeof(glm::vec2), renderer.spritePositions, GL_STREAM_DRAW);
 
-		glBindBuffer(GL_ARRAY_BUFFER, buffers[Renderer2DBufferType::quadColors]);
-		glBufferData(GL_ARRAY_BUFFER, spriteColorsCount * sizeof(glm::vec4), spriteColors, GL_STREAM_DRAW);
+		glBindBuffer(GL_ARRAY_BUFFER, renderer.buffers[Renderer2DBufferType::quadColors]);
+		glBufferData(GL_ARRAY_BUFFER, renderer.spriteColorsCount * sizeof(glm::vec4), renderer.spriteColors, GL_STREAM_DRAW);
 
-		glBindBuffer(GL_ARRAY_BUFFER, buffers[Renderer2DBufferType::texturePositions]);
-		glBufferData(GL_ARRAY_BUFFER, texturePositionsCount * sizeof(glm::vec2), texturePositions, GL_STREAM_DRAW);
+		glBindBuffer(GL_ARRAY_BUFFER, renderer.buffers[Renderer2DBufferType::texturePositions]);
+		glBufferData(GL_ARRAY_BUFFER, renderer.texturePositionsCount * sizeof(glm::vec2), renderer.texturePositions, GL_STREAM_DRAW);
 
 		//Instance render the textures
 		{
-			const int size = spriteTexturesCount;
+			const int size = renderer.spriteTexturesCount;
 			int pos = 0;
-			unsigned int id = spriteTextures[0].id;
+			unsigned int id = renderer.spriteTextures[0].id;
 
-			spriteTextures[0].bind();
+			renderer.spriteTextures[0].bind();
 
 			for (int i = 1; i < size; i++)
 			{
-				if (spriteTextures[i].id != id)
+				if (renderer.spriteTextures[i].id != id)
 				{
 					glDrawArrays(GL_TRIANGLES, pos * 6, 6 * (i - pos));
 
 					pos = i;
-					id = spriteTextures[i].id;
+					id = renderer.spriteTextures[i].id;
 
-					spriteTextures[i].bind();
+					renderer.spriteTextures[i].bind();
 				}
 
 			}
@@ -584,25 +553,31 @@ namespace gl2d
 			glBindVertexArray(0);
 		}
 
-		spritePositionsCount = 0;
-		spriteColorsCount = 0;
-		spriteTexturesCount = 0;
-		texturePositionsCount = 0;
+		renderer.spritePositionsCount = 0;
+		renderer.spriteColorsCount = 0;
+		renderer.spriteTexturesCount = 0;
+		renderer.texturePositionsCount = 0;
+	}
+
+	void gl2d::Renderer2D::flush()
+	{
+		glBindFramebuffer(GL_FRAMEBUFFER, defaultFBO);
+		internalFlush(*this);
 	}
 
 	void Renderer2D::flushFBO(FrameBuffer frameBuffer)
 	{
 		if (frameBuffer.fbo == 0) 
 		{
-			errorFunc("Framebuffer not initialized");
+			errorFunc("Framebuffer not initialized", userDefinedData);
 		}
 
 		glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer.fbo);
-		glBindTexture(GL_TEXTURE_2D, 0);
+		glBindTexture(GL_TEXTURE_2D, 0); //todo investigate and remove
 
-		flush();
+		internalFlush(*this);
 
-		glBindFramebuffer(GL_FRAMEBUFFER, 0);
+		glBindFramebuffer(GL_FRAMEBUFFER, defaultFBO);
 	}
 
 	void enableNecessaryGLFeatures()
@@ -629,7 +604,7 @@ namespace gl2d
 
 		if (textureCopy.id == 0)
 		{
-			errorFunc("Invalid texture");
+			errorFunc("Invalid texture", userDefinedData);
 			textureCopy = white1pxSquareTexture;
 		}
 
@@ -860,8 +835,8 @@ namespace gl2d
 	{
 		glm::vec4 colorData[4] = { color, color, color, color };
 
-		int w;
-		int h;
+		int w = 0;
+		int h = 0;
 		glBindTexture(GL_TEXTURE_2D, texture.id);
 		glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &w);
 		glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &h);
@@ -1035,13 +1010,15 @@ namespace gl2d
 
 	}
 
-	void Renderer2D::create()
+	void Renderer2D::create(GLuint fbo)
 	{
 		if (!hasInitialized)
 		{
-			errorFunc("Library not initialized. Have you forgotten to call gl2d::init() ?");
+			errorFunc("Library not initialized. Have you forgotten to call gl2d::init() ?", userDefinedData);
 		}
 
+		defaultFBO = fbo;
+
 		spritePositionsCount = 0;
 		spriteColorsCount = 0;
 		texturePositionsCount = 0;
@@ -1071,13 +1048,11 @@ namespace gl2d
 
 	void Renderer2D::clear()
 	{
-		//white1pxSquareTexture.cleanup(); //todo move
 		glDeleteVertexArrays(1, &vao);
 		glDeleteBuffers(Renderer2DBufferType::bufferSize, buffers);
-
 	}
 
-	void Renderer2D::pushShader(internal::ShaderProgram s)
+	void Renderer2D::pushShader(ShaderProgram s)
 	{
 		shaderPushPop.push_back(currentShader);
 		currentShader = s;
@@ -1087,7 +1062,7 @@ namespace gl2d
 	{
 		if (shaderPushPop.empty())
 		{
-			errorFunc("Pop on an empty stack on popShader");
+			errorFunc("Pop on an empty stack on popShader", userDefinedData);
 		}
 		else
 		{
@@ -1106,7 +1081,7 @@ namespace gl2d
 	{
 		if (cameraPushPop.empty())
 		{
-			errorFunc("Pop on an empty stack on popCamera");
+			errorFunc("Pop on an empty stack on popCamera", userDefinedData);
 		}
 		else
 		{
@@ -1186,7 +1161,7 @@ namespace gl2d
 	{
 		if (font.texture.id == 0)
 		{
-			errorFunc("Missing font");
+			errorFunc("Missing font", userDefinedData);
 			return {};
 		}
 
@@ -1268,7 +1243,7 @@ namespace gl2d
 	{
 		if (font.texture.id == 0)
 		{
-			errorFunc("Missing font");
+			errorFunc("Missing font", userDefinedData);
 			return;
 		}
 
@@ -1410,20 +1385,22 @@ namespace gl2d
 
 	void Renderer2D::clearScreen(const Color4f color)
 	{
+		glBindFramebuffer(GL_FRAMEBUFFER, defaultFBO);
+	
+		#if GL2D_USE_OPENGL_130
+			GLfloat oldColor[4];
+			glGetFloatv(GL_COLOR_CLEAR_VALUE, oldColor);
 
-	#if GL2D_USE_OPENGL_130
-		GLfloat oldColor[4];
-		glGetFloatv(GL_COLOR_CLEAR_VALUE, oldColor);
+			glClearColor(color.r, color.g, color.b, color.a);
+			glClear(GL_COLOR_BUFFER_BIT);
+			glClearColor(oldColor[0], oldColor[1], oldColor[2], oldColor[3]);
+		#else
+			glClearBufferfv(GL_COLOR, 0, &color[0]);
+		#endif
 
-		glClearColor(color.r, color.g, color.b, color.a);
-		glClear(GL_COLOR_BUFFER_BIT);
-		glClearColor(oldColor[0], oldColor[1], oldColor[2], oldColor[3]);
-	#else
-		glClearBufferfv(GL_COLOR, 0, &color[0]);
-	#endif
 	}
 
-	void Renderer2D::setShaderProgram(const internal::ShaderProgram shader)
+	void Renderer2D::setShaderProgram(const ShaderProgram shader)
 	{
 		currentShader = shader;
 	}
@@ -1684,7 +1661,7 @@ namespace gl2d
 			char c[300] = { 0 };
 			strcat(c, "error openning: ");
 			strcat(c + strlen(c), fileName);
-			errorFunc(c);
+			errorFunc(c, userDefinedData);
 			return;
 		}
 
@@ -1712,7 +1689,7 @@ namespace gl2d
 			char c[300] = { 0 };
 			strcat(c, "error openning: ");
 			strcat(c + strlen(c), fileName);
-			errorFunc(c);
+			errorFunc(c, userDefinedData);
 			return;
 		}
 
@@ -1961,566 +1938,7 @@ namespace gl2d
 		}
 	}
 
-	void ParticleSystem::initParticleSystem(int size)
-	{
-		cleanup();
-
-
-		//simdize size
-		size += 4 - (size % 4);
-		this->size = size;
-
-
-#pragma region allocations
-
-
-		int size32Aligned = size + (4 - (size % 4));
-
-		posX = new float[size32Aligned];
-		posY = new float[size32Aligned];
-		directionX = new float[size32Aligned];
-		directionY = new float[size32Aligned];
-		rotation = new float[size32Aligned];
-		sizeXY = new float[size32Aligned];
-		dragX = new float[size32Aligned];
-		dragY = new float[size32Aligned];
-		duration = new float[size32Aligned];
-		durationTotal = new float[size32Aligned];
-		color = new glm::vec4[size];
-		rotationSpeed = new float[size32Aligned];
-		rotationDrag = new float[size32Aligned];
-		deathRattle = new ParticleSettings * [size32Aligned];
-		thisParticleSettings = new ParticleSettings * [size32Aligned];
-		emitParticle = new ParticleSettings * [size32Aligned];
-		tranzitionType = new char[size32Aligned];
-		textures = new gl2d::Texture * [size32Aligned];
-		emitTime = new float[size32Aligned];
-
-#pragma endregion
-
-		for (int i = 0; i < size; i++)
-		{
-			duration[i] = 0;
-			sizeXY[i] = 0;
-			deathRattle[i] = 0;
-			textures[i] = nullptr;
-			thisParticleSettings[i] = nullptr;
-			emitParticle[i] = nullptr;
-		}
-
-		fb.create(100, 100);
-
-	}
-
-#if GL2D_SIMD != 0
-
-#if defined(_MSC_VER)
-	/* Microsoft C/C++-compatible compiler */
-#include <intrin.h>
-#elif defined(__GNUC__) && (defined(__x86_64__) || defined(__i386__))
-	/* GCC-compatible compiler, targeting x86/x86-64 */
-#include <x86intrin.h>
-#elif defined(__GNUC__) && defined(__ARM_NEON__)
-	/* GCC-compatible compiler, targeting ARM with NEON */
-#include <arm_neon.h>
-#elif defined(__GNUC__) && defined(__IWMMXT__)
-	/* GCC-compatible compiler, targeting ARM with WMMX */
-#include <mmintrin.h>
-#elif (defined(__GNUC__) || defined(__xlC__)) && (defined(__VEC__) || defined(__ALTIVEC__))
-	/* XLC or GCC-compatible compiler, targeting PowerPC with VMX/VSX */
-#include <altivec.h>
-#elif defined(__GNUC__) && defined(__SPE__)
-	/* GCC-compatible compiler, targeting PowerPC with SPE */
-#include <spe.h>
-#elif
-#undef GL2D_SIMD
-#define GL2D_SIMD 0
-#endif
-
-#endif
-
-	void ParticleSystem::applyMovement(float deltaTime)
-	{
-
-#pragma region newParticles
-
-		int recreatedParticlesThisFrame = 0;
-
-		//if(createdPosition < size && createTimeCountdown <= 0 && emitParticles)
-		//{
-		//	createTimeCountdown = rand(ps.emisSpeed);
-		//
-		//	for(int i=createdPosition; i<createdPosition+ maxCreatePerEvent; i++)
-		//	{
-		//		//reset particle
-		//		posX[i] = position.x;
-		//		posY[i] = position.y;
-		//		directionX[i] = rand(ps.directionX);
-		//		directionY[i] = rand(ps.directionY);
-		//		rotation[i] = rand(ps.rotation);;
-		//		sizeXY[i] = rand(ps.createApearence.size);
-		//		dragX[i] = rand(ps.dragX);
-		//		dragY[i] = rand(ps.dragY);
-		//		color[i].x = rand({ ps.createApearence.color1.x, ps.createApearence.color2.x });
-		//		color[i].y = rand({ ps.createApearence.color1.y, ps.createApearence.color2.y });
-		//		color[i].z = rand({ ps.createApearence.color1.z, ps.createApearence.color2.z });
-		//		color[i].w = rand({ ps.createApearence.color1.w, ps.createApearence.color2.w });
-		//		rotationSpeed[i] = rand(ps.rotationSpeed);
-		//		rotationDrag[i] = rand(ps.rotationDrag);
-		//		deathRattle[i] = 1;
-		//
-		//		duration[i] = rand(ps.particleLifeTime);
-		//		durationTotal[i] = duration[i];
-		//
-		//		recreatedParticlesThisFrame++;
-		//	}
-		//	
-		//	createdPosition++;
-		//
-		//
-		//}
-
-
-#pragma endregion
-
-
-		for (int i = 0; i < size; i++)
-		{
-
-			if (duration[i] > 0)
-				duration[i] -= deltaTime;
-
-			if (emitTime[i] > 0 && emitParticle[i])
-				emitTime[i] -= deltaTime;
-
-			if (duration[i] <= 0)
-			{
-				if (deathRattle[i] != nullptr && deathRattle[i]->onCreateCount)
-				{
-
-					this->emitParticleWave(deathRattle[i], { posX[i], posY[i] });
-
-				}
-
-				deathRattle[i] = nullptr;
-				duration[i] = 0;
-				sizeXY[i] = 0;
-				emitParticle[i] = nullptr;
-
-			}
-			else if (emitTime[i] <= 0 && emitParticle[i])
-			{
-				emitTime[i] = rand(thisParticleSettings[i]->subemitParticleTime);
-
-				//emit particle
-				this->emitParticleWave(emitParticle[i], { posX[i], posY[i] });
-
-			}
-
-		}
-
-		__m128 _deltaTime = _mm_set1_ps(deltaTime);
-
-#pragma region applyDrag
-
-#if GL2D_SIMD == 0
-		for (int i = 0; i < size; i++)
-		{
-			//if (duration[i] > 0)
-			directionX[i] += deltaTime * dragX[i];
-		}
-
-		for (int i = 0; i < size; i++)
-		{
-			//if (duration[i] > 0)
-			directionY[i] += deltaTime * dragY[i];
-
-		}
-
-		for (int i = 0; i < size; i++)
-		{
-
-			//if (duration[i] > 0)
-			rotationSpeed[i] += deltaTime * rotationDrag[i];
-		}
-#else
-
-		for (int i = 0; i < size; i += 4)
-		{
-			//directionX[i] += deltaTime * dragX[i];
-
-			__m128* dir = (__m128*) & (directionX[i]);
-			__m128* drag = (__m128*) & (dragX[i]);
-
-			*dir = _mm_fmadd_ps(_deltaTime, *drag, *dir);
-		}
-
-		for (int i = 0; i < size; i += 4)
-		{
-			//directionY[i] += deltaTime * dragY[i];
-
-			__m128* dir = (__m128*) & (directionY[i]);
-			__m128* drag = (__m128*) & (dragY[i]);
-
-			*dir = _mm_fmadd_ps(_deltaTime, *drag, *dir);
-		}
-
-		for (int i = 0; i < size; i+= 4)
-		{
-			//rotationSpeed[i] += deltaTime * rotationDrag[i];
-
-			__m128* dir = (__m128*) & (rotationSpeed[i]);
-			__m128* drag = (__m128*) & (rotationDrag[i]);
-
-			*dir = _mm_fmadd_ps(_deltaTime, *drag, *dir);
-		}
-#endif
-
-
-
-#pragma endregion
-
-
-#pragma region apply movement
-
-
-#if GL2D_SIMD == 0
-		for (int i = 0; i < size; i++)
-		{
-			//if (duration[i] > 0)
-			posX[i] += deltaTime * directionX[i];
-
-		}
-
-
-		for (int i = 0; i < size; i++)
-		{
-			//if (duration[i] > 0)
-			posY[i] += deltaTime * directionY[i];
-
-		}
-
-		for (int i = 0; i < size; i++)
-		{
-			//if (duration[i] > 0)
-			rotation[i] += deltaTime * rotationSpeed[i];
-
-		}
-#else 
-		for (int i = 0; i < size; i += 4)
-		{
-			//posX[i] += deltaTime * directionX[i];
-			__m128* dir = (__m128*) & (posX[i]);
-			__m128* drag = (__m128*) & (directionX[i]);
-
-			*dir = _mm_fmadd_ps(_deltaTime, *drag, *dir);
-		}
-
-
-		for (int i = 0; i < size; i++)
-		{
-			//posY[i] += deltaTime * directionY[i];
-			__m128* dir = (__m128*) & (posY[i]);
-			__m128* drag = (__m128*) & (directionY[i]);
-
-			*dir = _mm_fmadd_ps(_deltaTime, *drag, *dir);
-		}
-
-		for (int i = 0; i < size; i++)
-		{
-			//rotation[i] += deltaTime * rotationSpeed[i];
-			__m128* dir = (__m128*) & (rotation[i]);
-			__m128* drag = (__m128*) & (rotationSpeed[i]);
-
-			*dir = _mm_fmadd_ps(_deltaTime, *drag, *dir);
-		}
-
-#endif
-
-#pragma endregion
-
-
-
-	}
-
-	void ParticleSystem::cleanup()
-	{
-		delete[] posX;
-		delete[] posY;
-
-		delete[] directionX;
-		delete[] directionY;
-		delete[] rotation;
-
-		delete[] sizeXY;
-
-		delete[] dragY;
-		delete[] dragX;
-		delete[] duration;
-		delete[] durationTotal;
-		delete[] color;
-		delete[] rotationSpeed;
-		delete[] rotationDrag;
-		delete[] emitTime;
-		delete[] tranzitionType;
-		delete[] deathRattle;
-		delete[] thisParticleSettings;
-		delete[] emitParticle;
-		delete[] textures;
-
-
-		posX = 0;
-		posY = 0;
-		directionX = 0;
-		directionY = 0;
-		rotation = 0;
-		sizeXY = 0;
-		dragX = 0;
-		dragY = 0;
-		duration = 0;
-		durationTotal = 0;
-		color = 0;
-		rotationSpeed = 0;
-		rotationDrag = 0;
-		emitTime = 0;
-		tranzitionType = 0;
-		deathRattle = 0;
-		thisParticleSettings = 0;
-		emitParticle = 0;
-		textures = 0;
-
-		size = 0;
-
-
-		fb.cleanup();
-	}
-
-	void ParticleSystem::emitParticleWave(ParticleSettings* ps, glm::vec2 pos)
-	{
-		int recreatedParticlesThisFrame = 0;
-
-		for (int i = 0; i < size; i++)
-		{
-
-			if (recreatedParticlesThisFrame < ps->onCreateCount &&
-				sizeXY[i] == 0)
-			{
-
-				duration[i] = rand(ps->particleLifeTime);
-				durationTotal[i] = duration[i];
-
-				//reset particle
-				posX[i] = pos.x + rand(ps->positionX);
-				posY[i] = pos.y + rand(ps->positionY);
-				directionX[i] = rand(ps->directionX);
-				directionY[i] = rand(ps->directionY);
-				rotation[i] = rand(ps->rotation);;
-				sizeXY[i] = rand(ps->createApearence.size);
-				dragX[i] = rand(ps->dragX);
-				dragY[i] = rand(ps->dragY);
-				color[i].x = rand({ ps->createApearence.color1.x, ps->createApearence.color2.x });
-				color[i].y = rand({ ps->createApearence.color1.y, ps->createApearence.color2.y });
-				color[i].z = rand({ ps->createApearence.color1.z, ps->createApearence.color2.z });
-				color[i].w = rand({ ps->createApearence.color1.w, ps->createApearence.color2.w });
-				rotationSpeed[i] = rand(ps->rotationSpeed);
-				rotationDrag[i] = rand(ps->rotationDrag);
-				textures[i] = ps->texturePtr;
-				deathRattle[i] = ps->deathRattle;
-				tranzitionType[i] = ps->tranzitionType;
-				thisParticleSettings[i] = ps;
-				emitParticle[i] = ps->subemitParticle;
-				emitTime[i] = rand(thisParticleSettings[i]->subemitParticleTime);
-
-				recreatedParticlesThisFrame++;
-			}
-
-
-
-		}
-
-
-	}
-
-	float interpolate(float a, float b, float perc)
-	{
-		return a * perc + b * (1 - perc);
-
-	}
-
-	void ParticleSystem::draw(Renderer2D& r)
-	{
-
-		unsigned int w = r.windowW;
-		unsigned int h = r.windowH;
-
-		auto cam = r.currentCamera;
-
-		if (postProcessing)
-		{
-
-			r.flush();
-
-			if (fb.texture.GetSize() != glm::ivec2{ w / pixelateFactor,h / pixelateFactor })
-			{
-				fb.resize(w / pixelateFactor, h / pixelateFactor);
-
-			}
-
-			r.updateWindowMetrics(w / pixelateFactor, h / pixelateFactor);
-
-		}
-
-
-		for (int i = 0; i < size; i++)
-		{
-			if (sizeXY[i] == 0) { continue; }
-
-			float lifePerc = duration[i] / durationTotal[i]; //close to 0 when gone, 1 when full
-
-			switch (this->tranzitionType[i])
-			{
-			case gl2d::TRANZITION_TYPES::none:
-				lifePerc = 1;
-				break;
-			case gl2d::TRANZITION_TYPES::linear:
-
-				break;
-			case gl2d::TRANZITION_TYPES::curbe:
-				lifePerc *= lifePerc;
-				break;
-			case gl2d::TRANZITION_TYPES::abruptCurbe:
-				lifePerc *= lifePerc * lifePerc;
-				break;
-			case gl2d::TRANZITION_TYPES::wave:
-				lifePerc = (std::cos(lifePerc * 5 * 3.141592) * lifePerc + lifePerc) / 2.f;
-				break;
-			case gl2d::TRANZITION_TYPES::wave2:
-				lifePerc = std::cos(lifePerc * 5 * 3.141592) * std::sqrt(lifePerc) * 0.9f + 0.1f;
-				break;
-			case gl2d::TRANZITION_TYPES::delay:
-				lifePerc = (std::cos(lifePerc * 3.141592 * 2) * std::sin(lifePerc * lifePerc)) / 2.f;
-				break;
-			case gl2d::TRANZITION_TYPES::delay2:
-				lifePerc = (std::atan(2 * lifePerc * lifePerc * lifePerc * 3.141592)) / 2.f;
-				break;
-			default:
-				break;
-			}
-
-			glm::vec4 pos = {};
-			glm::vec4 c;
-
-			if (thisParticleSettings[i])
-			{
-				pos.x = posX[i];
-				pos.y = posY[i];
-				pos.z = interpolate(sizeXY[i], thisParticleSettings[i]->createEndApearence.size.x, lifePerc);
-				pos.w = pos.z;
-
-				c.x = interpolate(color[i].x, thisParticleSettings[i]->createEndApearence.color1.x, lifePerc);
-				c.y = interpolate(color[i].y, thisParticleSettings[i]->createEndApearence.color1.y, lifePerc);
-				c.z = interpolate(color[i].z, thisParticleSettings[i]->createEndApearence.color1.z, lifePerc);
-				c.w = interpolate(color[i].w, thisParticleSettings[i]->createEndApearence.color1.w, lifePerc);
-			}
-			else
-			{
-				pos.x = posX[i];
-				pos.y = posY[i];
-				pos.z = sizeXY[i];
-				pos.w = pos.z;
-
-				c.x = color[i].x;
-				c.y = color[i].y;
-				c.z = color[i].z;
-				c.w = color[i].w;
-			}
-
-			glm::vec4 p;
-
-			if (postProcessing)
-			{
-				r.currentCamera = cam;
-
-				p = pos / pixelateFactor;
-
-				//p.x += 200;
-				//p.y += 200;
-
-				p.x -= r.currentCamera.position.x / pixelateFactor;
-				p.y -= r.currentCamera.position.y / pixelateFactor;
-				//
-
-				r.currentCamera.position = {};
-				//r.currentCamera.position.x += w / (2.f );
-				//r.currentCamera.position.y += h / (2.f );
-				//
-				//r.currentCamera.position /= pixelateFactor/2.f;
-				//
-				//r.currentCamera.position.x -= w / (2.f);
-				//r.currentCamera.position.y -= h / (2.f);
-
-
-				//r.currentCamera.position += glm::vec2{w / (pixelateFactor * 2.f), h / (pixelateFactor*2.f)};
-				//r.currentCamera.position *= pixelateFactor;
-				//c.w = sqrt(c.w);
-				// c.w = 1;
-			}
-			else
-			{
-				p = pos;
-			}
-
-
-			if (textures[i] != nullptr)
-			{
-				r.renderRectangle(p, c, { 0,0 }, rotation[i], *textures[i]);
-			}
-			else
-			{
-				r.renderRectangle(p, c, { 0,0 }, rotation[i]);
-			}
-
-
-		}
-
-
-		if (postProcessing)
-		{
-			fb.clear();
-			r.flushFBO(fb);
-
-
-
-			r.updateWindowMetrics(w, h);
-			r.currentCamera.setDefault();
-
-
-			auto s = r.currentShader;
-
-			r.renderRectangle({ 0,0,w,h }, {}, 0, fb.texture);
-
-			r.setShaderProgram(defaultParticleShader);
-			r.flush();
-
-			r.setShaderProgram(s);
-
-		}
-
-		r.currentCamera = cam;
-
-	}
-
-	float ParticleSystem::rand(glm::vec2 v)
-	{
-		if (v.x > v.y)
-		{
-			std::swap(v.x, v.y);
-		}
-
-		std::uniform_real_distribution<float> dist(v.x, v.y);
-
-		return dist(random);
-	}
+	
 
 
 }

+ 643 - 0
Pika/thirdparty/gl2d/src/gl2dParticleSystem.cpp

@@ -0,0 +1,643 @@
+#include <gl2d/gl2dParticleSystem.h>
+
+namespace gl2d
+{
+
+	static ShaderProgram defaultParticleShader = {};
+
+	static const char *defaultParticleVertexShader =
+		GL2D_OPNEGL_SHADER_VERSION "\n"
+		GL2D_OPNEGL_SHADER_PRECISION "\n"
+		"in vec2 quad_positions;\n"
+		"in vec4 quad_colors;\n"
+		"in vec2 texturePositions;\n"
+		"out vec4 v_color;\n"
+		"out vec2 v_texture;\n"
+		"void main()\n"
+		"{\n"
+		"	gl_Position = vec4(quad_positions, 0, 1);\n"
+		"	v_color = quad_colors;\n"
+		"	v_texture = texturePositions;\n"
+		"}\n";
+
+	static const char *defaultParcileFragmentShader =
+		GL2D_OPNEGL_SHADER_VERSION "\n"
+		GL2D_OPNEGL_SHADER_PRECISION "\n"
+		R"(out vec4 color;
+			in vec4 v_color;
+			in vec2 v_texture;
+			uniform sampler2D u_sampler;
+			
+			vec3 rgbTohsv(vec3 c)
+			{
+				vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
+				vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));
+				vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));
+			
+				float d = q.x - min(q.w, q.y);
+				float e = 1.0e-10;
+				return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
+			}
+			
+			vec3 hsvTorgb(vec3 c)
+			{
+				vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
+				vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
+				return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
+			}
+			
+			const float cFilter = 5.f;
+			
+			void main()
+			{
+				color = v_color * texture2D(u_sampler, v_texture);
+				
+				if(color.a <0.01)discard;
+				//color.a = 1.f;
+			
+				//color.a = pow(color.a, 0.2); 
+			
+				color.rgb *= cFilter;				//
+				color.rgb = floor(color.rgb);		//remove color quality to get a retro effect
+				color.rgb /= cFilter;				//
+			
+				//color.rgb = rgbTohsv(color.rgb);
+			
+				//color.rgb = hsvTorgb(color.rgb);
+			
+			})";
+
+
+void ParticleSystem::initParticleSystem(int size)
+{
+	cleanup();
+
+
+	//simdize size
+	size += 4 - (size % 4);
+	this->size = size;
+
+
+#pragma region allocations
+
+
+	int size32Aligned = size + (4 - (size % 4));
+
+	posX = new float[size32Aligned];
+	posY = new float[size32Aligned];
+	directionX = new float[size32Aligned];
+	directionY = new float[size32Aligned];
+	rotation = new float[size32Aligned];
+	sizeXY = new float[size32Aligned];
+	dragX = new float[size32Aligned];
+	dragY = new float[size32Aligned];
+	duration = new float[size32Aligned];
+	durationTotal = new float[size32Aligned];
+	color = new glm::vec4[size];
+	rotationSpeed = new float[size32Aligned];
+	rotationDrag = new float[size32Aligned];
+	deathRattle = new ParticleSettings * [size32Aligned];
+	thisParticleSettings = new ParticleSettings * [size32Aligned];
+	emitParticle = new ParticleSettings * [size32Aligned];
+	tranzitionType = new char[size32Aligned];
+	textures = new gl2d::Texture * [size32Aligned];
+	emitTime = new float[size32Aligned];
+
+#pragma endregion
+
+	for (int i = 0; i < size; i++)
+	{
+		duration[i] = 0;
+		sizeXY[i] = 0;
+		deathRattle[i] = 0;
+		textures[i] = nullptr;
+		thisParticleSettings[i] = nullptr;
+		emitParticle[i] = nullptr;
+	}
+
+	fb.create(100, 100);
+
+}
+
+#if GL2D_SIMD != 0
+
+#if defined(_MSC_VER)
+/* Microsoft C/C++-compatible compiler */
+#include <intrin.h>
+#elif defined(__GNUC__) && (defined(__x86_64__) || defined(__i386__))
+/* GCC-compatible compiler, targeting x86/x86-64 */
+#include <x86intrin.h>
+#elif defined(__GNUC__) && defined(__ARM_NEON__)
+/* GCC-compatible compiler, targeting ARM with NEON */
+#include <arm_neon.h>
+#elif defined(__GNUC__) && defined(__IWMMXT__)
+/* GCC-compatible compiler, targeting ARM with WMMX */
+#include <mmintrin.h>
+#elif (defined(__GNUC__) || defined(__xlC__)) && (defined(__VEC__) || defined(__ALTIVEC__))
+/* XLC or GCC-compatible compiler, targeting PowerPC with VMX/VSX */
+#include <altivec.h>
+#elif defined(__GNUC__) && defined(__SPE__)
+/* GCC-compatible compiler, targeting PowerPC with SPE */
+#include <spe.h>
+#elif
+#undef GL2D_SIMD
+#define GL2D_SIMD 0
+#endif
+
+#endif
+
+void ParticleSystem::applyMovement(float deltaTime)
+{
+
+#pragma region newParticles
+
+	int recreatedParticlesThisFrame = 0;
+
+	//if(createdPosition < size && createTimeCountdown <= 0 && emitParticles)
+	//{
+	//	createTimeCountdown = rand(ps.emisSpeed);
+	//
+	//	for(int i=createdPosition; i<createdPosition+ maxCreatePerEvent; i++)
+	//	{
+	//		//reset particle
+	//		posX[i] = position.x;
+	//		posY[i] = position.y;
+	//		directionX[i] = rand(ps.directionX);
+	//		directionY[i] = rand(ps.directionY);
+	//		rotation[i] = rand(ps.rotation);;
+	//		sizeXY[i] = rand(ps.createApearence.size);
+	//		dragX[i] = rand(ps.dragX);
+	//		dragY[i] = rand(ps.dragY);
+	//		color[i].x = rand({ ps.createApearence.color1.x, ps.createApearence.color2.x });
+	//		color[i].y = rand({ ps.createApearence.color1.y, ps.createApearence.color2.y });
+	//		color[i].z = rand({ ps.createApearence.color1.z, ps.createApearence.color2.z });
+	//		color[i].w = rand({ ps.createApearence.color1.w, ps.createApearence.color2.w });
+	//		rotationSpeed[i] = rand(ps.rotationSpeed);
+	//		rotationDrag[i] = rand(ps.rotationDrag);
+	//		deathRattle[i] = 1;
+	//
+	//		duration[i] = rand(ps.particleLifeTime);
+	//		durationTotal[i] = duration[i];
+	//
+	//		recreatedParticlesThisFrame++;
+	//	}
+	//	
+	//	createdPosition++;
+	//
+	//
+	//}
+
+
+#pragma endregion
+
+
+	for (int i = 0; i < size; i++)
+	{
+
+		if (duration[i] > 0)
+			duration[i] -= deltaTime;
+
+		if (emitTime[i] > 0 && emitParticle[i])
+			emitTime[i] -= deltaTime;
+
+		if (duration[i] <= 0)
+		{
+			if (deathRattle[i] != nullptr && deathRattle[i]->onCreateCount)
+			{
+
+				this->emitParticleWave(deathRattle[i], {posX[i], posY[i]});
+
+			}
+
+			deathRattle[i] = nullptr;
+			duration[i] = 0;
+			sizeXY[i] = 0;
+			emitParticle[i] = nullptr;
+
+		}
+		else if (emitTime[i] <= 0 && emitParticle[i])
+		{
+			emitTime[i] = rand(thisParticleSettings[i]->subemitParticleTime);
+
+			//emit particle
+			this->emitParticleWave(emitParticle[i], {posX[i], posY[i]});
+
+		}
+
+	}
+
+	__m128 _deltaTime = _mm_set1_ps(deltaTime);
+
+#pragma region applyDrag
+
+#if GL2D_SIMD == 0
+	for (int i = 0; i < size; i++)
+	{
+		//if (duration[i] > 0)
+		directionX[i] += deltaTime * dragX[i];
+	}
+
+	for (int i = 0; i < size; i++)
+	{
+		//if (duration[i] > 0)
+		directionY[i] += deltaTime * dragY[i];
+
+	}
+
+	for (int i = 0; i < size; i++)
+	{
+
+		//if (duration[i] > 0)
+		rotationSpeed[i] += deltaTime * rotationDrag[i];
+	}
+#else
+
+	for (int i = 0; i < size; i += 4)
+	{
+		//directionX[i] += deltaTime * dragX[i];
+
+		__m128 *dir = (__m128 *) & (directionX[i]);
+		__m128 *drag = (__m128 *) & (dragX[i]);
+
+		*dir = _mm_fmadd_ps(_deltaTime, *drag, *dir);
+	}
+
+	for (int i = 0; i < size; i += 4)
+	{
+		//directionY[i] += deltaTime * dragY[i];
+
+		__m128 *dir = (__m128 *) & (directionY[i]);
+		__m128 *drag = (__m128 *) & (dragY[i]);
+
+		*dir = _mm_fmadd_ps(_deltaTime, *drag, *dir);
+	}
+
+	for (int i = 0; i < size; i += 4)
+	{
+		//rotationSpeed[i] += deltaTime * rotationDrag[i];
+
+		__m128 *dir = (__m128 *) & (rotationSpeed[i]);
+		__m128 *drag = (__m128 *) & (rotationDrag[i]);
+
+		*dir = _mm_fmadd_ps(_deltaTime, *drag, *dir);
+	}
+#endif
+
+
+
+#pragma endregion
+
+
+#pragma region apply movement
+
+
+#if GL2D_SIMD == 0
+	for (int i = 0; i < size; i++)
+	{
+		//if (duration[i] > 0)
+		posX[i] += deltaTime * directionX[i];
+
+	}
+
+
+	for (int i = 0; i < size; i++)
+	{
+		//if (duration[i] > 0)
+		posY[i] += deltaTime * directionY[i];
+
+	}
+
+	for (int i = 0; i < size; i++)
+	{
+		//if (duration[i] > 0)
+		rotation[i] += deltaTime * rotationSpeed[i];
+
+	}
+#else 
+	for (int i = 0; i < size; i += 4)
+	{
+		//posX[i] += deltaTime * directionX[i];
+		__m128 *dir = (__m128 *) & (posX[i]);
+		__m128 *drag = (__m128 *) & (directionX[i]);
+
+		*dir = _mm_fmadd_ps(_deltaTime, *drag, *dir);
+	}
+
+
+	for (int i = 0; i < size; i++)
+	{
+		//posY[i] += deltaTime * directionY[i];
+		__m128 *dir = (__m128 *) & (posY[i]);
+		__m128 *drag = (__m128 *) & (directionY[i]);
+
+		*dir = _mm_fmadd_ps(_deltaTime, *drag, *dir);
+	}
+
+	for (int i = 0; i < size; i++)
+	{
+		//rotation[i] += deltaTime * rotationSpeed[i];
+		__m128 *dir = (__m128 *) & (rotation[i]);
+		__m128 *drag = (__m128 *) & (rotationSpeed[i]);
+
+		*dir = _mm_fmadd_ps(_deltaTime, *drag, *dir);
+	}
+
+#endif
+
+#pragma endregion
+
+
+
+}
+
+void ParticleSystem::cleanup()
+{
+	delete[] posX;
+	delete[] posY;
+
+	delete[] directionX;
+	delete[] directionY;
+	delete[] rotation;
+
+	delete[] sizeXY;
+
+	delete[] dragY;
+	delete[] dragX;
+	delete[] duration;
+	delete[] durationTotal;
+	delete[] color;
+	delete[] rotationSpeed;
+	delete[] rotationDrag;
+	delete[] emitTime;
+	delete[] tranzitionType;
+	delete[] deathRattle;
+	delete[] thisParticleSettings;
+	delete[] emitParticle;
+	delete[] textures;
+
+
+	posX = 0;
+	posY = 0;
+	directionX = 0;
+	directionY = 0;
+	rotation = 0;
+	sizeXY = 0;
+	dragX = 0;
+	dragY = 0;
+	duration = 0;
+	durationTotal = 0;
+	color = 0;
+	rotationSpeed = 0;
+	rotationDrag = 0;
+	emitTime = 0;
+	tranzitionType = 0;
+	deathRattle = 0;
+	thisParticleSettings = 0;
+	emitParticle = 0;
+	textures = 0;
+
+	size = 0;
+
+
+	fb.cleanup();
+}
+
+void ParticleSystem::emitParticleWave(ParticleSettings *ps, glm::vec2 pos)
+{
+	int recreatedParticlesThisFrame = 0;
+
+	for (int i = 0; i < size; i++)
+	{
+
+		if (recreatedParticlesThisFrame < ps->onCreateCount &&
+			sizeXY[i] == 0)
+		{
+
+			duration[i] = rand(ps->particleLifeTime);
+			durationTotal[i] = duration[i];
+
+			//reset particle
+			posX[i] = pos.x + rand(ps->positionX);
+			posY[i] = pos.y + rand(ps->positionY);
+			directionX[i] = rand(ps->directionX);
+			directionY[i] = rand(ps->directionY);
+			rotation[i] = rand(ps->rotation);;
+			sizeXY[i] = rand(ps->createApearence.size);
+			dragX[i] = rand(ps->dragX);
+			dragY[i] = rand(ps->dragY);
+			color[i].x = rand({ps->createApearence.color1.x, ps->createApearence.color2.x});
+			color[i].y = rand({ps->createApearence.color1.y, ps->createApearence.color2.y});
+			color[i].z = rand({ps->createApearence.color1.z, ps->createApearence.color2.z});
+			color[i].w = rand({ps->createApearence.color1.w, ps->createApearence.color2.w});
+			rotationSpeed[i] = rand(ps->rotationSpeed);
+			rotationDrag[i] = rand(ps->rotationDrag);
+			textures[i] = ps->texturePtr;
+			deathRattle[i] = ps->deathRattle;
+			tranzitionType[i] = ps->tranzitionType;
+			thisParticleSettings[i] = ps;
+			emitParticle[i] = ps->subemitParticle;
+			emitTime[i] = rand(thisParticleSettings[i]->subemitParticleTime);
+
+			recreatedParticlesThisFrame++;
+		}
+
+
+
+	}
+
+
+}
+
+float interpolate(float a, float b, float perc)
+{
+	return a * perc + b * (1 - perc);
+
+}
+
+void ParticleSystem::draw(Renderer2D &r)
+{
+
+	unsigned int w = r.windowW;
+	unsigned int h = r.windowH;
+
+	auto cam = r.currentCamera;
+
+	if (postProcessing)
+	{
+
+		r.flush();
+
+		if (fb.texture.GetSize() != glm::ivec2{w / pixelateFactor,h / pixelateFactor})
+		{
+			fb.resize(w / pixelateFactor, h / pixelateFactor);
+
+		}
+
+		r.updateWindowMetrics(w / pixelateFactor, h / pixelateFactor);
+
+	}
+
+
+	for (int i = 0; i < size; i++)
+	{
+		if (sizeXY[i] == 0) { continue; }
+
+		float lifePerc = duration[i] / durationTotal[i]; //close to 0 when gone, 1 when full
+
+		switch (this->tranzitionType[i])
+		{
+		case gl2d::TRANZITION_TYPES::none:
+		lifePerc = 1;
+		break;
+		case gl2d::TRANZITION_TYPES::linear:
+
+		break;
+		case gl2d::TRANZITION_TYPES::curbe:
+		lifePerc *= lifePerc;
+		break;
+		case gl2d::TRANZITION_TYPES::abruptCurbe:
+		lifePerc *= lifePerc * lifePerc;
+		break;
+		case gl2d::TRANZITION_TYPES::wave:
+		lifePerc = (std::cos(lifePerc * 5 * 3.141592) * lifePerc + lifePerc) / 2.f;
+		break;
+		case gl2d::TRANZITION_TYPES::wave2:
+		lifePerc = std::cos(lifePerc * 5 * 3.141592) * std::sqrt(lifePerc) * 0.9f + 0.1f;
+		break;
+		case gl2d::TRANZITION_TYPES::delay:
+		lifePerc = (std::cos(lifePerc * 3.141592 * 2) * std::sin(lifePerc * lifePerc)) / 2.f;
+		break;
+		case gl2d::TRANZITION_TYPES::delay2:
+		lifePerc = (std::atan(2 * lifePerc * lifePerc * lifePerc * 3.141592)) / 2.f;
+		break;
+		default:
+		break;
+		}
+
+		glm::vec4 pos = {};
+		glm::vec4 c;
+
+		if (thisParticleSettings[i])
+		{
+			pos.x = posX[i];
+			pos.y = posY[i];
+			pos.z = interpolate(sizeXY[i], thisParticleSettings[i]->createEndApearence.size.x, lifePerc);
+			pos.w = pos.z;
+
+			c.x = interpolate(color[i].x, thisParticleSettings[i]->createEndApearence.color1.x, lifePerc);
+			c.y = interpolate(color[i].y, thisParticleSettings[i]->createEndApearence.color1.y, lifePerc);
+			c.z = interpolate(color[i].z, thisParticleSettings[i]->createEndApearence.color1.z, lifePerc);
+			c.w = interpolate(color[i].w, thisParticleSettings[i]->createEndApearence.color1.w, lifePerc);
+		}
+		else
+		{
+			pos.x = posX[i];
+			pos.y = posY[i];
+			pos.z = sizeXY[i];
+			pos.w = pos.z;
+
+			c.x = color[i].x;
+			c.y = color[i].y;
+			c.z = color[i].z;
+			c.w = color[i].w;
+		}
+
+		glm::vec4 p;
+
+		if (postProcessing)
+		{
+			r.currentCamera = cam;
+
+			p = pos / pixelateFactor;
+
+			//p.x += 200;
+			//p.y += 200;
+
+			p.x -= r.currentCamera.position.x / pixelateFactor;
+			p.y -= r.currentCamera.position.y / pixelateFactor;
+			//
+
+			r.currentCamera.position = {};
+			//r.currentCamera.position.x += w / (2.f );
+			//r.currentCamera.position.y += h / (2.f );
+			//
+			//r.currentCamera.position /= pixelateFactor/2.f;
+			//
+			//r.currentCamera.position.x -= w / (2.f);
+			//r.currentCamera.position.y -= h / (2.f);
+
+
+			//r.currentCamera.position += glm::vec2{w / (pixelateFactor * 2.f), h / (pixelateFactor*2.f)};
+			//r.currentCamera.position *= pixelateFactor;
+			//c.w = sqrt(c.w);
+			// c.w = 1;
+		}
+		else
+		{
+			p = pos;
+		}
+
+
+		if (textures[i] != nullptr)
+		{
+			r.renderRectangle(p, c, {0,0}, rotation[i], *textures[i]);
+		}
+		else
+		{
+			r.renderRectangle(p, c, {0,0}, rotation[i]);
+		}
+
+
+	}
+
+
+	if (postProcessing)
+	{
+		fb.clear();
+		r.flushFBO(fb);
+
+
+
+		r.updateWindowMetrics(w, h);
+		r.currentCamera.setDefault();
+
+
+		auto s = r.currentShader;
+
+		r.renderRectangle({0,0,w,h}, {}, 0, fb.texture);
+
+		r.setShaderProgram(defaultParticleShader);
+		r.flush();
+
+		r.setShaderProgram(s);
+
+	}
+
+	r.currentCamera = cam;
+
+}
+
+float ParticleSystem::rand(glm::vec2 v)
+{
+	if (v.x > v.y)
+	{
+		std::swap(v.x, v.y);
+	}
+
+	std::uniform_real_distribution<float> dist(v.x, v.y);
+
+	return dist(random);
+}
+
+void initgl2dParticleSystem()
+{
+	defaultParticleShader = createShaderProgram(defaultParticleVertexShader, defaultParcileFragmentShader);
+}
+
+void cleanupgl2dParticleSystem()
+{
+	glDeleteShader(defaultParticleShader.id);
+}
+
+
+};