Text now renders and have a framebuffer system to potentially only render once then reuse the image.
parent
f2c6110058
commit
21ad27d146
Binary file not shown.
@ -0,0 +1,11 @@ |
||||
#version 330 core |
||||
out vec4 FragColor; |
||||
|
||||
in vec2 TexCoords; |
||||
|
||||
uniform sampler2D screenTexture; |
||||
|
||||
void main() |
||||
{ |
||||
FragColor = texture(screenTexture, TexCoords); |
||||
} |
||||
@ -0,0 +1,11 @@ |
||||
#version 330 core |
||||
layout (location = 0) in vec2 aPos; |
||||
layout (location = 1) in vec2 aTexCoords; |
||||
|
||||
out vec2 TexCoords; |
||||
|
||||
void main() |
||||
{ |
||||
gl_Position = vec4(aPos.x, aPos.y, 0.0, 1.0); |
||||
TexCoords = aTexCoords; |
||||
} |
||||
@ -0,0 +1,12 @@ |
||||
#version 330 core |
||||
in vec2 TexCoords; |
||||
out vec4 color; |
||||
|
||||
uniform sampler2D text; |
||||
uniform vec3 textColor; |
||||
|
||||
void main() |
||||
{ |
||||
vec4 sampled = vec4(1.0, 1.0, 1.0, texture(text, TexCoords).r); |
||||
color = vec4(textColor, 1.0) * sampled; |
||||
} |
||||
@ -0,0 +1,11 @@ |
||||
#version 330 core |
||||
layout (location = 0) in vec4 vertex; // <vec2 pos, vec2 tex> |
||||
out vec2 TexCoords; |
||||
|
||||
uniform mat4 projection; |
||||
|
||||
void main() |
||||
{ |
||||
gl_Position = projection * vec4(vertex.xy, 0.0, 1.0); |
||||
TexCoords = vertex.zw; |
||||
} |
||||
@ -0,0 +1,311 @@ |
||||
#ifndef __khrplatform_h_ |
||||
#define __khrplatform_h_ |
||||
|
||||
/*
|
||||
** Copyright (c) 2008-2018 The Khronos Group Inc. |
||||
** |
||||
** Permission is hereby granted, free of charge, to any person obtaining a |
||||
** copy of this software and/or associated documentation files (the |
||||
** "Materials"), to deal in the Materials without restriction, including |
||||
** without limitation the rights to use, copy, modify, merge, publish, |
||||
** distribute, sublicense, and/or sell copies of the Materials, and to |
||||
** permit persons to whom the Materials are furnished to do so, subject to |
||||
** the following conditions: |
||||
** |
||||
** The above copyright notice and this permission notice shall be included |
||||
** in all copies or substantial portions of the Materials. |
||||
** |
||||
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
||||
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
||||
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. |
||||
** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY |
||||
** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, |
||||
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE |
||||
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. |
||||
*/ |
||||
|
||||
/* Khronos platform-specific types and definitions.
|
||||
* |
||||
* The master copy of khrplatform.h is maintained in the Khronos EGL |
||||
* Registry repository at https://github.com/KhronosGroup/EGL-Registry
|
||||
* The last semantic modification to khrplatform.h was at commit ID: |
||||
* 67a3e0864c2d75ea5287b9f3d2eb74a745936692 |
||||
* |
||||
* Adopters may modify this file to suit their platform. Adopters are |
||||
* encouraged to submit platform specific modifications to the Khronos |
||||
* group so that they can be included in future versions of this file. |
||||
* Please submit changes by filing pull requests or issues on |
||||
* the EGL Registry repository linked above. |
||||
* |
||||
* |
||||
* See the Implementer's Guidelines for information about where this file |
||||
* should be located on your system and for more details of its use: |
||||
* http://www.khronos.org/registry/implementers_guide.pdf
|
||||
* |
||||
* This file should be included as |
||||
* #include <KHR/khrplatform.h> |
||||
* by Khronos client API header files that use its types and defines. |
||||
* |
||||
* The types in khrplatform.h should only be used to define API-specific types. |
||||
* |
||||
* Types defined in khrplatform.h: |
||||
* khronos_int8_t signed 8 bit |
||||
* khronos_uint8_t unsigned 8 bit |
||||
* khronos_int16_t signed 16 bit |
||||
* khronos_uint16_t unsigned 16 bit |
||||
* khronos_int32_t signed 32 bit |
||||
* khronos_uint32_t unsigned 32 bit |
||||
* khronos_int64_t signed 64 bit |
||||
* khronos_uint64_t unsigned 64 bit |
||||
* khronos_intptr_t signed same number of bits as a pointer |
||||
* khronos_uintptr_t unsigned same number of bits as a pointer |
||||
* khronos_ssize_t signed size |
||||
* khronos_usize_t unsigned size |
||||
* khronos_float_t signed 32 bit floating point |
||||
* khronos_time_ns_t unsigned 64 bit time in nanoseconds |
||||
* khronos_utime_nanoseconds_t unsigned time interval or absolute time in |
||||
* nanoseconds |
||||
* khronos_stime_nanoseconds_t signed time interval in nanoseconds |
||||
* khronos_boolean_enum_t enumerated boolean type. This should |
||||
* only be used as a base type when a client API's boolean type is |
||||
* an enum. Client APIs which use an integer or other type for |
||||
* booleans cannot use this as the base type for their boolean. |
||||
* |
||||
* Tokens defined in khrplatform.h: |
||||
* |
||||
* KHRONOS_FALSE, KHRONOS_TRUE Enumerated boolean false/true values. |
||||
* |
||||
* KHRONOS_SUPPORT_INT64 is 1 if 64 bit integers are supported; otherwise 0. |
||||
* KHRONOS_SUPPORT_FLOAT is 1 if floats are supported; otherwise 0. |
||||
* |
||||
* Calling convention macros defined in this file: |
||||
* KHRONOS_APICALL |
||||
* KHRONOS_APIENTRY |
||||
* KHRONOS_APIATTRIBUTES |
||||
* |
||||
* These may be used in function prototypes as: |
||||
* |
||||
* KHRONOS_APICALL void KHRONOS_APIENTRY funcname( |
||||
* int arg1, |
||||
* int arg2) KHRONOS_APIATTRIBUTES; |
||||
*/ |
||||
|
||||
#if defined(__SCITECH_SNAP__) && !defined(KHRONOS_STATIC) |
||||
# define KHRONOS_STATIC 1 |
||||
#endif |
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Definition of KHRONOS_APICALL |
||||
*------------------------------------------------------------------------- |
||||
* This precedes the return type of the function in the function prototype. |
||||
*/ |
||||
#if defined(KHRONOS_STATIC) |
||||
/* If the preprocessor constant KHRONOS_STATIC is defined, make the
|
||||
* header compatible with static linking. */ |
||||
# define KHRONOS_APICALL |
||||
#elif defined(_WIN32) |
||||
# define KHRONOS_APICALL __declspec(dllimport) |
||||
#elif defined (__SYMBIAN32__) |
||||
# define KHRONOS_APICALL IMPORT_C |
||||
#elif defined(__ANDROID__) |
||||
# define KHRONOS_APICALL __attribute__((visibility("default"))) |
||||
#else |
||||
# define KHRONOS_APICALL |
||||
#endif |
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Definition of KHRONOS_APIENTRY |
||||
*------------------------------------------------------------------------- |
||||
* This follows the return type of the function and precedes the function |
||||
* name in the function prototype. |
||||
*/ |
||||
#if defined(_WIN32) && !defined(_WIN32_WCE) && !defined(__SCITECH_SNAP__) |
||||
/* Win32 but not WinCE */ |
||||
# define KHRONOS_APIENTRY __stdcall |
||||
#else |
||||
# define KHRONOS_APIENTRY |
||||
#endif |
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Definition of KHRONOS_APIATTRIBUTES |
||||
*------------------------------------------------------------------------- |
||||
* This follows the closing parenthesis of the function prototype arguments. |
||||
*/ |
||||
#if defined (__ARMCC_2__) |
||||
#define KHRONOS_APIATTRIBUTES __softfp |
||||
#else |
||||
#define KHRONOS_APIATTRIBUTES |
||||
#endif |
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* basic type definitions |
||||
*-----------------------------------------------------------------------*/ |
||||
#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__GNUC__) || defined(__SCO__) || defined(__USLC__) |
||||
|
||||
|
||||
/*
|
||||
* Using <stdint.h> |
||||
*/ |
||||
#include <stdint.h> |
||||
typedef int32_t khronos_int32_t; |
||||
typedef uint32_t khronos_uint32_t; |
||||
typedef int64_t khronos_int64_t; |
||||
typedef uint64_t khronos_uint64_t; |
||||
#define KHRONOS_SUPPORT_INT64 1 |
||||
#define KHRONOS_SUPPORT_FLOAT 1 |
||||
/*
|
||||
* To support platform where unsigned long cannot be used interchangeably with |
||||
* inptr_t (e.g. CHERI-extended ISAs), we can use the stdint.h intptr_t. |
||||
* Ideally, we could just use (u)intptr_t everywhere, but this could result in |
||||
* ABI breakage if khronos_uintptr_t is changed from unsigned long to |
||||
* unsigned long long or similar (this results in different C++ name mangling). |
||||
* To avoid changes for existing platforms, we restrict usage of intptr_t to |
||||
* platforms where the size of a pointer is larger than the size of long. |
||||
*/ |
||||
#if defined(__SIZEOF_LONG__) && defined(__SIZEOF_POINTER__) |
||||
#if __SIZEOF_POINTER__ > __SIZEOF_LONG__ |
||||
#define KHRONOS_USE_INTPTR_T |
||||
#endif |
||||
#endif |
||||
|
||||
#elif defined(__VMS ) || defined(__sgi) |
||||
|
||||
/*
|
||||
* Using <inttypes.h> |
||||
*/ |
||||
#include <inttypes.h> |
||||
typedef int32_t khronos_int32_t; |
||||
typedef uint32_t khronos_uint32_t; |
||||
typedef int64_t khronos_int64_t; |
||||
typedef uint64_t khronos_uint64_t; |
||||
#define KHRONOS_SUPPORT_INT64 1 |
||||
#define KHRONOS_SUPPORT_FLOAT 1 |
||||
|
||||
#elif defined(_WIN32) && !defined(__SCITECH_SNAP__) |
||||
|
||||
/*
|
||||
* Win32 |
||||
*/ |
||||
typedef __int32 khronos_int32_t; |
||||
typedef unsigned __int32 khronos_uint32_t; |
||||
typedef __int64 khronos_int64_t; |
||||
typedef unsigned __int64 khronos_uint64_t; |
||||
#define KHRONOS_SUPPORT_INT64 1 |
||||
#define KHRONOS_SUPPORT_FLOAT 1 |
||||
|
||||
#elif defined(__sun__) || defined(__digital__) |
||||
|
||||
/*
|
||||
* Sun or Digital |
||||
*/ |
||||
typedef int khronos_int32_t; |
||||
typedef unsigned int khronos_uint32_t; |
||||
#if defined(__arch64__) || defined(_LP64) |
||||
typedef long int khronos_int64_t; |
||||
typedef unsigned long int khronos_uint64_t; |
||||
#else |
||||
typedef long long int khronos_int64_t; |
||||
typedef unsigned long long int khronos_uint64_t; |
||||
#endif /* __arch64__ */ |
||||
#define KHRONOS_SUPPORT_INT64 1 |
||||
#define KHRONOS_SUPPORT_FLOAT 1 |
||||
|
||||
#elif 0 |
||||
|
||||
/*
|
||||
* Hypothetical platform with no float or int64 support |
||||
*/ |
||||
typedef int khronos_int32_t; |
||||
typedef unsigned int khronos_uint32_t; |
||||
#define KHRONOS_SUPPORT_INT64 0 |
||||
#define KHRONOS_SUPPORT_FLOAT 0 |
||||
|
||||
#else |
||||
|
||||
/*
|
||||
* Generic fallback |
||||
*/ |
||||
#include <stdint.h> |
||||
typedef int32_t khronos_int32_t; |
||||
typedef uint32_t khronos_uint32_t; |
||||
typedef int64_t khronos_int64_t; |
||||
typedef uint64_t khronos_uint64_t; |
||||
#define KHRONOS_SUPPORT_INT64 1 |
||||
#define KHRONOS_SUPPORT_FLOAT 1 |
||||
|
||||
#endif |
||||
|
||||
|
||||
/*
|
||||
* Types that are (so far) the same on all platforms |
||||
*/ |
||||
typedef signed char khronos_int8_t; |
||||
typedef unsigned char khronos_uint8_t; |
||||
typedef signed short int khronos_int16_t; |
||||
typedef unsigned short int khronos_uint16_t; |
||||
|
||||
/*
|
||||
* Types that differ between LLP64 and LP64 architectures - in LLP64, |
||||
* pointers are 64 bits, but 'long' is still 32 bits. Win64 appears |
||||
* to be the only LLP64 architecture in current use. |
||||
*/ |
||||
#ifdef KHRONOS_USE_INTPTR_T |
||||
typedef intptr_t khronos_intptr_t; |
||||
typedef uintptr_t khronos_uintptr_t; |
||||
#elif defined(_WIN64) |
||||
typedef signed long long int khronos_intptr_t; |
||||
typedef unsigned long long int khronos_uintptr_t; |
||||
#else |
||||
typedef signed long int khronos_intptr_t; |
||||
typedef unsigned long int khronos_uintptr_t; |
||||
#endif |
||||
|
||||
#if defined(_WIN64) |
||||
typedef signed long long int khronos_ssize_t; |
||||
typedef unsigned long long int khronos_usize_t; |
||||
#else |
||||
typedef signed long int khronos_ssize_t; |
||||
typedef unsigned long int khronos_usize_t; |
||||
#endif |
||||
|
||||
#if KHRONOS_SUPPORT_FLOAT |
||||
/*
|
||||
* Float type |
||||
*/ |
||||
typedef float khronos_float_t; |
||||
#endif |
||||
|
||||
#if KHRONOS_SUPPORT_INT64 |
||||
/* Time types
|
||||
* |
||||
* These types can be used to represent a time interval in nanoseconds or |
||||
* an absolute Unadjusted System Time. Unadjusted System Time is the number |
||||
* of nanoseconds since some arbitrary system event (e.g. since the last |
||||
* time the system booted). The Unadjusted System Time is an unsigned |
||||
* 64 bit value that wraps back to 0 every 584 years. Time intervals |
||||
* may be either signed or unsigned. |
||||
*/ |
||||
typedef khronos_uint64_t khronos_utime_nanoseconds_t; |
||||
typedef khronos_int64_t khronos_stime_nanoseconds_t; |
||||
#endif |
||||
|
||||
/*
|
||||
* Dummy value used to pad enum types to 32 bits. |
||||
*/ |
||||
#ifndef KHRONOS_MAX_ENUM |
||||
#define KHRONOS_MAX_ENUM 0x7FFFFFFF |
||||
#endif |
||||
|
||||
/*
|
||||
* Enumerated boolean type |
||||
* |
||||
* Values other than zero should be considered to be true. Therefore |
||||
* comparisons should not be made against KHRONOS_TRUE. |
||||
*/ |
||||
typedef enum { |
||||
KHRONOS_FALSE = 0, |
||||
KHRONOS_TRUE = 1, |
||||
KHRONOS_BOOLEAN_ENUM_FORCE_SIZE = KHRONOS_MAX_ENUM |
||||
} khronos_boolean_enum_t; |
||||
|
||||
#endif /* __khrplatform_h_ */ |
||||
@ -0,0 +1,6 @@ |
||||
#pragma once |
||||
|
||||
#define INSTANCE_COUNT 5 |
||||
|
||||
const unsigned int SCR_WIDTH = 1792; |
||||
const unsigned int SCR_HEIGHT = 1008; |
||||
@ -0,0 +1,55 @@ |
||||
#include "framebuffer.hpp" |
||||
#include <glad/glad.h> |
||||
#include <GLFW/glfw3.h> |
||||
#include "config.hpp" |
||||
|
||||
void FrameBuffer::init() { |
||||
glGenFramebuffers(1, &target_fb); |
||||
glBindFramebuffer(GL_FRAMEBUFFER, target_fb); |
||||
glGenTextures(1, &texture_color_buffer); |
||||
|
||||
glBindTexture(GL_TEXTURE_2D, texture_color_buffer); |
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, SCR_WIDTH, SCR_HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); |
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); |
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); |
||||
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture_color_buffer, 0); |
||||
|
||||
glGenRenderbuffers(1, &target_rbo); |
||||
glBindRenderbuffer(GL_RENDERBUFFER, target_rbo); |
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, SCR_WIDTH, SCR_HEIGHT); |
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, target_rbo); |
||||
|
||||
dbc::check(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE, "Failed to init framebuffer."); |
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0); |
||||
|
||||
invariant(); |
||||
} |
||||
|
||||
void FrameBuffer::begin() { |
||||
glBindFramebuffer(GL_FRAMEBUFFER, target_fb); |
||||
glEnable(GL_DEPTH_TEST); |
||||
glClearColor(0.0f, 1.0f, 0.0f, 1.0f); |
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); |
||||
} |
||||
|
||||
void FrameBuffer::commit() { |
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0); |
||||
glDisable(GL_DEPTH_TEST); |
||||
glClearColor(0.0f, 0.0f, 1.0, 1.0f); |
||||
glClear(GL_COLOR_BUFFER_BIT); |
||||
} |
||||
|
||||
void FrameBuffer::draw(Screen& screen) { |
||||
screen.shader.use(); |
||||
glBindVertexArray(screen.target_VAO); |
||||
glActiveTexture(GL_TEXTURE0 + screen.texture_id); |
||||
glBindTexture(GL_TEXTURE_2D, texture_color_buffer); |
||||
glDrawArrays(GL_TRIANGLES, 0, 6); |
||||
} |
||||
|
||||
void FrameBuffer::invariant() { |
||||
dbc::check(target_fb != UINT_MAX, "target_fb not initialized"); |
||||
dbc::check(texture_color_buffer != UINT_MAX, "texture_color_buffer not initialized"); |
||||
} |
||||
@ -0,0 +1,17 @@ |
||||
#pragma once |
||||
|
||||
#include "shader.hpp" |
||||
#include "screen.hpp" |
||||
|
||||
struct FrameBuffer { |
||||
unsigned int target_fb = UINT_MAX; |
||||
unsigned int target_rbo = UINT_MAX; |
||||
unsigned int texture_color_buffer = UINT_MAX; |
||||
|
||||
|
||||
void init(); |
||||
void begin(); |
||||
void commit(); |
||||
void draw(Screen& screen); |
||||
void invariant(); |
||||
}; |
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,140 @@ |
||||
#include "bezos.hpp" |
||||
#define _USE_MATH_DEFINES |
||||
#include <glm/glm.hpp> |
||||
#include <glm/gtc/matrix_transform.hpp> |
||||
#include <glm/gtc/type_ptr.hpp> |
||||
#include <stb_image.h> |
||||
#include <fmt/core.h> |
||||
#include <glad/glad.h> |
||||
#include <GLFW/glfw3.h> |
||||
#include "text.hpp" |
||||
#include "config.hpp" |
||||
#include "screen.hpp" |
||||
#include "framebuffer.hpp" |
||||
|
||||
int main(int argc, char *argv[]) { |
||||
Deck deck = Bezos::load("lua/builder_test.lua"); |
||||
Bezos::dump(deck); |
||||
float mouse_x = 0; |
||||
float mouse_y = 0; |
||||
|
||||
void framebuffer_size_callback(GLFWwindow *window, int width, int height); |
||||
|
||||
struct State { |
||||
FrameBuffer framebuffer; |
||||
Screen screen; |
||||
std::string text_content{"Hi!"}; |
||||
Text text{.font_size=202}; |
||||
|
||||
State() { |
||||
text.load_font(); |
||||
screen.init(); |
||||
framebuffer.init(); |
||||
} |
||||
}; |
||||
|
||||
void init_glfw() { |
||||
glfwInit(); |
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); |
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); |
||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); |
||||
|
||||
#ifdef __APPLE__ |
||||
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); |
||||
#endif |
||||
} |
||||
|
||||
void framebuffer_size_callback(GLFWwindow *, int width, int height) { |
||||
glViewport(0, 0, width, height); |
||||
} |
||||
|
||||
void mouse_callback(GLFWwindow *window, double xpos, double ypos) { |
||||
fmt::println("mouse click: {},{}", xpos, ypos); |
||||
mouse_x = xpos; |
||||
mouse_y = ypos; |
||||
} |
||||
|
||||
void scroll_callback(GLFWwindow *window, double xoffset, double yoffset) { |
||||
} |
||||
|
||||
GLFWwindow* create_window() { |
||||
GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL); |
||||
dbc::check(window != NULL, "failed to open window"); |
||||
|
||||
glfwMakeContextCurrent(window); |
||||
|
||||
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback); |
||||
|
||||
auto good = gladLoadGLLoader((GLADloadproc)glfwGetProcAddress); |
||||
dbc::check(good, "failed to load GLAD"); |
||||
|
||||
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); |
||||
glfwSetCursorPosCallback(window, mouse_callback); |
||||
glfwSetScrollCallback(window, scroll_callback); |
||||
|
||||
return window; |
||||
} |
||||
|
||||
void process_input(GLFWwindow *window) { |
||||
if(glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) { |
||||
glfwSetWindowShouldClose(window, true); |
||||
} |
||||
|
||||
if(glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS) { |
||||
fmt::println("move window left"); |
||||
} |
||||
|
||||
if(glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS) { |
||||
fmt::println("move window left"); |
||||
} |
||||
} |
||||
|
||||
void setup() { |
||||
glEnable(GL_DEPTH_TEST); |
||||
glEnable(GL_BLEND); |
||||
glEnable(GL_CULL_FACE); |
||||
glEnable(GL_MULTISAMPLE); |
||||
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); |
||||
|
||||
glDepthFunc(GL_LESS); |
||||
} |
||||
|
||||
void update(GLFWwindow* window) { |
||||
glfwPollEvents(); |
||||
process_input(window); |
||||
} |
||||
|
||||
void render(GLFWwindow* window, State &state) { |
||||
state.framebuffer.begin(); |
||||
|
||||
glClearColor(0.1f, 0.1f, 0.1f, 1.0f); |
||||
glClear(GL_COLOR_BUFFER_BIT); |
||||
|
||||
state.text.render(state.text_content, 25.0f, SCR_HEIGHT - state.text.font_size - 20, 1.0f, |
||||
glm::vec3(1.0f, 1.0f, 1.0f)); |
||||
|
||||
state.framebuffer.commit(); |
||||
state.framebuffer.draw(state.screen); |
||||
|
||||
glfwSwapBuffers(window); |
||||
} |
||||
|
||||
void quit(GLFWwindow* window) { |
||||
glfwTerminate(); |
||||
} |
||||
|
||||
int main() { |
||||
init_glfw(); |
||||
|
||||
auto window = create_window(); |
||||
setup(); |
||||
State state; |
||||
|
||||
// glfwSetWindowUserPointer(window, scene.get());
|
||||
|
||||
while(!glfwWindowShouldClose(window)) { |
||||
update(window); |
||||
render(window, state); |
||||
} |
||||
|
||||
quit(window); |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
@ -0,0 +1,18 @@ |
||||
#include "screen.hpp" |
||||
#include <glad/glad.h> |
||||
#include <GLFW/glfw3.h> |
||||
|
||||
void Screen::init() { |
||||
shader.use(); |
||||
shader.setInt("screenTexture", texture_id); |
||||
|
||||
glGenVertexArrays(1, &target_VAO); |
||||
glGenBuffers(1, &target_VBO); |
||||
glBindVertexArray(target_VAO); |
||||
glBindBuffer(GL_ARRAY_BUFFER, target_VBO); |
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), &vertices, GL_STATIC_DRAW); |
||||
glEnableVertexAttribArray(0); |
||||
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void *)0); |
||||
glEnableVertexAttribArray(1); |
||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)(2 * sizeof(float))); |
||||
} |
||||
@ -0,0 +1,23 @@ |
||||
#pragma once |
||||
#include "shader.hpp" |
||||
|
||||
struct Screen { |
||||
Shader shader{{"shaders/screen.vert.glsl", "shaders/screen.frag.glsl", ""}}; |
||||
unsigned int target_VAO = 0; |
||||
unsigned int target_VBO = 0; |
||||
unsigned int texture_id = 10; |
||||
|
||||
float vertices[24] = { |
||||
// vertex attributes for a quad that fills the entire screen in Normalized Device Coordinates.
|
||||
// positions // texCoords
|
||||
-1.0f, 1.0f, 0.0f, 1.0f, |
||||
-1.0f, -1.0f, 0.0f, 0.0f, |
||||
1.0f, -1.0f, 1.0f, 0.0f, |
||||
|
||||
-1.0f, 1.0f, 0.0f, 1.0f, |
||||
1.0f, -1.0f, 1.0f, 0.0f, |
||||
1.0f, 1.0f, 1.0f, 1.0f |
||||
}; |
||||
|
||||
void init(); |
||||
}; |
||||
@ -0,0 +1,148 @@ |
||||
#include "shader.hpp" |
||||
#include <iostream> |
||||
#include <fstream> |
||||
#include <sstream> |
||||
#include <print> |
||||
#include <filesystem> |
||||
#include "dbc.hpp" |
||||
#include <glm/glm.hpp> |
||||
#include <glm/gtc/matrix_transform.hpp> |
||||
#include <glm/gtc/type_ptr.hpp> |
||||
|
||||
namespace fs = std::filesystem; |
||||
|
||||
inline std::string read_file(const std::string& filename) { |
||||
// load the file
|
||||
std::ifstream in_file{filename, std::ios::binary}; |
||||
|
||||
// get the size of the file
|
||||
std::stringstream in_str; |
||||
in_str << in_file.rdbuf(); |
||||
return in_str.str(); |
||||
} |
||||
|
||||
void check_error(const std::string& what, unsigned int thing, GLenum check_type) { |
||||
int success = 0; |
||||
char infoLog[512] = {0}; |
||||
|
||||
if(check_type == GL_LINK_STATUS) { |
||||
glGetProgramiv(thing, check_type, &success); |
||||
|
||||
if(!success) { |
||||
glGetProgramInfoLog(thing, 512, NULL, infoLog); |
||||
dbc::sentinel(std::format("ERROR: Program {} compile failed: {}", what, infoLog)); |
||||
} |
||||
} else { |
||||
glGetShaderiv(thing, check_type, &success); |
||||
|
||||
if(!success) { |
||||
glGetShaderInfoLog(thing, 512, NULL, infoLog); |
||||
dbc::sentinel(std::format("ERROR: Shader {} compile failed: {}", what, infoLog)); |
||||
} |
||||
} |
||||
} |
||||
|
||||
unsigned int Shader::load_shader(const std::string& filename, GLenum shader_type) { |
||||
dbc::log($F("Loading shader {}", filename)); |
||||
dbc::check(fs::exists(filename), |
||||
std::format("shader file {} does not exist", filename)); |
||||
|
||||
// create the shader
|
||||
std::string shader_code = read_file(filename); |
||||
const char* shader_code_ptr = shader_code.c_str(); |
||||
|
||||
int shader_id = glCreateShader(shader_type); |
||||
glShaderSource(shader_id, 1, &shader_code_ptr, NULL); |
||||
glCompileShader(shader_id); |
||||
|
||||
check_error(filename, shader_id, GL_COMPILE_STATUS); |
||||
|
||||
// check compile error
|
||||
return shader_id; |
||||
} |
||||
|
||||
|
||||
Shader::Shader(ShaderConfig c) : config(c) |
||||
{ |
||||
dbc::log($F("Loading shaders vert={}, frag={}, geom={}", config.vertex_path, config.frag_path, config.geometry_path)); |
||||
|
||||
unsigned int vertex = load_shader(config.vertex_path, GL_VERTEX_SHADER); |
||||
unsigned int fragment = load_shader(config.frag_path, GL_FRAGMENT_SHADER); |
||||
unsigned int geometry = UINT_MAX; |
||||
|
||||
ID = glCreateProgram(); |
||||
dbc::log($F("Created shader program ID: {}", ID)); |
||||
glAttachShader(ID, vertex); |
||||
glAttachShader(ID, fragment); |
||||
|
||||
if(config.geometry_path != "") { |
||||
geometry = load_shader(config.geometry_path, GL_GEOMETRY_SHADER); |
||||
glAttachShader(ID, geometry); |
||||
} |
||||
|
||||
glLinkProgram(ID); |
||||
check_error("link", ID, GL_LINK_STATUS); |
||||
|
||||
glDeleteShader(vertex); |
||||
glDeleteShader(fragment); |
||||
|
||||
if(config.geometry_path != "") { |
||||
glDeleteShader(geometry); |
||||
} |
||||
} |
||||
|
||||
void Shader::use() const { |
||||
glUseProgram(ID); |
||||
} |
||||
|
||||
void Shader::cleanup() { |
||||
glDeleteProgram(ID); |
||||
} |
||||
|
||||
void Shader::setBool(const std::string &name, bool value) const { |
||||
auto uniform = glGetUniformLocation(ID, name.c_str()); |
||||
glUniform1i(uniform, (int)value); |
||||
} |
||||
|
||||
void Shader::setInt(const std::string &name, int value) const { |
||||
auto uniform = glGetUniformLocation(ID, name.c_str()); |
||||
glUniform1i(uniform, value); |
||||
} |
||||
|
||||
void Shader::setFloat(const std::string &name, float value) const { |
||||
auto uniform = glGetUniformLocation(ID, name.c_str()); |
||||
glUniform1f(uniform, value); |
||||
} |
||||
|
||||
void Shader::setVec4(const std::string &name, float v1, float v2, float v3, float v4) const { |
||||
auto uniform = glGetUniformLocation(ID, name.c_str()); |
||||
glUniform4f(uniform, v1, v2, v3, v4); |
||||
} |
||||
|
||||
void Shader::setVec4(const std::string &name, const glm::vec4& value) const |
||||
{ |
||||
auto uniform = glGetUniformLocation(ID, name.c_str()); |
||||
glUniform4fv(uniform, 1, &value[0]); |
||||
} |
||||
|
||||
void Shader::setVec2(const std::string &name, const glm::vec2& value) const |
||||
{ |
||||
auto uniform = glGetUniformLocation(ID, name.c_str()); |
||||
glUniform2fv(uniform, 1, &value[0]); |
||||
} |
||||
|
||||
void Shader::setVec3(const std::string &name, const glm::vec3& value) const |
||||
{ |
||||
auto uniform = glGetUniformLocation(ID, name.c_str()); |
||||
glUniform3fv(uniform, 1, &value[0]); |
||||
} |
||||
|
||||
void Shader::setVec3(const std::string &name, float v1, float v2, float v3) const { |
||||
auto uniform = glGetUniformLocation(ID, name.c_str()); |
||||
glUniform3f(uniform, v1, v2, v3); |
||||
} |
||||
|
||||
void Shader::setMat4(const std::string &name, const glm::mat4& mat) const { |
||||
unsigned int loc = glGetUniformLocation(ID, name.c_str()); |
||||
glUniformMatrix4fv(loc, 1, GL_FALSE, glm::value_ptr(mat)); |
||||
} |
||||
@ -0,0 +1,37 @@ |
||||
#pragma once |
||||
|
||||
#include <glad/glad.h> |
||||
#include <string> |
||||
#include <climits> |
||||
#include <glm/glm.hpp> |
||||
#include <vector> |
||||
#include <format> |
||||
#include "dbc.hpp" |
||||
|
||||
struct ShaderConfig { |
||||
std::string vertex_path; |
||||
std::string frag_path; |
||||
std::string geometry_path; |
||||
}; |
||||
|
||||
class Shader |
||||
{ |
||||
public: |
||||
unsigned int ID = UINT_MAX; |
||||
ShaderConfig config; |
||||
|
||||
Shader(ShaderConfig config); |
||||
|
||||
unsigned int load_shader(const std::string& filename, GLenum shader_type); |
||||
void use() const; |
||||
void setBool(const std::string &name, bool value) const; |
||||
void setInt(const std::string &name, int value) const; |
||||
void setFloat(const std::string &name, float value) const; |
||||
void setVec4(const std::string &name, float v1, float v2, float v3, float v4) const; |
||||
void setVec4(const std::string &name, const glm::vec4& value) const; |
||||
void setVec3(const std::string &name, float v1, float v2, float v3) const; |
||||
void setVec3(const std::string &name, const glm::vec3& value) const; |
||||
void setVec2(const std::string &name, const glm::vec2& value) const; |
||||
void setMat4(const std::string &name, const glm::mat4& what) const; |
||||
void cleanup(); |
||||
}; |
||||
@ -0,0 +1,2 @@ |
||||
#define STB_IMAGE_IMPLEMENTATION |
||||
#include <stb_image.h> |
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,114 @@ |
||||
#include "text.hpp" |
||||
#include <glm/glm.hpp> |
||||
#include <glm/gtc/matrix_transform.hpp> |
||||
#include <glm/gtc/type_ptr.hpp> |
||||
#include <glad/glad.h> |
||||
#include <GLFW/glfw3.h> |
||||
#include <ft2build.h> |
||||
#include "config.hpp" |
||||
#include FT_FREETYPE_H |
||||
|
||||
void Text::render(const std::string& text, float x, float y, float scale, glm::vec3 color) { |
||||
text_shader.use(); |
||||
glm::mat4 projection = glm::ortho(0.0f, static_cast<float>(SCR_WIDTH), 0.0f, static_cast<float>(SCR_HEIGHT)); |
||||
text_shader.setMat4("projection", projection); |
||||
|
||||
glUniform3f(glGetUniformLocation(text_shader.ID, "textColor"), color.x, color.y, color.z); |
||||
glActiveTexture(GL_TEXTURE0); |
||||
glBindVertexArray(text_vao); |
||||
|
||||
for(auto c : text) { |
||||
auto& ch = characters.at(c); |
||||
float xpos = x + ch.bearing.x * scale; |
||||
float ypos = y - (ch.size.y - ch.bearing.y) * scale; |
||||
float w = ch.size.x * scale; |
||||
float h = ch.size.y * scale; |
||||
|
||||
float vertices[6][4] = { |
||||
{ xpos, ypos + h, 0.0f, 0.0f }, |
||||
{ xpos, ypos, 0.0f, 1.0f }, |
||||
{ xpos + w, ypos, 1.0f, 1.0f }, |
||||
|
||||
{ xpos, ypos + h, 0.0f, 0.0f }, |
||||
{ xpos + w, ypos, 1.0f, 1.0f }, |
||||
{ xpos + w, ypos + h, 1.0f, 0.0f } |
||||
}; |
||||
|
||||
// rander glyph texture over quad
|
||||
glBindTexture(GL_TEXTURE_2D, ch.texture_id); |
||||
|
||||
// update content of VBO memory
|
||||
glBindBuffer(GL_ARRAY_BUFFER, text_vbo); |
||||
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices); |
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0); |
||||
// render quad
|
||||
glDrawArrays(GL_TRIANGLES, 0, 6); |
||||
|
||||
x += (ch.advance >> 6) * scale; |
||||
} |
||||
|
||||
glBindVertexArray(0); |
||||
glBindTexture(GL_TEXTURE_2D, 0); |
||||
} |
||||
|
||||
void Text::load_font() { |
||||
FT_Library ft; |
||||
int fail = FT_Init_FreeType(&ft); |
||||
dbc::check(fail == 0, "FreeType failed."); |
||||
|
||||
FT_Face face; |
||||
fail = FT_New_Face(ft, font.c_str(), 0, &face); |
||||
dbc::check(fail == 0, "Failed to load font."); |
||||
|
||||
// load the font bitmaps
|
||||
FT_Set_Pixel_Sizes(face, 0, font_size); |
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1); |
||||
|
||||
for(unsigned char c = 0; c < 255; c++) { |
||||
fail = FT_Load_Char(face, c, FT_LOAD_RENDER); |
||||
dbc::check(fail == 0, $F("Failed to load char {}", int(c))); |
||||
|
||||
unsigned int texture = UINT_MAX; |
||||
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); |
||||
|
||||
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); |
||||
|
||||
characters.try_emplace(c, |
||||
texture, |
||||
glm::ivec2(face->glyph->bitmap.width, face->glyph->bitmap.rows), |
||||
glm::ivec2(face->glyph->bitmap_left, face->glyph->bitmap_top), |
||||
static_cast<unsigned int>(face->glyph->advance.x)); |
||||
} |
||||
|
||||
// unbind
|
||||
glBindTexture(GL_TEXTURE_2D, 0); |
||||
|
||||
// cleanup
|
||||
FT_Done_Face(face); |
||||
FT_Done_FreeType(ft); |
||||
|
||||
// create teh vao/vbo
|
||||
glGenVertexArrays(1, &text_vao); |
||||
glGenBuffers(1, &text_vbo); |
||||
glBindVertexArray(text_vao); |
||||
glBindBuffer(GL_ARRAY_BUFFER, text_vbo); |
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 6 * 4, NULL, GL_DYNAMIC_DRAW); |
||||
glEnableVertexAttribArray(0); |
||||
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(float), 0); |
||||
glBindVertexArray(0); |
||||
} |
||||
@ -0,0 +1,24 @@ |
||||
#pragma once |
||||
#include "shader.hpp" |
||||
#include <string> |
||||
#include <unordered_map> |
||||
#include <glm/glm.hpp> |
||||
|
||||
struct Character { |
||||
unsigned int texture_id; |
||||
glm::ivec2 size; |
||||
glm::ivec2 bearing; |
||||
unsigned int advance; |
||||
}; |
||||
|
||||
struct Text { |
||||
int font_size = 48; |
||||
std::string font{"assets/fonts/text.ttf"}; |
||||
Shader text_shader{{"shaders/text.vert.glsl", "shaders/text.frag.glsl", ""}}; |
||||
unsigned int text_vao = UINT_MAX; |
||||
unsigned int text_vbo = UINT_MAX; |
||||
std::unordered_map<unsigned char, Character> characters{}; |
||||
|
||||
void render(const std::string& text, float x, float y, float scale, glm::vec3 color); |
||||
void load_font(); |
||||
}; |
||||
@ -0,0 +1,11 @@ |
||||
[wrap-file] |
||||
directory = freetype-2.13.3 |
||||
source_url = https://download.savannah.gnu.org/releases/freetype/freetype-2.13.3.tar.xz |
||||
source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/freetype2_2.13.3-1/freetype-2.13.3.tar.xz |
||||
source_filename = freetype-2.13.3.tar.xz |
||||
source_hash = 0550350666d427c74daeb85d5ac7bb353acba5f76956395995311a9c6f063289 |
||||
wrapdb_version = 2.13.3-1 |
||||
|
||||
[provide] |
||||
freetype2 = freetype_dep |
||||
freetype = freetype_dep |
||||
@ -0,0 +1,13 @@ |
||||
[wrap-file] |
||||
directory = glfw-3.4 |
||||
source_url = https://github.com/glfw/glfw/archive/refs/tags/3.4.tar.gz |
||||
source_filename = glfw-3.4.tar.gz |
||||
source_hash = c038d34200234d071fae9345bc455e4a8f2f544ab60150765d7704e08f3dac01 |
||||
patch_filename = glfw_3.4-1_patch.zip |
||||
patch_url = https://wrapdb.mesonbuild.com/v2/glfw_3.4-1/get_patch |
||||
patch_hash = 58a6a6cdb28195d7f7e6f5de85dff7044d378e49b46bf1d4a9b04c97ed93e6b0 |
||||
source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/glfw_3.4-1/glfw-3.4.tar.gz |
||||
wrapdb_version = 3.4-1 |
||||
|
||||
[provide] |
||||
glfw3 = glfw_dep |
||||
@ -0,0 +1,13 @@ |
||||
[wrap-file] |
||||
directory = glm-1.0.1 |
||||
source_url = https://github.com/g-truc/glm/archive/refs/tags/1.0.1.tar.gz |
||||
source_filename = glm-1.0.1.tar.gz |
||||
source_hash = 9f3174561fd26904b23f0db5e560971cbf9b3cbda0b280f04d5c379d03bf234c |
||||
patch_filename = glm_1.0.1-1_patch.zip |
||||
patch_url = https://wrapdb.mesonbuild.com/v2/glm_1.0.1-1/get_patch |
||||
patch_hash = 25679275e26bc4c36bb617d1b4a52197039402af828d2a4bf67b3c0260a5df6a |
||||
source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/glm_1.0.1-1/glm-1.0.1.tar.gz |
||||
wrapdb_version = 1.0.1-1 |
||||
|
||||
[provide] |
||||
glm = glm_dep |
||||
Loading…
Reference in new issue