123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390 |
- #include "Wrapper.h"
- DummyClient DummyClient::dummy;
- IClient* Engine::client = &DummyClient::dummy;
- GLFWwindow* Engine::window = nullptr;
- // active program
- GLuint Engine::activeProgram = 0;
- // world data
- ShaderProgram Engine::worldShader;
- GLuint Engine::worldFrameBuffer = 0;
- GLuint Engine::worldPositionTexture = 0;
- GLuint Engine::worldNormalTexture = 0;
- GLuint Engine::worldColorTexture = 0;
- GLuint Engine::worldDepthRenderBuffer = 0;
- // post shader
- GLuint Engine::postVba = 0;
- GLuint Engine::postVbo = 0;
- ShaderProgram Engine::postShader;
- int Engine::scale = 1;
- int Engine::width = 0;
- int Engine::height = 0;
- bool Engine::lineMode = false;
- float Engine::testX = 0;
- float Engine::testY = 0;
- float Engine::testZ = 0;
- bool Engine::init(int width, int height, const char* name)
- {
- Engine::width = width;
- Engine::height = height;
- updateScale();
-
- if(!glfwInit())
- {
- cout << "could not initialize GLFW" << endl;
- return false;
- }
- glfwDefaultWindowHints();
- glfwWindowHint(GLFW_VISIBLE, 0);
- glfwWindowHint(GLFW_RESIZABLE, 1);
- window = glfwCreateWindow(width, height, name, nullptr, nullptr);
- if(!window)
- {
- cout << "could not create window" << endl;
- glfwTerminate();
- return false;
- }
- glfwMakeContextCurrent(window);
- glfwSwapInterval(1);
- glfwShowWindow(window);
- GLenum err = glewInit();
- if(GLEW_OK != err)
- {
- cout << "could not initialize GLEW: " << glewGetErrorString(err) << endl;
- return false;
- }
- cout << "Status: Using GLEW " << glewGetString(GLEW_VERSION) << endl;
- worldShader.compile("shader/worldVertex.vs", "shader/worldFragment.fs");
- if(!worldShader.isValid())
- {
- glfwDestroyWindow(window);
- glfwTerminate();
- return false;
- }
- activeProgram = worldShader.getProgram();
- postShader.compile("shader/postVertex.vs", "shader/postFragment.fs");
- if(!postShader.isValid())
- {
- glfwDestroyWindow(window);
- glfwTerminate();
- return false;
- }
-
- glfwSetKeyCallback(window, onKeyEvent);
- glfwSetMouseButtonCallback(window, onMouseClick);
- glfwSetFramebufferSizeCallback(window, onWindowResize);
- //glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
- //glfwSetCursorPosCallback(window, onMouseMove);
- return true;
- }
- void Engine::start(IClient* client)
- {
- if(client != nullptr)
- {
- Engine::client = client;
- }
-
- onInit();
- glEnable(GL_CULL_FACE);
- glDepthFunc(GL_LEQUAL);
-
- uint64_t newTime = glfwGetTimerValue();
- uint64_t oldTime = newTime;
- uint64_t lag = 0;
- while(!glfwWindowShouldClose(window))
- {
- oldTime = newTime;
- newTime = glfwGetTimerValue();
- lag += newTime - oldTime;
- int ticksPerFrame = 0;
- while(lag >= NANOS_PER_TICK)
- {
- lag -= NANOS_PER_TICK;
- Engine::client->tick();
- ticksPerFrame++;
- if(ticksPerFrame >= MAX_TICKS_PER_FRAME)
- {
- long skip = lag / NANOS_PER_TICK;
- lag -= skip * NANOS_PER_TICK;
- if(skip > 0)
- {
- cout << "skipped " << skip << " game ticks " << lag << endl;
- }
- break;
- }
- }
- onRenderTick((float) lag / NANOS_PER_TICK);
-
- glfwSwapBuffers(window);
- glfwPollEvents();
- }
-
- onTerm();
- glfwDestroyWindow(window);
- glfwTerminate();
- }
- void Engine::stop()
- {
- glfwSetWindowShouldClose(window, 1);
- }
- void Engine::onKeyEvent(GLFWwindow* w, int key, int scancode, int action, int mods)
- {
- client->onKeyEvent(key, scancode, action, mods);
- }
- void Engine::onMouseClick(GLFWwindow* w, int button, int action, int mods)
- {
- client->onMouseClick(button, action, mods);
- }
- void Engine::onWindowResize(GLFWwindow* w, int width, int height)
- {
- glViewport(0, 0, width, height);
- Engine::width = width;
- Engine::height = height;
- updateScale();
-
- /*glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer);
- glBindTexture(GL_TEXTURE_2D, frameTexture);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
- glBindTexture(GL_TEXTURE_2D, 0);
- glBindRenderbuffer(GL_RENDERBUFFER, depthTexture);
- glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width, height);
- glBindRenderbuffer(GL_RENDERBUFFER, 0);
- glBindFramebuffer(GL_FRAMEBUFFER, 0);*/
- }
- void Engine::updateScale()
- {
- scale = 1;
- while(width / (scale + 1) >= 400 && height / (scale + 1) >= 300)
- {
- scale++;
- }
- }
- int Engine::getScale()
- {
- return scale;
- }
- int Engine::getWidth()
- {
- return width;
- }
- int Engine::getHeight()
- {
- return height;
- }
- GLint Engine::getUniformLocation(const GLchar* name)
- {
- return glGetUniformLocation(activeProgram, name);
- }
- void Engine::setMatrix(GLint location, const GLfloat* m)
- {
- glUniformMatrix4fv(location, 1, 0, m);
- }
- void Engine::setInt(GLint location, GLint i)
- {
- glUniform1i(location, i);
- }
- void Engine::setFloat(GLint location, GLfloat f1, GLfloat f2, GLfloat f3, GLfloat f4)
- {
- glUniform4f(location, f1, f2, f3, f4);
- }
- void Engine::printError()
- {
- GLenum error = glGetError();
- switch(error)
- {
- case GL_NO_ERROR:
- cout << "> No error has been recorded." << endl;
- break;
- case GL_INVALID_ENUM:
- cout << "> An unacceptable value is specified for an enumerated argument." << endl;
- break;
- case GL_INVALID_VALUE:
- cout << "> A numeric argument is out of range." << endl;
- break;
- case GL_INVALID_OPERATION:
- cout << "> The specified operation is not allowed in the current state." << endl;
- break;
- case GL_INVALID_FRAMEBUFFER_OPERATION:
- cout << "> The framebuffer object is not complete." << endl;
- break;
- case GL_OUT_OF_MEMORY:
- cout << "> There is not enough memory left to execute the command." << endl;
- break;
- case GL_STACK_UNDERFLOW:
- cout << "> An attempt has been made to perform an operation that would cause an internal stack to underflow." << endl;
- break;
- case GL_STACK_OVERFLOW:
- cout << "> An attempt has been made to perform an operation that would cause an internal stack to overflow." << endl;
- break;
- default:
- cout << "> Unknown OpenGL error: " << error << endl;
- }
- }
- void Engine::onInit()
- {
- // generate framebuffer and textures for world buffer
- glGenFramebuffers(1, &worldFrameBuffer);
- glBindFramebuffer(GL_FRAMEBUFFER, worldFrameBuffer);
- // world position texture
- glGenTextures(1, &worldPositionTexture);
- glBindTexture(GL_TEXTURE_2D, worldPositionTexture);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, width, height, 0, GL_RGB, GL_FLOAT, NULL);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, worldPositionTexture, 0);
- // world normal texture
- glGenTextures(1, &worldNormalTexture);
- glBindTexture(GL_TEXTURE_2D, worldNormalTexture);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, width, height, 0, GL_RGB, GL_FLOAT, NULL);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, worldNormalTexture, 0);
- // world color texture
- glGenTextures(1, &worldColorTexture);
- glBindTexture(GL_TEXTURE_2D, worldColorTexture);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, worldColorTexture, 0);
- // set color attachements for the worldFrameBuffer
- GLuint attachments[3] =
- {
- GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2
- };
- glDrawBuffers(3, attachments);
- // generate depth render buffer
- glGenRenderbuffers(1, &worldDepthRenderBuffer);
- glBindRenderbuffer(GL_RENDERBUFFER, worldDepthRenderBuffer);
- glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height);
- glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, worldDepthRenderBuffer);
- glBindRenderbuffer(GL_RENDERBUFFER, 0);
- // check if world framebuffer is okay
- if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
- {
- cout << "world frame buffer is not complete!" << endl;
- }
- glBindFramebuffer(GL_FRAMEBUFFER, 0);
-
- // generate data for drawing previously generated framebuffer as rectangle
- glGenVertexArrays(1, &postVba);
- glBindVertexArray(postVba);
-
- glGenBuffers(1, &postVbo);
- glBindBuffer(GL_ARRAY_BUFFER, postVbo);
- glVertexAttribPointer(0, 2, GL_FLOAT, 0, sizeof(float) * 4, (GLvoid*) 0);
- glEnableVertexAttribArray(0);
- glVertexAttribPointer(1, 2, GL_FLOAT, 0, sizeof(float) * 4, (GLvoid*) (sizeof(float) * 2));
- glEnableVertexAttribArray(1);
-
- float data[] =
- {
- -1.0f, 1.0f, 0.0f, 1.0f,
- -1.0f, -1.0f, 0.0f, 0.0f,
- 1.0f, -1.0f, 1.0f, 0.0f,
- -1.0f, 1.0f, 0.0f, 1.0f,
- 1.0f, -1.0f, 1.0f, 0.0f,
- 1.0f, 1.0f, 1.0f, 1.0f
- };
-
- glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 24, data, GL_STATIC_DRAW);
- }
- void Engine::onRenderTick(float lag)
- {
- //--------------------------------------------------------------------------
- // Stage 1: draw scene in world framebuffer
- //--------------------------------------------------------------------------
- glActiveTexture(GL_TEXTURE0);
-
- activeProgram = worldShader.getProgram();
- glUseProgram(activeProgram);
-
- glBindFramebuffer(GL_FRAMEBUFFER, worldFrameBuffer);
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
- glEnable(GL_DEPTH_TEST);
- if(lineMode)
- {
- glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
- Engine::client->renderTick(lag);
- glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
- }
- else
- {
- Engine::client->renderTick(lag);
- }
- //--------------------------------------------------------------------------
- // Stage 2: draw textured framebuffer
- //--------------------------------------------------------------------------
- glActiveTexture(GL_TEXTURE1);
- glBindTexture(GL_TEXTURE_2D, worldPositionTexture);
- glActiveTexture(GL_TEXTURE2);
- glBindTexture(GL_TEXTURE_2D, worldNormalTexture);
- glActiveTexture(GL_TEXTURE3);
- glBindTexture(GL_TEXTURE_2D, worldColorTexture);
- activeProgram = postShader.getProgram();
- glUseProgram(activeProgram);
-
- glUniform3f(glGetUniformLocation(activeProgram, "viewPos"), testX, testY, testZ);
- glBindFramebuffer(GL_FRAMEBUFFER, 0);
- glClear(GL_COLOR_BUFFER_BIT);
- glDisable(GL_DEPTH_TEST);
- glBindVertexArray(postVba);
- glBindBuffer(GL_ARRAY_BUFFER, postVbo);
- glDrawArrays(GL_TRIANGLES, 0, 6);
- }
- void Engine::onTerm()
- {
- glDeleteVertexArrays(1, &postVba);
- glDeleteBuffers(1, &postVbo);
-
- glDeleteFramebuffers(1, &worldFrameBuffer);
- glDeleteTextures(1, &worldPositionTexture);
- glDeleteTextures(1, &worldNormalTexture);
- glDeleteTextures(1, &worldColorTexture);
- glDeleteRenderbuffers(1, &worldDepthRenderBuffer);
- }
- void Engine::setLineMode(bool mode)
- {
- lineMode = mode;
- }
|