diff --git a/Game.h b/Game.h index 494bdb0..c384813 100755 --- a/Game.h +++ b/Game.h @@ -8,6 +8,7 @@ namespace ZL { + namespace GameConsts { constexpr float yAcceleration = -0.0003f; diff --git a/OpenGlExtensions.cpp b/OpenGlExtensions.cpp index 87451cf..0ae3156 100755 --- a/OpenGlExtensions.cpp +++ b/OpenGlExtensions.cpp @@ -107,11 +107,16 @@ PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC glGetActiveUniformBlockName = NULL; PFNGLUNIFORMBLOCKBINDINGPROC glUniformBlockBinding = NULL; PFNGLBINDBUFFERBASEPROC glBindBufferBase = NULL; + +PFNGLGENVERTEXARRAYSPROC glGenVertexArrays = NULL; +PFNGLBINDVERTEXARRAYPROC glBindVertexArray = NULL; +PFNGLDELETEVERTEXARRAYSPROC glDeleteVertexArray = NULL; + namespace ZL { bool BindOpenGlFunctions() { - char* extensionList = (char*)glGetString(GL_EXTENSIONS); + //char* extensionList = (char*)glGetString(GL_EXTENSIONS); char* glVersion = (char*)glGetString(GL_VERSION); bool ok = true; @@ -226,7 +231,7 @@ namespace ZL { ok = false; } - if (findString("GL_ARB_framebuffer_object", extensionList)) + //if (findString("GL_ARB_framebuffer_object", extensionList)) { glIsRenderbuffer = (PFNGLISRENDERBUFFERPROC)wglGetProcAddress("glIsRenderbuffer"); glBindRenderbuffer = (PFNGLBINDRENDERBUFFERPROC)wglGetProcAddress("glBindRenderbuffer"); @@ -275,12 +280,12 @@ namespace ZL { } - else + /*else { ok = false; - } + }*/ - if (findString("GL_ARB_uniform_buffer_object", extensionList)) + //if (findString("GL_ARB_uniform_buffer_object", extensionList)) { glGetUniformIndices = (PFNGLGETUNIFORMINDICESPROC)wglGetProcAddress("glGetUniformIndices"); @@ -304,11 +309,23 @@ namespace ZL { ok = false; } } - else + /*else + { + ok = false; + }*/ + + glGenVertexArrays = (PFNGLGENVERTEXARRAYSPROC)wglGetProcAddress("glGenVertexArrays"); + glBindVertexArray = (PFNGLBINDVERTEXARRAYPROC)wglGetProcAddress("glBindVertexArray"); + glDeleteVertexArray = (PFNGLDELETEVERTEXARRAYSPROC)wglGetProcAddress("glBindVertexArray"); + + if (glGenVertexArrays == NULL || + glBindVertexArray == NULL || + glDeleteVertexArray == NULL) { ok = false; } + return ok; } diff --git a/OpenGlExtensions.h b/OpenGlExtensions.h index bcbad23..0005252 100755 --- a/OpenGlExtensions.h +++ b/OpenGlExtensions.h @@ -122,6 +122,11 @@ extern PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC glGetActiveUniformBlockName; extern PFNGLUNIFORMBLOCKBINDINGPROC glUniformBlockBinding; extern PFNGLBINDBUFFERBASEPROC glBindBufferBase; + +extern PFNGLGENVERTEXARRAYSPROC glGenVertexArrays; +extern PFNGLBINDVERTEXARRAYPROC glBindVertexArray; +extern PFNGLDELETEVERTEXARRAYSPROC glDeleteVertexArray; + namespace ZL { bool BindOpenGlFunctions(); diff --git a/Renderer.cpp b/Renderer.cpp index 7e52e69..23726de 100755 --- a/Renderer.cpp +++ b/Renderer.cpp @@ -19,6 +19,22 @@ namespace ZL { return Buffer; } + VAOHolder::VAOHolder() + { + glGenVertexArrays(1, &vao); + } + + VAOHolder::~VAOHolder() + { + glDeleteVertexArray(1, &vao); + //glDeleteBuffers(1, &Buffer); + } + + GLuint VAOHolder::getBuffer() + { + return vao; + } + VertexDataStruct CreateRect2D(Vector2f center, Vector2f halfWidthHeight, float zLevel) { @@ -106,6 +122,13 @@ namespace ZL { { //Check if main thread, check if data is not empty... + if (!vao) + { + vao = std::make_shared(); + } + + glBindVertexArray(vao->getBuffer()); + if (!positionVBO) { positionVBO = std::make_shared(); @@ -135,14 +158,14 @@ namespace ZL { glEnable(GL_BLEND); glActiveTexture(GL_TEXTURE0); - glEnable(GL_TEXTURE_2D); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glDepthFunc(GL_LEQUAL); + CheckGlError(); + } void Renderer::PushProjectionMatrix(float width, float height, float zNear, float zFar) diff --git a/Renderer.h b/Renderer.h index 3dd3b07..8036342 100755 --- a/Renderer.h +++ b/Renderer.h @@ -1,7 +1,6 @@ #pragma once #include "OpenGlExtensions.h" - #include "Math.h" #include "ShaderManager.h" @@ -25,11 +24,27 @@ namespace ZL { GLuint getBuffer(); }; + class VAOHolder { + GLuint vao; + + public: + VAOHolder(); + + VAOHolder(const VAOHolder& v) = delete; + + VAOHolder& operator=(const VAOHolder& v) = delete; + + ~VAOHolder(); + + GLuint getBuffer(); + }; + struct VertexDataStruct { std::vector PositionData; std::vector TexCoordData; + std::shared_ptr vao; std::shared_ptr positionVBO; std::shared_ptr texCoordVBO; diff --git a/ShaderManager.h b/ShaderManager.h index bb88b32..dd84eed 100755 --- a/ShaderManager.h +++ b/ShaderManager.h @@ -1,7 +1,5 @@ #pragma once - #include "OpenGlExtensions.h" - #include "Utils.h" namespace ZL { diff --git a/TextureManager.cpp b/TextureManager.cpp index 2ec7592..df3fd6e 100755 --- a/TextureManager.cpp +++ b/TextureManager.cpp @@ -18,11 +18,17 @@ namespace ZL glBindTexture(GL_TEXTURE_2D, texID); + CheckGlError(); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + CheckGlError(); + //This should be only for Windows - glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE); + //glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE); + + CheckGlError(); if (texData.bitSize == TextureDataStruct::BS_24BIT) { @@ -33,6 +39,8 @@ namespace ZL glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, static_cast(texData.width), static_cast(texData.height), 0, GL_RGBA, GL_UNSIGNED_BYTE, &texData.data[0]); } + CheckGlError(); + } Texture::~Texture() diff --git a/TextureManager.h b/TextureManager.h index 68519d0..19c4644 100755 --- a/TextureManager.h +++ b/TextureManager.h @@ -1,7 +1,6 @@ #pragma once #include "OpenGlExtensions.h" - #include "Utils.h" namespace ZL diff --git a/ZeptoLabTest1.vcxproj b/ZeptoLabTest1.vcxproj index 2f6d781..a546666 100755 --- a/ZeptoLabTest1.vcxproj +++ b/ZeptoLabTest1.vcxproj @@ -29,26 +29,26 @@ Application true - v142 + v143 Unicode Application false - v142 + v143 true Unicode Application true - v142 + v143 Unicode Application false - v142 + v143 true Unicode @@ -116,11 +116,15 @@ true _DEBUG;_CONSOLE;%(PreprocessorDefinitions) true + C:\Work\SDL2-2.28.3\include - Windows + Console true - opengl32.lib;glu32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + SDL2.lib;SDL2main.lib;opengl32.lib;glu32.lib;shell32.lib;opengl32.lib;glu32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;$(CoreLibraryDependencies);%(AdditionalDependencies) + C:\Work\SDL2-2.28.3\lib\x64 + + diff --git a/ZeptoLabTestBin/bird.bmp32 b/ZeptoLabTestBin/bird.bmp32 index 1f99674..6e2e132 100755 Binary files a/ZeptoLabTestBin/bird.bmp32 and b/ZeptoLabTestBin/bird.bmp32 differ diff --git a/bird.bmp32 b/bird.bmp32 index 1f99674..6e2e132 100755 Binary files a/bird.bmp32 and b/bird.bmp32 differ diff --git a/default.fragment b/default.fragment index 40c4643..f47edba 100755 --- a/default.fragment +++ b/default.fragment @@ -1,4 +1,3 @@ -precision mediump float; uniform sampler2D Texture; varying vec2 texCoord; diff --git a/main.cpp b/main.cpp index c621301..b617f17 100755 --- a/main.cpp +++ b/main.cpp @@ -5,7 +5,9 @@ #include "Physics.h" #include -#include +//#include +#include "SDL.h" +//#include "SDL_image.h" #include #include @@ -16,18 +18,14 @@ namespace ZL { - HGLRC hRC; //Render context - HWND Hwnd; //Main window handle - HDC hDC; //Device context + static SDL_Window* window = NULL; + static SDL_GLContext gl_context; Renderer renderer; GameState gs; - //There might be anything - const wchar_t CONST_WINDOW_CLASS_NAME[] = L"ZeptoLabClass"; - const size_t CONST_TIMER_INTERVAL = 10; const size_t CONST_MAX_TIME_INTERVAL = 1000; @@ -129,7 +127,6 @@ namespace ZL glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); - CheckGlError(); glViewport(0, 0, Env::width, Env::height); @@ -138,6 +135,7 @@ namespace ZL renderer.RenderUniform1i(textureUniformName, 0); renderer.EnableVertexAttribArray(vPositionName); + renderer.EnableVertexAttribArray(vTexCoordName); renderer.PushProjectionMatrix(static_cast(Env::width), static_cast(Env::height)); @@ -157,7 +155,8 @@ namespace ZL renderer.shaderManager.PopShader(); - SwapBuffers(hDC); + CheckGlError(); + } @@ -167,11 +166,11 @@ namespace ZL if (LastTickCount == 0) { - LastTickCount = GetTickCount64(); + LastTickCount = SDL_GetTicks64(); return; } - NewTickCount = GetTickCount64(); + NewTickCount = SDL_GetTicks64(); if (NewTickCount - LastTickCount > CONST_TIMER_INTERVAL) { if (NewTickCount - LastTickCount > CONST_MAX_TIME_INTERVAL) @@ -188,183 +187,12 @@ namespace ZL } - - LRESULT WINAPI WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) - { - static PAINTSTRUCT ps; - - switch (uMsg) - { - case WM_CLOSE: - PostQuitMessage(0); - ExitGameLoop = true; - break; - case WM_PAINT: - - DrawScene(); - BeginPaint(hWnd, &ps); - EndPaint(hWnd, &ps); - - ProcessTickCount(); - break; - case WM_SIZE: - - PostMessage(hWnd, WM_PAINT, 0, 0); - break; - case WM_LBUTTONDOWN: - case WM_RBUTTONDOWN: - - if (gs.isGameOver) - { - gs.RestartGame(); - } - else - { - gs.BirdJump(); - } - break; - } - - return DefWindowProc(hWnd, uMsg, wParam, lParam); - } + void setup() { - bool CreateOpenGLWindow(const wchar_t* title, int x, int y, int width, int height, HWND& hWnd, HDC& hDC, HGLRC& hRC) - { - int pf; - WNDCLASS wc; - PIXELFORMATDESCRIPTOR pfd; - static HINSTANCE hInstance = 0; + ZL::BindOpenGlFunctions(); - if (!hInstance) - { - hInstance = GetModuleHandle(NULL); - wc.style = CS_OWNDC; - wc.lpfnWndProc = (WNDPROC)WindowProc; - wc.cbClsExtra = 0; - wc.cbWndExtra = 0; - wc.hInstance = hInstance; - wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); - wc.hCursor = LoadCursor(NULL, IDC_ARROW); - wc.hbrBackground = NULL; - wc.lpszMenuName = NULL; - wc.lpszClassName = CONST_WINDOW_CLASS_NAME; - - if (!RegisterClass(&wc)) - { - return NULL; - } - } - - RECT r; - r.left = x; - r.right = x + width; - r.top = y; - r.bottom = y + height; - - DWORD windowStyle = WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN; - - AdjustWindowRect(&r, windowStyle, false); - - Env::windowHeaderHeight = abs(r.top); - - hWnd = CreateWindow(CONST_WINDOW_CLASS_NAME, title, windowStyle, 0, 0, r.right - r.left, r.bottom - r.top, NULL, NULL, hInstance, NULL); - - if (hWnd == NULL) - { - return false; - } - - hDC = GetDC(hWnd); - - memset(&pfd, 0, sizeof(pfd)); - pfd.nSize = sizeof(pfd); - pfd.nVersion = 1; - pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER; - pfd.iPixelType = PFD_TYPE_RGBA; - pfd.cColorBits = 32; - - pf = ChoosePixelFormat(hDC, &pfd); - if (pf == 0) - { - return false; - } - - if (SetPixelFormat(hDC, pf, &pfd) == FALSE) - { - return false; - } - - hRC = wglCreateContext(hDC); - wglMakeCurrent(hDC, hRC); - - return true; - } - - - void DestroyEngine() - { - - wglMakeCurrent(NULL, NULL); - ReleaseDC(Hwnd, hDC); - wglDeleteContext(hRC); - DestroyWindow(Hwnd); - - } - - void MainLoop() - { - - MSG msg; - - ShowWindow(Hwnd, SW_SHOW); - UpdateWindow(Hwnd); - - NewTickCount = GetTickCount64(); - LastTickCount = NewTickCount; - - while (!ExitGameLoop) - { - while (PeekMessage(&msg, Hwnd, 0, 0, PM_NOREMOVE)) - { - if (GetMessage(&msg, Hwnd, 0, 0)) - { - TranslateMessage(&msg); - DispatchMessage(&msg); - } - else - { - ExitGameLoop = true; - } - } - DrawScene(); - - ProcessTickCount(); - } - } - -}; - -int CALLBACK WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPSTR lpCmdLine, _In_ int nCmdShow) -{ - using namespace ZL; - - try { - - srand((unsigned)time(NULL)); - - constexpr int CONST_WIDTH = 1280; - constexpr int CONST_HEIGHT = 720; - - Env::width = CONST_WIDTH; - Env::height = CONST_HEIGHT; - - if (!CreateOpenGLWindow(L"ZeptoLabTest", 0, 0, Env::width, Env::height, Hwnd, hDC, hRC)) - { - throw std::exception("Failed to create OpenGL Window!"); - } - - BindOpenGlFunctions(); + CheckGlError(); //Load shaders: renderer.shaderManager.AddShaderFromFiles("default", "./default.vertex", "./default.fragment"); @@ -376,7 +204,7 @@ int CALLBACK WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, GameObjects::gameOverTexturePtr = std::make_shared(CreateTextureDataFromBmp32("./game_over.bmp32")); - + CheckGlError(); //Create bird mesh GameObjects::birdMesh = CreateRect2D({ 0.f, 0.f }, { GameConsts::birdScale * GameObjects::birdTexturePtr->getWidth(), GameConsts::birdScale * GameObjects::birdTexturePtr->getHeight() }, 0); @@ -393,7 +221,7 @@ int CALLBACK WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, GameObjects::backgroundMesh = CreateRectHorizontalSections2D({ GameObjects::backgroundTexturePtr->getWidth() * backgroundTextureScale * (0.5f), GameObjects::backgroundTexturePtr->getHeight() * backgroundTextureScale * (0.5f) }, { GameObjects::backgroundTexturePtr->getWidth() * backgroundTextureScale * 0.5f, GameObjects::backgroundTexturePtr->getHeight() * backgroundTextureScale * 0.5f }, 0, 2); - + CheckGlError(); //Create Game Over UI mesh depending on screen size @@ -414,15 +242,100 @@ int CALLBACK WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, renderer.InitOpenGL(); - MainLoop(); + CheckGlError(); + } + + void render() { + + SDL_GL_MakeCurrent(window, gl_context); + + CheckGlError(); + + glClearColor(1.0f, 0.0f, 0.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + DrawScene(); + ProcessTickCount(); + + SDL_GL_SwapWindow(window); - DestroyEngine(); } - catch (const std::exception& e) - { - std::cerr << "Oops: " << e.what() << std::endl; + + void update() { + SDL_Event event; + while (SDL_PollEvent(&event)) { + if (event.type == SDL_QUIT) { + ExitGameLoop = true; + } + if (event.type == SDL_MOUSEBUTTONDOWN) + { + if (gs.isGameOver) + { + gs.RestartGame(); + } + else + { + gs.BirdJump(); + } + } + } + + render(); + + }; + +}; + +int main(int argc, char* argv[]) +{ +#ifdef EMSCRIPTEN + SDL_Renderer* renderer = NULL; + SDL_CreateWindowAndRenderer(512, 512, SDL_WINDOW_OPENGL, &window, &renderer); +#else + if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS) != 0) { + SDL_Log("Failed to initialize SDL: %s", SDL_GetError()); + return 1; } + + constexpr int CONST_WIDTH = 1280; + constexpr int CONST_HEIGHT = 720; + + ZL::Env::width = CONST_WIDTH; + ZL::Env::height = CONST_HEIGHT; + - return 0; -} \ No newline at end of file + // Use a core profile setup. + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); + ZL::window = SDL_CreateWindow("title", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, CONST_WIDTH, CONST_HEIGHT, SDL_WINDOW_OPENGL); + + //todo + ZL::Env::windowHeaderHeight = 0; + + ZL::gl_context = SDL_GL_CreateContext(ZL::window); + + ZL::CheckGlError(); + + +#endif + ZL::setup(); +#ifdef EMSCRIPTEN + // register update as callback + emscripten_set_main_loop(ZL::update, 0, 1); +#else + while (!ZL::ExitGameLoop) { + + ZL::update(); + SDL_Delay(2); + + } + SDL_GL_DeleteContext(ZL::gl_context); + SDL_DestroyWindow(ZL::window); + SDL_Quit(); + + exit(0); +#endif + +}