summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
Diffstat (limited to 'source')
-rw-r--r--source/main.cpp314
-rw-r--r--source/math.h32
-rw-r--r--source/shaders/ui_text_shader.fs.glsl12
-rw-r--r--source/shaders/ui_text_shader.vs.glsl12
4 files changed, 327 insertions, 43 deletions
diff --git a/source/main.cpp b/source/main.cpp
index 7deb893..6df5451 100644
--- a/source/main.cpp
+++ b/source/main.cpp
@@ -3,6 +3,7 @@
#include <SDL2/SDL.h>
#include <glad/glad.h>
#include <vector>
+#include <map>
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
@@ -50,6 +51,8 @@ typedef u8 b8;
// =========== Shader Loading =============
+#define GL2D_UScale(x) (Vec2{(x), (x)})
+
enum Texture_Filtering { TF_NEAREST, TF_LINEAR };
struct GlTexturedQuad {
@@ -211,7 +214,7 @@ s32 gl_load_texture(u32 texture_id, char *path, enum Texture_Filtering filter)
return 0;
}
-GlTexturedQuad gl_setup_textured_quad(char* texture_path, enum Texture_Filtering filter)
+GlTexturedQuad gl2d_setup_textured_quad(char* texture_path, enum Texture_Filtering filter)
{
// rendering is clock-wise
r32 quad_vertices[] = {
@@ -247,11 +250,32 @@ GlTexturedQuad gl_setup_textured_quad(char* texture_path, enum Texture_Filtering
return tex_quad;
}
-void gl_draw_tex_quad(u32 shader_program, GlTexturedQuad tex_quad)
+void gl2d_draw_tex_quad(GlShader shader, GlTexturedQuad tex_quad, Vec3 position, Vec2 scale, r32 angle)
{
- glUseProgram(shader_program);
- s32 tex_id_loc = glGetUniformLocation(shader_program, "Texture");
+ glUseProgram(shader.id);
+ s32 tex_id_loc = glGetUniformLocation(shader.id, "Texture");
glUniform1i(tex_id_loc, 0);
+
+ // 1. Rotation
+ Mat4 model = init_value4m(1.0f);
+ if (angle)
+ {
+ Mat4 rotation = rotation_matrix4m(angle, Vec3{0.0f, 0.0f, 1.0f});
+ model = multiply4m(rotation, model);
+ }
+ // 2. Scale
+ if (scale.x != 1.0f || scale.y != 1.0f)
+ {
+ Mat4 scaling = scaling_matrix4m(scale.x, scale.y, 1.0f);
+ model = multiply4m(scaling, model);
+ }
+ // 3. Translation
+ Mat4 translation = translation_matrix4m(position.x, position.y, position.z);
+ model = multiply4m(translation, model);
+
+ // sending model to the shader
+ glUniformMatrix4fv(shader.model_loc, 1, GL_TRUE, model.buffer);
+
glBindVertexArray(tex_quad.vao);
glBindTexture(GL_TEXTURE_2D, tex_quad.texture_id);
glDrawArrays(GL_TRIANGLES, 0, 6);
@@ -285,20 +309,76 @@ Vec3 camera_look_around(r32 angle_pitch, r32 angle_yaw)
return camera_look;
}
+struct TextChar {
+ u32 texture_id;
+ Vec2 size;
+ Vec2 bearing;
+ s64 advance;
+};
+
+struct CameraOrtho {
+ r32 left;
+ r32 right;
+ r32 bottom;
+ r32 top;
+ r32 near;
+ r32 far;
+ Vec2 resolution;
+ Vec2 dimensions;
+ Mat4 projection;
+};
+
+CameraOrtho camera_orthographic(r32 height, Vec2 resolution, r32 near, r32 far)
+{
+ CameraOrtho camera = { 0 };
+
+ r32 aspect_ratio = resolution.x / resolution.y;
+ r32 width = height * aspect_ratio;
+
+ r32 left = -width/2.0f;
+ r32 right = width/2.0f;
+
+ r32 bottom = -height/2.0f;
+ r32 top = height/2.0f;
+
+ camera.resolution = resolution;
+ camera.dimensions = Vec2{width, height};
+ camera.left = left;
+ camera.right = right;
+ camera.bottom = bottom;
+ camera.top = top;
+ camera.near = near;
+ camera.far = far;
+
+ camera.projection = orthographic_projection4m(left, right, bottom, top, near, far);
+
+ return camera;
+}
+
+Vec2 camera_from_screen(CameraOrtho camera, Vec2 position)
+{
+ Vec2 camera_space = { 0 };
+
+ camera_space.x = camera.left + position.x * (camera.dimensions.x/camera.resolution.x);
+ camera_space.y = camera.top - position.y * (camera.dimensions.y/camera.resolution.y);
+
+ return camera_space;
+}
+
int main(int argc, char* argv[])
{
// Load freetype
- FT_Library library;
+ FT_Library ft_lib;
FT_Face face;
- if (FT_Init_FreeType(&library))
+ if (FT_Init_FreeType(&ft_lib))
{
printf("Error: Could not init freetype library\n");
return -1;
}
- FT_Error error = FT_New_Face(library, "assets/fonts/Arial.ttf", 0, &face);
+ FT_Error error = FT_New_Face(ft_lib, "assets/fonts/Arial.ttf", 0, &face);
if (error == FT_Err_Unknown_File_Format)
{
printf("Error: Font Loading Failed. The font format is unsupported.\n");
@@ -310,8 +390,6 @@ int main(int argc, char* argv[])
return -1;
}
- FT_Set_Pixel_Sizes(face, 0, 48);
-
int width = 1024;
int height = 768;
@@ -353,7 +431,7 @@ int main(int argc, char* argv[])
}
// vsync controls: 0 = OFF | 1 = ON (Default)
- // SDL_GL_SetSwapInterval(0);
+ SDL_GL_SetSwapInterval(1);
// filesystem playground stuff
size_t read_count;
@@ -361,20 +439,83 @@ int main(int argc, char* argv[])
tex_quad_shader.id = gl_shader_program_from_path("./source/shaders/textured_quad.vs.glsl", "./source/shaders/textured_quad.fs.glsl");
gl_shader_load_locations(&tex_quad_shader);
- GlTexturedQuad tex_quad1 = gl_setup_textured_quad("./assets/smiling.png", TF_LINEAR);
- GlTexturedQuad tex_quad2 = gl_setup_textured_quad("./assets/container.jpg", TF_LINEAR);
+ u32 ui_text_sp = gl_shader_program_from_path("./source/shaders/ui_text_shader.vs.glsl", "./source/shaders/ui_text_shader.fs.glsl");
+
+ GlTexturedQuad tex_quad1 = gl2d_setup_textured_quad("./assets/smiling.png", TF_LINEAR);
+ GlTexturedQuad tex_quad2 = gl2d_setup_textured_quad("./assets/container.jpg", TF_LINEAR);
- // objects
- Vec3 model_translations[] = {
- Vec3{ 0.5, 0.0, 0.0}, // 0: origin square
- Vec3{ -1.0, 0.0, -1.0}, // 1: plane
- Vec3{ -1.0, 0.0, -0.5}, // 2: window between squares
- Vec3{ 0.0, 0.0, 3.0}, // 3: window infront of origin square
- Vec3{ -2.5, 0.0, -0.5}, // 4: square to the left
- Vec3{ -1.0, 0.0, -1.5}, // 5: random square behind window between squares
- Vec3{ -1.0, 0.0, -8.0}, // 6: reflective plane
- Vec3{ -1.0, 2.0, -8.0}, // 6: refractive "window"
- };
+ // ====================
+ // setup_text
+ // debug only
+ std::map<char, TextChar> all_text_chars;
+
+ FT_Set_Pixel_Sizes(face, 0, 48);
+
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+ // generate characters
+ for (unsigned char c = 0; c < 128; c++)
+ {
+ if (FT_Load_Char(face, c, FT_LOAD_RENDER))
+ {
+ printf("Error: Freetype failed to load glyph: %c", c);
+ }
+ else
+ {
+ // generate texture
+ u32 texture;
+ glGenTextures(1, &texture);
+ glBindTexture(GL_TEXTURE_2D, texture);
+ glTexImage2D(
+ GL_TEXTURE_2D,
+ 0,
+ GL_RED,
+ face->glyph->bitmap.width,
+ face->glyph->bitmap.rows,
+ 0,
+ GL_RED,
+ GL_UNSIGNED_BYTE,
+ face->glyph->bitmap.buffer
+ );
+ // set texture options
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+ TextChar tc = {
+ texture,
+ Vec2{(r32)face->glyph->bitmap.width, (r32)face->glyph->bitmap.rows},
+ Vec2{(r32)face->glyph->bitmap_left, (r32)face->glyph->bitmap_top},
+ face->glyph->advance.x
+ };
+
+ all_text_chars.insert(std::pair<char, TextChar>(c, tc));
+ }
+
+ }
+ r32 vertices[] = {
+ 0.0f, 0.0f,
+ 0.0f, 1.0f,
+ 1.0f, 1.0f,
+
+ 0.0f, 0.0f,
+ 1.0f, 1.0f,
+ 1.0f, 0.0f
+ };
+
+ u32 vao, vbo;
+ glGenVertexArrays(1, &vao);
+ glGenBuffers(1, &vbo);
+ glBindVertexArray(vao);
+ glBindBuffer(GL_ARRAY_BUFFER, vbo);
+ glBufferData(GL_ARRAY_BUFFER, 6*5*sizeof(r32), NULL, GL_DYNAMIC_DRAW);
+ glEnableVertexAttribArray(0);
+ glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(r32), 0);
+ glEnableVertexAttribArray(1);
+ glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(r32), (void*)(3*sizeof(r32)));
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+ glBindVertexArray(0);
+ // ==================== END setup_text
r32 FOV = 90.0;
r32 time_curr;
@@ -396,13 +537,37 @@ int main(int argc, char* argv[])
Mat4 view = camera_create4m(camera_pos, camera_look, preset_up_dir);
Mat4 proj = perspective4m((r32)To_Radian(90.0), (r32)width / (r32)height, 0.1f, 1000.0f);
+ Vec2 camera_res = {1024.0f, 768.0f};
+ r32 ortho_cam_height = 2.0f;
+ // CameraOrtho ortho_cam = camera_orthographic(ortho_cam_height, Vec2{camera_res.x, camera_res.y}, 0.1f, 1000.0f);
+ Mat4 ortho_proj = orthographic_projection4m(0.0f, 1024.0f, 0.0f, 768.0f, 0.1f, 1000.0f);
+
+ // objects
+ Vec3 model_translations[] = {
+ Vec3{ 0.0, 0.0, 0.0}, // 0: origin square
+ Vec3{ -1.0, 0.0, -1.0}, // 1: plane
+ Vec3{ -1.0, 0.0, -0.5}, // 2: window between squares
+ Vec3{ 0.0, 0.0, 3.0}, // 3: window infront of origin square
+ Vec3{ -2.5, 0.0, -0.5}, // 4: square to the left
+ Vec3{ -1.0, 0.0, -1.5}, // 5: random square behind window between squares
+ Vec3{ -1.0, 0.0, -8.0}, // 6: reflective plane
+ Vec3{ -1.0, 2.0, -8.0}, // 6: refractive "window"
+ };
s32 proj_loc;
- glUniformMatrix4fv(tex_quad_shader.proj_loc, 1, GL_TRUE, proj.buffer);
+ glUseProgram(ui_text_sp);
+ proj_loc = glGetUniformLocation(ui_text_sp, "Projection");
+ // glUniformMatrix4fv(proj_loc, 1, GL_TRUE, ortho_cam.projection.buffer);
+ glUniformMatrix4fv(proj_loc, 1, GL_TRUE, ortho_proj.buffer);
+
+ //glUseProgram(tex_quad_shader.id);
+ //glUniformMatrix4fv(tex_quad_shader.proj_loc, 1, GL_TRUE, ortho_cam.projection.buffer);
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
u8 game_running = true;
@@ -481,6 +646,7 @@ int main(int argc, char* argv[])
} break;
case (SDL_MOUSEMOTION):
{
+ #if 0
SDL_MouseMotionEvent mouse_event = ev.motion;
r32 x_motion = (r32)mouse_event.xrel;
r32 y_motion = (r32)mouse_event.yrel;
@@ -491,6 +657,7 @@ int main(int argc, char* argv[])
camera_look = camera_look_around(angle_pitch, angle_yaw);
}
+ #endif
} break;
default:
{
@@ -503,47 +670,107 @@ int main(int argc, char* argv[])
if (move_w)
{
camera_pos = add3v(camera_pos, camera_look_increment);
+ //model_translations[0].y += 0.25f;
}
if (move_s)
{
camera_pos = subtract3v(camera_pos, camera_look_increment);
+ //model_translations[0].y -= 0.25f;
}
if (move_a)
{
Vec3 camera_right = normalize3v(cross_multiply3v(preset_up_dir, camera_look));
Vec3 camera_right_scaled = scaler_multiply3v(camera_right, camera_speed_adjusted);
camera_pos = add3v(camera_pos, camera_right_scaled);
+ //model_translations[0].x -= 0.25f;
}
if (move_d)
{
Vec3 camera_right = normalize3v(cross_multiply3v(preset_up_dir, camera_look));
Vec3 camera_right_scaled = scaler_multiply3v(camera_right, camera_speed_adjusted);
camera_pos = subtract3v(camera_pos, camera_right_scaled);
+ //model_translations[0].x += 0.25f;
}
view = camera_create4m(camera_pos, add3v(camera_pos, camera_look), preset_up_dir);
// object shader program stuff
time_prev = time_curr;
- glUniformMatrix4fv(tex_quad_shader.view_loc, 1, GL_TRUE, view.buffer);
+ //glUseProgram(tex_quad_shader.id);
+ //glUniformMatrix4fv(tex_quad_shader.view_loc, 1, GL_TRUE, view.buffer);
// OUTPUT
glClearColor(1.0f, 0.6f, .6f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ // glDisable(GL_BLEND);
+ //gl2d_draw_tex_quad(tex_quad_shader, tex_quad1, model_translations[1], GL2D_UScale(3.0f), To_Radian(-5.0f));
+ //gl2d_draw_tex_quad(tex_quad_shader, tex_quad2, model_translations[0], GL2D_UScale(1.0f), 0.0f);
+ // gl_text_render(ui_tex_sp, // shader program
+ // Vec3{startx, starty, zindex}, // coords
+ // "hello, sailor!\nhow do you do?"); // text to render
{
- glUseProgram(tex_quad_shader.id);
- Vec3 pos = model_translations[0];
- Mat4 translation = translation_matrix4m(pos.x, pos.y, pos.z);
- glUniformMatrix4fv(tex_quad_shader.model_loc, 1, GL_TRUE, translation.buffer);
- gl_draw_tex_quad(tex_quad_shader.id, tex_quad1);
- }
- {
- glUseProgram(tex_quad_shader.id);
- Vec3 pos = model_translations[1];
- Mat4 translation = translation_matrix4m(pos.x, pos.y, pos.z);
- glUniformMatrix4fv(tex_quad_shader.model_loc, 1, GL_TRUE, translation.buffer);
- gl_draw_tex_quad(tex_quad_shader.id, tex_quad2);
+ // render ui text
+ glUseProgram(ui_text_sp);
+ s32 text_color_loc = glGetUniformLocation(ui_text_sp, "TextColor");
+ glUniform3f(text_color_loc, 0.0f, 0.8f, 0.0f);
+ glActiveTexture(GL_TEXTURE0);
+
+ glBindVertexArray(vao);
+
+ const char text_to_render[] = "hello, sailor!\nhow does your journey go?";
+ r32 startx = 512.0f;
+ r32 starty = 700.0f;
+ r32 linex = startx;
+ r32 zindex = 3.0f;
+ r32 scale = 1.0f;
+ r32 max_size = 0.0f;
+ for (u32 i = 0; i < sizeof(text_to_render) - 1; i++)
+ {
+ char c = text_to_render[i];
+ TextChar rc = all_text_chars[c];
+ if (rc.size.y > max_size)
+ {
+ max_size = rc.size.y;
+ }
+ if (c == '\n')
+ {
+ linex = startx;
+ starty = starty - (rc.size.y * 1.5 * scale); // line_height: 1.5;
+ continue;
+ }
+ else if (c == ' ')
+ {
+ linex += (rc.advance >> 6) * scale;
+ continue;
+ }
+ r32 xpos = linex + (scale * rc.bearing.x);
+ r32 ypos = starty - (rc.size.y - rc.bearing.y) * scale;
+
+ r32 w = scale * rc.size.x;
+ r32 h = scale * rc.size.y;
+
+ // update VBO for each character
+ float vertices[6][5] = {
+ // z-index to render on (part of layering)
+ { xpos, ypos + h, -zindex, 0.0f, 0.0f },
+ { xpos, ypos, -zindex, 0.0f, 1.0f },
+ { xpos + w, ypos, -zindex, 1.0f, 1.0f },
+
+ { xpos, ypos + h, -zindex, 0.0f, 0.0f },
+ { xpos + w, ypos, -zindex, 1.0f, 1.0f },
+ { xpos + w, ypos + h, -zindex, 1.0f, 0.0f }
+ };
+
+ glBindTexture(GL_TEXTURE_2D, rc.texture_id);
+ glBindBuffer(GL_ARRAY_BUFFER, vbo);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices);
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+
+ glDrawArrays(GL_TRIANGLES, 0, 6);
+ linex += (rc.advance >> 6) * scale;
+ }
+ r32 test = 1;
}
SDL_GL_SwapWindow(window);
@@ -552,11 +779,14 @@ int main(int argc, char* argv[])
// opengl free calls
// it is up to the renderer to free everything here
// of course I have not bothered to set that up so it does not matter
- glDeleteVertexArrays(1, &tex_quad1.vao);
- glDeleteVertexArrays(1, &tex_quad2.vao);
- glDeleteBuffers(1, &tex_quad1.vao);
- glDeleteBuffers(1, &tex_quad2.vao);
-
+ // glDeleteVertexArrays(1, &tex_quad1.vao);
+ // glDeleteVertexArrays(1, &tex_quad2.vao);
+ // glDeleteBuffers(1, &tex_quad1.vao);
+ // glDeleteBuffers(1, &tex_quad2.vao);
+
+ FT_Done_Face(face);
+ FT_Done_FreeType(ft_lib);
+
// sdl free calls
SDL_GL_DeleteContext(context);
SDL_DestroyWindow(window);
diff --git a/source/math.h b/source/math.h
index fda6bf8..d2b8ed0 100644
--- a/source/math.h
+++ b/source/math.h
@@ -5,6 +5,7 @@
#define Square(x) ((x)*(x))
#define To_Radian(x) ((x) * PI / 180.0f)
#define To_Degree(x) ((x) * 180.0f / PI)
+#define Ortho_Default_H 10.0f
// @notes:
// I dislike the mat4 discrepancy in the raw data. It's called buffer here while everywhere else it's called
@@ -341,7 +342,7 @@ Mat4 rotation_matrix4m(r32 angle_radians, Vec3 axis) // generates a 4x4 rotation
return res;
}
-Mat4 perspective_projection_matrix4m(r32 left, r32 right, r32 bottom, r32 top, r32 near, r32 far)
+Mat4 perspective_projection4m(r32 left, r32 right, r32 bottom, r32 top, r32 near, r32 far)
{
Mat4 res = { 0 };
@@ -377,6 +378,35 @@ Mat4 perspective4m(r32 fov, r32 aspect_ratio, r32 near, r32 far)
return res;
}
+Mat4 orthographic_projection4m(r32 left, r32 right, r32 bottom, r32 top, r32 near, r32 far)
+{
+ // @todo: understand the derivation once I am done experimenting
+ Mat4 res = { 0 };
+ res.data[0][0] = 2.0f/(right - left); res.data[0][3] = -(right + left)/(right - left);
+ res.data[1][1] = 2.0f/(top - bottom); res.data[1][3] = -(top + bottom)/(top - bottom);
+ res.data[2][2] = -2.0f/(far - near); res.data[2][3] = -(far + near)/(far - near);
+ res.data[3][3] = 1.0f;
+
+ return res;
+}
+
+// @note: takes the screen width, screen height, near and far values, and creates an orthographic projection matrix
+// height: arbitrary and depend on the user/camera creator.
+// aspect_ratio: width/height, this too is user defined.
+// near, far: values of the near and far plane
+Mat4 orthographic4m(r32 height, r32 aspect_ratio, r32 near, r32 far)
+{
+ r32 width = height * aspect_ratio;
+
+ r32 left = -width/2.0f;
+ r32 right = width/2.0f;
+
+ r32 bottom = -height/2.0f;
+ r32 top = height/2.0f;
+
+ return orthographic_projection4m(left, right, bottom, top, near, far);
+}
+
Mat4 lookat4m(Vec3 up, Vec3 forward, Vec3 right, Vec3 position)
{
/*
diff --git a/source/shaders/ui_text_shader.fs.glsl b/source/shaders/ui_text_shader.fs.glsl
new file mode 100644
index 0000000..d8bdcfb
--- /dev/null
+++ b/source/shaders/ui_text_shader.fs.glsl
@@ -0,0 +1,12 @@
+#version 330 core
+
+in vec2 TexCoords;
+uniform sampler2D Texture;
+uniform vec3 TextColor;
+out vec4 FragColor;
+
+void main() {
+ vec4 sampled = vec4(1.0, 1.0, 1.0, texture(Texture, TexCoords));
+ FragColor = sampled * vec4(TextColor, 1.0);
+};
+
diff --git a/source/shaders/ui_text_shader.vs.glsl b/source/shaders/ui_text_shader.vs.glsl
new file mode 100644
index 0000000..ecaefa4
--- /dev/null
+++ b/source/shaders/ui_text_shader.vs.glsl
@@ -0,0 +1,12 @@
+#version 330 core
+layout(location=0) in vec3 aPos;
+layout(location=1) in vec2 aTex;
+
+uniform mat4 Projection;
+
+out vec2 TexCoords;
+
+void main() {
+ gl_Position = Projection * vec4(aPos, 1.0);
+ TexCoords = aTex;
+}