-OBJS = main.o implementations.o gameobject.o solidobject.o misc_objects.o helpers.o load_level.o water_tank.o
+OBJS = main.o implementations.o gameobject.o solidobject.o misc_objects.o helpers.o load_level.o water_tank.o hud.o
CXXFLAGS = -g -std=c++17 -Wall
LDFLAGS = -lGL -lglfw -lGLEW -pthread -g
test: all
./game
-${OBJS} : game.h misc_objects.h water_tank.h projectile.h explodingtarget.h cat.h
+${OBJS} : game.h misc_objects.h water_tank.h projectile.h explodingtarget.h cat.h hud.h
};
+#include "hud.h"
+
#ifdef MAIN
globals g;
vector<GameObject*> game_objects;
vector<SolidObject*> solid_objects;
+vector<Overlay*> overlays;
map<string, unsigned int> gl_resources;
+Hud *main_hud;
#else
extern globals g;
extern vector<GameObject*> game_objects;
extern vector<SolidObject*> solid_objects;
+extern vector<Overlay*> overlays;
extern map<string, unsigned int> gl_resources;
+extern Hud *main_hud;
#endif
struct vertex {
void load_level();
GameObject* find_object(string name);
bool can_see(vec3 A, vec3 B, float start_distance = 0.0f);
+unsigned int make_program(const char* v_file, const char* tcs_file, const char* tes_file, const char* g_file, const char* f_file);
+unsigned int load_texture(string texture_file);
#define PLAYER_ON_OBJECT 1
#define ACTIVATE 2
glGenTextures(1, &tex);
glBindTexture(GL_TEXTURE_2D, tex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, img_width, img_height, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
free(image);
gl_resources[texture_file] = tex;
}
}
+unsigned int make_program(const char* v_file, const char* tcs_file, const char* tes_file, const char* g_file, const char* f_file) {
+ unsigned int vs_reference = load_shader(v_file, GL_VERTEX_SHADER);
+ unsigned int tcs_reference = 0, tes_reference = 0;
+ if (tcs_file)
+ if (!(tcs_reference = load_shader(tcs_file, GL_TESS_CONTROL_SHADER)))
+ return 0;
+ if (tes_file)
+ if (!(tes_reference = load_shader(tes_file, GL_TESS_EVALUATION_SHADER)))
+ return 0;
+ unsigned int gs_reference = 0;
+ if (g_file)
+ gs_reference = load_shader(g_file, GL_GEOMETRY_SHADER);
+ unsigned int fs_reference = load_shader(f_file, GL_FRAGMENT_SHADER);
+ if (!(vs_reference && fs_reference))
+ return 0;
+ if (g_file && !gs_reference)
+ return 0;
+
+
+ unsigned int program = glCreateProgram();
+ glAttachShader(program, vs_reference);
+ if (g_file)
+ glAttachShader(program, gs_reference);
+ if (tcs_file)
+ glAttachShader(program, tcs_reference);
+ if (tes_file)
+ glAttachShader(program, tes_reference);
+ glAttachShader(program, fs_reference);
+ glLinkProgram(program);
+ GLint link_ok;
+ glGetProgramiv(program, GL_LINK_STATUS, &link_ok);
+ if (!link_ok) {
+ glGetProgramInfoLog(program, 2048, NULL, log_buffer);
+ puts(log_buffer);
+ puts("Link Failed");
+ return 0;
+ }
+
+ return program;
+}
+
bool GameObject::init(){
tinyobj::attrib_t attrib;
vector<tinyobj::shape_t> shapes;
glGenBuffers(1, &models_buffer);
glGenBuffers(1, &specials_buffer);
- unsigned int vs_reference = load_shader("shaders/vertex_shader.glsl", GL_VERTEX_SHADER);
- unsigned int fs_reference = load_shader("shaders/fragment_shader.glsl", GL_FRAGMENT_SHADER);
-
- program = glCreateProgram();
- glAttachShader(program, vs_reference);
- glAttachShader(program, fs_reference);
- glLinkProgram(program);
-
- int link_ok;
- glGetProgramiv(program, GL_LINK_STATUS, &link_ok);
- glGetProgramInfoLog(program, 2048, NULL, log_buffer);
- puts(log_buffer);
- if(!link_ok){
+ program = make_program("shaders/vertex_shader.glsl", 0, 0, 0, "shaders/fragment_shader.glsl");
+ if(!program){
printf("Link failure\n");
return false;
}
--- /dev/null
+#include "game.h"
+#include "hud.h"
+#include<stdarg.h>
+
+int Aimpoint::init(){
+ float vertices[] {
+ -.2, .002, 0,
+ .2, .002, 0,
+ .2, -.002, 0,
+ -.2, .002, 0,
+ .2, -.002, 0,
+ -.2, -.002, 0,
+
+ -.002, .2, 0,
+ .002, .2, 0,
+ .002, -.2, 0,
+ -.002, .2, 0,
+ .002, -.2, 0,
+ -.002, -.2, 0,
+ };
+ glGenBuffers(1, &vbuf);
+ glBindBuffer(GL_SHADER_STORAGE_BUFFER, vbuf);
+ glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
+ program = make_program("shaders/aimpoint_vertex_shader.glsl",0, 0, 0, "shaders/aimpoint_fragment_shader.glsl");
+ if (!program)
+ return 1;
+ v_attrib = glGetAttribLocation(program, "in_vertex");
+ return 0;
+}
+
+void Aimpoint::draw(){
+ glUseProgram(program);
+ glEnableVertexAttribArray(v_attrib);
+ glBindBuffer(GL_ARRAY_BUFFER, vbuf);
+ glVertexAttribPointer(v_attrib, 3, GL_FLOAT, GL_FALSE, 0, 0);
+ glDrawArrays(GL_TRIANGLES, 0, 12);
+}
+
+void Hud::set_char(int col, int line, char c){
+ float position = c - 32;
+ position /= 95;
+ size_t cstart = (col + line * char_width) * 12;
+ texcoords[cstart + 0] = position;
+ texcoords[cstart + 1] = 1.0f;
+ texcoords[cstart + 2] = position + 1.0f/95;
+ texcoords[cstart + 3] = 1.0f;
+ texcoords[cstart + 4] = position;
+ texcoords[cstart + 5] = 0.0f;
+ texcoords[cstart + 6] = position + 1.0f/95;
+ texcoords[cstart + 7] = 1.0f;
+ texcoords[cstart + 8] = position + 1.0f/95;
+ texcoords[cstart + 9] = 0.0f;
+ texcoords[cstart + 10] = position;
+ texcoords[cstart + 11] = 0.0f;
+
+}
+
+void Hud::lprintf(int line, const char *fmt, ...){
+ va_list args;
+ va_start(args, fmt);
+ char text[100];
+ vsprintf(text, fmt, args);
+ set_text_line(line, text);
+}
+
+void Hud::set_text_line(int line, const char* text){
+ for(int i = line * 1200; i < (line + 1) * 1200; i++)
+ texcoords[i] =0;
+ int col = 0;
+ for(; *text; text++){
+ set_char(col, line, *text);
+ col++;
+ }
+}
+
+void Hud::set_text(const char* text){
+ for(int i = 0; i < 3600; i++)
+ texcoords[i] = 0;
+ int col = 0, line = 0;
+ for(; *text; text++)
+ if(*text != '\n'){
+ set_char(col, line, *text);
+ col++;
+ } else {
+ col = 0;
+ line++;
+ }
+}
+
+int Hud::init(){
+ std::vector<float> vertices;
+ vertices.reserve(3600);
+ /* 100 character display, 3 lines */
+ for(float y = y_space; y >= -y_space; y -= y_space)
+ for(int i = 0; i < char_width; i++){
+ vertices.push_back(0.01f * i);
+ vertices.push_back(y);
+
+ vertices.push_back(0.01f * (i + 1));
+ vertices.push_back(y);
+
+ vertices.push_back(0.01f * i);
+ vertices.push_back(y - y_space);
+
+ vertices.push_back(0.01f * (i + 1));
+ vertices.push_back(y);
+
+ vertices.push_back(0.01f * (i + 1));
+ vertices.push_back(y - y_space);
+
+ vertices.push_back(0.01f * i);
+ vertices.push_back(y - y_space);
+
+ }
+ glGenBuffers(1, &vbuf);
+ glBindBuffer(GL_SHADER_STORAGE_BUFFER, vbuf);
+ glBufferData(GL_SHADER_STORAGE_BUFFER, vertices.size() * sizeof(float), vertices.data(), GL_STATIC_DRAW);
+
+ for(int i = 0; i < char_width * 3; i++)
+ set_char(i % char_width, i / char_width, '#');
+ glGenBuffers(1, &cbuf);
+
+ tex = load_texture("textures/letters.png");
+
+ program = make_program("shaders/hud_vertex_shader.glsl", 0, 0, 0, "shaders/hud_fragment_shader.glsl");
+ if(!program)
+ return 1;
+ v_attrib = glGetAttribLocation(program, "in_vertex");
+ t_attrib = glGetAttribLocation(program, "in_texcoord");
+ return 0;
+}
+
+void Hud::draw(){
+ glUseProgram(program);
+ glEnableVertexAttribArray(v_attrib);
+ glBindBuffer(GL_ARRAY_BUFFER, vbuf);
+ glVertexAttribPointer(v_attrib, 2, GL_FLOAT, GL_FALSE, 0, 0);
+
+ glBindBuffer(GL_SHADER_STORAGE_BUFFER, cbuf);
+ glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(texcoords), texcoords, GL_STATIC_DRAW);
+ glEnableVertexAttribArray(t_attrib);
+ glBindBuffer(GL_ARRAY_BUFFER, cbuf);
+ glVertexAttribPointer(t_attrib, 2, GL_FLOAT, GL_FALSE, 0, 0);
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, tex);
+
+ glDrawArrays(GL_TRIANGLES, 0, 1800);
+}
--- /dev/null
+#pragma once
+
+class Overlay {
+ public:
+ string name;
+ Overlay(string n) : name(n) {};
+ virtual int init() = 0;
+ virtual void draw() = 0;
+
+};
+
+class Aimpoint : public Overlay {
+ public:
+ Aimpoint(string n) : Overlay(n) {}
+ unsigned int vbuf, program, v_attrib;
+ int init() override;
+ void draw() override;
+};
+
+class Hud : public Overlay {
+ public:
+ Hud(string n) : Overlay(n) {}
+ unsigned int vbuf, program, v_attrib, tbuf, t_attrib, tex, cbuf;
+ float texcoords[3600];
+ int char_width = 100;
+ float y_space = 0.02f;
+
+ int init() override;
+ void draw() override;
+ void set_char(int col, int line, char c);
+ void lprintf(int line, const char *fmt, ...);
+ void set_text_line(int line, const char* text);
+ void set_text(const char* text);
+};
glfwSetCursorPosCallback(window, cursor_pos_callback);
glfwSetMouseButtonCallback(window, mouse_button_callback);
glfwSetFramebufferSizeCallback(window, window_size_callback);
+ glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
+
+ // Set up hud and aimpoint
+ Overlay *aimpoint = new Aimpoint("Aimpoint");
+ aimpoint->init();
+ overlays.push_back(aimpoint);
+ main_hud = new Hud("Main Hud");
+ main_hud->init();
+ overlays.push_back(main_hud);
+ main_hud->lprintf(1, "Hello World!");
load_level();
for(auto o : game_objects)
for(auto o : game_objects)
o->draw(vp);
+ for(auto o : overlays)
+ o->draw();
+
/* Not for a particular object */
glfwSwapBuffers(window);
framecount++;
--- /dev/null
+#version 460
+
+out vec4 outcolor;
+
+void main(void) {
+ outcolor = vec4(0.0f, 1.0f, 0.0f, 1.0f);
+}
--- /dev/null
+#version 460
+
+out vec4 outcolor;
+
+void main(void) {
+ outcolor = vec4(1.0f, 0.0f, 0.0f, 1.0f);
+}
--- /dev/null
+#version 460
+
+in vec3 in_vertex;
+out vec4 gl_Position;
+
+void main(void) {
+ gl_Position = vec4(in_vertex, 1.0);
+}
--- /dev/null
+#version 460
+
+in vec2 frag_texcoord;
+out vec4 outcolor;
+uniform sampler2D tex;
+
+void main(void) {
+ outcolor = texture(tex, vec2(frag_texcoord.x, -frag_texcoord.y));
+ if(outcolor.r < 0.1)
+ discard;
+}
--- /dev/null
+#version 460
+
+in vec2 in_vertex;
+in vec2 in_texcoord;
+out vec4 gl_Position;
+out vec2 frag_texcoord;
+
+void main(void) {
+ gl_Position = vec4(1.8 * in_vertex.x - 0.9, 1.8 * in_vertex.y + 0.8, 0.0, 1.0);
+ frag_texcoord = in_texcoord;
+}
--- /dev/null
+#version 460
+
+in vec2 in_vertex;
+in vec2 in_texcoord;
+out vec4 gl_Position;
+out vec2 frag_texcoord;
+
+void main(void) {
+ gl_Position = vec4(1.8 * in_vertex.x - 0.9, 1.8 * in_vertex.y + 0.8, 0.0, 1.0);
+ frag_texcoord = in_texcoord;
+}