font code works but things need to happen
BIN
src/data/fonts/scape.bmp
Normal file
After Width: | Height: | Size: 768 KiB |
BIN
src/data/fonts/scape.dat
Normal file
Before Width: | Height: | Size: 39 KiB |
Before Width: | Height: | Size: 39 KiB |
Before Width: | Height: | Size: 39 KiB |
|
@ -15,7 +15,7 @@ void main() {
|
|||
float diff = max(0.0, dot(norm, light_dir));
|
||||
vec3 diffuse = diff * light_color;
|
||||
|
||||
vec3 color = (ambient + diffuse) * f_color;
|
||||
vec3 color = (ambient + diffuse) * vec3(f_color);
|
||||
gl_FragColor = vec4(color, 1.0);
|
||||
//gl_FragColor = vec4(f_normal, 1.0);
|
||||
}
|
BIN
src/data/terrains/map-colors.bmp
Normal file
After Width: | Height: | Size: 29 KiB |
BIN
src/data/terrains/map-heights.bmp
Normal file
After Width: | Height: | Size: 29 KiB |
BIN
src/data/terrains/map-reserve.bmp
Normal file
After Width: | Height: | Size: 29 KiB |
|
@ -1,15 +1,11 @@
|
|||
#include "etc.h"
|
||||
|
||||
int color_eq(color_t a, color_t b) {
|
||||
return color_eqp(&a, &b);
|
||||
int color_eq(const color_t a, const color_t b) {
|
||||
return color_eqp(a, b);
|
||||
}
|
||||
|
||||
int color_eqp(const color_t* a, const color_t* b) {
|
||||
return
|
||||
(a->r == b->r) &&
|
||||
(a->g == b->g) &&
|
||||
(a->b == b->b) &&
|
||||
(a->a == b->a);
|
||||
int color_eqp(const color_t a, const color_t b) {
|
||||
return memcmp(a, b, 4) == 0;
|
||||
}
|
||||
|
||||
void mfree(int n, ...) {
|
||||
|
|
|
@ -9,12 +9,15 @@
|
|||
#define __MIN(A, B) ((A) < (B) ? (A) : (B))
|
||||
#define __MAX(A, B) ((A) > (B) ? (A) : (B))
|
||||
|
||||
typedef struct {
|
||||
uint8_t r, g, b, a;
|
||||
} color_t;
|
||||
#define _R_ 0
|
||||
#define _G_ 1
|
||||
#define _B_ 2
|
||||
#define _A_ 3
|
||||
|
||||
int color_eq(color_t, color_t);
|
||||
int color_eqp(const color_t*, const color_t*);
|
||||
typedef uint8_t color_t[4];
|
||||
|
||||
int color_eq(const color_t, const color_t);
|
||||
int color_eqp(const color_t, const color_t);
|
||||
|
||||
void mfree(int n, ...);
|
||||
uint8_t* ltoh(uint8_t*, int);
|
||||
|
|
|
@ -158,21 +158,21 @@ int bmp_reload_chunk(bmp_t* bmp, int x, int y, int width, int height) {
|
|||
|
||||
uint8_t buffer[4];
|
||||
for(int ay = 0; ay < height; ++ay) {
|
||||
fseek(fp,
|
||||
data->header_size
|
||||
+ (data->width * (data->height - (y + ay) - 1) * data->bytepp)
|
||||
+ x * data->bytepp,
|
||||
SEEK_SET
|
||||
fseek(
|
||||
fp,
|
||||
data->header_size
|
||||
+ (data->width * (data->height - (y + ay) - 1) * data->bytepp)
|
||||
+ x * data->bytepp,
|
||||
SEEK_SET
|
||||
);
|
||||
|
||||
for(int ax = 0; ax < width; ++ax) {
|
||||
fread(buffer, 1, data->bytepp, fp);
|
||||
|
||||
color_t* px = &bmp->pixels[ay][ax];
|
||||
px->b = buffer[0];
|
||||
px->g = buffer[1];
|
||||
px->r = buffer[2];
|
||||
px->a = 0xFF;
|
||||
bmp->pixels[ay][ax][_B_] = buffer[0];
|
||||
bmp->pixels[ay][ax][_G_] = buffer[1];
|
||||
bmp->pixels[ay][ax][_R_] = buffer[2];
|
||||
bmp->pixels[ay][ax][_A_] = 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -180,6 +180,42 @@ int bmp_reload_chunk(bmp_t* bmp, int x, int y, int width, int height) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
int _bmp_comp_cnt(int col) {
|
||||
int cnt = 0;
|
||||
for(int i = 0; i < KOA_COMPONENTS; ++i)
|
||||
cnt += (col >> i) & 0x1;
|
||||
|
||||
return cnt;
|
||||
}
|
||||
|
||||
uint8_t* bmp_gl_data(bmp_t* bmp, int col) {
|
||||
float* out = malloc(bmp_gl_data_size(bmp, col));
|
||||
bmp_gl_data_out(bmp, out, col);
|
||||
return out;
|
||||
}
|
||||
|
||||
void bmp_gl_data_out(bmp_t* bmp, uint8_t* out, int col) {
|
||||
const int comps = _bmp_comp_cnt(col);
|
||||
for(uint32_t y = 0; y < bmp->height; ++y) {
|
||||
for(uint32_t x = 0; x < bmp->width; ++x) {
|
||||
int at = 0;
|
||||
for(int i = 0; i < KOA_COMPONENTS; ++i) {
|
||||
if(!((col >> i) & 0x1))
|
||||
continue;
|
||||
|
||||
out[y * bmp->width * comps + x * comps + at] =
|
||||
bmp->pixels[y][x][i];
|
||||
++at;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t bmp_gl_data_size(bmp_t* bmp, int col) {
|
||||
return sizeof(uint8_t) * _bmp_comp_cnt(col)
|
||||
* bmp->width * bmp->height;
|
||||
}
|
||||
|
||||
void bmp_discard_pixels(bmp_t* bmp) {
|
||||
if(bmp->pixels == NULL)
|
||||
return;
|
||||
|
|
|
@ -20,6 +20,14 @@ char* file_read(const char*);
|
|||
|
||||
// BEGIN BMP LOADING FUNCTIONS
|
||||
|
||||
#define KOA_COMPONENTS 4
|
||||
#define KOA_R 1
|
||||
#define KOA_G 2
|
||||
#define KOA_B 4
|
||||
#define KOA_A 8
|
||||
#define KOA_RGB 7
|
||||
#define KOA_RGBA F
|
||||
|
||||
typedef struct {
|
||||
char file[4096];
|
||||
uint32_t width, height, size,
|
||||
|
@ -35,9 +43,15 @@ typedef struct {
|
|||
} bmp_t;
|
||||
|
||||
bmp_t* bmp_load(const char*);
|
||||
|
||||
bmp_t* bmp_load_chunk(const char*, int, int, int, int);
|
||||
int bmp_reload_chunk(bmp_t*, int, int, int, int);
|
||||
int bmp_load_metadata(const char*, bmp_meta_t*);
|
||||
|
||||
uint8_t* bmp_gl_data(bmp_t*, int);
|
||||
void bmp_gl_data_out(bmp_t*, uint8_t*, int);
|
||||
uint32_t bmp_gl_data_size(bmp_t*, int);
|
||||
|
||||
void bmp_discard_pixels(bmp_t*);
|
||||
void bmp_unload(bmp_t*);
|
||||
|
||||
|
|
79
src/main.c
|
@ -11,6 +11,7 @@
|
|||
#include "okuu/mesh.h"
|
||||
#include "okuu/shader.h"
|
||||
#include "okuu/terrain.h"
|
||||
#include "okuu/font.h"
|
||||
|
||||
#define WINDOW_WIDTH 640
|
||||
#define WINDOW_HEIGHT 480
|
||||
|
@ -20,7 +21,11 @@ struct {
|
|||
SDL_GLContext ctx;
|
||||
const uint8_t* keys;
|
||||
int mode, running;
|
||||
int mouse[3];
|
||||
|
||||
vec2 tlocs[10];
|
||||
font_t* scape;
|
||||
text_t* text;
|
||||
mesh_t* monkey;
|
||||
terrain_t* map;
|
||||
} _g;
|
||||
|
@ -39,15 +44,37 @@ int init();
|
|||
void deinit();
|
||||
void run();
|
||||
|
||||
void reset_text_locs() {
|
||||
for(int i = 0; i < 10; ++i) {
|
||||
_g.tlocs[i][0] = rand() % (WINDOW_WIDTH / 2);
|
||||
_g.tlocs[i][1] = rand() % WINDOW_HEIGHT;
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
if(init() < 0)
|
||||
return -1;
|
||||
|
||||
_g.monkey = mesh_load("data/player.rbm");
|
||||
font_init_subsystem(_g.window);
|
||||
|
||||
_g.scape = font_load(
|
||||
"data/fonts/scape.bmp",
|
||||
"data/fonts/scape.dat",
|
||||
GL_NEAREST
|
||||
);
|
||||
font_set_default(_g.scape);
|
||||
|
||||
_g.text = text_create(NULL);
|
||||
text_set(_g.text, "flashwave is cool !!!");
|
||||
text_set_size(_g.text, 32);
|
||||
text_set_rgb_hex(_g.text, 0x55007e);
|
||||
reset_text_locs();
|
||||
|
||||
_g.monkey = mesh_load("data/models/player.rbm");
|
||||
|
||||
_g.map = terrain_load(
|
||||
"data/map-heights.bmp",
|
||||
"data/map-colors.bmp",
|
||||
"data/terrains/map-heights.bmp",
|
||||
"data/terrains/map-colors.bmp",
|
||||
10, 10
|
||||
);
|
||||
|
||||
|
@ -55,9 +82,9 @@ int main(int argc, char* argv[]) {
|
|||
shader_layout(_s_def.shader, 4,
|
||||
"vertex", "texuv", "normal", "color"
|
||||
);
|
||||
shader_source(_s_def.shader, 2,
|
||||
"shaders/test.vert", GL_VERTEX_SHADER,
|
||||
"shaders/test.frag", GL_FRAGMENT_SHADER
|
||||
shader_source(_s_def.shader, SHADER_FILE, 2,
|
||||
"data/shaders/test.vert", GL_VERTEX_SHADER,
|
||||
"data/shaders/test.frag", GL_FRAGMENT_SHADER
|
||||
);
|
||||
shader_attribs(_s_def.shader, 3,
|
||||
"model", "view", "projection"
|
||||
|
@ -81,6 +108,7 @@ void run() {
|
|||
if(init) {
|
||||
//glm_rotate_make(model, glm_rad(90), (vec3){ 0.f, -1.f, 0.f });
|
||||
glm_mat4_identity(model);
|
||||
|
||||
glm_mat4_identity(map);
|
||||
|
||||
glm_mat4_identity(view);
|
||||
|
@ -117,12 +145,14 @@ void run() {
|
|||
view
|
||||
);
|
||||
|
||||
for(int i = 0; i < 10; ++i) {
|
||||
text_move(_g.text, _g.tlocs[i]);
|
||||
text_render(_g.text);
|
||||
}
|
||||
|
||||
shader_start(_s_def.shader); {
|
||||
glUniformMatrix4fv(_ATTR(DEF_VIEW), 1, GL_FALSE, (float*)view);
|
||||
|
||||
/*mesh_bind(_g.monkey);
|
||||
mesh_render(_g.monkey);
|
||||
mesh_unbind();*/
|
||||
glm_translate_make(model, (vec3){-x, -(_g.map->heights[(int)y][(int)x] + 2.f), -y});
|
||||
glm_mat4_mul(model, map, model);
|
||||
glUniformMatrix4fv(_ATTR(DEF_MODEL), 1, GL_FALSE, (float*)model);
|
||||
|
@ -173,10 +203,41 @@ void run() {
|
|||
glm_translate_make(map, (vec3){__MAX(0, x - CHUNK_SIZE / 2), 0, __MAX(0, y - CHUNK_SIZE / 2)});
|
||||
}
|
||||
|
||||
if(_g.keys[SDL_SCANCODE_P])
|
||||
reset_text_locs();
|
||||
|
||||
_g.mouse[2] = SDL_GetMouseState(&_g.mouse[0], &_g.mouse[1]);
|
||||
if(_g.mouse[2] & SDL_BUTTON(SDL_BUTTON_LEFT)) {
|
||||
|
||||
}
|
||||
|
||||
SDL_Event ev;
|
||||
while(SDL_PollEvent(&ev)) {
|
||||
if(ev.type == SDL_QUIT)
|
||||
_g.running = 0;
|
||||
else if(ev.type == SDL_WINDOWEVENT &&
|
||||
ev.window.event == SDL_WINDOWEVENT_SIZE_CHANGED)
|
||||
{
|
||||
glViewport(0, 0, ev.window.data1, ev.window.data2);
|
||||
font_window_changed(_g.window);
|
||||
}
|
||||
/*else if(ev.type == SDL_MOUSEBUTTONDOWN) {
|
||||
float mx = (float)ev.button.x / (float)WINDOW_WIDTH;
|
||||
float my = (float)ev.button.y / (float)WINDOW_HEIGHT;
|
||||
vec4 mouse = {mx * 2 - 1, (1 - my) * 2 - 1, -1.f, 1.f};
|
||||
mat4 imat;
|
||||
|
||||
glm_mat4_inv(projection, imat);
|
||||
glm_mat4_mulv(imat, mouse, mouse);
|
||||
mouse[2] = -1.f;
|
||||
mouse[3] = 0.f;
|
||||
|
||||
glm_mat4_inv(view, imat);
|
||||
glm_mat4_mulv(imat, mouse, mouse);
|
||||
|
||||
|
||||
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
|
|
419
src/okuu/font.c
Normal file
|
@ -0,0 +1,419 @@
|
|||
#include "font.h"
|
||||
|
||||
// SUBSYSTEM //
|
||||
|
||||
const char* _vertex_shader =
|
||||
"#version 100 \r\n"
|
||||
|
||||
"attribute vec2 coords;"
|
||||
"attribute vec2 texuv;"
|
||||
|
||||
"varying vec2 f_texuv;"
|
||||
|
||||
"uniform mat4 trans;"
|
||||
"uniform mat4 ortho;"
|
||||
|
||||
"void main() {"
|
||||
"gl_Position = ortho * trans * vec4(coords, 0.0, 1.0);"
|
||||
"f_texuv = texuv;"
|
||||
"}\r\n";
|
||||
const char* _fragment_shader =
|
||||
"#version 100 \n"
|
||||
"precision mediump float;\n"
|
||||
|
||||
"varying vec2 f_texuv;\n"
|
||||
|
||||
"uniform vec4 color;\n"
|
||||
"uniform sampler2D font;\n"
|
||||
|
||||
"void main() {\n"
|
||||
"vec4 fcol = texture2D(font, f_texuv);\n"
|
||||
"if(fcol.rgb == vec3(0.0)) discard;\n"
|
||||
"gl_FragColor = color * fcol;\n"
|
||||
"}\n";
|
||||
|
||||
struct {
|
||||
shader_t* shader;
|
||||
font_t* default_font;
|
||||
|
||||
enum {
|
||||
FONT_TRANS,
|
||||
FONT_ORTHO,
|
||||
FONT_COLOR,
|
||||
FONT_FONT
|
||||
};
|
||||
} _ss;
|
||||
|
||||
void _font_window_change(SDL_Window* window) {
|
||||
shader_start(_ss.shader);
|
||||
|
||||
mat4 ortho;
|
||||
int width, height;
|
||||
SDL_GetWindowSize(window, &width, &height);
|
||||
|
||||
glm_ortho(0.f, (float)width, (float)height, 0.f, -1.f, 1.f, ortho);
|
||||
glUniformMatrix4fv(
|
||||
_ATTR(FONT_ORTHO), 1, GL_FALSE, (float*)ortho
|
||||
);
|
||||
}
|
||||
|
||||
void font_init_subsystem(SDL_Window* window) {
|
||||
_ss.shader = shader_create("font");
|
||||
shader_layout(_ss.shader, 2,
|
||||
"coords", "texuv"
|
||||
);
|
||||
shader_source(_ss.shader, SHADER_SRC, 2,
|
||||
_vertex_shader, GL_VERTEX_SHADER,
|
||||
_fragment_shader, GL_FRAGMENT_SHADER
|
||||
);
|
||||
shader_attribs(_ss.shader, 4,
|
||||
"trans", "ortho", "color", "font"
|
||||
);
|
||||
|
||||
_font_window_change(window);
|
||||
}
|
||||
|
||||
void font_window_changed(SDL_Window* window) {
|
||||
_font_window_change(window);
|
||||
}
|
||||
|
||||
void font_set_default(font_t* font) {
|
||||
_ss.default_font = font;
|
||||
}
|
||||
|
||||
void font_deinit_subsystem() {
|
||||
shader_destroy(_ss.shader);
|
||||
}
|
||||
|
||||
// FONT FUNCTIONS //
|
||||
|
||||
font_t* font_load(const char* bmp_path, const char* data_path, int filter) {
|
||||
const int buffer_size = 0x111;
|
||||
int buffer_read = 0;
|
||||
uint8_t buffer[buffer_size];
|
||||
|
||||
FILE* fp = fopen(data_path, "rb");
|
||||
if(fp == NULL)
|
||||
return NULL;
|
||||
buffer_read = fread(buffer, 1, buffer_size, fp);
|
||||
fclose(fp);
|
||||
if(buffer_read != buffer_size)
|
||||
return NULL;
|
||||
if(buffer[0x10] != 0)
|
||||
return NULL;
|
||||
|
||||
bmp_t* bmp = bmp_load(bmp_path);
|
||||
if(bmp == NULL)
|
||||
return NULL;
|
||||
|
||||
font_t* font = malloc(sizeof(font_t));
|
||||
|
||||
font->width = bmp->width;
|
||||
font->height = bmp->height;
|
||||
font->cell_width = *(uint32_t*)ltoh(buffer + 0x08, 4);
|
||||
font->cell_height = *(uint32_t*)ltoh(buffer + 0x0C, 4);
|
||||
|
||||
for(int i = 0; i < 256; ++i) {
|
||||
glyph_t* glyph = font->glyphs + i;
|
||||
uint32_t width = buffer[0x11 + i];
|
||||
|
||||
glyph->width = (float)width / (float)font->cell_width;
|
||||
int x = (font->cell_width * i) % font->width;
|
||||
int y = ((font->cell_width * i) / font->width) * font->cell_height;
|
||||
|
||||
glyph->top_left[0] = (float)x / (float)font->width;
|
||||
glyph->top_left[1] = (float)y / (float)font->height;
|
||||
|
||||
glyph->bottom_right[0] = (float)(x + width) / (float)font->width;
|
||||
glyph->bottom_right[1] =
|
||||
(float)(y + font->cell_height) / (float)font->height;
|
||||
}
|
||||
|
||||
uint8_t* pixels = bmp_gl_data(bmp, KOA_RGB);
|
||||
|
||||
glGenTextures(1, &font->texture);
|
||||
glBindTexture(GL_TEXTURE_2D, font->texture);
|
||||
glTexImage2D(
|
||||
GL_TEXTURE_2D, 0, GL_RGB,
|
||||
font->width, font->height, 0,
|
||||
GL_RGB, GL_UNSIGNED_BYTE,
|
||||
pixels
|
||||
);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter);
|
||||
|
||||
bmp_unload(bmp);
|
||||
free(pixels);
|
||||
|
||||
return font;
|
||||
}
|
||||
|
||||
void font_bind(font_t* font) {
|
||||
glBindTexture(GL_TEXTURE_2D, font->texture);
|
||||
}
|
||||
|
||||
void font_unbind() {
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
}
|
||||
|
||||
void font_unload(font_t* font) {
|
||||
glDeleteTextures(1, font->texture);
|
||||
free(font);
|
||||
}
|
||||
|
||||
// TEXT FUNCTIONS //
|
||||
|
||||
text_t* text_create(font_t* font) {
|
||||
text_t* text = malloc(sizeof(text_t));
|
||||
|
||||
if(font == NULL)
|
||||
text->font = _ss.default_font;
|
||||
text->text = NULL;
|
||||
glm_vec4_copy((vec4){0.f, 0.f, 0.f, 1.f}, text->color);
|
||||
|
||||
text->length =
|
||||
text->size =
|
||||
text->wrap =
|
||||
text->tri_cnt = 0;
|
||||
|
||||
text->vert_inv =
|
||||
text->texuv_inv = 1;
|
||||
|
||||
glm_mat4_identity(text->trans_mat);
|
||||
glGenVertexArrays(1, &text->vao);
|
||||
glGenBuffers(2, text->buffers);
|
||||
|
||||
glBindVertexArray(text->vao); {
|
||||
glEnableVertexAttribArray(0);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, text->buffers[0]);
|
||||
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, (void*)0);
|
||||
|
||||
glEnableVertexAttribArray(1);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, text->buffers[1]);
|
||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, (void*)0);
|
||||
} glBindVertexArray(0);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
void text_set(text_t* text, const char* value) {
|
||||
uint32_t value_len = strlen(value);
|
||||
if(text->text == NULL || strcmp(value, text->text) != 0) {
|
||||
text->texuv_inv = 1;
|
||||
text->vert_inv = 1;
|
||||
}
|
||||
|
||||
free(text->text);
|
||||
text->length = value_len;
|
||||
text->text = strdup(value);
|
||||
}
|
||||
|
||||
void text_set_font(text_t* text, font_t* font) {
|
||||
text->font = font;
|
||||
|
||||
text->texuv_inv = 1;
|
||||
text->vert_inv = 1;
|
||||
}
|
||||
|
||||
void text_set_size(text_t* text, uint32_t size) {
|
||||
text->size = size;
|
||||
text->vert_inv = 1;
|
||||
}
|
||||
|
||||
void text_set_rgb
|
||||
(text_t* text, uint8_t r, uint8_t g, uint8_t b)
|
||||
{
|
||||
text_set_rgba(text, r, g, b, 0xFF);
|
||||
}
|
||||
|
||||
void text_set_rgba
|
||||
(text_t* text, uint8_t r, uint8_t g, uint8_t b, uint8_t a)
|
||||
{
|
||||
glm_vec4_copy(
|
||||
(vec4){
|
||||
(float)r / 255.f,
|
||||
(float)g / 255.f,
|
||||
(float)b / 255.f,
|
||||
(float)a / 255.f
|
||||
},
|
||||
text->color
|
||||
);
|
||||
}
|
||||
|
||||
void text_set_rgb_gl(text_t* text, vec3 color) {
|
||||
vec4 color4;
|
||||
glm_vec4(color, 1.f, color4);
|
||||
text_set_rgba_gl(text, color4);
|
||||
}
|
||||
|
||||
void text_set_rgba_gl(text_t* text, vec4 color) {
|
||||
glm_vec4_copy(color, text->color);
|
||||
}
|
||||
|
||||
void text_set_rgb_hex(text_t* text, uint32_t color) {
|
||||
color &= 0x00FFFFFF;
|
||||
color <<= 8;
|
||||
color |= 0xFF;
|
||||
|
||||
text_set_rgba_hex(text, color);
|
||||
}
|
||||
|
||||
void text_set_rgba_hex(text_t* text, uint32_t color) {
|
||||
text_set_rgba(text,
|
||||
(color >> 24) & 0xFF,
|
||||
(color >> 16) & 0xFF,
|
||||
(color >> 8) & 0xFF,
|
||||
color & 0xFF
|
||||
);
|
||||
}
|
||||
|
||||
void text_move(text_t* text, vec2 coords) {
|
||||
vec3 coords3 = { coords[0], coords[1], 0.f };
|
||||
glm_translate_make(text->trans_mat, coords3);
|
||||
}
|
||||
|
||||
void text_move_xy(text_t* text, float x, float y) {
|
||||
vec2 coords = { x, y };
|
||||
text_move(text, coords);
|
||||
}
|
||||
|
||||
void text_wrap(text_t* text, uint32_t wrap) {
|
||||
text->wrap = wrap;
|
||||
text->vert_inv = 1;
|
||||
}
|
||||
|
||||
void text_redraw(text_t* text) {
|
||||
if(!text->vert_inv && !text->texuv_inv)
|
||||
return;
|
||||
|
||||
text->tri_cnt = 2 * text->length;
|
||||
|
||||
float* verts = NULL;
|
||||
float* texuvs = NULL;
|
||||
|
||||
if(text->vert_inv)
|
||||
verts = malloc(sizeof(float) * 6 * text->tri_cnt);
|
||||
if(text->texuv_inv)
|
||||
texuvs = malloc(sizeof(float) * 6 * text->tri_cnt);
|
||||
|
||||
uint32_t top_x = 0, top_y = 0;
|
||||
for(uint32_t i = 0; i < text->length; ++i) {
|
||||
glyph_t* glyph = text->font->glyphs + text->text[i];
|
||||
uint32_t width = (uint32_t)(text->size * glyph->width),
|
||||
height = text->size;
|
||||
|
||||
if(top_x + width > text->wrap && text->wrap != 0) {
|
||||
top_x = 0;
|
||||
top_y += height;
|
||||
}
|
||||
|
||||
// !! TRIANGLES WOUND CCW FOR CULLING !! //
|
||||
|
||||
if(verts != NULL) {
|
||||
// TRIANGLE 1 //
|
||||
// TOP LEFT
|
||||
verts[i * 12] = top_x;
|
||||
verts[i * 12 + 1] = top_y;
|
||||
// BOTTOM LEFT
|
||||
verts[i * 12 + 2] = top_x;
|
||||
verts[i * 12 + 3] = top_y + height;
|
||||
// TOP RIGHT
|
||||
verts[i * 12 + 4] = top_x + width;
|
||||
verts[i * 12 + 5] = top_y;
|
||||
|
||||
// TRIANGLE 2 //
|
||||
// BOTTOM RIGHT
|
||||
verts[i * 12 + 6] = top_x + width;
|
||||
verts[i * 12 + 7] = top_y + height;
|
||||
// TOP RIGHT
|
||||
verts[i * 12 + 8] = top_x + width;
|
||||
verts[i * 12 + 9] = top_y;
|
||||
// BOTTOM LEFT
|
||||
verts[i * 12 + 10] = top_x;
|
||||
verts[i * 12 + 11] = top_y + height;
|
||||
}
|
||||
|
||||
if(texuvs != NULL) {
|
||||
// TRIANGLE 1 //
|
||||
// TOP LEFT
|
||||
texuvs[i * 12] = glyph->top_left[0];
|
||||
texuvs[i * 12 + 1] = glyph->top_left[1];
|
||||
// BOTTOM LEFT
|
||||
texuvs[i * 12 + 2] = glyph->top_left[0];
|
||||
texuvs[i * 12 + 3] = glyph->bottom_right[1];
|
||||
// TOP RIGHT
|
||||
texuvs[i * 12 + 4] = glyph->bottom_right[0];
|
||||
texuvs[i * 12 + 5] = glyph->top_left[1];
|
||||
|
||||
// TRIANGLE 2 //
|
||||
// BOTTOM RIGHT
|
||||
texuvs[i * 12 + 6] = glyph->bottom_right[0];
|
||||
texuvs[i * 12 + 7] = glyph->bottom_right[1];
|
||||
// TOP RIGHT
|
||||
texuvs[i * 12 + 8] = glyph->bottom_right[0];
|
||||
texuvs[i * 12 + 9] = glyph->top_left[1];
|
||||
// BOTTOM LEFT
|
||||
texuvs[i * 12 + 10] = glyph->top_left[0];
|
||||
texuvs[i * 12 + 11] = glyph->bottom_right[1];
|
||||
}
|
||||
|
||||
top_x += width;
|
||||
}
|
||||
|
||||
if(verts != NULL) {
|
||||
glBindBuffer(GL_ARRAY_BUFFER, text->buffers[0]);
|
||||
glBufferData(
|
||||
GL_ARRAY_BUFFER,
|
||||
text->tri_cnt * 6 * sizeof(float),
|
||||
verts,
|
||||
GL_DYNAMIC_DRAW
|
||||
);
|
||||
}
|
||||
|
||||
if(texuvs != NULL) {
|
||||
glBindBuffer(GL_ARRAY_BUFFER, text->buffers[1]);
|
||||
glBufferData(
|
||||
GL_ARRAY_BUFFER,
|
||||
text->tri_cnt * 6 * sizeof(float),
|
||||
texuvs,
|
||||
GL_DYNAMIC_DRAW
|
||||
);
|
||||
}
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
|
||||
free(verts);
|
||||
free(texuvs);
|
||||
|
||||
text->vert_inv = 0;
|
||||
text->texuv_inv = 0;
|
||||
}
|
||||
|
||||
void text_render(text_t* text) {
|
||||
text_redraw(text);
|
||||
shader_start(_ss.shader);
|
||||
|
||||
glUniformMatrix4fv(
|
||||
_ATTR(FONT_TRANS),
|
||||
1, GL_FALSE,
|
||||
(float*)text->trans_mat
|
||||
);
|
||||
glUniform4fv(
|
||||
_ATTR(FONT_COLOR), 1,
|
||||
(float*)text->color
|
||||
);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
|
||||
font_bind(text->font);
|
||||
glBindVertexArray(text->vao);
|
||||
glDrawArrays(GL_TRIANGLES, 0, text->tri_cnt * 3);
|
||||
}
|
||||
|
||||
void text_destroy(text_t* text) {
|
||||
glDeleteBuffers(2, text->buffers);
|
||||
glDeleteVertexArrays(1, &text->vao);
|
||||
|
||||
free(text->text);
|
||||
free(text);
|
||||
}
|
78
src/okuu/font.h
Normal file
|
@ -0,0 +1,78 @@
|
|||
#ifndef OKUU_FONT_H
|
||||
#define OKUU_FONT_H
|
||||
|
||||
#include <SDL.h>
|
||||
#include <GL/glew.h>
|
||||
#include <SDL_opengl.h>
|
||||
#include <cglm/cglm.h>
|
||||
#include <GL/glu.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "shader.h"
|
||||
#include "koa/etc.h"
|
||||
|
||||
typedef struct {
|
||||
float width;
|
||||
vec2 top_left,
|
||||
bottom_right;
|
||||
} glyph_t;
|
||||
|
||||
typedef struct {
|
||||
GLuint texture;
|
||||
uint32_t width, height,
|
||||
cell_width, cell_height;
|
||||
glyph_t glyphs[256];
|
||||
} font_t;
|
||||
|
||||
typedef struct {
|
||||
font_t* font;
|
||||
char* text;
|
||||
vec4 color;
|
||||
uint32_t
|
||||
length, size,
|
||||
wrap, tri_cnt;
|
||||
|
||||
mat4 trans_mat;
|
||||
GLuint vao, buffers[2];
|
||||
uint8_t vert_inv, texuv_inv;
|
||||
} text_t;
|
||||
|
||||
void font_init_subsystem(SDL_Window*);
|
||||
void font_window_changed(SDL_Window*);
|
||||
void font_set_default(font_t*);
|
||||
void font_deinit_subsystem();
|
||||
|
||||
font_t* font_load(const char*, const char*, int);
|
||||
void font_bind(font_t*);
|
||||
void font_unbind();
|
||||
void font_unload(font_t*);
|
||||
|
||||
text_t* text_create(font_t*);
|
||||
void text_set(text_t*, const char*);
|
||||
void text_set_font(text_t*, font_t*);
|
||||
void text_set_size(text_t*, uint32_t);
|
||||
|
||||
void text_set_rgb(text_t*, uint8_t, uint8_t, uint8_t);
|
||||
void text_set_rgba(text_t*, uint8_t, uint8_t, uint8_t, uint8_t);
|
||||
void text_set_rgb_gl(text_t*, vec3);
|
||||
void text_set_rgba_gl(text_t*, vec4);
|
||||
void text_set_rgb_hex(text_t*, uint32_t);
|
||||
void text_set_rgba_hex(text_t*, uint32_t);
|
||||
|
||||
void text_move(text_t*, vec2);
|
||||
void text_move_xy(text_t*, float, float);
|
||||
void text_wrap(text_t*, uint32_t);
|
||||
|
||||
void text_redraw(text_t*);
|
||||
void text_render(text_t*);
|
||||
|
||||
/*void text_get_bounds(text_t*, vec2);
|
||||
uint32_t text_line_count(text_t*);*/
|
||||
|
||||
void text_destroy(text_t*);
|
||||
|
||||
#endif
|
|
@ -31,7 +31,7 @@ int shader_layout(shader_t* shader, int count, ...) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int shader_source(shader_t* shader, int files, ...) {
|
||||
int shader_source(shader_t* shader, int is_src, int files, ...) {
|
||||
if(shader->loaded)
|
||||
return -1;
|
||||
|
||||
|
@ -42,16 +42,23 @@ int shader_source(shader_t* shader, int files, ...) {
|
|||
va_list args;
|
||||
va_start(args, files);
|
||||
for(int i = 0; i < files; ++i) {
|
||||
const char* file_name = va_arg(args, const char*);
|
||||
char* source = file_read(file_name);
|
||||
if(source == NULL) {
|
||||
failed = 1;
|
||||
break;
|
||||
}
|
||||
char* file_name = "INLINE";
|
||||
char* source = NULL;
|
||||
|
||||
if(!is_src) {
|
||||
file_name = va_arg(args, char*);
|
||||
source = file_read(file_name);
|
||||
if(source == NULL) {
|
||||
failed = 1;
|
||||
break;
|
||||
}
|
||||
} else
|
||||
source = va_arg(args, char*);
|
||||
|
||||
shaders[i] = glCreateShader(va_arg(args, GLuint));
|
||||
if(shaders[i] == 0) {
|
||||
free(source);
|
||||
if(!is_src)
|
||||
free(source);
|
||||
failed = 1;
|
||||
break;
|
||||
}
|
||||
|
@ -68,13 +75,15 @@ int shader_source(shader_t* shader, int files, ...) {
|
|||
fprintf(__STDERR, "[ERROR] (%s (COMPILER)) %s\n", file_name, msg);
|
||||
free(msg);
|
||||
|
||||
free(source);
|
||||
if(!is_src)
|
||||
free(source);
|
||||
failed = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
glAttachShader(shader->program, shaders[i]);
|
||||
free(source);
|
||||
if(!is_src)
|
||||
free(source);
|
||||
}
|
||||
va_end(args);
|
||||
|
||||
|
@ -149,8 +158,10 @@ shader_t* shader_active() {
|
|||
}
|
||||
|
||||
void shader_start(shader_t* shader) {
|
||||
glUseProgram(shader->program);
|
||||
_active = shader;
|
||||
if(_active == NULL || _active->program != shader->program) {
|
||||
glUseProgram(shader->program);
|
||||
_active = shader;
|
||||
}
|
||||
}
|
||||
|
||||
void shader_stop() {
|
||||
|
|
|
@ -12,6 +12,9 @@
|
|||
#define _SHADER shader_active()
|
||||
#define _ATTR(I) shader_attr(_SHADER, I)
|
||||
|
||||
#define SHADER_FILE 0
|
||||
#define SHADER_SRC 1
|
||||
|
||||
typedef char layout_name_t[256];
|
||||
|
||||
typedef struct {
|
||||
|
@ -27,7 +30,7 @@ typedef struct {
|
|||
shader_t* shader_create(const char*);
|
||||
|
||||
int shader_layout(shader_t*, int, ...);
|
||||
int shader_source(shader_t*, int, ...);
|
||||
int shader_source(shader_t*, int, int, ...);
|
||||
int shader_attribs(shader_t*, int, ...);
|
||||
GLint shader_attr(const shader_t*, int);
|
||||
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
#include "terrain.h"
|
||||
|
||||
#define _HGT_AT(A, X, Y) (A->bmps[0]->pixels[Y][X].r / 10.f)
|
||||
#define _HGT_AT(A, X, Y) (A->bmps[0]->pixels[Y][X][_R_] / 10.f)
|
||||
#define _RWCOL_AT(A, X, Y) (A->bmps[1]->pixels[Y][X])
|
||||
#define _RCOL_AT(A, X, Y, C) (_RWCOL_AT(A, X, Y).C)
|
||||
#define _RCOL_AT(A, X, Y, C) (_RWCOL_AT(A, X, Y)[C])
|
||||
#define _COL_AT(A, X, Y, C) (_RCOL_AT(A, X, Y, C) / 255.f)
|
||||
#define _COL_EQ(A, X1, Y1, X2, Y2) \
|
||||
(color_eqp(&A->bmps[1]->pixels[Y1][X1], &A->bmps[1]->pixels[Y2][X2]))
|
||||
(color_eqp(A->bmps[1]->pixels[Y1][X1], A->bmps[1]->pixels[Y2][X2]))
|
||||
|
||||
float _avg_hgt(terrain_t* map, int x, int y) {
|
||||
return
|
||||
|
@ -250,14 +250,12 @@ void terrain_move(terrain_t* terrain, int center_x, int center_y) {
|
|||
memcpy(data + at + 12, data + at + 3, 3 * sizeof(float));
|
||||
memcpy(data + at + 24, data + at + 3, 3 * sizeof(float));
|
||||
memcpy(data + at + 33, data + at + 3, 3 * sizeof(float));
|
||||
|
||||
//_norm_smooth(data, x, y);
|
||||
break;
|
||||
case 3:
|
||||
for(int j = 0; j < 12; ++j) {
|
||||
data[at + j * 3] = _COL_AT(terrain, x, y, r);
|
||||
data[at + j * 3 + 1] = _COL_AT(terrain, x, y, g);
|
||||
data[at + j * 3 + 2] = _COL_AT(terrain, x, y, b);
|
||||
data[at + j * 3] = _COL_AT(terrain, x, y, _R_);
|
||||
data[at + j * 3 + 1] = _COL_AT(terrain, x, y, _G_);
|
||||
data[at + j * 3 + 2] = _COL_AT(terrain, x, y, _B_);
|
||||
}
|
||||
|
||||
const color_t path_colors[] = {
|
||||
|
@ -267,7 +265,7 @@ void terrain_move(terrain_t* terrain, int center_x, int center_y) {
|
|||
|
||||
int found = 0;
|
||||
for(int j = 0; j < sizeof(path_colors) / sizeof(color_t); ++j) {
|
||||
if(color_eqp(&path_colors[j], &_RWCOL_AT(terrain, x, y))) {
|
||||
if(color_eqp(path_colors[j], _RWCOL_AT(terrain, x, y))) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
|
@ -301,17 +299,17 @@ void terrain_move(terrain_t* terrain, int center_x, int center_y) {
|
|||
{
|
||||
data[at + j * 9] = _COL_AT(terrain,
|
||||
x + coords[j][0],
|
||||
y + coords[j][1], r
|
||||
y + coords[j][1], _R_
|
||||
);
|
||||
|
||||
data[at + j * 9 + 1] = _COL_AT(terrain,
|
||||
x + coords[j][0],
|
||||
y + coords[j][1], g
|
||||
y + coords[j][1], _G_
|
||||
);
|
||||
|
||||
data[at + j * 9 + 2] = _COL_AT(terrain,
|
||||
x + coords[j][0],
|
||||
y + coords[j][1], b
|
||||
y + coords[j][1], _B_
|
||||
);
|
||||
|
||||
memcpy(data + at + j * 9 + 3, data + at + j * 9, 3 * sizeof(float));
|
||||
|
@ -319,31 +317,6 @@ void terrain_move(terrain_t* terrain, int center_x, int center_y) {
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
for(int j = 0; j < 4; ++j) {
|
||||
if(_COL_EQ(terrain,
|
||||
x + coords[j][0],
|
||||
y + coords[j][1],
|
||||
x + coords[j][2],
|
||||
y + coords[j][3]))
|
||||
{
|
||||
for(int k = 0; k < 6; ++k) {
|
||||
data[at + ((k * 3 + j * 9) % 36)] =
|
||||
_COL_AT(terrain,
|
||||
x + coords[j][0],
|
||||
y + coords[j][1], r);
|
||||
data[at + ((k * 3 + j * 9 + 1) % 36)] =
|
||||
_COL_AT(terrain,
|
||||
x + coords[j][0],
|
||||
y + coords[j][1], g);
|
||||
data[at + ((k * 3 + j * 9 + 2) % 36)] =
|
||||
_COL_AT(terrain,
|
||||
x + coords[j][0],
|
||||
y + coords[j][1], b);
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|