diff --git a/assets/shaders/basic_vs.vert b/assets/shaders/basic_vs.vert index d834ce2..c4cfdc3 100644 --- a/assets/shaders/basic_vs.vert +++ b/assets/shaders/basic_vs.vert @@ -1,14 +1,20 @@ -// Basic Vertex Shader -#version 140 - +// Basic Vertex Shader Template with Model, View, Project matrixes +#version 140 + in vec3 in_Position; in vec3 in_Color; +in vec2 in_UV; + +uniform mat4 in_Model; +uniform mat4 in_View; +uniform mat4 in_Proj; + out vec3 ex_Color; - -void main(void) { - gl_Position.xyz = in_Position.xyz; - gl_Position.w = 1.0; +out vec2 ex_UV; - ex_Color = vec3(1.0, 0.0, 0.0); +void main(void) { + gl_Position = in_Proj * (in_View * (in_Model * vec4(in_Position, 1.0))); + ex_Color = vec3(in_Color); + ex_UV = in_UV; } diff --git a/assets/shaders/retro_texture.frag b/assets/shaders/retro_texture.frag index 44ea4a2..7d58eb8 100644 --- a/assets/shaders/retro_texture.frag +++ b/assets/shaders/retro_texture.frag @@ -18,13 +18,13 @@ out vec4 out_Color; // width of a pixel in texture units, // should be set to 1 / width, 1 / height. uniform vec2 pixelSize = vec2(1.0/(320.0), 1.0/(240.0) ); - + // how sharp the bilinear filter is, 0 - 1 const float sharpness = 0.75; // How many are misalign the color beams const float misalign = 0.4; - + // how much a scanline should darken its line, 0-1 const float scanIntensity = 0.1; @@ -36,7 +36,7 @@ const float distortion = 0.08; // Flicker intesity //const float flicker = 0.025; - + // Time depedent FX uniform float time = 0.0; @@ -51,13 +51,13 @@ uniform float brightness = 0.0; vec2 barrelDistortion(vec2 coord) { vec2 cc = coord - 0.5; float dist = dot(cc, cc) * distortion; - return coord + cc * (1.0 - dist) * dist; + return coord + cc * (1.0 - dist) * dist; } void main(void) { // Apply curvature fx vec2 uv = barrelDistortion(ex_UV); - if ( (uv.x <0 || uv.x > 1.0) || (uv.y <0 || uv.y > 1.0)) { + if ( (uv.x <0.0 || uv.x > 1.0) || (uv.y <0.0 || uv.y > 1.0)) { // Ignore fragments that are outside of the screen discard; return; @@ -65,7 +65,7 @@ void main(void) { // Precalculate misalign in function of horizontal pos float mis = misalign * pixelSize.x * (misalign + (1.0 - misalign)*2 * abs(uv.x - 0.5)); - + // Precalculate bilinear filter things float xInc = pixelSize.x * (1.0 - sharpness) / 2.0; float yInc = pixelSize.y * (1.0 - sharpness) / 2.0; @@ -75,17 +75,17 @@ void main(void) { uvs[1] = uv + vec2(xInc, -yInc); uvs[2] = uv + vec2(-xInc, yInc); uvs[3] = uv + vec2(xInc, yInc); - + for (int i=0; i < 4; i++) { middle[i] = texture(texture0, uvs[i] ).rgb; - + // Generate color border (misaligment) vec3 col; col.r = texture(texture0,vec2(uvs[i].x + mis ,uvs[i].y)).x; col.g = texture(texture0,vec2(uvs[i].x ,uvs[i].y)).y; col.b = texture(texture0,vec2(uvs[i].x - mis ,uvs[i].y)).z; middle[i] = middle[i]*0.2 + col*0.8; - + // scanlines if (scanIntensity > 0.0 && mod(uvs[i].y, pixelSize.y ) > (pixelSize.y/2)) { middle[i].r = max(middle[i].r - scanIntensity, 0); @@ -100,14 +100,14 @@ void main(void) { // noise result = result + noise * fract(sin(dot(uv.xy , vec2(12.9898 + time, 78.233 + tan(time)))) * 43758.5453); - + // contrast curve //result.xyz = clamp(0.5*result.xyz + 0.5*result.xyz * 1.2*result.xyz, 0.0 , 1.0); - + //flickering (semi-randomized) // result *= 1.0 - flicker * fract(sin(dot(vec2(1.0) , vec2(12.9898 + time, 78.233 + tan(time)))) * 43758.5453); - + out_Color.xyz = result * (1.0 + brightness); out_Color.w = 1.0; - + } diff --git a/src/devices/timer.cpp b/src/devices/timer.cpp index a9a975a..153035b 100644 --- a/src/devices/timer.cpp +++ b/src/devices/timer.cpp @@ -360,11 +360,11 @@ void Timer::WriteDW (DWord addr, DWord val) { break; case 0x11E008: - tmr1 = tmr1; + tmr1 = val; break; case 0x11E00C: - re1 = re1; + re1 = val; break; case 0x11E010: diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index 37555e3..b575636 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -2,6 +2,10 @@ SET(BUILD_TOOLS_SCREEN TRUE CACHE BOOL "Build Trillek VCOMPUTER tools with virtual screen") SET(BUILD_TOOLS_AUDIO TRUE CACHE BOOL "Build Trillek VCOMPUTER tools with audio") +# Give these some dummy values and if the platform is LINUX or OSX they will be set accordingly. +SET(X11_LIBRARIES "") +SET(OSX_LIBRARIES "") + # FIND GLFW3 AND OPENGL libs FIND_PACKAGE(GLFW3) IF (NOT GLFW3_FOUND) @@ -89,8 +93,40 @@ SET(MEDIA_LINK_LIBS # If we have OpenGL / GLFW3 / GLM / GLEW libs IF (GLFW3_ENABLE EQUAL 1) - MESSAGE(STATUS "vc executable have Virtual Screen enabled") + IF (NOT APPLE) # X11 and GLEW are not needed on OSX. + FIND_PACKAGE(X11) + SET(USE_STATIC_GLEW CACHE BOOL "Build against GLEW static (default no)") + FIND_PACKAGE(GLEW REQUIRED) # We find GLEW here as OSX doesn't need it. + ENDIF (NOT APPLE) + + IF (APPLE) # Mac OSX + SET(GLEW_LIBRARY "") # Set a dummy value for GLEW. + + SET(CMAKE_XCODE_ATTRIBUTE_SUPPORTED_PLATFORMS macosx) + + # Need the 10.7 SDK or later. + EXECUTE_PROCESS(COMMAND xcodebuild -sdk macosx -version SDKVersion OUTPUT_VARIABLE OSX_SDK_VERSION) + IF (NOT (OSX_SDK_VERSION VERSION_GREATER 10.7 OR OSX_SDK_VERSION VERSION_EQUAL 10.7)) + MESSAGE(FATAL_ERROR "The installed version of Xcode does not support the 10.7 SDK or later. Please upgrade Xcode and try again.") + ENDIF (NOT (OSX_SDK_VERSION VERSION_GREATER 10.7 OR OSX_SDK_VERSION VERSION_EQUAL 10.7)) + + # Configure the project to use the correct SDK. + IF (XCODE_VERSION) + SET(CMAKE_OSX_SYSROOT macosx) + ELSE (XCODE_VERSION) + # Non-Xcode generators need the full path. + EXECUTE_PROCESS(COMMAND xcodebuild -sdk macosx -version Path | head -n 1 OUTPUT_VARIABLE CMAKE_OSX_SYSROOT) + STRING(REGEX REPLACE "(\r?\n)+$" "" CMAKE_OSX_SYSROOT "${CMAKE_OSX_SYSROOT}") + ENDIF (XCODE_VERSION) + + # Can deploy back to 10.7, the first OS X to support the GL Core. + SET(CMAKE_OSX_DEPLOYMENT_TARGET 10.7) + + # Need Core Foundation and libobjc. + SET(OSX_LIBRARIES "-framework CoreFoundation /usr/lib/libobjc.dylib") + ENDIF (APPLE) + MESSAGE(STATUS "vc executable have Virtual Screen enabled") # Some auxiliar libs FILE(GLOB TOOL_OTHER_SRC "${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp" @@ -106,6 +142,8 @@ IF (GLFW3_ENABLE EQUAL 1) ) SET(MEDIA_LINK_LIBS + ${X11_LIBRARIES} + ${OSX_LIBRARIES} ${MEDIA_LINK_LIBS} ${OPENGL_LIBRARIES} ${GLEW_LIBRARIES} @@ -116,6 +154,8 @@ IF (GLFW3_ENABLE EQUAL 1) # TDA VIEWER Can only be build with OpenGL stuff ADD_EXECUTABLE( tda_view ./tda_view.cpp + ./src/gl_engine.cpp + ./src/glerror.cpp ) SET(TARGETS ${TARGETS} "tda_view") diff --git a/tools/config_main.hpp.in b/tools/config_main.hpp.in index ee8db0c..7a7051a 100644 --- a/tools/config_main.hpp.in +++ b/tools/config_main.hpp.in @@ -12,8 +12,10 @@ #if GLFW3_ENABLE == 0 #undef GLFW3_ENABLE #else - #ifdef __APPLE__ + #include + #define GLFW_INCLUDE_GLCOREARB + #include // Needed so we can disable retina support for our window. #define GLFW_EXPOSE_NATIVE_COCOA 1 #define GLFW_EXPOSE_NATIVE_NSGL 1 @@ -22,16 +24,16 @@ typedef void* SEL; extern "C" id objc_msgSend(id self, SEL op, ...); extern "C" SEL sel_getUid(const char *str); + #else #include #ifndef __unix #include #endif + #include #endif - #include - #ifndef GLM_FORCE_RADIANS #define GLM_FORCE_RADIANS // Removes anoying messages of depracated angles on degress #endif diff --git a/tools/include/gl_engine.hpp b/tools/include/gl_engine.hpp index 80bffe9..da61d18 100644 --- a/tools/include/gl_engine.hpp +++ b/tools/include/gl_engine.hpp @@ -27,10 +27,14 @@ class GlEngine { yaw = 0; pith = 0; - zoom = 6.0; + zoom = 4.7; frame_count = 0; t_acu = 0; + + vertShaderFile = "basic_vs.vert"; + fragShaderFile = "retro_texture.frag"; + this->pbo = 0; } ~GlEngine () { @@ -44,6 +48,13 @@ class GlEngine { } } + void setVertexShaderFile (const std::string& file) { + this->vertShaderFile = file; + } + void setFragmentShaderFile (const std::string& file) { + this->fragShaderFile = file; + } + //! Init OpenGL int initGL(OS::OS& os); @@ -64,7 +75,8 @@ class GlEngine { //bool capture_keyboard = false; GLuint screenTex; // ID of screen Texture - GLuint tex_pbo; // ID of the screen texture PBO + GLuint tex_pbo[2];// IDs of the screen texture PBO + size_t pbo; // Handler of shader program GLuint shaderProgram; @@ -87,19 +99,16 @@ class GlEngine { static const unsigned int sh_in_Color; static const unsigned int sh_in_UV; - static const GLfloat N_VERTICES; + static const GLsizei N_VERTICES; - GLuint vertexbuffer; + GLuint vao, vbo[3]; // vbo = {vdata, color, uv} static const float vdata[]; - - GLuint colorbuffer; static const float color_data[]; - - GLuint uvbuffer; static const float uv_data[]; glm::mat4 proj, view, model; //! MVP Matrixes + // Camera position float yaw; float pith; float zoom; @@ -108,6 +117,9 @@ class GlEngine { double t_acu; //! Acumulated time std::function painter; //! Function that paints screen texture + + std::string vertShaderFile; + std::string fragShaderFile; }; #endif diff --git a/tools/include/glerror.hpp b/tools/include/glerror.hpp new file mode 100644 index 0000000..96ef907 --- /dev/null +++ b/tools/include/glerror.hpp @@ -0,0 +1,33 @@ +/** + * Trillek Virtual Computer - glerror.hpp + * Function/macros to debug OpenGL code + */ + +#ifndef __TR_GL_ERROR_HPP_ +#define __TR_GL_ERROR_HPP_ 1 + +namespace trillek { + /** + * Check if there is a OpenGL error and display it + * @param file Source file + * @param line Source line + */ + void tr_check_gl_error(const char *file, int line); +} // End of namespace trillek + +#ifndef NDEBUG +/** + * Usage + * [... some opengl calls] + * glCheckError(); + */ +#define check_gl_error() trillek::tr_check_gl_error(__FILE__,__LINE__) + +#else + +#define check_gl_error() + +#endif + +#endif // __TR_GL_ERROR_HPP_ + diff --git a/tools/include/os.hpp b/tools/include/os.hpp index 5f3e1a8..455cb11 100644 --- a/tools/include/os.hpp +++ b/tools/include/os.hpp @@ -20,8 +20,15 @@ #include "keyboard_input_system.hpp" #include +#include namespace OS { + // Error helper function used by GLFW for error messaging. + // Currently outputs to std::cout. + static void ErrorCallback(int error, const char* description) { + std::cerr << error << " -> " << description << std::endl; + } + class OS { public: OS() : mouseLock(false) { @@ -30,38 +37,65 @@ namespace OS { ~OS() { } - bool InitializeWindow(const int width, const int height, const std::string title, const unsigned int glMajor = 3, const unsigned int glMinor = 2) { - // Initialize the library. - if (glfwInit() != GL_TRUE) { - return false; - } - - glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_API); - glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); - glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, glMajor); - glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, glMinor); - -#ifdef __APPLE__ - // Must use the Core Profile on OS X to get GL 3.2. - glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); -#else - glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_COMPAT_PROFILE); -#endif - - // Create a windowed mode window and its OpenGL context. - this->window = glfwCreateWindow(width, height, title.c_str(), NULL, NULL); - - if (!this->window) { - // Try with core profile + bool InitializeWindow(const int width, const int height, const std::string title, const unsigned int glMajor = 3, const unsigned int glMinor = 2) { + assert(glMajor >= 4 || (glMajor == 3 && glMinor >= 2)); + std::string glcx_major = "1"; + std::string glcx_version; + glfwSetErrorCallback(ErrorCallback); + + // Initialize the library. + if (glfwInit() != GL_TRUE) { + return false; + } + + glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_API); + glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, glMajor); + glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, glMinor); + glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); + // Create a windowed mode window and its OpenGL context. + this->window = glfwCreateWindow(width, height, title.c_str(), NULL, NULL); + if (this->window) { + // Make the window's context current. + glfwMakeContextCurrent(this->window); + + glcx_version = (char*)glGetString(GL_VERSION); + glcx_major = glcx_version.substr(0, glcx_version.find('.', 0)); + } + + if (glcx_major == "1" || glcx_major == "2") { + std::clog << "Trying again to geta valid OpenGL context\n"; + // we got a old version context or failed. So try again. + if (this->window) { + glfwMakeContextCurrent(nullptr); + glfwDestroyWindow(this->window); + } + // Try again, enforcing Core profile + glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_API); + glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, glMajor); + glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, glMinor); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); + glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); this->window = glfwCreateWindow(width, height, title.c_str(), NULL, NULL); if (!this->window) { glfwTerminate(); return false; } + // attach the context + glfwMakeContextCurrent(this->window); + + // check the context version again + glcx_version = (char*)glGetString(GL_VERSION); + glcx_major = glcx_version.substr(0, glcx_version.find('.', 0)); + if(glcx_major == "1") { + // still 1, higher versions probably not supported + glfwTerminate(); + std::cerr << "Initializing OpenGL failed, unsupported version: " << glcx_version << '\n'; + std::cerr << "Press \"Enter\" to exit\n"; + std::cin.get(); + return false; + } } - this->width = width; this->height = height; @@ -70,16 +104,11 @@ namespace OS { id cocoaWindow = glfwGetCocoaWindow(this->window); id cocoaGLView = ((id (*)(id, SEL)) objc_msgSend)(cocoaWindow, sel_getUid("contentView")); ((void (*)(id, SEL, bool)) objc_msgSend)(cocoaGLView, sel_getUid("setWantsBestResolutionOpenGLSurface:"), false); -#endif - - // Make the window's context current. - glfwMakeContextCurrent(this->window); -#ifndef __APPLE__ +#else // setting glewExperimental fixes a glfw context problem // (tested on Ubuntu 13.04) glewExperimental = GL_TRUE; - // Init GLEW. GLuint error = glewInit(); if (error != GLEW_OK) { diff --git a/tools/main.cpp b/tools/main.cpp index f8cb4a3..5897c96 100644 --- a/tools/main.cpp +++ b/tools/main.cpp @@ -351,7 +351,7 @@ int main(int argc, char* argv[]) { useOpenGL = false; //return -1; } else if (gl.initGL(glfwos) != 0) { - std::cerr << "Error initiating OpenGL\n"; + std::clog << "Error initiating OpenGL\n"; useOpenGL = false; //return -1; } diff --git a/tools/src/gl_engine.cpp b/tools/src/gl_engine.cpp index 35c396b..9e4fddb 100644 --- a/tools/src/gl_engine.cpp +++ b/tools/src/gl_engine.cpp @@ -16,13 +16,16 @@ #pragma comment(lib, "comsuppw") #endif +#include "glerror.hpp" + #ifdef GLFW3_ENABLE +// Constants const unsigned int GlEngine::sh_in_Position = 0; const unsigned int GlEngine::sh_in_Color = 1; -const unsigned int GlEngine::sh_in_UV = 3; +const unsigned int GlEngine::sh_in_UV = 2; -const GLfloat GlEngine::N_VERTICES = 4; +const GLsizei GlEngine::N_VERTICES = 4; const float GlEngine::vdata[] = { 3.2, 2.4, 0.0, // Top Right @@ -50,14 +53,14 @@ void GlEngine::SetTextureCB (std::function painter) { this->painter = painter; } - int GlEngine::initGL(OS::OS& os) { + check_gl_error(); int OpenGLVersion[2]; // Use the GL3 way to get the version number glGetIntegerv(GL_MAJOR_VERSION, &OpenGLVersion[0]); glGetIntegerv(GL_MINOR_VERSION, &OpenGLVersion[1]); - std::cout << "OpenGL " << OpenGLVersion[0] << "." << OpenGLVersion[1] << "\n"; + std::cout << "Using OpenGL " << OpenGLVersion[0] << "." << OpenGLVersion[1] << " Core\n"; // Sanity check to make sure we are at least in a good major version number. assert((OpenGLVersion[0] > 1) && (OpenGLVersion[0] < 5)); @@ -83,61 +86,73 @@ int GlEngine::initGL(OS::OS& os) { 10000.0f); // Far cliping plane glPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); -#if __APPLE__ - // GL_MULTISAMPLE are Core. glEnable(GL_MULTISAMPLE); -#else - if (GLEW_ARB_multisample) { - glEnable(GL_MULTISAMPLE_ARB); - } -#endif glEnable(GL_CULL_FACE); glCullFace(GL_BACK); glEnable(GL_DEPTH_TEST); - // Accept fragment if it closer to the camera than the former one glDepthFunc(GL_LESS); - // Initialize VBOs ******************************************************** - glGenBuffers(1, &vertexbuffer); - glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer); - // Upload data to VBO + // Generate VAO + glGenVertexArrays(1, &vao); + glBindVertexArray(vao); + + // Allocate VBOs (position, color, UV) + glGenBuffers(3, vbo); + check_gl_error(); + + // Upload vertex position + glBindBuffer(GL_ARRAY_BUFFER, vbo[sh_in_Position]); glBufferData(GL_ARRAY_BUFFER, sizeof(vdata), vdata, GL_STATIC_DRAW); + // Vertex data to attribute index 0 (shadderAttribute) and is 3 floats + glVertexAttribPointer(sh_in_Position, 3, GL_FLOAT, GL_FALSE, 0, 0); + glEnableVertexAttribArray(sh_in_Position); + check_gl_error(); - glGenBuffers(1, &colorbuffer); - glBindBuffer(GL_ARRAY_BUFFER, colorbuffer); - // Upload data to VBO + // Upload color + glBindBuffer(GL_ARRAY_BUFFER, vbo[sh_in_Color]); glBufferData(GL_ARRAY_BUFFER, sizeof(color_data), color_data, GL_STATIC_DRAW); + // Vertex data to attribute index 0 (shadderAttribute) and is 3 floats + glVertexAttribPointer(sh_in_Color, 3, GL_FLOAT, GL_FALSE, 0, 0); + glEnableVertexAttribArray(sh_in_Color); + check_gl_error(); - glGenBuffers(1, &uvbuffer); - glBindBuffer(GL_ARRAY_BUFFER, uvbuffer); - // Upload data to VBO + // Upload UV + glBindBuffer(GL_ARRAY_BUFFER, vbo[sh_in_UV]); glBufferData(GL_ARRAY_BUFFER, sizeof(uv_data), uv_data, GL_STATIC_DRAW); + // Vertex data to attribute index 0 (shadderAttribute) and is 3 floats + glVertexAttribPointer(sh_in_UV, 2, GL_FLOAT, GL_FALSE, 0, 0); + glEnableVertexAttribArray(sh_in_UV); + check_gl_error(); // Initialize PBO ********************************************************* - glGenBuffers(1, &tex_pbo); - glBindBuffer(GL_PIXEL_UNPACK_BUFFER, tex_pbo); + glGenBuffers(2, tex_pbo); + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, tex_pbo[pbo]); + glBufferData(GL_PIXEL_UNPACK_BUFFER, 320*240*4, nullptr, GL_STREAM_DRAW); + pbo = (pbo+1) % 2; + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, tex_pbo[pbo]); glBufferData(GL_PIXEL_UNPACK_BUFFER, 320*240*4, nullptr, GL_STREAM_DRAW); + check_gl_error(); // Initialize Texture ***************************************************** glGenTextures(1, &screenTex); glBindTexture(GL_TEXTURE_2D, screenTex); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 320, 240, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); + check_gl_error(); - //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + check_gl_error(); // Loading shaders ******************************************************** FILE* f_vs = nullptr; FILE* f_fs = nullptr; #if WIN32 // TODO We should get path from HKEY_LOCAL_MACHINE\SOFTWARE\Trillek\Trillek VComputer - const std::string vertShaderFilename = "assets\\shaders\\mvp_template.vert"; - const std::string fragShaderFilename = "assets\\shaders\\retro_texture.frag"; + const std::string vertShaderFilename = "assets\\shaders\\" + this->vertShaderFile; + const std::string fragShaderFilename = "assets\\shaders\\" + this->fragShaderFile; std::string programFilesPath = ""; LPWSTR wszPath = nullptr; HRESULT hr; @@ -157,8 +172,8 @@ int GlEngine::initGL(OS::OS& os) { CoTaskMemFree(wszPath); } #else - const std::string vertShaderFilename = "assets/shaders/mvp_template.vert"; - const std::string fragShaderFilename = "assets/shaders/retro_texture.frag"; + const std::string vertShaderFilename = "assets/shaders/" + this->vertShaderFile; + const std::string fragShaderFilename = "assets/shaders/" + this->fragShaderFile; std::string path = "./"+ vertShaderFilename; std::clog << "Trying " << path << std::endl; f_vs = std::fopen(path.c_str(), "r"); @@ -296,10 +311,31 @@ int GlEngine::initGL(OS::OS& os) { // Attach our shaders to our program glAttachShader(shaderProgram, vertexShader); glAttachShader(shaderProgram, fragmentShader); + check_gl_error(); // Link shader program glLinkProgram(shaderProgram); + int IsLinked; int maxLength; + glGetProgramiv(shaderProgram, GL_LINK_STATUS, (int *)&IsLinked); + if(IsLinked == GL_FALSE) { + /* Noticed that glGetProgramiv is used to get the length for a shader program, not glGetShaderiv. */ + glGetProgramiv(shaderProgram, GL_INFO_LOG_LENGTH, &maxLength); + + /* The maxLength includes the NULL character */ + auto shaderProgramInfoLog = (char *)malloc(maxLength); + + /* Notice that glGetProgramInfoLog, not glGetShaderInfoLog. */ + glGetProgramInfoLog(shaderProgram, maxLength, &maxLength, shaderProgramInfoLog); + + std::cerr << shaderProgramInfoLog << std::endl; + glDeleteShader(vertexShader); + glDeleteShader(fragmentShader); + + free(shaderProgramInfoLog); + return -1; + } + // Bind attributes indexes glBindAttribLocation(shaderProgram, sh_in_Position, "in_Position"); glBindAttribLocation(shaderProgram, sh_in_Color, "in_Color"); @@ -311,18 +347,11 @@ int GlEngine::initGL(OS::OS& os) { timeId = glGetUniformLocation(shaderProgram, "time"); + check_gl_error(); glDeleteShader(vertexShader); glDeleteShader(fragmentShader); - - // Camera matrix - view = glm::lookAt( - glm::vec3(3,3,7), // Camera is at (3,3,7), in World Space - glm::vec3(0,0,0), // and looks at the origin - glm::vec3(0,1,0) // Head is up (set to 0,-1,0 to look upside-down) - ); - return 0; } @@ -331,7 +360,6 @@ void GlEngine::UpdScreen (OS::OS& os, const double delta) { // Clear The Screen And The Depth Buffer frame_count += 1.0; - glClearColor( 0.1f, 0.1f, 0.1f, 1.0f ); glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); @@ -348,7 +376,7 @@ void GlEngine::UpdScreen (OS::OS& os, const double delta) { glm::vec3(0,1,0) // Head is up (set to 0,-1,0 to look upside-down) ); - // Drawing ... + // Binding shader glUseProgram(shaderProgram); // Set sampler to user Texture Unit 0 glUniform1i(glGetUniformLocation( shaderProgram, "texture0" ), 0); @@ -361,12 +389,14 @@ void GlEngine::UpdScreen (OS::OS& os, const double delta) { t_acu -= 0.04; // Stream the texture ************************************************* - glBindBuffer(GL_PIXEL_UNPACK_BUFFER, tex_pbo); + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, tex_pbo[pbo]); // Copy the PBO to the texture glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 320, 240, GL_RGBA, GL_UNSIGNED_BYTE, 0); - // Updates the PBO with the new texture + pbo = (pbo+1) % 2; + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, tex_pbo[pbo]); + // Updates the other PBO with the new texture auto tdata = glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY); if (tdata != nullptr) { //std::fill_n(tdata, 320*240, 0xFF800000); @@ -380,42 +410,8 @@ void GlEngine::UpdScreen (OS::OS& os, const double delta) { glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); // Release the PBO } - // Enable attribute in_Position as being used - glEnableVertexAttribArray(sh_in_Position); - glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer); - - // Vertex data to attribute index 0 (shadderAttribute) and is 3 floats - glVertexAttribPointer( - sh_in_Position, - 3, - GL_FLOAT, - GL_FALSE, - 0, - 0 ); - - // Enable attribute in_Color as being used - glEnableVertexAttribArray(sh_in_Color); - glBindBuffer(GL_ARRAY_BUFFER, colorbuffer); - // Vertex data to attribute index 0 (shadderAttribute) and is 3 floats - glVertexAttribPointer( - sh_in_Color, - 3, - GL_FLOAT, - GL_FALSE, - 0, - 0 ); - - // Enable attribute in_UV as being used - glEnableVertexAttribArray(sh_in_UV); - glBindBuffer(GL_ARRAY_BUFFER, uvbuffer); - // Vertex data to attribute index 0 (shadderAttribute) and is 3 floats - glVertexAttribPointer( - sh_in_UV, - 2, - GL_FLOAT, - GL_FALSE, - 0, - 0 ); + // Binding VAO + glBindVertexArray(vao); // Send M, V, P matrixes to the uniform inputs, glUniformMatrix4fv(modelId, 1, GL_FALSE, &model[0][0]); @@ -426,9 +422,9 @@ void GlEngine::UpdScreen (OS::OS& os, const double delta) { glDrawArrays(GL_TRIANGLE_STRIP, sh_in_Position, N_VERTICES); - glDisableVertexAttribArray(sh_in_Position); - glDisableVertexAttribArray(sh_in_Color); - glDisableVertexAttribArray(sh_in_UV); + // Unbind + glBindVertexArray(0); + glUseProgram(0); // Update host window os.SwapBuffers(); diff --git a/tools/src/glerror.cpp b/tools/src/glerror.cpp new file mode 100644 index 0000000..90252b3 --- /dev/null +++ b/tools/src/glerror.cpp @@ -0,0 +1,46 @@ +/** + * + */ +#include "glerror.hpp" +#include "config_main.hpp" + +#include +#include + +namespace trillek { + +void tr_check_gl_error(const char *file, int line) { +#ifndef NDEBUG + GLenum err (glGetError()); + unsigned count =0; + while(err!=GL_NO_ERROR) { + std::string error; + + switch(err) { + case GL_INVALID_OPERATION: + error="INVALID_OPERATION"; + break; + case GL_INVALID_ENUM: + error="INVALID_ENUM"; + break; + case GL_INVALID_VALUE: + error="INVALID_VALUE"; + break; + case GL_OUT_OF_MEMORY: + error="OUT_OF_MEMORY"; + break; + case GL_INVALID_FRAMEBUFFER_OPERATION: + error="INVALID_FRAMEBUFFER_OPERATION"; + break; + default: + error="UNKNOW_ERROR"; + } + std::cerr << "#" << count << " " << err << ": GL_" << error.c_str() + << " - " << file << ":" << line << std::endl; + err=glGetError(); + count++; + } +#endif +} +} // End of namespace trillek + diff --git a/tools/tda_view.cpp b/tools/tda_view.cpp index d05f74b..33e6968 100644 --- a/tools/tda_view.cpp +++ b/tools/tda_view.cpp @@ -1,6 +1,8 @@ /** * Trillek Virtual Computer - tda_view.cpp * Tool that visualizes a image of a TDA screen using a stored TDA state + * + * \copyright LGPL v3 */ #include "os.hpp" #include "devices/tda.hpp" @@ -16,6 +18,7 @@ #include #include #include +#include #if WIN32 #include @@ -25,494 +28,103 @@ #pragma comment(lib, "comsuppw") #endif -unsigned winWidth; -unsigned winHeight; - -GLuint screenTex; // ID of screen Texture -GLuint tex_pbo; // ID of the screen texture PBO - -// Handler of shader program -GLuint shaderProgram; - -// Ptrs to source doe of shaders -GLchar *vertexSource = nullptr; -GLchar *fragmentSource = nullptr; - -// Handlers of the shader programs -GLuint vertexShader, fragmentShader; - -// Handles for uniform inputs to the shader -GLuint modelId; -GLuint viewId; -GLuint projId; -GLuint timeId; - -const unsigned int sh_in_Position = 0; -const unsigned int sh_in_Color = 1; -const unsigned int sh_in_UV = 3; - -static const GLfloat N_VERTICES=4; -GLuint vertexbuffer; -static const float vdata[] = { - 3.2, 2.4, 0.0, // Top Right - -3.2, 2.4, 0.0, // Top Left - 3.2, -2.4, 0.0, // Botton Right - -3.2, -2.4, 0.0, // Bottom Left -}; - -GLuint colorbuffer; -static const float color_data[] = { - 1.0, 1.0, 1.0, // Top Right - 1.0, 1.0, 1.0, // Top Left - 1.0, 1.0, 1.0, // Botton Right - 1.0, 1.0, 1.0, // Bottom Left -}; - -GLuint uvbuffer; -static const float uv_data[] = { - 1.0, 0.0, // Top Right - 0.0, 0.0, // Top Left - 1.0, 1.0, // Botton Right - 0.0, 1.0, // Bottom Left -}; - -glm::mat4 proj, view, model; // MVP Matrixes -float yaw = 0.0; -float pith = 0.0; -float zoom = 6.0; - -void initGL(OS::OS& os); +#include "gl_engine.hpp" int main (int argc, char* argv[]) { - using namespace trillek; - using namespace trillek::computer::tda; + using namespace trillek; + using namespace trillek::computer::tda; + GlEngine gl; - // TODO load screen from a file + // TODO load screen from a file - OS::OS glfwos; + OS::OS glfwos; if (!glfwos.InitializeWindow(1024, 768, "TDA screen dump viewer")) { std::clog << "Failed creating the window or context."; return -1; } - initGL(glfwos); - std::printf("Initiated OpenGL\n"); - float frame_count = 0; // Count frames - double deltat = glfwos.GetDeltaTime(); - double t_acu = 0; // Time acumulator - - // TODO Here insert a callback from events - - // Test screen - TDAScreen screen; - screen.txt_buffer[0] = 0x0F00 | 'H'; - screen.txt_buffer[1] = 0x1F00 | 'e'; - screen.txt_buffer[2] = 0x2F00 | 'l'; - screen.txt_buffer[3] = 0x3F00 | 'l'; - screen.txt_buffer[4] = 0x4F00 | 'o'; - screen.txt_buffer[5] = 0x5F00 | ' '; - screen.txt_buffer[6] = 0x6F00 | 'w'; - screen.txt_buffer[7] = 0x7F00 | 'o'; - screen.txt_buffer[8] = 0x8F00 | 'r'; - screen.txt_buffer[9] = 0x9F00 | 'l'; - screen.txt_buffer[10] = 0xAF00 | 'd'; - screen.txt_buffer[11] = 0xBF00 | '!'; - - screen.cursor = true; - screen.cur_col = 20; - screen.cur_row = 0; - screen.cur_start = 5; - screen.cur_end = 7; - screen.cur_color = 15; - - for (unsigned i= 40; i < WIDTH_CHARS*HEIGHT_CHARS; i++ ) { - Byte fg = i % 16; - Byte bg = (15 - i) % 16; - screen.txt_buffer[i] = (bg << 12) | (fg << 8) | ((i-40) % 256); - } - - bool loop = true; - while ( loop) { - if (glfwos.Closing()) { - loop = false; - continue; - } - - // Clear The Screen And The Depth Buffer - frame_count += 1.0; - - glClearColor( 0.1f, 0.1f, 0.1f, 1.0f ); - glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - // Model matrix <- Identity - model = glm::mat4(1.0f); - - // Camera Matrix - view = glm::lookAt( - glm::vec3( - (float)(zoom * sin(yaw)*cos(pith)), - (float)(zoom * sin(pith)), - (float)(zoom * cos(yaw))*cos(pith)), // Were is the camera - glm::vec3(0,0,0), // and looks at the origin - glm::vec3(0,1,0) // Head is up (set to 0,-1,0 to look upside-down) - ); - - // Drawing ... - glUseProgram(shaderProgram); - // Set sampler to user Texture Unit 0 - glUniform1i(glGetUniformLocation( shaderProgram, "texture0" ), 0); - - // Bind texture - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, screenTex); - - if (t_acu >= 0.04) { // Updates screen texture at a rate of ~25 Hz - t_acu -= 0.04; - - // Stream the texture ************************************************* - glBindBuffer(GL_PIXEL_UNPACK_BUFFER, tex_pbo); - - // Copy the PBO to the texture - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 320, 240, GL_RGBA, GL_UNSIGNED_BYTE, 0); - - // Updates the PBO with the new texture - auto tdata = (DWord*) glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY); - if (tdata != nullptr) { - TDAtoRGBATexture(screen, tdata); // Write the texture to the PBO buffer - - glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER); - } - - glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); // Release the PBO + if ( gl.initGL(glfwos) != 0) { + std::clog << "Error initiating OpenGL\n"; + return -1; } - // Enable attribute in_Position as being used - glEnableVertexAttribArray(sh_in_Position); - glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer); - // Vertex data to attribute index 0 (shadderAttribute) and is 3 floats - glVertexAttribPointer( - sh_in_Position, - 3, - GL_FLOAT, - GL_FALSE, - 0, - 0 ); - - // Enable attribute in_Color as being used - glEnableVertexAttribArray(sh_in_Color); - glBindBuffer(GL_ARRAY_BUFFER, colorbuffer); - // Vertex data to attribute index 0 (shadderAttribute) and is 3 floats - glVertexAttribPointer( - sh_in_Color, - 3, - GL_FLOAT, - GL_FALSE, - 0, - 0 ); - - // Enable attribute in_UV as being used - glEnableVertexAttribArray(sh_in_UV); - glBindBuffer(GL_ARRAY_BUFFER, uvbuffer); - // Vertex data to attribute index 0 (shadderAttribute) and is 3 floats - glVertexAttribPointer( - sh_in_UV, - 2, - GL_FLOAT, - GL_FALSE, - 0, - 0 ); - - // Send M, V, P matrixes to the uniform inputs, - glUniformMatrix4fv(modelId, 1, GL_FALSE, &model[0][0]); - glUniformMatrix4fv(viewId, 1, GL_FALSE, &view[0][0]); - glUniformMatrix4fv(projId, 1, GL_FALSE, &proj[0][0]); - - glUniform1f(timeId, (float)((int)frame_count +1)); - - glDrawArrays(GL_TRIANGLE_STRIP, sh_in_Position, N_VERTICES); - - glDisableVertexAttribArray(sh_in_Position); - glDisableVertexAttribArray(sh_in_Color); - glDisableVertexAttribArray(sh_in_UV); - - // Update host window - glfwos.SwapBuffers(); - glfwos.OSMessageLoop(); - - deltat = glfwos.GetDeltaTime(); // Gets new Delta time - t_acu += deltat; - } - - return 0; -} - -// Init OpenGL ************************************************************ -void initGL(OS::OS& os) { - int OpenGLVersion[2]; - - // Use the GL3 way to get the version number - glGetIntegerv(GL_MAJOR_VERSION, &OpenGLVersion[0]); - glGetIntegerv(GL_MINOR_VERSION, &OpenGLVersion[1]); - std::cout << "OpenGL " << OpenGLVersion[0] << "." << OpenGLVersion[1] << "\n"; - - // Sanity check to make sure we are at least in a good major version number. - assert((OpenGLVersion[0] > 1) && (OpenGLVersion[0] < 5)); - - winWidth = os.GetWindowWidth(); winHeight = os.GetWindowHeight(); - - // Determine the aspect ratio and sanity check it to a safe ratio - GLfloat aspectRatio = static_cast(winWidth) / static_cast(winHeight); - if (aspectRatio < 1.0f) { - aspectRatio = 4.0f / 3.0f; + std::printf("Initiated OpenGL\n"); + + // Test screen + TDAScreen screen; + screen.txt_buffer[0] = 0x0F00 | 'H'; + screen.txt_buffer[1] = 0x1F00 | 'e'; + screen.txt_buffer[2] = 0x2F00 | 'l'; + screen.txt_buffer[3] = 0x3F00 | 'l'; + screen.txt_buffer[4] = 0x4F00 | 'o'; + screen.txt_buffer[5] = 0x5F00 | ' '; + screen.txt_buffer[6] = 0x6F00 | 'w'; + screen.txt_buffer[7] = 0x7F00 | 'o'; + screen.txt_buffer[8] = 0x8F00 | 'r'; + screen.txt_buffer[9] = 0x9F00 | 'l'; + screen.txt_buffer[10] = 0xAF00 | 'd'; + screen.txt_buffer[11] = 0xBF00 | '!'; + + screen.cursor = true; + screen.cur_col = 20; + screen.cur_row = 0; + screen.cur_start = 5; + screen.cur_end = 7; + screen.cur_color = 15; + + for (unsigned i= 40; i < WIDTH_CHARS*HEIGHT_CHARS; i++ ) { + Byte fg = i % 16; + Byte bg = (15 - i) % 16; + screen.txt_buffer[i] = (bg << 12) | (fg << 8) | ((i-40) % 256); } - // Projection matrix : 45° Field of View - proj = glm::perspective( - 45.0f, // FOV - aspectRatio, - 0.1f, // Near cliping plane - 10000.0f); // Far cliping plane - - glPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); - #if __APPLE__ - // GL_MULTISAMPLE are Core. - glEnable(GL_MULTISAMPLE); - #else - if (GLEW_ARB_multisample) { - glEnable(GL_MULTISAMPLE_ARB); - } - #endif - glEnable(GL_CULL_FACE); - glCullFace(GL_BACK); - - glEnable(GL_DEPTH_TEST); - // Accept fragment if it closer to the camera than the former one - glDepthFunc(GL_LESS); - - // Initialize VBOs ******************************************************** - glGenBuffers(1, &vertexbuffer); - glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer); - // Upload data to VBO - glBufferData(GL_ARRAY_BUFFER, sizeof(vdata), vdata, GL_STATIC_DRAW); + // Function to update texture from TDAScreen object + gl.SetTextureCB ([&screen] (void* tdata) { + // Update Texture callback + DWord* tex = (DWord*)tdata; + TDAtoRGBATexture(screen, tex); // Write the texture to the PBO buffer + }); - glGenBuffers(1, &colorbuffer); - glBindBuffer(GL_ARRAY_BUFFER, colorbuffer); - // Upload data to VBO - glBufferData(GL_ARRAY_BUFFER, sizeof(color_data), color_data, GL_STATIC_DRAW); + using namespace std::chrono; + auto clock = high_resolution_clock::now(); + double delta; // Time delta in seconds - glGenBuffers(1, &uvbuffer); - glBindBuffer(GL_ARRAY_BUFFER, uvbuffer); - // Upload data to VBO - glBufferData(GL_ARRAY_BUFFER, sizeof(uv_data), uv_data, GL_STATIC_DRAW); + bool loop = true; + while ( loop) { + // Calcs delta time - // Initialize PBO ********************************************************* - glGenBuffers(1, &tex_pbo); - glBindBuffer(GL_PIXEL_UNPACK_BUFFER, tex_pbo); - glBufferData(GL_PIXEL_UNPACK_BUFFER, 320*240*4, nullptr, GL_STREAM_DRAW); + auto oldClock = clock; + clock = high_resolution_clock::now(); + delta = duration_cast(clock - oldClock).count(); - // Initialize Texture ***************************************************** - glGenTextures(1, &screenTex); - glBindTexture(GL_TEXTURE_2D, screenTex); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 320, 240, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); - - //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - - // Loading shaders ******************************************************** - FILE* f_vs = nullptr; - FILE* f_fs = nullptr; -#if WIN32 - // TODO We should get path from HKEY_LOCAL_MACHINE\SOFTWARE\Trillek\Trillek VComputer - const std::string vertShaderFilename = "assets\\shaders\\mvp_template.vert"; - const std::string fragShaderFilename = "assets\\shaders\\retro_texture.frag"; - std::string programFilesPath = ""; - std::string path; - LPWSTR wszPath = nullptr; - HRESULT hr; - - hr = SHGetKnownFolderPath(FOLDERID_ProgramFiles, 0, NULL, &wszPath); - if (SUCCEEDED(hr) ) { - _bstr_t bstrPath(wszPath); - programFilesPath = (char*)bstrPath; - path = programFilesPath + "\\Trillek VComputer\\"+ vertShaderFilename; - std::clog << "Trying " << path << std::endl; - f_vs = std::fopen(path.c_str(), "r"); - - path = programFilesPath + "\\Trillek VComputer\\" + fragShaderFilename; - std::clog << "Trying " << path << std::endl; - f_fs = std::fopen(path.c_str(), "r"); - - CoTaskMemFree(wszPath); - } - - if (f_vs == nullptr) { - path = ".\\"+ vertShaderFilename; - std::clog << "Trying " << path << std::endl; - f_vs = std::fopen(path.c_str(), "r"); - } - if (f_fs == nullptr) { - path = ".\\"+ fragShaderFilename; - std::clog << "Trying " << path << std::endl; - f_fs = std::fopen(path.c_str(), "r"); - } -#else - const std::string vertShaderFilename = "assets/shaders/mvp_template.vert"; - const std::string fragShaderFilename = "assets/shaders/retro_texture.frag"; - std::string path = "./"+ vertShaderFilename; - std::clog << "Trying " << path << std::endl; - f_vs = std::fopen(path.c_str(), "r"); - if (f_vs == nullptr) { - path = "/usr/share/trillek-tools/"+ vertShaderFilename; - std::clog << "Trying " << path << std::endl; - f_vs = std::fopen(path.c_str(), "r"); - } - if (f_vs == nullptr) { - path = "/usr/local/share/trillek-tools/"+ vertShaderFilename; - std::clog << "Trying " << path << std::endl; - f_vs = std::fopen(path.c_str(), "r"); - } - if (f_vs == nullptr) { - path = "/opt/trillek-tools/"+ vertShaderFilename; - std::clog << "Trying " << path << std::endl; - f_vs = std::fopen(path.c_str(), "r"); - } - - path = "./"+ fragShaderFilename; - std::clog << "Trying " << path << std::endl; - f_fs = std::fopen(path.c_str(), "r"); - if (f_fs == nullptr) { - path = "/usr/share/trillek-tools/"+ fragShaderFilename; - std::clog << "Trying " << path << std::endl; - f_fs = std::fopen(path.c_str(), "r"); - } - if (f_fs == nullptr) { - path = "/usr/local/share/trillek-tools/"+ fragShaderFilename; - std::clog << "Trying " << path << std::endl; - f_fs = std::fopen(path.c_str(), "r"); - } - if (f_fs == nullptr) { - path = "/opt/trillek-tools/"+ fragShaderFilename; - std::clog << "Trying " << path << std::endl; - f_fs = std::fopen(path.c_str(), "r"); - } - -#endif - - if (f_vs != nullptr) { - fseek(f_vs, 0L, SEEK_END); - size_t bufsize = ftell(f_vs); - vertexSource = new GLchar[bufsize + 1](); - - fseek(f_vs, 0L, SEEK_SET); - auto t = fread(vertexSource, sizeof(GLchar), bufsize, f_vs); - if (t <= 0) { - std::cerr << "Error reading Vertex Shader\n"; - exit(-1); + if (glfwos.Closing()) { + loop = false; + continue; } - - fclose(f_vs); - vertexSource[bufsize] = 0; // Enforce null char - } else { - std::cerr << "Can't load Vertex Shader\n"; - exit(-1); - } - - if (f_fs != nullptr) { - fseek(f_fs, 0L, SEEK_END); - size_t bufsize = ftell(f_fs); - fragmentSource = new GLchar[bufsize +1 ](); - - fseek(f_fs, 0L, SEEK_SET); - auto t = fread(fragmentSource, sizeof(GLchar), bufsize, f_fs); - if (t <= 0) { - std::cerr << "Error reading Fragment Shader\n"; - exit(-1); + // Ugly hack + for(unsigned long i=0; i < 10000000 ; i++) { + ; } - fclose(f_fs); - fragmentSource[bufsize] = 0; // Enforce null char - } else { - std::cerr << "Can't load Fragment Shader\n"; - exit(-1); + gl.UpdScreen (glfwos, delta); } - // Assign our handles a "name" to new shader objects - vertexShader = glCreateShader(GL_VERTEX_SHADER); - fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); - - // Associate the source code buffers with each handle - glShaderSource(vertexShader, 1, (const GLchar**)&vertexSource, 0); - glShaderSource(fragmentShader, 1, (const GLchar**)&fragmentSource, 0); - - // Compile our shader objects - glCompileShader(vertexShader); - glCompileShader(fragmentShader); - - if (vertexSource != nullptr) - delete[] vertexSource; - - if (fragmentSource != nullptr) - delete[] fragmentSource; - - - GLint Result = GL_FALSE; - int InfoLogLength; - - // Vertex Shader compiling error messages - glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &Result); - glGetShaderiv(vertexShader, GL_INFO_LOG_LENGTH, &InfoLogLength); - std::vector VertexShaderErrorMessage(InfoLogLength); - glGetShaderInfoLog(vertexShader, InfoLogLength, NULL, &VertexShaderErrorMessage[0]); - std::printf("%s\n", &VertexShaderErrorMessage[0]); - - // Fragment Shader compiling error messages - glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &Result); - glGetShaderiv(fragmentShader, GL_INFO_LOG_LENGTH, &InfoLogLength); - std::vector FragmentShaderErrorMessage(InfoLogLength); - glGetShaderInfoLog(fragmentShader, InfoLogLength, NULL, &FragmentShaderErrorMessage[0]); - std::printf("%s\n", &FragmentShaderErrorMessage[0]); - - - // Assign our program handle a "name" - shaderProgram = glCreateProgram(); - - // Attach our shaders to our program - glAttachShader(shaderProgram, vertexShader); - glAttachShader(shaderProgram, fragmentShader); - - // Link shader program - glLinkProgram(shaderProgram); - - - // Bind attributes indexes - glBindAttribLocation(shaderProgram, sh_in_Position, "in_Position"); - glBindAttribLocation(shaderProgram, sh_in_Color, "in_Color"); - glBindAttribLocation(shaderProgram, sh_in_UV, "in_UV"); - - modelId = glGetUniformLocation(shaderProgram, "in_Model"); - viewId = glGetUniformLocation(shaderProgram, "in_View"); - projId = glGetUniformLocation(shaderProgram, "in_Proj"); - - timeId = glGetUniformLocation(shaderProgram, "time"); - - - glDeleteShader(vertexShader); - glDeleteShader(fragmentShader); - - - // Camera matrix - view = glm::lookAt( - glm::vec3(3,3,7), // Camera is at (3,3,7), in World Space - glm::vec3(0,0,0), // and looks at the origin - glm::vec3(0,1,0) // Head is up (set to 0,-1,0 to look upside-down) - ); - - + // Cleanup all the things we bound and allocated + /* + glUseProgram(0); + glDisableVertexAttribArray(sh_in_Position); + glDisableVertexAttribArray(sh_in_Color); + glDisableVertexAttribArray(sh_in_UV); + /*glDetachShader(shaderprogram, vertexshader); + glDetachShader(shaderprogram, fragmentshader); + glDeleteProgram(shaderprogram); + glDeleteShader(vertexshader); + glDeleteShader(fragmentshader);*/ /* + glDeleteBuffers(3, vbo); + glDeleteVertexArrays(1, &vao); + */ + glfwos.Terminate(); + return 0; } -