diff options
Diffstat (limited to 'source')
| -rw-r--r-- | source/main.cpp | 314 | ||||
| -rw-r--r-- | source/math.h | 32 | ||||
| -rw-r--r-- | source/shaders/ui_text_shader.fs.glsl | 12 | ||||
| -rw-r--r-- | source/shaders/ui_text_shader.vs.glsl | 12 | 
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; +}  | 
