summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKelly Rauchenberger <fefferburbia@gmail.com>2015-02-14 12:09:41 -0500
committerKelly Rauchenberger <fefferburbia@gmail.com>2015-02-14 12:09:41 -0500
commitde5a458cb037bb8e1e80c849c5e6525f9413b43a (patch)
tree97d7aebcf21e4db3c3e19d4a9c7ec906114e5558
downloadtherapy-de5a458cb037bb8e1e80c849c5e6525f9413b43a.tar.gz
therapy-de5a458cb037bb8e1e80c849c5e6525f9413b43a.tar.bz2
therapy-de5a458cb037bb8e1e80c849c5e6525f9413b43a.zip
Monitor stuff is looking pretty cool!
-rw-r--r--.gitignore2
-rw-r--r--CMakeLists.txt33
-rw-r--r--maps/bigmap.txt25
-rw-r--r--maps/testmap.txt16
-rw-r--r--res/artifacts.bmpbin0 -> 192056 bytes
-rw-r--r--res/scanlines.bmpbin0 -> 236 bytes
-rw-r--r--res/tiles.bmpbin0 -> 196664 bytes
-rw-r--r--shaders/blit.fragment12
-rw-r--r--shaders/blit.vertex13
-rw-r--r--shaders/fill.fragment10
-rw-r--r--shaders/fill.vertex8
-rw-r--r--shaders/final.fragment56
-rw-r--r--shaders/final.vertex14
-rw-r--r--shaders/ntsc.fragment64
-rw-r--r--shaders/ntsc.vertex11
-rw-r--r--src/main.cpp149
-rw-r--r--src/map.cpp241
-rw-r--r--src/map.h42
-rw-r--r--src/mob.h10
-rw-r--r--src/renderer.cpp582
-rw-r--r--src/renderer.h42
21 files changed, 1330 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d76b74e --- /dev/null +++ b/.gitignore
@@ -0,0 +1,2 @@
1build
2.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 @@
1cmake_minimum_required(VERSION 2.6)
2project(Aromatherapy)
3
4# Use our modified FindSDL2* modules
5set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${Aromatherapy_SOURCE_DIR}/cmake")
6# Set an output directory for our binaries
7set(BIN_DIR ${Aromatherapy_SOURCE_DIR}/bin)
8
9# Bump up warning levels appropriately for clang, gcc & msvc
10# Also set debug/optimization flags depending on the build type. IDE users choose this when
11# selecting the build mode in their IDE
12if (${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU" OR ${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang")
13 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -pedantic -std=c++11")
14 set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_DEBUG} -g")
15 set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_RELEASE} -O2")
16elseif (${CMAKE_CXX_COMPILER_ID} STREQUAL "MSVC")
17 if (CMAKE_CXX_FLAGS MATCHES "/W[0-4]")
18 string(REGEX REPLACE "/W[0-4]" "/W4" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
19 else()
20 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4")
21 endif()
22endif()
23
24# Look up SDL2 and add the include directory to our include path
25find_package(OpenGL REQUIRED)
26find_package(GLEW REQUIRED)
27find_package(GLFW REQUIRED)
28
29# include_directories(${SDL2_INCLUDE_DIR})
30set(CMAKE_BUILD_TYPE Debug)
31add_executable(Aromatherapy src/main.cpp src/map.cpp src/renderer.cpp)
32target_link_libraries(Aromatherapy ${OPENGL_LIBRARY} ${GLEW_LIBRARY} ${GLFW_LIBRARY})
33install(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 @@
1XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
2XXXXXXXXXXXXXXXXXXXXXXXXX XX
3XXXXXXXXXXXXXXXXXXXXXX X
4XXXXXXXXXXXXXXXXX X
5XXXXXXXXXXXXXX X
6XXXXXXXXXXXXXX XXXX
7XXXXXXXXXXXX XXXXXX
8XXXXXXX XXXXXXX
9XXX XXXXXXXXXXXX
10 XXXXXX
11
12 PPPP
13
14 PPPPPP
15 PPPP
16
17
18 PPPP
19
20
21 XXXXXXXXXXXXXXXXXXXX
22 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
23XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
24XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
25XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX \ 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 @@
1XXXXXXXXXXXXXXXX
2XXXXXX XXXXXX
3XX X
4X X
5X XXXX
6 PPPP
7
8 PPPP
9
10 PPPP
11
12
13XXXXXXXX X
14XXXP XX
15XXXX XXX
16XXXXXXXXXXXXXXXX
diff --git a/res/artifacts.bmp b/res/artifacts.bmp new file mode 100644 index 0000000..b350c42 --- /dev/null +++ b/res/artifacts.bmp
Binary files differ
diff --git a/res/scanlines.bmp b/res/scanlines.bmp new file mode 100644 index 0000000..5a9c404 --- /dev/null +++ b/res/scanlines.bmp
Binary files differ
diff --git a/res/tiles.bmp b/res/tiles.bmp new file mode 100644 index 0000000..a873b2a --- /dev/null +++ b/res/tiles.bmp
Binary files 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 @@
1#version 330 core
2
3in vec2 UV;
4
5out vec3 color;
6
7uniform sampler2D srctex;
8
9void main()
10{
11 color = texture(srctex, UV).xyz;
12}
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 @@
1#version 330 core
2
3layout(location = 0) in vec2 vertexPosition;
4layout(location = 1) in vec2 texcoordPosition;
5
6out vec2 UV;
7
8void main()
9{
10 gl_Position = vec4(vertexPosition, 0.0f, 1.0f);
11
12 UV = texcoordPosition;
13}
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 @@
1#version 330 core
2
3out vec3 color;
4
5uniform vec3 vecColor;
6
7void main()
8{
9 color = vecColor;
10}
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 @@
1#version 330 core
2
3layout(location = 0) in vec3 vertexPosition;
4
5void main()
6{
7 gl_Position = vec4(vertexPosition, 1);
8}
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 @@
1#version 330 core
2
3in vec2 UV;
4in vec3 norm;
5
6out vec3 color;
7
8uniform sampler2D rendertex;
9uniform sampler2D scanlinestex;
10
11const vec2 UVScalar = vec2(1.0, 1.0);
12const vec2 UVOffset = vec2(0.0, 0.0);
13const vec2 CRTMask_Scale = vec2(85.0, 153.6);
14const vec2 CRTMask_Offset = vec2(0.0, 0.0);
15const float Tuning_Overscan = 1.0;
16const float Tuning_Dimming = 0.5;
17const float Tuning_Satur = 1.35;
18const float Tuning_ReflScalar = 0.3;
19const float Tuning_Barrel = 0.12;
20const float Tuning_Scanline_Brightness = 0.25;
21const float Tuning_Scanline_Opacity = 0.5;
22const float Tuning_Diff_Brightness = 0.5;
23const float Tuning_Spec_Brightness = 0.35;
24const float Tuning_Spec_Power = 50.0;
25const float Tuning_Fres_Brightness = 1.0;
26const vec3 Tuning_LightPos = vec3(5.0, -10.0, 0.0);
27
28vec4 sampleCRT(vec2 uv)
29{
30 vec2 ScaledUV = uv;
31 ScaledUV *= UVScalar;
32 ScaledUV += UVOffset;
33
34 vec2 scanuv = ScaledUV * CRTMask_Scale;
35 vec3 scantex = texture(scanlinestex, scanuv).rgb;
36 scantex += Tuning_Scanline_Brightness;
37 scantex = mix(vec3(1,1,1), scantex, Tuning_Scanline_Opacity);
38
39 vec2 overscanuv = (ScaledUV * Tuning_Overscan) - ((Tuning_Overscan - 1.0f) * 0.5f);
40 overscanuv = overscanuv - vec2(0.5, 0.5);
41 float rsq = (overscanuv.x*overscanuv.x) + (overscanuv.y*overscanuv.y);
42 overscanuv = overscanuv + (overscanuv * (Tuning_Barrel * rsq)) + vec2(0.5,0.5);
43
44 vec3 comptex = texture(rendertex, overscanuv).rgb;
45
46 vec4 emissive = vec4(comptex * scantex, 1);
47 float desat = dot(vec4(0.299, 0.587, 0.114, 0.0), emissive);
48 emissive = mix(vec4(desat, desat, desat, 1), emissive, Tuning_Satur);
49
50 return emissive;
51}
52
53void main()
54{
55 color = sampleCRT(UV).rgb;
56}
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 @@
1#version 330 core
2
3layout(location = 0) in vec3 vertexPosition_modelspace;
4layout(location = 1) in vec3 vertexNormal;
5
6out vec2 UV;
7out vec3 norm;
8
9void main()
10{
11 gl_Position = vec4(vertexPosition_modelspace,1);
12 UV = (vertexPosition_modelspace.xy+vec2(1,1))/2.0;
13 norm = vertexNormal;
14}
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 @@
1#version 330 core
2
3in vec2 UV;
4
5out vec3 color;
6
7uniform sampler2D curFrameSampler;
8uniform sampler2D NTSCArtifactSampler;
9uniform sampler2D prevFrameSampler;
10
11const float Tuning_Sharp = 0.8;
12const vec4 Tuning_Persistence = vec4(0.7,0.7,0.7,0.7);
13const float Tuning_Bleed = 0.5;
14const float Tuning_NTSC = 0.35;
15uniform float NTSCLerp;
16
17const vec2 RcpScrWidth = vec2(1.0f / 320.f, 0.0f);
18const vec2 RcpScrHeight = vec2(0.0f, 1.0f / 200.0f);
19
20float Brightness(vec4 InVal)
21{
22 return dot(InVal, vec4(0.299, 0.587, 0.114, 0.0));
23}
24
25const float SharpWeight[3] = float[3](1.0, -0.3162277, 0.1);
26
27void main()
28{
29 vec4 NTSCArtifact1 = texture(NTSCArtifactSampler, UV);
30 vec4 NTSCArtifact2 = texture(NTSCArtifactSampler, UV + RcpScrHeight);
31 vec4 NTSCArtifact = mix(NTSCArtifact1, NTSCArtifact2, NTSCLerp);
32
33 vec2 LeftUV = UV - RcpScrWidth;
34 vec2 RightUV = UV + RcpScrWidth;
35
36 vec4 Cur_Left = texture(curFrameSampler, LeftUV);
37 vec4 Cur_Local = texture(curFrameSampler, UV);
38 vec4 Cur_Right = texture(curFrameSampler, RightUV);
39
40 vec4 Prev_Left = texture(prevFrameSampler, LeftUV);
41 vec4 Prev_Local = texture(prevFrameSampler, UV);
42 vec4 Prev_Right = texture(prevFrameSampler, RightUV);
43
44 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));
45
46 float curBrt = Brightness(Cur_Local);
47 float offset = 0;
48
49 for (int i=0; i<3; ++i)
50 {
51 vec2 StepSize = (RcpScrWidth * float(i+1));
52 vec4 neighborleft = texture(curFrameSampler, UV - StepSize);
53 vec4 neighborright = texture(curFrameSampler, UV + StepSize);
54
55 float NBrtL = Brightness(neighborleft);
56 float NBrtR = Brightness(neighborright);
57 offset += ((curBrt - NBrtL) + (curBrt - NBrtR)) * SharpWeight[i];
58 }
59
60 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));
61 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));
62
63 color = Cur_Local.xyz;
64}
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 @@
1#version 330 core
2
3layout(location = 0) in vec3 vertexPosition_modelspace;
4
5out vec2 UV;
6
7void main()
8{
9 gl_Position = vec4(vertexPosition_modelspace,1);
10 UV = (vertexPosition_modelspace.xy+vec2(1,1))/2.0;
11}
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 @@
1#include <ctime>
2#include <list>
3#include "map.h"
4#include "renderer.h"
5
6using namespace::std;
7
8#if defined(__WIN32__) || defined(_WIN32) || defined(WIN32) || defined(__WINDOWS__) || defined(__TOS_WIN__)
9
10 #include <windows.h>
11
12 inline void delay( unsigned long ms )
13 {
14 Sleep( ms );
15 }
16
17#else /* presume POSIX */
18
19 #include <unistd.h>
20
21 inline void delay( unsigned long ms )
22 {
23 usleep( ms * 1000 );
24 }
25
26#endif
27
28const int FRAMES_PER_SECOND = 60;
29bool holding_left = false;
30bool holding_right = false;
31bool quit = false;
32mob_t* player;
33
34// Initialize jump physics
35double jump_height = TILE_HEIGHT*3;
36double jump_length = 0.25 * FRAMES_PER_SECOND;
37double jump_velocity = -2 * jump_height / jump_length;
38double jump_gravity = -1 * jump_velocity / jump_length;
39
40void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
41{
42 if (action == GLFW_PRESS)
43 {
44 switch (key)
45 {
46 case GLFW_KEY_LEFT: holding_left = true; break;
47 case GLFW_KEY_RIGHT: holding_right = true; break;
48 case GLFW_KEY_UP: player->y_vel = jump_velocity; break;
49 case GLFW_KEY_ESCAPE: quit = true; break;
50 }
51 } else if (action == GLFW_RELEASE)
52 {
53 switch (key)
54 {
55 case GLFW_KEY_LEFT: holding_left = false; break;
56 case GLFW_KEY_RIGHT: holding_right = false; break;
57 }
58 }
59}
60
61int main()
62{
63 GLFWwindow* window = initRenderer();
64 glfwSwapInterval(1);
65 glfwSetKeyCallback(window, key_callback);
66
67 Texture* buffer = createTexture(GAME_WIDTH, GAME_HEIGHT);
68
69 // Initialize player data
70 player = new mob_t();
71 player->x = 100;
72 player->y = 100;
73 player->x_vel = 0;
74 player->y_vel = 0;
75 player->x_accel = 0;
76 player->y_accel = jump_gravity;
77 player->w = 10;
78 player->h = 14;
79
80 Map* map = new Map();
81
82 Texture* tiles = loadTextureFromBMP("../res/tiles.bmp");
83
84 double lastTime = glfwGetTime();
85 int nbFrames = 0;
86
87 while (!quit)
88 {
89 double currentTime = glfwGetTime();
90 nbFrames++;
91 if ( currentTime - lastTime >= 1.0 ){ // If last prinf() was more than 1 sec ago
92 // printf and reset timer
93 printf("%f ms/frame\n", 1000.0/double(nbFrames));
94 nbFrames = 0;
95 lastTime += 1.0;
96 }
97
98 if (holding_left && player->x_vel >= 0)
99 {
100 player->x_vel = -2;
101 } else if (holding_right && player->x_vel <= 0)
102 {
103 player->x_vel = 2;
104 } else if (!holding_left && !holding_right) {
105 player->x_vel = 0;
106 }
107
108 player->x_vel += player->x_accel;
109 if (player->x_vel < -16) player->x_vel = -16;
110 if (player->x_vel > 16) player->x_vel = 16;
111 int playerx_next = player->x + player->x_vel;
112
113 player->y_vel += player->y_accel;
114 if (player->y_vel > 16) player->y_vel = 16; // Terminal velocity
115 if (player->y_vel < -16) player->y_vel = -16;
116 int playery_next = player->y + player->y_vel;
117
118 map->check_collisions(player, playerx_next, playery_next);
119
120 // Do rendering
121 map->render(buffer);
122
123 //Rectangle src_rect(96, 0, 8, 8);
124 Rectangle dst_rect(player->x, player->y, player->w, player->h);
125
126 //blitTexture(tiles, buffer, &src_rect, &dst_rect);
127 fillTexture(buffer, &dst_rect, 85, 85, 255);
128 //fillTexture(buffer, NULL, 85, 85, 0);
129
130 renderScreen(buffer);
131
132 //fuckThePolice(buffer);
133
134 glfwPollEvents();
135
136 // Regulate frame rate
137 /*if ((clock() - frame_start) < CLOCKS_PER_SEC / FRAMES_PER_SECOND)
138 {
139 //delay(((CLOCKS_PER_SEC / FRAMES_PER_SECOND) - clock() + frame_start) * CLOCKS_PER_SEC / 1000);
140 }*/
141 }
142
143 delete map;
144 delete player;
145
146 destroyRenderer();
147
148 return 0;
149}
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 @@
1#include "map.h"
2
3struct platform_t {
4 int x;
5 int y;
6 int w;
7 int h;
8 bool enter_from_left;
9 bool enter_from_right;
10 bool enter_from_top;
11 bool enter_from_bottom;
12 int r;
13 int g;
14 int b;
15 int a;
16};
17
18Map::Map()
19{
20 add_collision(-6, 0, GAME_WIDTH, left, 1);
21 add_collision(GAME_WIDTH+6, 0, GAME_WIDTH, right, 1);
22
23 FILE* f = fopen("../maps/bigmap.txt", "r");
24 char* mapbuf = (char*) malloc(MAP_WIDTH*MAP_HEIGHT*sizeof(char));
25
26 for (int i=0; i<MAP_HEIGHT; i++)
27 {
28 fread(mapbuf + i*MAP_WIDTH, sizeof(char), MAP_WIDTH, f);
29 fgetc(f);
30 }
31
32 fclose(f);
33
34 //Texture* tiles = loadTextureFromBMP("../res/tiles.bmp");
35 bg = createTexture(GAME_WIDTH, GAME_HEIGHT);
36 fillTexture(bg, NULL, 0, 0, 0);
37
38 for (int i=0; i<MAP_WIDTH*MAP_HEIGHT; i++)
39 {
40 int x = i % MAP_WIDTH;
41 int y = i / MAP_WIDTH;
42 Rectangle dst(x*TILE_WIDTH, y*TILE_HEIGHT, TILE_WIDTH, TILE_HEIGHT);
43 //Rectangle src;
44
45 switch (mapbuf[i])
46 {
47 case ' ': break;
48 case 'X': fillTexture(bg, &dst, 255, 85, 85); break;
49 case 'P': fillTexture(bg, &dst, 85, 255, 255); break;
50 }
51
52 //blitTexture(tiles, bg, &src, &dst);
53
54 if (mapbuf[i] == 'X')
55 {
56 if ((x != 0) && (mapbuf[i-1] != 'X'))
57 {
58 add_collision(x*TILE_WIDTH, y*TILE_HEIGHT, (y+1)*TILE_HEIGHT, right, 0);
59 }
60
61 if ((x != 15) && (mapbuf[i+1] != 'X'))
62 {
63 add_collision((x+1)*TILE_WIDTH, y*TILE_HEIGHT, (y+1)*TILE_HEIGHT, left, 0);
64 }
65
66 if ((y != 0) && (mapbuf[i-MAP_WIDTH] != 'X'))
67 {
68 add_collision(y*TILE_HEIGHT, x*TILE_WIDTH, (x+1)*TILE_WIDTH, down, 0);
69 }
70
71 if ((y != 15) && (mapbuf[i+MAP_WIDTH] != 'X'))
72 {
73 add_collision((y+1)*TILE_HEIGHT, x*TILE_WIDTH, (x+1)*TILE_WIDTH, up, 0);
74 }
75 } else if (mapbuf[i] == 'P')
76 {
77 add_collision(y*TILE_HEIGHT, x*TILE_WIDTH, (x+1)*TILE_WIDTH, down, 0);
78 }
79 }
80
81 //destroyTexture(tiles);
82}
83
84Map::~Map()
85{
86 destroyTexture(bg);
87}
88
89void Map::add_collision(int axis, int lower, int upper, direction_t dir, int type)
90{
91 //printf("added collision\n");
92 list<collision_t>::iterator it;
93
94 switch (dir)
95 {
96 case up:
97 it = up_collisions.begin();
98 for (; it!=up_collisions.end(); it++)
99 {
100 if (it->axis < axis) break;
101 }
102
103 up_collisions.insert(it, {axis, lower, upper, type});
104
105 break;
106 case down:
107 it = down_collisions.begin();
108 for (; it!=down_collisions.end(); it++)
109 {
110 if (it->axis > axis) break;
111 }
112
113 down_collisions.insert(it, {axis, lower, upper, type});
114
115 break;
116 case left:
117 it = left_collisions.begin();
118 for (; it!=left_collisions.end(); it++)
119 {
120 if (it->axis < axis) break;
121 }
122
123 left_collisions.insert(it, {axis, lower, upper, type});
124
125 break;
126 case right:
127 it = right_collisions.begin();
128 for (; it!=right_collisions.end(); it++)
129 {
130 if (it->axis > axis) break;
131 }
132
133 right_collisions.insert(it, {axis, lower, upper, type});
134
135 break;
136 }
137}
138
139void Map::check_collisions(mob_t* mob, int x_next, int y_next)
140{
141 if (x_next < mob->x)
142 {
143 for (list<collision_t>::iterator it=left_collisions.begin(); it!=left_collisions.end(); it++)
144 {
145 if (it->axis > mob->x) continue;
146 if (it->axis < x_next) break;
147
148 if ((mob->y+mob->h > it->lower) && (mob->y < it->upper))
149 {
150 // We have a collision!
151 if (it->type == 0)
152 {
153 x_next = it->axis;
154 mob->x_vel = 0;
155 } else if (it->type == 1)
156 {
157 x_next = GAME_WIDTH-mob->w/2;
158 }
159
160 break;
161 }
162 }
163 } else if (x_next > mob->x)
164 {
165 for (list<collision_t>::iterator it=right_collisions.begin(); it!=right_collisions.end(); it++)
166 {
167 if (it->axis < mob->x+mob->w) continue;
168 if (it->axis > x_next+mob->w) break;
169
170 if ((mob->y+mob->h > it->lower) && (mob->y < it->upper))
171 {
172 // We have a collision!
173 if (it->type == 0)
174 {
175 x_next = it->axis - mob->w;
176 mob->x_vel = 0;
177 } else if (it->type == 1)
178 {
179 x_next = -mob->w/2;
180 }
181
182 break;
183 }
184 }
185 }
186
187 mob->x = x_next;
188
189 if (y_next < mob->y)
190 {
191 for (list<collision_t>::iterator it=up_collisions.begin(); it!=up_collisions.end(); it++)
192 {
193 if (it->axis > mob->y) continue;
194 if (it->axis < y_next) break;
195
196 if ((mob->x+mob->w > it->lower) && (mob->x < it->upper))
197 {
198 // We have a collision!
199 if (it->type == 0)
200 {
201 y_next = it->axis;
202 mob->y_vel = 0;
203 } else if (it->type == 1)
204 {
205 y_next = GAME_HEIGHT-mob->h/2-1;
206 }
207
208 break;
209 }
210 }
211 } else if (y_next > mob->y)
212 {
213 for (list<collision_t>::iterator it=down_collisions.begin(); it!=down_collisions.end(); it++)
214 {
215 if (it->axis < mob->y+mob->h) continue;
216 if (it->axis > y_next+mob->h) break;
217
218 if ((mob->x+mob->w > it->lower) && (mob->x < it->upper))
219 {
220 // We have a collision!
221 if (it->type == 0)
222 {
223 y_next = it->axis - mob->h;
224 mob->y_vel = 0;
225 } else if (it->type == 1)
226 {
227 y_next = 1 - mob->h/2;
228 }
229
230 break;
231 }
232 }
233 }
234
235 mob->y = y_next;
236}
237
238void Map::render(Texture* buffer)
239{
240 blitTexture(bg, buffer, NULL, NULL);
241}
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 @@
1#include <list>
2#include <vector>
3#include "mob.h"
4#include "renderer.h"
5
6using namespace::std;
7
8const int TILE_WIDTH = 8;
9const int TILE_HEIGHT = 8;
10const int GAME_WIDTH = 320;
11const int GAME_HEIGHT = 200;
12const int MAP_WIDTH = GAME_WIDTH/TILE_WIDTH;
13const int MAP_HEIGHT = GAME_HEIGHT/TILE_HEIGHT;
14
15enum direction_t {
16 up, left, down, right
17};
18
19typedef struct {
20 int axis;
21 int lower;
22 int upper;
23 int type;
24} collision_t;
25
26class Map {
27public:
28 Map();
29 ~Map();
30 void render(Texture* buffer);
31 void check_collisions(mob_t* mob, int x_next, int y_next);
32
33private:
34 void add_collision(int axis, int lower, int upper, direction_t dir, int type);
35
36 list<collision_t> left_collisions;
37 list<collision_t> right_collisions;
38 list<collision_t> up_collisions;
39 list<collision_t> down_collisions;
40
41 Texture* bg;
42}; \ 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 @@
1typedef struct {
2 int x;
3 int y;
4 double x_vel;
5 double y_vel;
6 double x_accel;
7 double y_accel;
8 int w;
9 int h;
10} 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 @@
1#include "renderer.h"
2#include <string>
3#include <fstream>
4#include <vector>
5#include <cstdio>
6#include "map.h"
7
8static bool rendererInitialized = false;
9
10static GLFWwindow* window;
11
12static GLuint FramebufferName; // The framebuffer
13static GLuint ntscShader; // The NTSC shader
14static GLuint finalShader; // The passthrough shader
15static GLuint blitShader; // The blitting shader
16static GLuint fillShader; // The fill shader
17
18// The buffers for the NTSC rendering process
19static GLuint renderedTex1;
20static GLuint renderedTex2;
21static GLuint renderedTexBufs[2];
22static int curBuf;
23static GLuint artifactsTex;
24static GLuint scanlinesTex;
25
26GLuint LoadShaders(const char* vertex_file_path, const char* fragment_file_path)
27{
28 // Create the shaders
29 GLuint VertexShaderID = glCreateShader(GL_VERTEX_SHADER);
30 GLuint FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
31
32 // Read the Vertex Shader code from the file
33 std::string VertexShaderCode;
34 std::ifstream VertexShaderStream(vertex_file_path, std::ios::in);
35 if(VertexShaderStream.is_open())
36 {
37 std::string Line = "";
38 while(getline(VertexShaderStream, Line))
39 VertexShaderCode += "\n" + Line;
40 VertexShaderStream.close();
41 }
42
43 // Read the Fragment Shader code from the file
44 std::string FragmentShaderCode;
45 std::ifstream FragmentShaderStream(fragment_file_path, std::ios::in);
46 if(FragmentShaderStream.is_open()){
47 std::string Line = "";
48 while(getline(FragmentShaderStream, Line))
49 FragmentShaderCode += "\n" + Line;
50 FragmentShaderStream.close();
51 }
52
53 GLint Result = GL_FALSE;
54 int InfoLogLength;
55
56 // Compile Vertex Shader
57 printf("Compiling shader : %s\n", vertex_file_path);
58 char const * VertexSourcePointer = VertexShaderCode.c_str();
59 glShaderSource(VertexShaderID, 1, &VertexSourcePointer , NULL);
60 glCompileShader(VertexShaderID);
61
62 // Check Vertex Shader
63 glGetShaderiv(VertexShaderID, GL_COMPILE_STATUS, &Result);
64 glGetShaderiv(VertexShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
65 std::vector<char> VertexShaderErrorMessage(InfoLogLength);
66 glGetShaderInfoLog(VertexShaderID, InfoLogLength, NULL, &VertexShaderErrorMessage[0]);
67 fprintf(stdout, "%s\n", &VertexShaderErrorMessage[0]);
68
69 // Compile Fragment Shader
70 printf("Compiling shader : %s\n", fragment_file_path);
71 char const * FragmentSourcePointer = FragmentShaderCode.c_str();
72 glShaderSource(FragmentShaderID, 1, &FragmentSourcePointer , NULL);
73 glCompileShader(FragmentShaderID);
74
75 // Check Fragment Shader
76 glGetShaderiv(FragmentShaderID, GL_COMPILE_STATUS, &Result);
77 glGetShaderiv(FragmentShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
78 std::vector<char> FragmentShaderErrorMessage(InfoLogLength);
79 glGetShaderInfoLog(FragmentShaderID, InfoLogLength, NULL, &FragmentShaderErrorMessage[0]);
80 fprintf(stdout, "%s\n", &FragmentShaderErrorMessage[0]);
81
82 // Link the program
83 fprintf(stdout, "Linking program\n");
84 GLuint ProgramID = glCreateProgram();
85 glAttachShader(ProgramID, VertexShaderID);
86 glAttachShader(ProgramID, FragmentShaderID);
87 glLinkProgram(ProgramID);
88
89 // Check the program
90 glGetProgramiv(ProgramID, GL_LINK_STATUS, &Result);
91 glGetProgramiv(ProgramID, GL_INFO_LOG_LENGTH, &InfoLogLength);
92 std::vector<char> ProgramErrorMessage( glm::max(InfoLogLength, int(1)) );
93 glGetProgramInfoLog(ProgramID, InfoLogLength, NULL, &ProgramErrorMessage[0]);
94 fprintf(stdout, "%s\n", &ProgramErrorMessage[0]);
95
96 glDeleteShader(VertexShaderID);
97 glDeleteShader(FragmentShaderID);
98
99 return ProgramID;
100}
101
102GLuint loadBMP_custom(const char * imagepath){
103
104 printf("Reading image %s\n", imagepath);
105
106 // Data read from the header of the BMP file
107 unsigned char header[54];
108 unsigned int dataPos;
109 unsigned int imageSize;
110 unsigned int width, height;
111 // Actual RGB data
112 unsigned char * data;
113
114 // Open the file
115 FILE * file = fopen(imagepath,"rb");
116 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;}
117
118 // Read the header, i.e. the 54 first bytes
119
120 // If less than 54 bytes are read, problem
121 if ( fread(header, 1, 54, file)!=54 ){
122 printf("Not a correct BMP file\n");
123 return 0;
124 }
125 // A BMP files always begins with "BM"
126 if ( header[0]!='B' || header[1]!='M' ){
127 printf("Not a correct BMP file\n");
128 return 0;
129 }
130 // Make sure this is a 24bpp file
131 if ( *(int*)&(header[0x1E])!=0 ) {printf("Not a correct BMP file\n"); return 0;}
132 if ( *(int*)&(header[0x1C])!=24 ) {printf("Not a correct BMP file\n"); return 0;}
133
134 // Read the information about the image
135 dataPos = *(int*)&(header[0x0A]);
136 imageSize = *(int*)&(header[0x22]);
137 width = *(int*)&(header[0x12]);
138 height = *(int*)&(header[0x16]);
139
140 // Some BMP files are misformatted, guess missing information
141 if (imageSize==0) imageSize=width*height*3; // 3 : one byte for each Red, Green and Blue component
142 if (dataPos==0) dataPos=54; // The BMP header is done that way
143
144 // Create a buffer
145 data = new unsigned char [imageSize];
146
147 // Read the actual data from the file into the buffer
148 fread(data,1,imageSize,file);
149
150 // Everything is in memory now, the file wan be closed
151 fclose (file);
152
153 // Create one OpenGL texture
154 GLuint textureID;
155 glGenTextures(1, &textureID);
156
157 // "Bind" the newly created texture : all future texture functions will modify this texture
158 glBindTexture(GL_TEXTURE_2D, textureID);
159
160 // Give the image to OpenGL
161 glTexImage2D(GL_TEXTURE_2D, 0,GL_RGB, width, height, 0, GL_BGR, GL_UNSIGNED_BYTE, data);
162
163 // OpenGL has now copied the data. Free our own version
164 delete [] data;
165
166 // Poor filtering, or ...
167 //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
168 //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
169
170 // ... nice trilinear filtering.
171 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
172 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
173 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
174 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
175 glGenerateMipmap(GL_TEXTURE_2D);
176
177 // Return the ID of the texture we just created
178 return textureID;
179}
180
181GLFWwindow* initRenderer()
182{
183 if (rendererInitialized)
184 {
185 fprintf(stderr, "Renderer already initialized\n");
186 exit(-1);
187 }
188
189 // Initialize GLFW
190 if (!glfwInit())
191 {
192 fprintf(stderr, "Failed to initialize GLFW\n");
193 exit(-1);
194 }
195
196 glfwWindowHint(GLFW_SAMPLES, 4); // 4x antialiasing
197 glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); // We want version 3.3
198 glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
199 glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // Mac requires this
200 glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
201
202 // Create a window
203 window = glfwCreateWindow(1024, 768, "Aromatherapy", NULL, NULL);
204 if (window == NULL)
205 {
206 fprintf(stderr, "Failed to open GLFW window\n");
207 glfwTerminate();
208 exit(-1);
209 }
210
211 glfwMakeContextCurrent(window);
212 glewExperimental = true; // Needed in core profile
213 if (glewInit() != GLEW_OK)
214 {
215 fprintf(stderr, "Failed to initialize GLEW\n");
216 exit(-1);
217 }
218
219 // Set up vertex array object
220 GLuint VertexArrayID;
221 glGenVertexArrays(1, &VertexArrayID);
222 glBindVertexArray(VertexArrayID);
223
224 // Set up the framebuffer
225 glGenFramebuffers(1, &FramebufferName);
226 glBindFramebuffer(GL_FRAMEBUFFER, FramebufferName);
227 GLenum DrawBuffers[1] = {GL_COLOR_ATTACHMENT0};
228 glDrawBuffers(1, DrawBuffers);
229
230 // Set up the NTSC rendering buffers
231 glGenTextures(1, &renderedTex1);
232 glBindTexture(GL_TEXTURE_2D, renderedTex1);
233 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, GAME_WIDTH, GAME_HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
234 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
235 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
236 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
237 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
238 renderedTexBufs[0] = renderedTex1;
239
240 glGenTextures(1, &renderedTex2);
241 glBindTexture(GL_TEXTURE_2D, renderedTex2);
242 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, GAME_WIDTH, GAME_HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
243 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
244 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
245 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
246 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
247 renderedTexBufs[1] = renderedTex2;
248
249 curBuf = 0;
250
251 artifactsTex = loadBMP_custom("../res/artifacts.bmp");
252 scanlinesTex = loadBMP_custom("../res/scanlines.bmp");
253
254 // Load the shaders
255 ntscShader = LoadShaders("../shaders/ntsc.vertex", "../shaders/ntsc.fragment");
256 finalShader = LoadShaders("../shaders/final.vertex", "../shaders/final.fragment");
257 blitShader = LoadShaders("../shaders/blit.vertex", "../shaders/blit.fragment");
258 fillShader = LoadShaders("../shaders/fill.vertex", "../shaders/fill.fragment");
259
260 rendererInitialized = true;
261
262 return window;
263}
264
265void destroyRenderer()
266{
267 if (!rendererInitialized)
268 {
269 fprintf(stderr, "Renderer not initialized\n");
270 exit(-1);
271 }
272
273 // Delete the shaders
274 glDeleteProgram(ntscShader);
275 glDeleteProgram(finalShader);
276 glDeleteProgram(blitShader);
277 glDeleteProgram(fillShader);
278
279 // Delete the NTSC rendering buffers
280 glDeleteTextures(1, &renderedTex1);
281 glDeleteTextures(1, &renderedTex2);
282 glDeleteTextures(1, &artifactsTex);
283 glDeleteTextures(1, &scanlinesTex);
284
285 // Delete the framebuffer
286 glDeleteFramebuffers(1, &FramebufferName);
287
288 // Kill the window
289 glfwTerminate();
290
291 rendererInitialized = false;
292}
293
294Texture* createTexture(int width, int height)
295{
296 if (!rendererInitialized)
297 {
298 fprintf(stderr, "Renderer not initialized\n");
299 exit(-1);
300 }
301
302 Texture* tex = new Texture();
303 tex->width = width;
304 tex->height = height;
305
306 glGenTextures(1, &(tex->texID));
307 glBindTexture(GL_TEXTURE_2D, tex->texID);
308 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
309 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
310 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
311 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
312 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
313
314 return tex;
315}
316
317void destroyTexture(Texture* tex)
318{
319 if (!rendererInitialized)
320 {
321 fprintf(stderr, "Renderer not initialized\n");
322 exit(-1);
323 }
324
325 glDeleteTextures(1, &(tex->texID));
326
327 delete tex;
328}
329
330Texture* loadTextureFromBMP(char* filename)
331{
332 if (!rendererInitialized)
333 {
334 fprintf(stderr, "Renderer not initialized\n");
335 exit(-1);
336 }
337
338 Texture* tex = new Texture();
339 tex->texID = loadBMP_custom(filename);
340
341 glBindTexture(GL_TEXTURE_2D, tex->texID);
342 glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &(tex->width));
343 glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &(tex->height));
344
345 return tex;
346}
347
348void fillTexture(Texture* tex, Rectangle* dstrect, int r, int g, int b)
349{
350 if (!rendererInitialized)
351 {
352 fprintf(stderr, "Renderer not initialized\n");
353 exit(-1);
354 }
355
356 // Target the framebuffer
357 glBindFramebuffer(GL_FRAMEBUFFER, FramebufferName);
358 glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex->texID, 0);
359
360 // Set up the vertex attributes
361 GLfloat minx = (dstrect == NULL) ? 0.0f : dstrect->x;
362 GLfloat miny = (dstrect == NULL) ? 0.0f : dstrect->y;
363 GLfloat maxx = (dstrect == NULL) ? tex->width : dstrect->x + dstrect->w;
364 GLfloat maxy = (dstrect == NULL) ? tex->height : dstrect->y + dstrect->h;
365
366 minx = minx / tex->width * 2.0 - 1.0;
367 miny = -(miny / tex->height * 2.0 - 1.0);
368 maxx = maxx / tex->width * 2.0 - 1.0;
369 maxy = -(maxy / tex->height * 2.0 - 1.0);
370
371 GLfloat vertexbuffer_data[] = {
372 minx, miny,
373 maxx, miny,
374 maxx, maxy,
375 minx, miny,
376 minx, maxy,
377 maxx, maxy
378 };
379 GLuint vertexbuffer;
380 glGenBuffers(1, &vertexbuffer);
381 glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
382 glBufferData(GL_ARRAY_BUFFER, sizeof(vertexbuffer_data), vertexbuffer_data, GL_STATIC_DRAW);
383 glEnableVertexAttribArray(0);
384 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, (void*)0);
385
386 glViewport(0, 0, tex->width, tex->height);
387 glUseProgram(fillShader);
388 glUniform3f(glGetUniformLocation(fillShader, "vecColor"), r / 255.0, g / 255.0, b / 255.0);
389
390 glDrawArrays(GL_TRIANGLES, 0, 6);
391
392 glDisableVertexAttribArray(0);
393 glDeleteBuffers(1, &vertexbuffer);
394}
395
396void blitTexture(Texture* srctex, Texture* dsttex, Rectangle* srcrect, Rectangle* dstrect)
397{
398 if (!rendererInitialized)
399 {
400 fprintf(stderr, "Renderer not initialized\n");
401 exit(-1);
402 }
403
404 // Target the framebuffer
405 glBindFramebuffer(GL_FRAMEBUFFER, FramebufferName);
406 glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, dsttex->texID, 0);
407
408 // Set up the vertex attributes
409 GLfloat minx = (dstrect == NULL) ? 0.0f : dstrect->x;
410 GLfloat miny = (dstrect == NULL) ? 0.0f : dstrect->y;
411 GLfloat maxx = (dstrect == NULL) ? dsttex->width : dstrect->x + dstrect->w;
412 GLfloat maxy = (dstrect == NULL) ? dsttex->height : dstrect->y + dstrect->h;
413
414 minx = minx / dsttex->width * 2.0 - 1.0;
415 miny = -(miny / dsttex->height * 2.0 - 1.0);
416 maxx = maxx / dsttex->width * 2.0 - 1.0;
417 maxy = -(maxy / dsttex->height * 2.0 - 1.0);
418
419 GLfloat vertexbuffer_data[] = {
420 minx, miny,
421 maxx, miny,
422 minx, maxy,
423 maxx, maxy
424 };
425 GLuint vertexbuffer;
426 glGenBuffers(1, &vertexbuffer);
427 glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
428 glBufferData(GL_ARRAY_BUFFER, sizeof(vertexbuffer_data), vertexbuffer_data, GL_STATIC_DRAW);
429 glEnableVertexAttribArray(0);
430 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, (void*)0);
431
432 GLfloat minu = (srcrect == NULL) ? 0.0f : srcrect->x;
433 GLfloat minv = (srcrect == NULL) ? 0.0f : srcrect->y;
434 GLfloat maxu = (srcrect == NULL) ? srctex->width : srcrect->x + srcrect->w;
435 GLfloat maxv = (srcrect == NULL) ? srctex->height : srcrect->y + srcrect->h;
436
437 minu = minu / srctex->width;
438 minv = 1 - (minv / srctex->height);
439 maxu = maxu / srctex->width;
440 maxv = 1 - (maxv / srctex->height);
441
442 GLfloat texcoordbuffer_data[] = {
443 minu, minv,
444 maxu, minv,
445 minu, maxv,
446 maxu, maxv
447 };
448 GLuint texcoordbuffer;
449 glGenBuffers(1, &texcoordbuffer);
450 glBindBuffer(GL_ARRAY_BUFFER, texcoordbuffer);
451 glBufferData(GL_ARRAY_BUFFER, sizeof(texcoordbuffer_data), texcoordbuffer_data, GL_STATIC_DRAW);
452 glEnableVertexAttribArray(1);
453 glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, (void*)0);
454
455 // Set up the shader
456 glUseProgram(blitShader);
457 glViewport(0, 0, dsttex->width, dsttex->height);
458
459 glActiveTexture(GL_TEXTURE0);
460 glBindTexture(GL_TEXTURE_2D, srctex->texID);
461 glUniform1i(glGetUniformLocation(blitShader, "srctex"), 0);
462
463 // Blit!
464 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
465
466 // Unload everything
467 glDisableVertexAttribArray(1);
468 glDisableVertexAttribArray(0);
469 glDeleteBuffers(1, &texcoordbuffer);
470 glDeleteBuffers(1, &vertexbuffer);
471}
472
473void renderScreen(Texture* tex)
474{
475 if (!rendererInitialized)
476 {
477 fprintf(stderr, "Renderer not initialized\n");
478 exit(-1);
479 }
480
481 // Set up framebuffer
482 glBindFramebuffer(GL_FRAMEBUFFER, FramebufferName);
483 glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, renderedTexBufs[curBuf], 0);
484
485 // Set up renderer
486 glViewport(0,0,GAME_WIDTH,GAME_HEIGHT);
487 glClear(GL_COLOR_BUFFER_BIT);
488 glUseProgram(ntscShader);
489
490 glActiveTexture(GL_TEXTURE0);
491 glBindTexture(GL_TEXTURE_2D, tex->texID);
492 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
493 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
494 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
495 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
496 glUniform1i(glGetUniformLocation(ntscShader, "curFrameSampler"), 0);
497
498 glActiveTexture(GL_TEXTURE1);
499 glBindTexture(GL_TEXTURE_2D, renderedTexBufs[(curBuf + 1) % 2]);
500 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
501 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
502 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
503 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
504 glUniform1i(glGetUniformLocation(ntscShader, "prevFrameSampler"), 1);
505
506 glActiveTexture(GL_TEXTURE2);
507 glBindTexture(GL_TEXTURE_2D, artifactsTex);
508 glUniform1i(glGetUniformLocation(ntscShader, "NTSCArtifactSampler"), 2);
509
510 glUniform1f(glGetUniformLocation(ntscShader, "NTSCLerp"), curBuf * 1.0);
511
512 GLfloat g_quad_vertex_buffer_data[] = {
513 -1.0f, -1.0f, 0.0f,
514 1.0f, -1.0f, 0.0f,
515 -1.0f, 1.0f, 0.0f,
516 -1.0f, 1.0f, 0.0f,
517 1.0f, -1.0f, 0.0f,
518 1.0f, 1.0f, 0.0f,
519 };
520
521 GLuint quad_vertexbuffer;
522 glGenBuffers(1, &quad_vertexbuffer);
523 glBindBuffer(GL_ARRAY_BUFFER, quad_vertexbuffer);
524 glBufferData(GL_ARRAY_BUFFER, sizeof(g_quad_vertex_buffer_data), g_quad_vertex_buffer_data, GL_STATIC_DRAW);
525
526 glEnableVertexAttribArray(0);
527 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
528 glDrawArrays(GL_TRIANGLES, 0, 6);
529 glDisableVertexAttribArray(0);
530
531 GLfloat g_norms_data[] = {
532 0.0f, 0.0f, 1.0f,
533 0.0f, 0.0f, 1.0f,
534 0.0f, 0.0f, 1.0f,
535 0.0f, 0.0f, 1.0f,
536 0.0f, 0.0f, 1.0f,
537 0.0f, 0.0f, 1.0f
538 };
539
540 GLuint g_norms;
541 glGenBuffers(1, &g_norms);
542 glBindBuffer(GL_ARRAY_BUFFER, g_norms);
543 glBufferData(GL_ARRAY_BUFFER, sizeof(g_norms_data), g_norms_data, GL_STATIC_DRAW);
544
545 glBindFramebuffer(GL_FRAMEBUFFER, 0);
546 glViewport(0,0,1024,768);
547 glClear(GL_COLOR_BUFFER_BIT);
548 glUseProgram(finalShader);
549 glActiveTexture(GL_TEXTURE0);
550 glBindTexture(GL_TEXTURE_2D, renderedTexBufs[curBuf]);
551 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
552 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
553 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
554 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
555 float border_color[] = {0.0f, 0.0f, 0.0f, 1.0f};
556 glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, border_color);
557 glGenerateMipmap(GL_TEXTURE_2D);
558 glUniform1i(glGetUniformLocation(finalShader, "rendertex"), 0);
559
560 glActiveTexture(GL_TEXTURE1);
561 glBindTexture(GL_TEXTURE_2D, scanlinesTex);
562 glUniform1i(glGetUniformLocation(finalShader, "scanlinestex"), 1);
563
564 glEnableVertexAttribArray(0);
565 glBindBuffer(GL_ARRAY_BUFFER, quad_vertexbuffer);
566 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
567
568 glEnableVertexAttribArray(1);
569 glBindBuffer(GL_ARRAY_BUFFER, g_norms);
570 glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
571
572 glDrawArrays(GL_TRIANGLES, 0, 6);
573 glDisableVertexAttribArray(1);
574 glDisableVertexAttribArray(0);
575
576 glfwSwapBuffers(window);
577
578 glDeleteBuffers(1, &g_norms);
579 glDeleteBuffers(1, &quad_vertexbuffer);
580
581 curBuf = (curBuf + 1) % 2;
582}
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 @@
1#include <GL/glew.h>
2#include <GLFW/glfw3.h>
3#include <glm/glm.hpp>
4
5using namespace glm;
6
7#ifndef RENDERER_H
8#define RENDERER_H
9
10struct Rectangle {
11 int x;
12 int y;
13 int w;
14 int h;
15
16 Rectangle() {};
17
18 Rectangle(int m_x, int m_y, int m_w, int m_h)
19 {
20 x = m_x;
21 y = m_y;
22 w = m_w;
23 h = m_h;
24 }
25};
26
27struct Texture {
28 GLuint texID;
29 int width;
30 int height;
31};
32
33GLFWwindow* initRenderer();
34void destroyRenderer();
35Texture* createTexture(int width, int height);
36void destroyTexture(Texture* tex);
37Texture* loadTextureFromBMP(char* filename);
38void fillTexture(Texture* tex, Rectangle* loc, int r, int g, int b);
39void blitTexture(Texture* srctex, Texture* dsttex, Rectangle* srcrect, Rectangle* dstrect);
40void renderScreen(Texture* tex);
41
42#endif