From de5a458cb037bb8e1e80c849c5e6525f9413b43a Mon Sep 17 00:00:00 2001 From: Kelly Rauchenberger Date: Sat, 14 Feb 2015 12:09:41 -0500 Subject: Monitor stuff is looking pretty cool! --- .gitignore | 2 + CMakeLists.txt | 33 +++ maps/bigmap.txt | 25 +++ maps/testmap.txt | 16 ++ res/artifacts.bmp | Bin 0 -> 192056 bytes res/scanlines.bmp | Bin 0 -> 236 bytes res/tiles.bmp | Bin 0 -> 196664 bytes shaders/blit.fragment | 12 + shaders/blit.vertex | 13 ++ shaders/fill.fragment | 10 + shaders/fill.vertex | 8 + shaders/final.fragment | 56 +++++ shaders/final.vertex | 14 ++ shaders/ntsc.fragment | 64 ++++++ shaders/ntsc.vertex | 11 + src/main.cpp | 149 +++++++++++++ src/map.cpp | 241 ++++++++++++++++++++ src/map.h | 42 ++++ src/mob.h | 10 + src/renderer.cpp | 582 +++++++++++++++++++++++++++++++++++++++++++++++++ src/renderer.h | 42 ++++ 21 files changed, 1330 insertions(+) create mode 100644 .gitignore create mode 100644 CMakeLists.txt create mode 100644 maps/bigmap.txt create mode 100644 maps/testmap.txt create mode 100644 res/artifacts.bmp create mode 100644 res/scanlines.bmp create mode 100644 res/tiles.bmp create mode 100644 shaders/blit.fragment create mode 100644 shaders/blit.vertex create mode 100644 shaders/fill.fragment create mode 100644 shaders/fill.vertex create mode 100644 shaders/final.fragment create mode 100644 shaders/final.vertex create mode 100644 shaders/ntsc.fragment create mode 100644 shaders/ntsc.vertex create mode 100644 src/main.cpp create mode 100644 src/map.cpp create mode 100644 src/map.h create mode 100644 src/mob.h create mode 100644 src/renderer.cpp create mode 100644 src/renderer.h diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d76b74e --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +build +.DS_Store diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..c0e0339 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,33 @@ +cmake_minimum_required(VERSION 2.6) +project(Aromatherapy) + +# Use our modified FindSDL2* modules +set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${Aromatherapy_SOURCE_DIR}/cmake") +# Set an output directory for our binaries +set(BIN_DIR ${Aromatherapy_SOURCE_DIR}/bin) + +# Bump up warning levels appropriately for clang, gcc & msvc +# Also set debug/optimization flags depending on the build type. IDE users choose this when +# selecting the build mode in their IDE +if (${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU" OR ${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -pedantic -std=c++11") + set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_DEBUG} -g") + set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_RELEASE} -O2") +elseif (${CMAKE_CXX_COMPILER_ID} STREQUAL "MSVC") + if (CMAKE_CXX_FLAGS MATCHES "/W[0-4]") + string(REGEX REPLACE "/W[0-4]" "/W4" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") + else() + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4") + endif() +endif() + +# Look up SDL2 and add the include directory to our include path +find_package(OpenGL REQUIRED) +find_package(GLEW REQUIRED) +find_package(GLFW REQUIRED) + +# include_directories(${SDL2_INCLUDE_DIR}) +set(CMAKE_BUILD_TYPE Debug) +add_executable(Aromatherapy src/main.cpp src/map.cpp src/renderer.cpp) +target_link_libraries(Aromatherapy ${OPENGL_LIBRARY} ${GLEW_LIBRARY} ${GLFW_LIBRARY}) +install(TARGETS Aromatherapy RUNTIME DESTINATION ${BIN_DIR}) diff --git a/maps/bigmap.txt b/maps/bigmap.txt new file mode 100644 index 0000000..ac5e9e2 --- /dev/null +++ b/maps/bigmap.txt @@ -0,0 +1,25 @@ +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +XXXXXXXXXXXXXXXXXXXXXXXXX XX +XXXXXXXXXXXXXXXXXXXXXX X +XXXXXXXXXXXXXXXXX X +XXXXXXXXXXXXXX X +XXXXXXXXXXXXXX XXXX +XXXXXXXXXXXX XXXXXX +XXXXXXX XXXXXXX +XXX XXXXXXXXXXXX + XXXXXX + + PPPP + + PPPPPP + PPPP + + + PPPP + + + XXXXXXXXXXXXXXXXXXXX + XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX \ No newline at end of file diff --git a/maps/testmap.txt b/maps/testmap.txt new file mode 100644 index 0000000..7fc55ab --- /dev/null +++ b/maps/testmap.txt @@ -0,0 +1,16 @@ +XXXXXXXXXXXXXXXX +XXXXXX XXXXXX +XX X +X X +X XXXX + PPPP + + PPPP + + PPPP + + +XXXXXXXX X +XXXP XX +XXXX XXX +XXXXXXXXXXXXXXXX diff --git a/res/artifacts.bmp b/res/artifacts.bmp new file mode 100644 index 0000000..b350c42 Binary files /dev/null and b/res/artifacts.bmp differ diff --git a/res/scanlines.bmp b/res/scanlines.bmp new file mode 100644 index 0000000..5a9c404 Binary files /dev/null and b/res/scanlines.bmp differ diff --git a/res/tiles.bmp b/res/tiles.bmp new file mode 100644 index 0000000..a873b2a Binary files /dev/null and b/res/tiles.bmp differ diff --git a/shaders/blit.fragment b/shaders/blit.fragment new file mode 100644 index 0000000..07a0279 --- /dev/null +++ b/shaders/blit.fragment @@ -0,0 +1,12 @@ +#version 330 core + +in vec2 UV; + +out vec3 color; + +uniform sampler2D srctex; + +void main() +{ + color = texture(srctex, UV).xyz; +} diff --git a/shaders/blit.vertex b/shaders/blit.vertex new file mode 100644 index 0000000..4a9aa6a --- /dev/null +++ b/shaders/blit.vertex @@ -0,0 +1,13 @@ +#version 330 core + +layout(location = 0) in vec2 vertexPosition; +layout(location = 1) in vec2 texcoordPosition; + +out vec2 UV; + +void main() +{ + gl_Position = vec4(vertexPosition, 0.0f, 1.0f); + + UV = texcoordPosition; +} diff --git a/shaders/fill.fragment b/shaders/fill.fragment new file mode 100644 index 0000000..ab7d9c9 --- /dev/null +++ b/shaders/fill.fragment @@ -0,0 +1,10 @@ +#version 330 core + +out vec3 color; + +uniform vec3 vecColor; + +void main() +{ + color = vecColor; +} diff --git a/shaders/fill.vertex b/shaders/fill.vertex new file mode 100644 index 0000000..44445fe --- /dev/null +++ b/shaders/fill.vertex @@ -0,0 +1,8 @@ +#version 330 core + +layout(location = 0) in vec3 vertexPosition; + +void main() +{ + gl_Position = vec4(vertexPosition, 1); +} diff --git a/shaders/final.fragment b/shaders/final.fragment new file mode 100644 index 0000000..c900973 --- /dev/null +++ b/shaders/final.fragment @@ -0,0 +1,56 @@ +#version 330 core + +in vec2 UV; +in vec3 norm; + +out vec3 color; + +uniform sampler2D rendertex; +uniform sampler2D scanlinestex; + +const vec2 UVScalar = vec2(1.0, 1.0); +const vec2 UVOffset = vec2(0.0, 0.0); +const vec2 CRTMask_Scale = vec2(85.0, 153.6); +const vec2 CRTMask_Offset = vec2(0.0, 0.0); +const float Tuning_Overscan = 1.0; +const float Tuning_Dimming = 0.5; +const float Tuning_Satur = 1.35; +const float Tuning_ReflScalar = 0.3; +const float Tuning_Barrel = 0.12; +const float Tuning_Scanline_Brightness = 0.25; +const float Tuning_Scanline_Opacity = 0.5; +const float Tuning_Diff_Brightness = 0.5; +const float Tuning_Spec_Brightness = 0.35; +const float Tuning_Spec_Power = 50.0; +const float Tuning_Fres_Brightness = 1.0; +const vec3 Tuning_LightPos = vec3(5.0, -10.0, 0.0); + +vec4 sampleCRT(vec2 uv) +{ + vec2 ScaledUV = uv; + ScaledUV *= UVScalar; + ScaledUV += UVOffset; + + vec2 scanuv = ScaledUV * CRTMask_Scale; + vec3 scantex = texture(scanlinestex, scanuv).rgb; + scantex += Tuning_Scanline_Brightness; + scantex = mix(vec3(1,1,1), scantex, Tuning_Scanline_Opacity); + + vec2 overscanuv = (ScaledUV * Tuning_Overscan) - ((Tuning_Overscan - 1.0f) * 0.5f); + overscanuv = overscanuv - vec2(0.5, 0.5); + float rsq = (overscanuv.x*overscanuv.x) + (overscanuv.y*overscanuv.y); + overscanuv = overscanuv + (overscanuv * (Tuning_Barrel * rsq)) + vec2(0.5,0.5); + + vec3 comptex = texture(rendertex, overscanuv).rgb; + + vec4 emissive = vec4(comptex * scantex, 1); + float desat = dot(vec4(0.299, 0.587, 0.114, 0.0), emissive); + emissive = mix(vec4(desat, desat, desat, 1), emissive, Tuning_Satur); + + return emissive; +} + +void main() +{ + color = sampleCRT(UV).rgb; +} diff --git a/shaders/final.vertex b/shaders/final.vertex new file mode 100644 index 0000000..825eb49 --- /dev/null +++ b/shaders/final.vertex @@ -0,0 +1,14 @@ +#version 330 core + +layout(location = 0) in vec3 vertexPosition_modelspace; +layout(location = 1) in vec3 vertexNormal; + +out vec2 UV; +out vec3 norm; + +void main() +{ + gl_Position = vec4(vertexPosition_modelspace,1); + UV = (vertexPosition_modelspace.xy+vec2(1,1))/2.0; + norm = vertexNormal; +} diff --git a/shaders/ntsc.fragment b/shaders/ntsc.fragment new file mode 100644 index 0000000..12d6873 --- /dev/null +++ b/shaders/ntsc.fragment @@ -0,0 +1,64 @@ +#version 330 core + +in vec2 UV; + +out vec3 color; + +uniform sampler2D curFrameSampler; +uniform sampler2D NTSCArtifactSampler; +uniform sampler2D prevFrameSampler; + +const float Tuning_Sharp = 0.8; +const vec4 Tuning_Persistence = vec4(0.7,0.7,0.7,0.7); +const float Tuning_Bleed = 0.5; +const float Tuning_NTSC = 0.35; +uniform float NTSCLerp; + +const vec2 RcpScrWidth = vec2(1.0f / 320.f, 0.0f); +const vec2 RcpScrHeight = vec2(0.0f, 1.0f / 200.0f); + +float Brightness(vec4 InVal) +{ + return dot(InVal, vec4(0.299, 0.587, 0.114, 0.0)); +} + +const float SharpWeight[3] = float[3](1.0, -0.3162277, 0.1); + +void main() +{ + vec4 NTSCArtifact1 = texture(NTSCArtifactSampler, UV); + vec4 NTSCArtifact2 = texture(NTSCArtifactSampler, UV + RcpScrHeight); + vec4 NTSCArtifact = mix(NTSCArtifact1, NTSCArtifact2, NTSCLerp); + + vec2 LeftUV = UV - RcpScrWidth; + vec2 RightUV = UV + RcpScrWidth; + + vec4 Cur_Left = texture(curFrameSampler, LeftUV); + vec4 Cur_Local = texture(curFrameSampler, UV); + vec4 Cur_Right = texture(curFrameSampler, RightUV); + + vec4 Prev_Left = texture(prevFrameSampler, LeftUV); + vec4 Prev_Local = texture(prevFrameSampler, UV); + vec4 Prev_Right = texture(prevFrameSampler, RightUV); + + Cur_Local = clamp(Cur_Local + (((Cur_Left - Cur_Local) + (Cur_Right - Cur_Local)) * Tuning_NTSC), vec4(0,0,0,0), vec4(1,1,1,1)); + + float curBrt = Brightness(Cur_Local); + float offset = 0; + + for (int i=0; i<3; ++i) + { + vec2 StepSize = (RcpScrWidth * float(i+1)); + vec4 neighborleft = texture(curFrameSampler, UV - StepSize); + vec4 neighborright = texture(curFrameSampler, UV + StepSize); + + float NBrtL = Brightness(neighborleft); + float NBrtR = Brightness(neighborright); + offset += ((curBrt - NBrtL) + (curBrt - NBrtR)) * SharpWeight[i]; + } + + Cur_Local = clamp(Cur_Local + (offset * Tuning_Sharp * mix(vec4(1,1,1,1), NTSCArtifact, Tuning_NTSC)), vec4(0,0,0,0), vec4(1,1,1,1)); + Cur_Local = clamp(max(Cur_Local, Tuning_Persistence * (1.0 / (1.0 + (2.0 * Tuning_Bleed))) * (Prev_Local + ((Prev_Left + Prev_Right) * Tuning_Bleed))), vec4(0,0,0,0), vec4(1,1,1,1)); + + color = Cur_Local.xyz; +} diff --git a/shaders/ntsc.vertex b/shaders/ntsc.vertex new file mode 100644 index 0000000..81f8af3 --- /dev/null +++ b/shaders/ntsc.vertex @@ -0,0 +1,11 @@ +#version 330 core + +layout(location = 0) in vec3 vertexPosition_modelspace; + +out vec2 UV; + +void main() +{ + gl_Position = vec4(vertexPosition_modelspace,1); + UV = (vertexPosition_modelspace.xy+vec2(1,1))/2.0; +} diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..a2743d1 --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,149 @@ +#include +#include +#include "map.h" +#include "renderer.h" + +using namespace::std; + +#if defined(__WIN32__) || defined(_WIN32) || defined(WIN32) || defined(__WINDOWS__) || defined(__TOS_WIN__) + + #include + + inline void delay( unsigned long ms ) + { + Sleep( ms ); + } + +#else /* presume POSIX */ + + #include + + inline void delay( unsigned long ms ) + { + usleep( ms * 1000 ); + } + +#endif + +const int FRAMES_PER_SECOND = 60; +bool holding_left = false; +bool holding_right = false; +bool quit = false; +mob_t* player; + +// Initialize jump physics +double jump_height = TILE_HEIGHT*3; +double jump_length = 0.25 * FRAMES_PER_SECOND; +double jump_velocity = -2 * jump_height / jump_length; +double jump_gravity = -1 * jump_velocity / jump_length; + +void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) +{ + if (action == GLFW_PRESS) + { + switch (key) + { + case GLFW_KEY_LEFT: holding_left = true; break; + case GLFW_KEY_RIGHT: holding_right = true; break; + case GLFW_KEY_UP: player->y_vel = jump_velocity; break; + case GLFW_KEY_ESCAPE: quit = true; break; + } + } else if (action == GLFW_RELEASE) + { + switch (key) + { + case GLFW_KEY_LEFT: holding_left = false; break; + case GLFW_KEY_RIGHT: holding_right = false; break; + } + } +} + +int main() +{ + GLFWwindow* window = initRenderer(); + glfwSwapInterval(1); + glfwSetKeyCallback(window, key_callback); + + Texture* buffer = createTexture(GAME_WIDTH, GAME_HEIGHT); + + // Initialize player data + player = new mob_t(); + player->x = 100; + player->y = 100; + player->x_vel = 0; + player->y_vel = 0; + player->x_accel = 0; + player->y_accel = jump_gravity; + player->w = 10; + player->h = 14; + + Map* map = new Map(); + + Texture* tiles = loadTextureFromBMP("../res/tiles.bmp"); + + double lastTime = glfwGetTime(); + int nbFrames = 0; + + while (!quit) + { + double currentTime = glfwGetTime(); + nbFrames++; + if ( currentTime - lastTime >= 1.0 ){ // If last prinf() was more than 1 sec ago + // printf and reset timer + printf("%f ms/frame\n", 1000.0/double(nbFrames)); + nbFrames = 0; + lastTime += 1.0; + } + + if (holding_left && player->x_vel >= 0) + { + player->x_vel = -2; + } else if (holding_right && player->x_vel <= 0) + { + player->x_vel = 2; + } else if (!holding_left && !holding_right) { + player->x_vel = 0; + } + + player->x_vel += player->x_accel; + if (player->x_vel < -16) player->x_vel = -16; + if (player->x_vel > 16) player->x_vel = 16; + int playerx_next = player->x + player->x_vel; + + player->y_vel += player->y_accel; + if (player->y_vel > 16) player->y_vel = 16; // Terminal velocity + if (player->y_vel < -16) player->y_vel = -16; + int playery_next = player->y + player->y_vel; + + map->check_collisions(player, playerx_next, playery_next); + + // Do rendering + map->render(buffer); + + //Rectangle src_rect(96, 0, 8, 8); + Rectangle dst_rect(player->x, player->y, player->w, player->h); + + //blitTexture(tiles, buffer, &src_rect, &dst_rect); + fillTexture(buffer, &dst_rect, 85, 85, 255); + //fillTexture(buffer, NULL, 85, 85, 0); + + renderScreen(buffer); + + //fuckThePolice(buffer); + + glfwPollEvents(); + + // Regulate frame rate + /*if ((clock() - frame_start) < CLOCKS_PER_SEC / FRAMES_PER_SECOND) + { + //delay(((CLOCKS_PER_SEC / FRAMES_PER_SECOND) - clock() + frame_start) * CLOCKS_PER_SEC / 1000); + }*/ + } + + delete map; + delete player; + + destroyRenderer(); + + return 0; +} diff --git a/src/map.cpp b/src/map.cpp new file mode 100644 index 0000000..10cd313 --- /dev/null +++ b/src/map.cpp @@ -0,0 +1,241 @@ +#include "map.h" + +struct platform_t { + int x; + int y; + int w; + int h; + bool enter_from_left; + bool enter_from_right; + bool enter_from_top; + bool enter_from_bottom; + int r; + int g; + int b; + int a; +}; + +Map::Map() +{ + add_collision(-6, 0, GAME_WIDTH, left, 1); + add_collision(GAME_WIDTH+6, 0, GAME_WIDTH, right, 1); + + FILE* f = fopen("../maps/bigmap.txt", "r"); + char* mapbuf = (char*) malloc(MAP_WIDTH*MAP_HEIGHT*sizeof(char)); + + for (int i=0; i::iterator it; + + switch (dir) + { + case up: + it = up_collisions.begin(); + for (; it!=up_collisions.end(); it++) + { + if (it->axis < axis) break; + } + + up_collisions.insert(it, {axis, lower, upper, type}); + + break; + case down: + it = down_collisions.begin(); + for (; it!=down_collisions.end(); it++) + { + if (it->axis > axis) break; + } + + down_collisions.insert(it, {axis, lower, upper, type}); + + break; + case left: + it = left_collisions.begin(); + for (; it!=left_collisions.end(); it++) + { + if (it->axis < axis) break; + } + + left_collisions.insert(it, {axis, lower, upper, type}); + + break; + case right: + it = right_collisions.begin(); + for (; it!=right_collisions.end(); it++) + { + if (it->axis > axis) break; + } + + right_collisions.insert(it, {axis, lower, upper, type}); + + break; + } +} + +void Map::check_collisions(mob_t* mob, int x_next, int y_next) +{ + if (x_next < mob->x) + { + for (list::iterator it=left_collisions.begin(); it!=left_collisions.end(); it++) + { + if (it->axis > mob->x) continue; + if (it->axis < x_next) break; + + if ((mob->y+mob->h > it->lower) && (mob->y < it->upper)) + { + // We have a collision! + if (it->type == 0) + { + x_next = it->axis; + mob->x_vel = 0; + } else if (it->type == 1) + { + x_next = GAME_WIDTH-mob->w/2; + } + + break; + } + } + } else if (x_next > mob->x) + { + for (list::iterator it=right_collisions.begin(); it!=right_collisions.end(); it++) + { + if (it->axis < mob->x+mob->w) continue; + if (it->axis > x_next+mob->w) break; + + if ((mob->y+mob->h > it->lower) && (mob->y < it->upper)) + { + // We have a collision! + if (it->type == 0) + { + x_next = it->axis - mob->w; + mob->x_vel = 0; + } else if (it->type == 1) + { + x_next = -mob->w/2; + } + + break; + } + } + } + + mob->x = x_next; + + if (y_next < mob->y) + { + for (list::iterator it=up_collisions.begin(); it!=up_collisions.end(); it++) + { + if (it->axis > mob->y) continue; + if (it->axis < y_next) break; + + if ((mob->x+mob->w > it->lower) && (mob->x < it->upper)) + { + // We have a collision! + if (it->type == 0) + { + y_next = it->axis; + mob->y_vel = 0; + } else if (it->type == 1) + { + y_next = GAME_HEIGHT-mob->h/2-1; + } + + break; + } + } + } else if (y_next > mob->y) + { + for (list::iterator it=down_collisions.begin(); it!=down_collisions.end(); it++) + { + if (it->axis < mob->y+mob->h) continue; + if (it->axis > y_next+mob->h) break; + + if ((mob->x+mob->w > it->lower) && (mob->x < it->upper)) + { + // We have a collision! + if (it->type == 0) + { + y_next = it->axis - mob->h; + mob->y_vel = 0; + } else if (it->type == 1) + { + y_next = 1 - mob->h/2; + } + + break; + } + } + } + + mob->y = y_next; +} + +void Map::render(Texture* buffer) +{ + blitTexture(bg, buffer, NULL, NULL); +} diff --git a/src/map.h b/src/map.h new file mode 100644 index 0000000..7986e0d --- /dev/null +++ b/src/map.h @@ -0,0 +1,42 @@ +#include +#include +#include "mob.h" +#include "renderer.h" + +using namespace::std; + +const int TILE_WIDTH = 8; +const int TILE_HEIGHT = 8; +const int GAME_WIDTH = 320; +const int GAME_HEIGHT = 200; +const int MAP_WIDTH = GAME_WIDTH/TILE_WIDTH; +const int MAP_HEIGHT = GAME_HEIGHT/TILE_HEIGHT; + +enum direction_t { + up, left, down, right +}; + +typedef struct { + int axis; + int lower; + int upper; + int type; +} collision_t; + +class Map { +public: + Map(); + ~Map(); + void render(Texture* buffer); + void check_collisions(mob_t* mob, int x_next, int y_next); + +private: + void add_collision(int axis, int lower, int upper, direction_t dir, int type); + + list left_collisions; + list right_collisions; + list up_collisions; + list down_collisions; + + Texture* bg; +}; \ No newline at end of file diff --git a/src/mob.h b/src/mob.h new file mode 100644 index 0000000..7a4b707 --- /dev/null +++ b/src/mob.h @@ -0,0 +1,10 @@ +typedef struct { + int x; + int y; + double x_vel; + double y_vel; + double x_accel; + double y_accel; + int w; + int h; +} mob_t; diff --git a/src/renderer.cpp b/src/renderer.cpp new file mode 100644 index 0000000..e74c6a4 --- /dev/null +++ b/src/renderer.cpp @@ -0,0 +1,582 @@ +#include "renderer.h" +#include +#include +#include +#include +#include "map.h" + +static bool rendererInitialized = false; + +static GLFWwindow* window; + +static GLuint FramebufferName; // The framebuffer +static GLuint ntscShader; // The NTSC shader +static GLuint finalShader; // The passthrough shader +static GLuint blitShader; // The blitting shader +static GLuint fillShader; // The fill shader + +// The buffers for the NTSC rendering process +static GLuint renderedTex1; +static GLuint renderedTex2; +static GLuint renderedTexBufs[2]; +static int curBuf; +static GLuint artifactsTex; +static GLuint scanlinesTex; + +GLuint LoadShaders(const char* vertex_file_path, const char* fragment_file_path) +{ + // Create the shaders + GLuint VertexShaderID = glCreateShader(GL_VERTEX_SHADER); + GLuint FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER); + + // Read the Vertex Shader code from the file + std::string VertexShaderCode; + std::ifstream VertexShaderStream(vertex_file_path, std::ios::in); + if(VertexShaderStream.is_open()) + { + std::string Line = ""; + while(getline(VertexShaderStream, Line)) + VertexShaderCode += "\n" + Line; + VertexShaderStream.close(); + } + + // Read the Fragment Shader code from the file + std::string FragmentShaderCode; + std::ifstream FragmentShaderStream(fragment_file_path, std::ios::in); + if(FragmentShaderStream.is_open()){ + std::string Line = ""; + while(getline(FragmentShaderStream, Line)) + FragmentShaderCode += "\n" + Line; + FragmentShaderStream.close(); + } + + GLint Result = GL_FALSE; + int InfoLogLength; + + // Compile Vertex Shader + printf("Compiling shader : %s\n", vertex_file_path); + char const * VertexSourcePointer = VertexShaderCode.c_str(); + glShaderSource(VertexShaderID, 1, &VertexSourcePointer , NULL); + glCompileShader(VertexShaderID); + + // Check Vertex Shader + glGetShaderiv(VertexShaderID, GL_COMPILE_STATUS, &Result); + glGetShaderiv(VertexShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength); + std::vector VertexShaderErrorMessage(InfoLogLength); + glGetShaderInfoLog(VertexShaderID, InfoLogLength, NULL, &VertexShaderErrorMessage[0]); + fprintf(stdout, "%s\n", &VertexShaderErrorMessage[0]); + + // Compile Fragment Shader + printf("Compiling shader : %s\n", fragment_file_path); + char const * FragmentSourcePointer = FragmentShaderCode.c_str(); + glShaderSource(FragmentShaderID, 1, &FragmentSourcePointer , NULL); + glCompileShader(FragmentShaderID); + + // Check Fragment Shader + glGetShaderiv(FragmentShaderID, GL_COMPILE_STATUS, &Result); + glGetShaderiv(FragmentShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength); + std::vector FragmentShaderErrorMessage(InfoLogLength); + glGetShaderInfoLog(FragmentShaderID, InfoLogLength, NULL, &FragmentShaderErrorMessage[0]); + fprintf(stdout, "%s\n", &FragmentShaderErrorMessage[0]); + + // Link the program + fprintf(stdout, "Linking program\n"); + GLuint ProgramID = glCreateProgram(); + glAttachShader(ProgramID, VertexShaderID); + glAttachShader(ProgramID, FragmentShaderID); + glLinkProgram(ProgramID); + + // Check the program + glGetProgramiv(ProgramID, GL_LINK_STATUS, &Result); + glGetProgramiv(ProgramID, GL_INFO_LOG_LENGTH, &InfoLogLength); + std::vector ProgramErrorMessage( glm::max(InfoLogLength, int(1)) ); + glGetProgramInfoLog(ProgramID, InfoLogLength, NULL, &ProgramErrorMessage[0]); + fprintf(stdout, "%s\n", &ProgramErrorMessage[0]); + + glDeleteShader(VertexShaderID); + glDeleteShader(FragmentShaderID); + + return ProgramID; +} + +GLuint loadBMP_custom(const char * imagepath){ + + printf("Reading image %s\n", imagepath); + + // Data read from the header of the BMP file + unsigned char header[54]; + unsigned int dataPos; + unsigned int imageSize; + unsigned int width, height; + // Actual RGB data + unsigned char * data; + + // Open the file + FILE * file = fopen(imagepath,"rb"); + if (!file) {printf("%s could not be opened. Are you in the right directory ? Don't forget to read the FAQ !\n", imagepath); getchar(); return 0;} + + // Read the header, i.e. the 54 first bytes + + // If less than 54 bytes are read, problem + if ( fread(header, 1, 54, file)!=54 ){ + printf("Not a correct BMP file\n"); + return 0; + } + // A BMP files always begins with "BM" + if ( header[0]!='B' || header[1]!='M' ){ + printf("Not a correct BMP file\n"); + return 0; + } + // Make sure this is a 24bpp file + if ( *(int*)&(header[0x1E])!=0 ) {printf("Not a correct BMP file\n"); return 0;} + if ( *(int*)&(header[0x1C])!=24 ) {printf("Not a correct BMP file\n"); return 0;} + + // Read the information about the image + dataPos = *(int*)&(header[0x0A]); + imageSize = *(int*)&(header[0x22]); + width = *(int*)&(header[0x12]); + height = *(int*)&(header[0x16]); + + // Some BMP files are misformatted, guess missing information + if (imageSize==0) imageSize=width*height*3; // 3 : one byte for each Red, Green and Blue component + if (dataPos==0) dataPos=54; // The BMP header is done that way + + // Create a buffer + data = new unsigned char [imageSize]; + + // Read the actual data from the file into the buffer + fread(data,1,imageSize,file); + + // Everything is in memory now, the file wan be closed + fclose (file); + + // Create one OpenGL texture + GLuint textureID; + glGenTextures(1, &textureID); + + // "Bind" the newly created texture : all future texture functions will modify this texture + glBindTexture(GL_TEXTURE_2D, textureID); + + // Give the image to OpenGL + glTexImage2D(GL_TEXTURE_2D, 0,GL_RGB, width, height, 0, GL_BGR, GL_UNSIGNED_BYTE, data); + + // OpenGL has now copied the data. Free our own version + delete [] data; + + // Poor filtering, or ... + //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + + // ... nice trilinear filtering. + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + glGenerateMipmap(GL_TEXTURE_2D); + + // Return the ID of the texture we just created + return textureID; +} + +GLFWwindow* initRenderer() +{ + if (rendererInitialized) + { + fprintf(stderr, "Renderer already initialized\n"); + exit(-1); + } + + // Initialize GLFW + if (!glfwInit()) + { + fprintf(stderr, "Failed to initialize GLFW\n"); + exit(-1); + } + + glfwWindowHint(GLFW_SAMPLES, 4); // 4x antialiasing + glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); // We want version 3.3 + glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); + glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // Mac requires this + glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); + + // Create a window + window = glfwCreateWindow(1024, 768, "Aromatherapy", NULL, NULL); + if (window == NULL) + { + fprintf(stderr, "Failed to open GLFW window\n"); + glfwTerminate(); + exit(-1); + } + + glfwMakeContextCurrent(window); + glewExperimental = true; // Needed in core profile + if (glewInit() != GLEW_OK) + { + fprintf(stderr, "Failed to initialize GLEW\n"); + exit(-1); + } + + // Set up vertex array object + GLuint VertexArrayID; + glGenVertexArrays(1, &VertexArrayID); + glBindVertexArray(VertexArrayID); + + // Set up the framebuffer + glGenFramebuffers(1, &FramebufferName); + glBindFramebuffer(GL_FRAMEBUFFER, FramebufferName); + GLenum DrawBuffers[1] = {GL_COLOR_ATTACHMENT0}; + glDrawBuffers(1, DrawBuffers); + + // Set up the NTSC rendering buffers + glGenTextures(1, &renderedTex1); + glBindTexture(GL_TEXTURE_2D, renderedTex1); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, GAME_WIDTH, GAME_HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, 0); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + 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); + renderedTexBufs[0] = renderedTex1; + + glGenTextures(1, &renderedTex2); + glBindTexture(GL_TEXTURE_2D, renderedTex2); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, GAME_WIDTH, GAME_HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, 0); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + 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); + renderedTexBufs[1] = renderedTex2; + + curBuf = 0; + + artifactsTex = loadBMP_custom("../res/artifacts.bmp"); + scanlinesTex = loadBMP_custom("../res/scanlines.bmp"); + + // Load the shaders + ntscShader = LoadShaders("../shaders/ntsc.vertex", "../shaders/ntsc.fragment"); + finalShader = LoadShaders("../shaders/final.vertex", "../shaders/final.fragment"); + blitShader = LoadShaders("../shaders/blit.vertex", "../shaders/blit.fragment"); + fillShader = LoadShaders("../shaders/fill.vertex", "../shaders/fill.fragment"); + + rendererInitialized = true; + + return window; +} + +void destroyRenderer() +{ + if (!rendererInitialized) + { + fprintf(stderr, "Renderer not initialized\n"); + exit(-1); + } + + // Delete the shaders + glDeleteProgram(ntscShader); + glDeleteProgram(finalShader); + glDeleteProgram(blitShader); + glDeleteProgram(fillShader); + + // Delete the NTSC rendering buffers + glDeleteTextures(1, &renderedTex1); + glDeleteTextures(1, &renderedTex2); + glDeleteTextures(1, &artifactsTex); + glDeleteTextures(1, &scanlinesTex); + + // Delete the framebuffer + glDeleteFramebuffers(1, &FramebufferName); + + // Kill the window + glfwTerminate(); + + rendererInitialized = false; +} + +Texture* createTexture(int width, int height) +{ + if (!rendererInitialized) + { + fprintf(stderr, "Renderer not initialized\n"); + exit(-1); + } + + Texture* tex = new Texture(); + tex->width = width; + tex->height = height; + + glGenTextures(1, &(tex->texID)); + glBindTexture(GL_TEXTURE_2D, tex->texID); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, 0); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + + return tex; +} + +void destroyTexture(Texture* tex) +{ + if (!rendererInitialized) + { + fprintf(stderr, "Renderer not initialized\n"); + exit(-1); + } + + glDeleteTextures(1, &(tex->texID)); + + delete tex; +} + +Texture* loadTextureFromBMP(char* filename) +{ + if (!rendererInitialized) + { + fprintf(stderr, "Renderer not initialized\n"); + exit(-1); + } + + Texture* tex = new Texture(); + tex->texID = loadBMP_custom(filename); + + glBindTexture(GL_TEXTURE_2D, tex->texID); + glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &(tex->width)); + glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &(tex->height)); + + return tex; +} + +void fillTexture(Texture* tex, Rectangle* dstrect, int r, int g, int b) +{ + if (!rendererInitialized) + { + fprintf(stderr, "Renderer not initialized\n"); + exit(-1); + } + + // Target the framebuffer + glBindFramebuffer(GL_FRAMEBUFFER, FramebufferName); + glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex->texID, 0); + + // Set up the vertex attributes + GLfloat minx = (dstrect == NULL) ? 0.0f : dstrect->x; + GLfloat miny = (dstrect == NULL) ? 0.0f : dstrect->y; + GLfloat maxx = (dstrect == NULL) ? tex->width : dstrect->x + dstrect->w; + GLfloat maxy = (dstrect == NULL) ? tex->height : dstrect->y + dstrect->h; + + minx = minx / tex->width * 2.0 - 1.0; + miny = -(miny / tex->height * 2.0 - 1.0); + maxx = maxx / tex->width * 2.0 - 1.0; + maxy = -(maxy / tex->height * 2.0 - 1.0); + + GLfloat vertexbuffer_data[] = { + minx, miny, + maxx, miny, + maxx, maxy, + minx, miny, + minx, maxy, + maxx, maxy + }; + GLuint vertexbuffer; + glGenBuffers(1, &vertexbuffer); + glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(vertexbuffer_data), vertexbuffer_data, GL_STATIC_DRAW); + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, (void*)0); + + glViewport(0, 0, tex->width, tex->height); + glUseProgram(fillShader); + glUniform3f(glGetUniformLocation(fillShader, "vecColor"), r / 255.0, g / 255.0, b / 255.0); + + glDrawArrays(GL_TRIANGLES, 0, 6); + + glDisableVertexAttribArray(0); + glDeleteBuffers(1, &vertexbuffer); +} + +void blitTexture(Texture* srctex, Texture* dsttex, Rectangle* srcrect, Rectangle* dstrect) +{ + if (!rendererInitialized) + { + fprintf(stderr, "Renderer not initialized\n"); + exit(-1); + } + + // Target the framebuffer + glBindFramebuffer(GL_FRAMEBUFFER, FramebufferName); + glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, dsttex->texID, 0); + + // Set up the vertex attributes + GLfloat minx = (dstrect == NULL) ? 0.0f : dstrect->x; + GLfloat miny = (dstrect == NULL) ? 0.0f : dstrect->y; + GLfloat maxx = (dstrect == NULL) ? dsttex->width : dstrect->x + dstrect->w; + GLfloat maxy = (dstrect == NULL) ? dsttex->height : dstrect->y + dstrect->h; + + minx = minx / dsttex->width * 2.0 - 1.0; + miny = -(miny / dsttex->height * 2.0 - 1.0); + maxx = maxx / dsttex->width * 2.0 - 1.0; + maxy = -(maxy / dsttex->height * 2.0 - 1.0); + + GLfloat vertexbuffer_data[] = { + minx, miny, + maxx, miny, + minx, maxy, + maxx, maxy + }; + GLuint vertexbuffer; + glGenBuffers(1, &vertexbuffer); + glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(vertexbuffer_data), vertexbuffer_data, GL_STATIC_DRAW); + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, (void*)0); + + GLfloat minu = (srcrect == NULL) ? 0.0f : srcrect->x; + GLfloat minv = (srcrect == NULL) ? 0.0f : srcrect->y; + GLfloat maxu = (srcrect == NULL) ? srctex->width : srcrect->x + srcrect->w; + GLfloat maxv = (srcrect == NULL) ? srctex->height : srcrect->y + srcrect->h; + + minu = minu / srctex->width; + minv = 1 - (minv / srctex->height); + maxu = maxu / srctex->width; + maxv = 1 - (maxv / srctex->height); + + GLfloat texcoordbuffer_data[] = { + minu, minv, + maxu, minv, + minu, maxv, + maxu, maxv + }; + GLuint texcoordbuffer; + glGenBuffers(1, &texcoordbuffer); + glBindBuffer(GL_ARRAY_BUFFER, texcoordbuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(texcoordbuffer_data), texcoordbuffer_data, GL_STATIC_DRAW); + glEnableVertexAttribArray(1); + glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, (void*)0); + + // Set up the shader + glUseProgram(blitShader); + glViewport(0, 0, dsttex->width, dsttex->height); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, srctex->texID); + glUniform1i(glGetUniformLocation(blitShader, "srctex"), 0); + + // Blit! + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + + // Unload everything + glDisableVertexAttribArray(1); + glDisableVertexAttribArray(0); + glDeleteBuffers(1, &texcoordbuffer); + glDeleteBuffers(1, &vertexbuffer); +} + +void renderScreen(Texture* tex) +{ + if (!rendererInitialized) + { + fprintf(stderr, "Renderer not initialized\n"); + exit(-1); + } + + // Set up framebuffer + glBindFramebuffer(GL_FRAMEBUFFER, FramebufferName); + glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, renderedTexBufs[curBuf], 0); + + // Set up renderer + glViewport(0,0,GAME_WIDTH,GAME_HEIGHT); + glClear(GL_COLOR_BUFFER_BIT); + glUseProgram(ntscShader); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, tex->texID); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glUniform1i(glGetUniformLocation(ntscShader, "curFrameSampler"), 0); + + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, renderedTexBufs[(curBuf + 1) % 2]); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glUniform1i(glGetUniformLocation(ntscShader, "prevFrameSampler"), 1); + + glActiveTexture(GL_TEXTURE2); + glBindTexture(GL_TEXTURE_2D, artifactsTex); + glUniform1i(glGetUniformLocation(ntscShader, "NTSCArtifactSampler"), 2); + + glUniform1f(glGetUniformLocation(ntscShader, "NTSCLerp"), curBuf * 1.0); + + GLfloat g_quad_vertex_buffer_data[] = { + -1.0f, -1.0f, 0.0f, + 1.0f, -1.0f, 0.0f, + -1.0f, 1.0f, 0.0f, + -1.0f, 1.0f, 0.0f, + 1.0f, -1.0f, 0.0f, + 1.0f, 1.0f, 0.0f, + }; + + GLuint quad_vertexbuffer; + glGenBuffers(1, &quad_vertexbuffer); + glBindBuffer(GL_ARRAY_BUFFER, quad_vertexbuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(g_quad_vertex_buffer_data), g_quad_vertex_buffer_data, GL_STATIC_DRAW); + + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0); + glDrawArrays(GL_TRIANGLES, 0, 6); + glDisableVertexAttribArray(0); + + GLfloat g_norms_data[] = { + 0.0f, 0.0f, 1.0f, + 0.0f, 0.0f, 1.0f, + 0.0f, 0.0f, 1.0f, + 0.0f, 0.0f, 1.0f, + 0.0f, 0.0f, 1.0f, + 0.0f, 0.0f, 1.0f + }; + + GLuint g_norms; + glGenBuffers(1, &g_norms); + glBindBuffer(GL_ARRAY_BUFFER, g_norms); + glBufferData(GL_ARRAY_BUFFER, sizeof(g_norms_data), g_norms_data, GL_STATIC_DRAW); + + glBindFramebuffer(GL_FRAMEBUFFER, 0); + glViewport(0,0,1024,768); + glClear(GL_COLOR_BUFFER_BIT); + glUseProgram(finalShader); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, renderedTexBufs[curBuf]); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); + float border_color[] = {0.0f, 0.0f, 0.0f, 1.0f}; + glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, border_color); + glGenerateMipmap(GL_TEXTURE_2D); + glUniform1i(glGetUniformLocation(finalShader, "rendertex"), 0); + + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, scanlinesTex); + glUniform1i(glGetUniformLocation(finalShader, "scanlinestex"), 1); + + glEnableVertexAttribArray(0); + glBindBuffer(GL_ARRAY_BUFFER, quad_vertexbuffer); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0); + + glEnableVertexAttribArray(1); + glBindBuffer(GL_ARRAY_BUFFER, g_norms); + glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (void*)0); + + glDrawArrays(GL_TRIANGLES, 0, 6); + glDisableVertexAttribArray(1); + glDisableVertexAttribArray(0); + + glfwSwapBuffers(window); + + glDeleteBuffers(1, &g_norms); + glDeleteBuffers(1, &quad_vertexbuffer); + + curBuf = (curBuf + 1) % 2; +} diff --git a/src/renderer.h b/src/renderer.h new file mode 100644 index 0000000..de5fc31 --- /dev/null +++ b/src/renderer.h @@ -0,0 +1,42 @@ +#include +#include +#include + +using namespace glm; + +#ifndef RENDERER_H +#define RENDERER_H + +struct Rectangle { + int x; + int y; + int w; + int h; + + Rectangle() {}; + + Rectangle(int m_x, int m_y, int m_w, int m_h) + { + x = m_x; + y = m_y; + w = m_w; + h = m_h; + } +}; + +struct Texture { + GLuint texID; + int width; + int height; +}; + +GLFWwindow* initRenderer(); +void destroyRenderer(); +Texture* createTexture(int width, int height); +void destroyTexture(Texture* tex); +Texture* loadTextureFromBMP(char* filename); +void fillTexture(Texture* tex, Rectangle* loc, int r, int g, int b); +void blitTexture(Texture* srctex, Texture* dsttex, Rectangle* srcrect, Rectangle* dstrect); +void renderScreen(Texture* tex); + +#endif -- cgit 1.4.1