Large overhaul, added simple text
This commit is contained in:
parent
4d7084a6de
commit
f2db0dc5e8
Binary file not shown.
Binary file not shown.
Binary file not shown.
1
.gitignore
vendored
1
.gitignore
vendored
@ -2,6 +2,7 @@
|
||||
build/*
|
||||
assets/*
|
||||
bin/*
|
||||
.cache/*
|
||||
|
||||
# Prerequisites
|
||||
*.d
|
||||
|
4
Makefile
4
Makefile
@ -15,10 +15,10 @@ DEPEXT := d
|
||||
OBJEXT := o
|
||||
|
||||
#Flags, Libraries and Includes
|
||||
CFLAGS := -Wall -pedantic
|
||||
CFLAGS := -Wall -pedantic
|
||||
CFLAGS += -Ilib/cglm/include -Ilib/glad/include -Ilib/glfw/include -Ilib/stb
|
||||
CFLAGS += -Iinclude/ -I/usr/include/freetype2 -I/usr/include/stb
|
||||
LDFLAGS := -lglfw -ldl -lmpv -lfreetype -lm
|
||||
LDFLAGS := -lglfw -ldl -lmpv -lfreetype -lm
|
||||
INC := -I$(INCDIR) -I/usr/local/include
|
||||
INCDEP := -I$(INCDIR)
|
||||
|
||||
|
BIN
res/CC.ttf
Normal file
BIN
res/CC.ttf
Normal file
Binary file not shown.
@ -7,6 +7,6 @@ uniform mat4 transformation;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = transformation * vec4(vertex.xy, 0.0, 1.0);
|
||||
gl_Position = vec4(vertex.xy, 0.0, 1.0);
|
||||
TexCoords = vertex.zw;
|
||||
}
|
||||
|
@ -1,151 +0,0 @@
|
||||
#include "danmaku.h"
|
||||
|
||||
/// This is so fucking bad, just store everything and redraw with a translation in the shader holy shit
|
||||
float RenderText(Shader s, std::string text, float x, float y, float scale, glm::vec3 color, uint &VAO, uint &VBO, std::map<char, Character>& Characters, float window_width)
|
||||
{
|
||||
|
||||
// activate corresponding render state
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
s.use();
|
||||
|
||||
glUniform3f(glGetUniformLocation(s.ID, "textColor"), color.x, color.y, color.z);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindVertexArray(VAO);
|
||||
|
||||
Character ch;
|
||||
|
||||
float xpos;
|
||||
float ypos;
|
||||
float w;
|
||||
float h;
|
||||
|
||||
// iterate through all characters
|
||||
std::string::const_iterator c;
|
||||
for (c = text.begin(); c != text.end(); c++)
|
||||
{
|
||||
ch = Characters[*c];
|
||||
|
||||
xpos = x + ch.Bearing.x * scale;
|
||||
ypos = y - (ch.Size.y - ch.Bearing.y) * scale;
|
||||
|
||||
w = ch.Size.x * scale;
|
||||
h = ch.Size.y * scale;
|
||||
// update VBO for each character
|
||||
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 }
|
||||
};
|
||||
// render glyph texture over quad
|
||||
glBindTexture(GL_TEXTURE_2D, ch.TextureID);
|
||||
// update content of VBO memory
|
||||
glBindBuffer(GL_ARRAY_BUFFER, VBO);
|
||||
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
// render quad
|
||||
glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||
// now advance cursors for next glyph (note that advance is number of 1/64 pixels)
|
||||
x += (ch.Advance >> 6) * scale; // bitshift by 6 to get value in pixels (2^6 = 64)
|
||||
}
|
||||
glBindVertexArray(0);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
return xpos;
|
||||
}
|
||||
|
||||
|
||||
//TODO: Status <->
|
||||
|
||||
/*
|
||||
Sets nextRow to the index of the next free danmaku row and returns 1 if one is available, returns 0 otherwise.
|
||||
*/
|
||||
int getNextDanmakuRow(uint *ph_danmakuRows, int length, uint *nextRow) {
|
||||
for(int row = 0; row < length; row++) {
|
||||
if( (ph_danmakuRows)[row] ){
|
||||
*nextRow = row;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
Flips the status of the danmaku row.
|
||||
*/
|
||||
int updateDanmakuRow(uint *ph_danmakuRows, uint row) {
|
||||
ph_danmakuRows[row] = !ph_danmakuRows[row];
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
Updates danmaku array according to the delta between last frame and current frame.
|
||||
*/
|
||||
//int updateDanmakus(Render *r){
|
||||
//
|
||||
// // Amount of pixels to translate the danmakus by
|
||||
// float deltaPix = DANMAKU_SPEED*delta;
|
||||
// // Last glyph x-position (last pixel on the string)
|
||||
// float lastPix = 0.0f;
|
||||
//
|
||||
// // Keep track of danmaku index
|
||||
// uint danmakuIndex = 0;
|
||||
//
|
||||
// for(Danmaku &danmaku : danmakus) {
|
||||
// if(danmaku.isNew) {
|
||||
// // Try to assign the new danmaku's row to a free slot
|
||||
// if(getNextDanmakuRow(ph_danmakuRows, nb_danmakuRows, &(danmaku.row))){
|
||||
// // Compute the height for that row
|
||||
// danmaku.ypos = (r->h - DANMAKU_MARGIN_TOP) -
|
||||
// (danmaku.row + 1) * (DANMAKU_PADDING_V + GLYPH_SIZE);
|
||||
// danmaku.xpos = r->w;
|
||||
// // Set the slot to unavailable
|
||||
// updateDanmakuRow(ph_danmakuRows, danmaku.row);
|
||||
// danmaku.tailCheck = 0;
|
||||
// }
|
||||
// danmaku.isNew = 0;
|
||||
// }
|
||||
// else {
|
||||
// // Translate danmaku
|
||||
// danmaku.xpos -= deltaPix;
|
||||
// }
|
||||
//
|
||||
// // Draw the danmaku and get tail position
|
||||
// lastPix = RenderText(r, danmaku.text, danmaku.xpos, danmaku.ypos, 1.0f, glm::vec3(0.0, 0.26f, 0.0f));
|
||||
// if(lastPix + DANMAKU_PADDING_H < 0) {
|
||||
// danmakus.erase(danmakus.begin() + danmakuIndex);
|
||||
// }
|
||||
//
|
||||
// // Check if the tail of the danmaku is free (only check once)
|
||||
// if(!danmaku.tailCheck && (r->w > lastPix + (float)DANMAKU_PADDING_H)) {
|
||||
// // Free the row slot
|
||||
// updateDanmakuRow(ph_danmakuRows, danmaku.row);
|
||||
// danmaku.tailCheck = 1;
|
||||
// }
|
||||
// }
|
||||
// danmakuIndex++;
|
||||
// }
|
||||
// return 1;
|
||||
//}
|
||||
|
||||
|
||||
//OverlayHandler() {
|
||||
// init();
|
||||
//}
|
||||
//
|
||||
//int OverlayHandler::init() {
|
||||
// glGenVertexArrays(1, &VAO);
|
||||
// glGenBuffers(1, &VBO);
|
||||
// glBindVertexArray(VAO);
|
||||
// glBindBuffer(GL_ARRAY_BUFFER, 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);
|
||||
// glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
// glBindVertexArray(0);
|
||||
//
|
||||
//}
|
@ -1,65 +0,0 @@
|
||||
#ifndef _DANMAKU_H_
|
||||
#define _DANMAKU_H_
|
||||
|
||||
#include <shader.h>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include "stdlib.h"
|
||||
#include "stdio.h"
|
||||
|
||||
#include <ft2build.h>
|
||||
#include FT_FREETYPE_H
|
||||
|
||||
#define GLYPH_SIZE 36
|
||||
#define DANMAKU_MARGIN_TOP 50
|
||||
#define DANMAKU_MARGIN_BOT 50
|
||||
#define DANMAKU_PADDING_H 200
|
||||
#define DANMAKU_PADDING_V 20
|
||||
#define DANMAKU_SPEED_V 200.0f
|
||||
|
||||
// Glyphs
|
||||
typedef struct Character {
|
||||
unsigned int TextureID; // ID handle of the glyph texture
|
||||
glm::ivec2 Size; // Size of glyph
|
||||
glm::ivec2 Bearing; // Offset from baseline to left/top of glyph
|
||||
long int Advance; // Offset to advance to next glyph
|
||||
} Character;
|
||||
|
||||
// Danmaku
|
||||
typedef struct Danmaku {
|
||||
std::string text;
|
||||
uint isActive;
|
||||
float xpos;
|
||||
float ypos;
|
||||
uint isNew;
|
||||
uint row;
|
||||
uint tailCheck;
|
||||
} Danmaku;
|
||||
|
||||
//class OverlayHandler() {
|
||||
// public:
|
||||
// OverlayHandler();
|
||||
//
|
||||
// float RenderText(Shader, std::string, float, float, float, glm::vec3, uint &, uint &, std::map<char, Character>&);
|
||||
//
|
||||
// int init();
|
||||
//
|
||||
// private:
|
||||
// unsigned int VAO, VBO;
|
||||
//
|
||||
// void makeBitmaps(std::map<char, Character> &);
|
||||
//
|
||||
// Shader *glyphShader = new Shader("shaders/glyph_vs.glsl", "shaders/glyph_fs.glsl");
|
||||
//
|
||||
//
|
||||
//}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int getNextDanmakuRow(uint *, int, uint* );
|
||||
int updateDanmakuRow(uint *, uint);
|
||||
|
||||
int updateDanmakus(Danmaku *, float);
|
||||
#endif
|
118
src/gfx/bitmap.c
118
src/gfx/bitmap.c
@ -1,58 +1,64 @@
|
||||
#include "bitmap.h"
|
||||
|
||||
//void makeBitmaps(std::map<char, Character>& Characters){
|
||||
// ///////// FREETYPE2 INIT
|
||||
// FT_Library ft;
|
||||
// if (FT_Init_FreeType(&ft)){
|
||||
// std::cout << "ERROR::FREETYPE: Could not init FreeType Library" << std::endl;
|
||||
// exit(EXIT_FAILURE);
|
||||
// }
|
||||
// FT_Face face;
|
||||
// if (FT_New_Face(ft, "/usr/share/fonts/TTF/DejaVuSans.ttf", 0, &face)){
|
||||
// std::cout << "ERROR::FREETYPE: Failed to load font" << std::endl;
|
||||
// exit(EXIT_FAILURE);
|
||||
// }
|
||||
// FT_Set_Pixel_Sizes(face, 0, GLYPH_SIZE);
|
||||
// glPixelStorei(GL_UNPACK_ALIGNMENT, 1); // disable byte-alignment restriction
|
||||
// glEnable(GL_BLEND);
|
||||
//
|
||||
//
|
||||
// for (unsigned char c = 0; c < 128; c++){
|
||||
// // load character glyph
|
||||
// if (FT_Load_Char(face, c, FT_LOAD_RENDER)){
|
||||
// std::cout << "ERROR::FREETYTPE: Failed to load Glyph" << std::endl;
|
||||
// continue;
|
||||
// }
|
||||
// // generate texture
|
||||
// unsigned int 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);
|
||||
// // now store character for later use
|
||||
// Character character = {
|
||||
// texture,
|
||||
// glm::ivec2(face->glyph->bitmap.width, face->glyph->bitmap.rows),
|
||||
// glm::ivec2(face->glyph->bitmap_left, face->glyph->bitmap_top),
|
||||
// face->glyph->advance.x
|
||||
// };
|
||||
// Characters.insert(std::pair<char, Character>(c, character));
|
||||
// }
|
||||
// /// Clear glyphs
|
||||
// FT_Done_Face(face);
|
||||
// FT_Done_FreeType(ft);
|
||||
//}
|
||||
CharacterAtlas* makeBitmaps(){
|
||||
/////// FREETYPE2 INIT
|
||||
FT_Library ft;
|
||||
if (FT_Init_FreeType(&ft)){
|
||||
printf("ERROR::FREETYPE: Could not init FreeType Library\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
FT_Face face;
|
||||
if (FT_New_Face(ft, "res/CC.ttf", 0, &face)){
|
||||
printf("ERROR::FREETYPE: Failed to load font\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
FT_Set_Pixel_Sizes(face, 0, GLYPH_SIZE);
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1); // disable byte-alignment restriction
|
||||
glEnable(GL_BLEND);
|
||||
|
||||
CharacterAtlas *atlas = malloc(sizeof(CharacterAtlas));
|
||||
|
||||
for (unsigned char c = 0; c < 128; c++){
|
||||
// load character glyph
|
||||
if (FT_Load_Char(face, c, FT_LOAD_RENDER)){
|
||||
printf("ERROR::FREETYTPE: Failed to load Glyph\n");
|
||||
continue;
|
||||
}
|
||||
// generate texture
|
||||
unsigned int 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);
|
||||
// now store character for later use
|
||||
Character character = {
|
||||
texture,
|
||||
{face->glyph->bitmap.width, face->glyph->bitmap.rows},
|
||||
{face->glyph->bitmap_left, face->glyph->bitmap_top},
|
||||
face->glyph->advance.x
|
||||
};
|
||||
atlas->map[c] = character;
|
||||
atlas->hashmap[(int)c] = c; // trivial at this point
|
||||
}
|
||||
/// Clear glyphs
|
||||
FT_Done_Face(face);
|
||||
FT_Done_FreeType(ft);
|
||||
|
||||
return atlas;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,15 +1,40 @@
|
||||
#ifndef _BITMAP_H_
|
||||
#define _BITMAP_H_
|
||||
|
||||
#include "gfx.h"
|
||||
|
||||
#include <ft2build.h>
|
||||
#include FT_FREETYPE_H
|
||||
|
||||
//typedef struct Character {
|
||||
// unsigned int TextureID; // ID handle of the glyph texture
|
||||
// glm::ivec2 Size; // Size of glyph
|
||||
// glm::ivec2 Bearing; // Offset from baseline to left/top of glyph
|
||||
// long int Advance; // Offset to advance to next glyph
|
||||
//} Character;
|
||||
#include "stdlib.h"
|
||||
#include "stdio.h"
|
||||
|
||||
#include "../util/ivec2.h"
|
||||
|
||||
#define GLYPH_SIZE 36
|
||||
#define DANMAKU_MARGIN_TOP 50
|
||||
#define DANMAKU_MARGIN_BOT 50
|
||||
#define DANMAKU_PADDING_H 200
|
||||
#define DANMAKU_PADDING_V 20
|
||||
#define DANMAKU_SPEED_V 200.0f
|
||||
|
||||
#define MAP_SIZE 128
|
||||
|
||||
// Glyphs
|
||||
typedef struct Character {
|
||||
unsigned int TextureID; // ID handle of the glyph texture
|
||||
ivec2 Size; // Size of glyph
|
||||
ivec2 Bearing; // Offset from baseline to left/top of glyph
|
||||
long int Advance; // Offset to advance to next glyph
|
||||
} Character;
|
||||
|
||||
typedef struct CharacterAtlas {
|
||||
Character map[MAP_SIZE];
|
||||
int size;
|
||||
int hashmap[MAP_SIZE];
|
||||
} CharacterAtlas;
|
||||
|
||||
CharacterAtlas *makeBitmaps();
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -33,8 +33,6 @@ void player_init(struct Player *self) {
|
||||
mpv_set_wakeup_callback(self->handle, on_mpv_events, NULL);
|
||||
mpv_render_context_set_update_callback(self->ctx, on_mpv_render_update, NULL);
|
||||
|
||||
//const char *cmd[] = {"loadfile", argv[1], NULL};
|
||||
//mpv_command(mpv, cmd);
|
||||
mpv_set_option_string(self->handle, "loop", "");
|
||||
mpv_set_option_string(self->handle, "gpu-api", "opengl");
|
||||
mpv_set_option_string(self->handle, "hwdec", "auto");
|
||||
@ -65,7 +63,7 @@ static void *get_proc_address(void *ctx, const char *name)
|
||||
static void on_mpv_render_update(void *ctx)
|
||||
{
|
||||
// we set the wakeup flag here to enable the mpv_render_context_render path in the main loop.
|
||||
//wakeup = 1;
|
||||
wakeup = 1;
|
||||
}
|
||||
|
||||
static void on_mpv_events(void *ctx)
|
||||
@ -80,3 +78,8 @@ static inline void check_error(int status)
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void player_loadfile(struct Player* self, const char *file){
|
||||
const char *cmd[] = {"loadfile", file, NULL};
|
||||
mpv_command(self->handle, cmd);
|
||||
}
|
||||
|
@ -8,6 +8,8 @@
|
||||
#include <mpv/client.h>
|
||||
#include <mpv/render_gl.h>
|
||||
|
||||
extern int wakeup;
|
||||
|
||||
struct Player {
|
||||
mpv_handle *handle;
|
||||
mpv_render_context *ctx;
|
||||
@ -17,4 +19,6 @@ struct Player* player_create();
|
||||
void player_init(struct Player *self);
|
||||
void player_destroy(struct Player *self);
|
||||
|
||||
void player_loadfile(struct Player* self, const char *file);
|
||||
|
||||
#endif
|
||||
|
164
src/gfx/renderer.c
Normal file
164
src/gfx/renderer.c
Normal file
@ -0,0 +1,164 @@
|
||||
#include "renderer.h"
|
||||
#include "shader.h"
|
||||
#include "vao.h"
|
||||
#include "vbo.h"
|
||||
|
||||
void _renderer_mpv(struct Renderer *self);
|
||||
void _renderer_glyph(struct Renderer *self);
|
||||
|
||||
float quadVertices[] = {
|
||||
// positions // texCoords
|
||||
-1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
|
||||
-1.0f, -1.0f, 0.0f , 0.0f, 0.0f,
|
||||
1.0f, -1.0f, 0.0f, 1.0f, 0.0f,
|
||||
|
||||
-1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
|
||||
1.0f, -1.0f, 0.0f, 1.0f, 0.0f,
|
||||
1.0f, 1.0f, 0.0f, 1.0f, 1.0f
|
||||
};
|
||||
|
||||
int fbo_width = 1920;
|
||||
int fbo_height = 1080;
|
||||
|
||||
struct Renderer* renderer_create() {
|
||||
return malloc(sizeof(struct Renderer));
|
||||
}
|
||||
|
||||
void renderer_init(struct Renderer *self) {
|
||||
self->current_shader = SHADER_NONE;
|
||||
|
||||
// Compile shaders
|
||||
self->shaders[SHADER_MPV] = shader_create(
|
||||
"res/shaders/screen_vs.glsl", "res/shaders/screen_fs.glsl",
|
||||
2, (struct VertexAttr[]){
|
||||
{ .index = 0, .name = "pos" },
|
||||
{ .index = 1, .name = "texcoord" }
|
||||
});
|
||||
|
||||
self->shaders[SHADER_GLYPH] = shader_create(
|
||||
"res/shaders/glyph_vs.glsl", "res/shaders/glyph_fs.glsl",
|
||||
2, (struct VertexAttr[]){
|
||||
{ .index = 0, .name = "texcoord" }
|
||||
});
|
||||
|
||||
// Define buffers
|
||||
_renderer_mpv(self);
|
||||
_renderer_glyph(self);
|
||||
|
||||
// Create bitmaps
|
||||
self->atlas = makeBitmaps();
|
||||
}
|
||||
|
||||
void renderer_destroy(struct Renderer *self) {
|
||||
for (size_t i = 0; i <= SHADERS_LAST; i++) {
|
||||
shader_destroy(self->shaders[i]);
|
||||
}
|
||||
|
||||
vao_destroy(self->screenVAO);
|
||||
vbo_destroy(self->screenVBO);
|
||||
|
||||
free(self);
|
||||
}
|
||||
|
||||
/*
|
||||
Setting up the glyph renderer (for text)
|
||||
*/
|
||||
void _renderer_glyph(struct Renderer *self) {
|
||||
self->glyphVAO = vao_create();
|
||||
self->glyphVBO = vbo_create(GL_ARRAY_BUFFER, true);
|
||||
|
||||
vao_bind(self->glyphVAO);
|
||||
vbo_bind(self->glyphVBO);
|
||||
|
||||
vbo_buffer(self->glyphVBO, &quadVertices, 0, sizeof(float)*6*4);
|
||||
vao_attr(self->glyphVAO, self->glyphVBO, 0, 4, GL_FLOAT, 4*sizeof(float), 0);
|
||||
}
|
||||
|
||||
/*
|
||||
Setting up the mpv renderer
|
||||
*/
|
||||
void _renderer_mpv(struct Renderer *self) {
|
||||
|
||||
/* Screen VAO and VBO */
|
||||
self->screenVAO = vao_create();
|
||||
self->screenVBO = vbo_create(GL_ARRAY_BUFFER, false);
|
||||
|
||||
vao_bind(self->screenVAO);
|
||||
vbo_bind(self->screenVBO);
|
||||
|
||||
vbo_buffer(self->screenVBO, &quadVertices, 0, sizeof(quadVertices));
|
||||
vao_attr(self->screenVAO, self->screenVBO, 0, 3, GL_FLOAT, 5*sizeof(float), 0);
|
||||
vao_attr(self->screenVAO, self->screenVBO, 1, 2, GL_FLOAT, 5*sizeof(float), (3 * sizeof(float)));
|
||||
|
||||
/* Framebuffer for Video */
|
||||
glGenFramebuffers(1, &(self->video_framebuffer));
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, self->video_framebuffer);
|
||||
|
||||
/* create a color attachment texture */
|
||||
glGenTextures(1, &(self->video_textureColorbuffer));
|
||||
glBindTexture(GL_TEXTURE_2D, self->video_textureColorbuffer);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, fbo_width, fbo_height, 0, GL_RGBA, 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, self->video_textureColorbuffer, 0);
|
||||
|
||||
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
|
||||
printf("ERROR::FRAMEBUFFER:: VIDEO Framebuffer #%d is not complete!\n", self->video_framebuffer);
|
||||
self->mpv_fbo = (mpv_opengl_fbo){(int)(self->video_framebuffer), fbo_width, fbo_height, 0};
|
||||
}
|
||||
|
||||
/*
|
||||
Render text on the screen using the given Shader
|
||||
*/
|
||||
float render_text(struct Renderer *self, const char* text, uint length, float x, float y, float scale, float color[3])
|
||||
{
|
||||
shader_bind(self->shaders[SHADER_GLYPH]);
|
||||
glUniform3f(glGetUniformLocation((self->shaders[SHADER_GLYPH]).handle, "textColor"), color[0], color[1], color[2]);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
vao_bind(self->glyphVAO);
|
||||
|
||||
Character ch;
|
||||
|
||||
float xpos;
|
||||
float ypos;
|
||||
float w;
|
||||
float h;
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
// iterate through all characters
|
||||
for (unsigned char c = 0; c < length; c++){
|
||||
ch = self->atlas->map[self->atlas->hashmap[(int)text[c]]];
|
||||
|
||||
xpos = x + ch.Bearing[0] * scale;
|
||||
ypos = y - (ch.Size[1] - ch.Bearing[1]) * scale;
|
||||
|
||||
w = ch.Size[0] * scale;
|
||||
h = ch.Size[1] * scale;
|
||||
// update VBO for each character
|
||||
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 }
|
||||
};
|
||||
// render glyph texture over quad
|
||||
glBindTexture(GL_TEXTURE_2D, ch.TextureID);
|
||||
// update content of VBO memory
|
||||
vbo_bind(self->glyphVBO);
|
||||
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
// render quad
|
||||
glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||
// now advance cursors for next glyph (note that advance is number of 1/64 pixels)
|
||||
x += (ch.Advance >> 6) * scale; // bitshift by 6 to get value in pixels (2^6 = 64)
|
||||
}
|
||||
glBindVertexArray(0);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
return xpos;
|
||||
}
|
54
src/gfx/renderer.h
Normal file
54
src/gfx/renderer.h
Normal file
@ -0,0 +1,54 @@
|
||||
#ifndef _RENDERER_H_
|
||||
#define _RENDERER_H_
|
||||
|
||||
#include <mpv/render_gl.h>
|
||||
#include "shader.h"
|
||||
#include "vao.h"
|
||||
#include "vbo.h"
|
||||
#include "bitmap.h"
|
||||
|
||||
#define SHADERS_LAST SHADER_BASIC_COLOR
|
||||
enum ShaderType {
|
||||
SHADER_NONE = 0,
|
||||
SHADER_MPV,
|
||||
SHADER_GLYPH,
|
||||
SHADER_BASIC_COLOR,
|
||||
SHADER_BASIC_TEXTURE
|
||||
};
|
||||
|
||||
|
||||
struct Renderer{
|
||||
struct Shader shaders[SHADERS_LAST + 1];
|
||||
enum ShaderType current_shader;
|
||||
struct Shader shader;
|
||||
|
||||
|
||||
// TODO: all of these should be more generically defined
|
||||
struct VBO screenVBO;
|
||||
struct VAO screenVAO;
|
||||
|
||||
unsigned int video_framebuffer;
|
||||
unsigned int video_textureColorbuffer;
|
||||
|
||||
unsigned int screen_framebuffer;
|
||||
unsigned int screen_textureColorbuffer;
|
||||
|
||||
unsigned int screen_rbo;
|
||||
unsigned int video_rbo;
|
||||
|
||||
mpv_opengl_fbo mpv_fbo;
|
||||
mpv_render_param *params_fbo;
|
||||
|
||||
struct VBO glyphVBO;
|
||||
struct VAO glyphVAO;
|
||||
|
||||
CharacterAtlas *atlas;
|
||||
};
|
||||
|
||||
struct Renderer* renderer_create();
|
||||
void renderer_init(struct Renderer *self);
|
||||
void renderer_destroy(struct Renderer *self);
|
||||
|
||||
float render_text(struct Renderer *self, const char* text, uint length, float x, float y, float scale, float color[3]);
|
||||
|
||||
#endif
|
464
src/main.c
464
src/main.c
@ -3,12 +3,214 @@
|
||||
#include "gfx/vbo.h"
|
||||
#include "glad/glad.h"
|
||||
|
||||
static inline void check_error(int);
|
||||
|
||||
int main(int argc, char const *argv[])
|
||||
{
|
||||
if (argc < 2){
|
||||
//std::cout << "Usage: " << argv[0] << " videofilename" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
////////// GLFW INIT
|
||||
glfwInit();
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
|
||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||||
|
||||
///////// Create window
|
||||
if ((wwindow = glfwCreateWindow(window_width, window_height, "a-mpv", NULL, NULL)) == NULL){
|
||||
printf("ERROR::GLFW::Failed to create window\n");
|
||||
return -1;
|
||||
}
|
||||
glfwMakeContextCurrent(wwindow);
|
||||
glfwSetFramebufferSizeCallback(wwindow, framebuffer_size_callback);
|
||||
|
||||
///////// Load GLAD
|
||||
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)){
|
||||
printf("ERROR::GLAD::Failed to initialize GLAD\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
//////////// Initializing placeholder for FT text glyphs
|
||||
//std::map<char, Character> Characters;
|
||||
//makeBitmaps(Characters);
|
||||
|
||||
///////// GL parameters
|
||||
glEnable(GL_DEPTH);
|
||||
glEnable(GL_MULTISAMPLE);
|
||||
glfwWindowHint(GLFW_SAMPLES, 4);
|
||||
|
||||
/* Glyph shenanigans
|
||||
*/
|
||||
|
||||
//mat4s transformation = glms_ortho(0.0f, (float)(window_width), 0.0f, (float)window_height, -100, 100);
|
||||
|
||||
/* Setting up MPV player
|
||||
The mpv and mpv_ctx variables are temporary
|
||||
*/
|
||||
player = player_create();
|
||||
player_init(player);
|
||||
mpv = player->handle;
|
||||
mpv_ctx = player->ctx;
|
||||
|
||||
/* Setting the renderer
|
||||
The mpv and mpv_ctx variables are temporary
|
||||
*/
|
||||
renderer = renderer_create();
|
||||
renderer_init(renderer);
|
||||
|
||||
// this doesn't work when called inside the Renderer struct...
|
||||
int flip_y = 1;
|
||||
renderer->params_fbo = (mpv_render_param [3]){
|
||||
{MPV_RENDER_PARAM_OPENGL_FBO, &(renderer->mpv_fbo)},
|
||||
{MPV_RENDER_PARAM_FLIP_Y, &flip_y},
|
||||
{MPV_RENDER_PARAM_INVALID, NULL}};
|
||||
|
||||
/*
|
||||
Start video playback
|
||||
*/
|
||||
const char filename[] = "https://stream.wotos.eu/snw_master.m3u8";
|
||||
player_loadfile(player, filename);
|
||||
|
||||
const char *text = "I Joe";
|
||||
|
||||
while (!glfwWindowShouldClose(wwindow))
|
||||
{
|
||||
fcount++;
|
||||
float currentFrame = glfwGetTime();
|
||||
deltaTime = currentFrame - lastFrame;
|
||||
lastFrame = currentFrame;
|
||||
//if (fcount % 100 == 0){
|
||||
// std::cout << "FPS: " << 1 / deltaTime << "\n" << std::endl;
|
||||
// }
|
||||
processGLFWInput(wwindow, mpv);
|
||||
// -----
|
||||
|
||||
if (wakeup)
|
||||
{
|
||||
if ((mpv_render_context_update(mpv_ctx) & MPV_RENDER_UPDATE_FRAME))
|
||||
{
|
||||
mpv_render_context_render(mpv_ctx, renderer->params_fbo); // this "renders" to the video_framebuffer "linked by ID" in the params_fbo - BLOCKING
|
||||
glViewport(0, 0, window_width, window_height); // fucky
|
||||
}
|
||||
}
|
||||
//screenShader->use();
|
||||
shader_bind(renderer->shaders[SHADER_MPV]);
|
||||
|
||||
vao_bind(renderer->screenVAO);
|
||||
glBindTexture(GL_TEXTURE_2D, renderer->video_textureColorbuffer); // <-- SCREEN Colorbuffer IS THE TEXTURE
|
||||
glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||
|
||||
// -----
|
||||
if (wakeup)
|
||||
{
|
||||
mpv_render_context_report_swap(mpv_ctx);
|
||||
wakeup = 0;
|
||||
}
|
||||
|
||||
render_text(renderer, text, strlen(text), 0, 0, 0.001, (float [3]){0.0, 1.0, 0.0});
|
||||
|
||||
//glUniformMatrix4fv(glGetUniformLocation(renderer->shaders[SHADER_GLYPH].handle, "ransformation"), 1, GL_FALSE, (GLfloat *)&transformation.raw);
|
||||
|
||||
//Distance during deltaTime for consistent translation
|
||||
|
||||
//// Draw image
|
||||
//glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
//imgShader->use();
|
||||
//glBindVertexArray(imgVBO); // <-- The SCREEN QUAD
|
||||
//glBindTexture(GL_TEXTURE_2D, imgTex); // <-- SCREEN Colorbuffer IS THE TEXTURE
|
||||
|
||||
//imgMatrix = glm::translate(imgMatrix, glm::vec3(0.5/deltaPix, 0.0f, 0.0f));
|
||||
//glUniformMatrix4fv(glGetUniformLocation(imgShader->ID, "transformation"), 1, GL_FALSE, glm::value_ptr(imgMatrix));
|
||||
|
||||
//glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||
|
||||
|
||||
// // Glyphs
|
||||
//transformation = glm::translate(transformation, glm::vec3(deltaPix , 0.0f, 0.0f));
|
||||
|
||||
|
||||
/////////////////////////////////////////// SOCKET
|
||||
|
||||
//recv_bytes = recv(sock, buffer, RECV_BUFFER_SIZE, 0);
|
||||
//if(recv_bytes >= 1){
|
||||
// danmakus.push_back({buffer, 1, (float)window_width, 400.0f, 1, 0, 0});
|
||||
//}
|
||||
//std::cout << danmakus.front().text << std::endl;
|
||||
|
||||
/////////////////////////////////////////// Danmaku update
|
||||
//updateDanmakus(r);
|
||||
|
||||
//}
|
||||
|
||||
glfwSwapBuffers(wwindow);
|
||||
glfwPollEvents();
|
||||
usleep(16 * 1000); // we LIMIT the main render loop to 100FPS! If VSYSNC is enabled the limit is the VSYNC limit (~60fps)
|
||||
}
|
||||
renderer_destroy(renderer);
|
||||
player_destroy(player);
|
||||
mpv_render_context_free(mpv_ctx);
|
||||
mpv_terminate_destroy(mpv);
|
||||
glfwTerminate();
|
||||
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void processGLFWInput(GLFWwindow *window, mpv_handle *ctx)
|
||||
{
|
||||
glfwSetInputMode(window, GLFW_STICKY_KEYS, GLFW_FALSE);
|
||||
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) {
|
||||
glfwSetWindowShouldClose(window, true);
|
||||
}
|
||||
|
||||
if (glfwGetKey(window, GLFW_KEY_SPACE) == GLFW_PRESS) {
|
||||
const char *c[] = {"show-text", "lol", NULL};
|
||||
check_error(mpv_command(ctx, c));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void framebuffer_size_callback(GLFWwindow *window, int width, int height)
|
||||
{
|
||||
// we have to rescale the Texture and renderbuffer storage.
|
||||
window_height = height;
|
||||
window_width = width;
|
||||
glBindTexture(GL_TEXTURE_2D, renderer->screen_textureColorbuffer);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, window_width, window_height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, screen_rbo);
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, window_width, window_height);
|
||||
}
|
||||
|
||||
static inline void check_error(int status)
|
||||
{
|
||||
if (status < 0) {
|
||||
printf("mpv API error: %s\n", mpv_error_string(status));
|
||||
|
||||
//exit(1);
|
||||
}
|
||||
}
|
||||
//
|
||||
///** Returns true on success, or false if there was an error */
|
||||
//bool SetSocketBlockingEnabled(int fd, bool blocking)
|
||||
//{
|
||||
// if (fd < 0) return false;
|
||||
//
|
||||
//#ifdef _WIN32
|
||||
// unsigned long mode = blocking ? 0 : 1;
|
||||
// return (ioctlsocket(fd, FIONBIO, &mode) == 0) ? true : false;
|
||||
//#else
|
||||
// int flags = fcntl(fd, F_GETFL, 0);
|
||||
// if (flags == -1) return false;
|
||||
// flags = blocking ? (flags & ~O_NONBLOCK) : (flags | O_NONBLOCK);
|
||||
// return (fcntl(fd, F_SETFL, flags) == 0) ? true : false;
|
||||
//#endif
|
||||
|
||||
|
||||
|
||||
//////////// SOCKET SERVER
|
||||
//// create socket file descriptor
|
||||
//int server_fd;
|
||||
@ -45,117 +247,9 @@ int main(int argc, char const *argv[])
|
||||
// perror("listen failed");
|
||||
// exit(EXIT_FAILURE);
|
||||
//}
|
||||
//}
|
||||
|
||||
////////// GLFW INIT
|
||||
glfwInit();
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
|
||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||||
|
||||
///////// Create window
|
||||
if ((wwindow = glfwCreateWindow(window_width, window_height, "a-mpv", NULL, NULL)) == NULL){
|
||||
printf("ERROR::GLFW::Failed to create window\n");
|
||||
return -1;
|
||||
}
|
||||
glfwMakeContextCurrent(wwindow);
|
||||
glfwSetFramebufferSizeCallback(wwindow, framebuffer_size_callback);
|
||||
|
||||
///////// Load GLAD
|
||||
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)){
|
||||
printf("ERROR::GLAD::Failed to initialize GLAD\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
//////////// Initializing placeholder for FT text glyphs
|
||||
//std::map<char, Character> Characters;
|
||||
//makeBitmaps(Characters);
|
||||
|
||||
///////// GL parameters
|
||||
glEnable(GL_DEPTH);
|
||||
glEnable(GL_MULTISAMPLE);
|
||||
glfwWindowHint(GLFW_SAMPLES, 4);
|
||||
|
||||
///////// MPV INIT
|
||||
mpv = mpv_create();
|
||||
if (mpv_initialize(mpv) < MPV_ERROR_SUCCESS){
|
||||
printf("ERROR::MPV::Failed to initialize mpv\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
mpv_opengl_init_params opengl_init_params={get_proc_address, NULL};
|
||||
int adv = 1; // we will use the update callback
|
||||
mpv_render_param render_param[] = {
|
||||
{MPV_RENDER_PARAM_API_TYPE, (char *)(MPV_RENDER_API_TYPE_OPENGL)},
|
||||
{MPV_RENDER_PARAM_OPENGL_INIT_PARAMS, &opengl_init_params},
|
||||
{MPV_RENDER_PARAM_ADVANCED_CONTROL, &adv},
|
||||
{MPV_RENDER_PARAM_BLOCK_FOR_TARGET_TIME, NULL},
|
||||
{MPV_RENDER_PARAM_INVALID, NULL},
|
||||
};
|
||||
|
||||
if (mpv_render_context_create(&mpv_ctx, mpv, render_param) < MPV_ERROR_SUCCESS){
|
||||
printf("ERROR::MPV::Failed to create MPV render context\n");
|
||||
return -1;
|
||||
}
|
||||
mpv_set_wakeup_callback(mpv, on_mpv_events, NULL);
|
||||
mpv_render_context_set_update_callback(mpv_ctx, on_mpv_render_update, NULL);
|
||||
|
||||
const char *cmd[] = {"loadfile", argv[1], NULL};
|
||||
mpv_command(mpv, cmd);
|
||||
mpv_set_option_string(mpv, "loop", "");
|
||||
mpv_set_option_string(mpv, "gpu-api", "opengl");
|
||||
mpv_set_option_string(mpv, "hwdec", "auto");
|
||||
mpv_set_option_string(mpv, "vd-lavc-dr", "yes");
|
||||
//mpv_set_option_string(mpv, "terminal", "yes");
|
||||
// mpv_set_option_string(mpv, "video-timing-offset", "0"); // this need manual fps adjustment mpv_render_frame_info()
|
||||
check_error(mpv_set_option_string(mpv, "input-default-bindings", "yes"));
|
||||
mpv_set_option_string(mpv, "input-vo-keyboard", "yes");
|
||||
int val = 1;
|
||||
check_error(mpv_set_option(mpv, "osc", MPV_FORMAT_FLAG, &val));
|
||||
|
||||
|
||||
|
||||
|
||||
struct Shader screenShader = shader_create(
|
||||
"res/shaders/screen_vs.glsl", "res/shaders/screen_fs.glsl",
|
||||
2, (struct VertexAttr[]){
|
||||
{ .index = 0, .name = "pos" },
|
||||
{ .index = 1, .name = "texCoords"}
|
||||
});
|
||||
|
||||
|
||||
//// TEST VAO REPLACE
|
||||
|
||||
quadVAOTEST = vao_create();
|
||||
quadVBOTEST = vbo_create(GL_ARRAY_BUFFER, false);
|
||||
|
||||
vao_bind(quadVAOTEST);
|
||||
vbo_bind(quadVBOTEST);
|
||||
|
||||
vbo_buffer(quadVBOTEST, &quadVertices, 0, sizeof(quadVertices));
|
||||
vao_attr(quadVAOTEST, quadVBOTEST, 0, 3, GL_FLOAT, 5*sizeof(float), 0);
|
||||
vao_attr(quadVAOTEST, quadVBOTEST, 1, 2, GL_FLOAT, 5*sizeof(float), (3 * sizeof(float)));
|
||||
|
||||
//Framebuffer for Video
|
||||
glGenFramebuffers(1, &video_framebuffer);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, video_framebuffer);
|
||||
|
||||
// create a color attachment texture
|
||||
glGenTextures(1, &video_textureColorbuffer);
|
||||
glBindTexture(GL_TEXTURE_2D, video_textureColorbuffer);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, fbo_width, fbo_height, 0, GL_RGBA, 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, video_textureColorbuffer, 0);
|
||||
|
||||
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
|
||||
printf("ERROR::FRAMEBUFFER:: VIDEO Framebuffer #%d is not complete!\n", video_framebuffer);
|
||||
mpv_opengl_fbo mpv_fbo = {(int)(video_framebuffer), fbo_width, fbo_height, 0};
|
||||
int flip_y = 1;
|
||||
mpv_render_param params_fbo[] = {
|
||||
{MPV_RENDER_PARAM_OPENGL_FBO, &mpv_fbo},
|
||||
{MPV_RENDER_PARAM_FLIP_Y, &flip_y},
|
||||
{MPV_RENDER_PARAM_INVALID, NULL}};
|
||||
|
||||
//// BUNCH OF CRAP
|
||||
////////// IMAGE TEST
|
||||
//// Import image
|
||||
//int imgWidth, imgHeight, imgChan;
|
||||
@ -265,153 +359,3 @@ int main(int argc, char const *argv[])
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
while (!glfwWindowShouldClose(wwindow))
|
||||
{
|
||||
fcount++;
|
||||
float currentFrame = glfwGetTime();
|
||||
deltaTime = currentFrame - lastFrame;
|
||||
lastFrame = currentFrame;
|
||||
//if (fcount % 100 == 0){
|
||||
// std::cout << "FPS: " << 1 / deltaTime << "\n" << std::endl;
|
||||
// }
|
||||
processGLFWInput(wwindow, mpv);
|
||||
// -----
|
||||
|
||||
if (wakeup)
|
||||
{
|
||||
if ((mpv_render_context_update(mpv_ctx) & MPV_RENDER_UPDATE_FRAME))
|
||||
{
|
||||
mpv_render_context_render(mpv_ctx, params_fbo); // this "renders" to the video_framebuffer "linked by ID" in the params_fbo - BLOCKING
|
||||
glViewport(0, 0, window_width, window_height); // fucky
|
||||
}
|
||||
}
|
||||
//screenShader->use();
|
||||
shader_bind(screenShader);
|
||||
|
||||
//glBindVertexArray(quadVBO); // <-- The SCREEN QUAD
|
||||
vao_bind(quadVAOTEST);
|
||||
glBindTexture(GL_TEXTURE_2D, video_textureColorbuffer); // <-- SCREEN Colorbuffer IS THE TEXTURE
|
||||
glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||
|
||||
// -----
|
||||
if (wakeup)
|
||||
{
|
||||
mpv_render_context_report_swap(mpv_ctx);
|
||||
wakeup = 0;
|
||||
}
|
||||
|
||||
//Distance during deltaTime for consistent translation
|
||||
|
||||
//// Draw image
|
||||
//glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
//imgShader->use();
|
||||
//glBindVertexArray(imgVBO); // <-- The SCREEN QUAD
|
||||
//glBindTexture(GL_TEXTURE_2D, imgTex); // <-- SCREEN Colorbuffer IS THE TEXTURE
|
||||
|
||||
//imgMatrix = glm::translate(imgMatrix, glm::vec3(0.5/deltaPix, 0.0f, 0.0f));
|
||||
//glUniformMatrix4fv(glGetUniformLocation(imgShader->ID, "transformation"), 1, GL_FALSE, glm::value_ptr(imgMatrix));
|
||||
|
||||
//glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||
|
||||
|
||||
// // Glyphs
|
||||
//transformation = glm::translate(transformation, glm::vec3(deltaPix , 0.0f, 0.0f));
|
||||
|
||||
//glyphShader->use();
|
||||
|
||||
//// TEMPORARY
|
||||
//glUniformMatrix4fv(glGetUniformLocation(glyphShader->ID, "transformation"), 1, GL_FALSE, glm::value_ptr(transformation));
|
||||
|
||||
/////////////////////////////////////////// SOCKET
|
||||
|
||||
//recv_bytes = recv(sock, buffer, RECV_BUFFER_SIZE, 0);
|
||||
//if(recv_bytes >= 1){
|
||||
// danmakus.push_back({buffer, 1, (float)window_width, 400.0f, 1, 0, 0});
|
||||
//}
|
||||
//std::cout << danmakus.front().text << std::endl;
|
||||
|
||||
/////////////////////////////////////////// Danmaku update
|
||||
//updateDanmakus(r);
|
||||
|
||||
//}
|
||||
|
||||
glfwSwapBuffers(wwindow);
|
||||
glfwPollEvents();
|
||||
//usleep(10000); // we LIMIT the main render loop to 100FPS! If VSYSNC is enabled the limit is the VSYNC limit (~60fps)
|
||||
}
|
||||
mpv_render_context_free(mpv_ctx);
|
||||
mpv_terminate_destroy(mpv);
|
||||
glfwTerminate();
|
||||
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void processGLFWInput(GLFWwindow *window, mpv_handle *ctx)
|
||||
{
|
||||
glfwSetInputMode(window, GLFW_STICKY_KEYS, GLFW_FALSE);
|
||||
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) {
|
||||
glfwSetWindowShouldClose(window, true);
|
||||
}
|
||||
|
||||
if (glfwGetKey(window, GLFW_KEY_SPACE) == GLFW_PRESS) {
|
||||
const char *c[] = {"show-text", "lol", NULL};
|
||||
check_error(mpv_command(ctx, c));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Returns the address of the specified function (name) for the given context (ctx)
|
||||
static void *get_proc_address(void *ctx, const char *name)
|
||||
{
|
||||
glfwGetCurrentContext();
|
||||
return (void *)(glfwGetProcAddress(name));
|
||||
}
|
||||
|
||||
static void on_mpv_render_update(void *ctx)
|
||||
{
|
||||
// we set the wakeup flag here to enable the mpv_render_context_render path in the main loop.
|
||||
wakeup = 1;
|
||||
}
|
||||
|
||||
static void on_mpv_events(void *ctx)
|
||||
{
|
||||
//std::cout << "INFO::" << __func__ << std::endl;
|
||||
}
|
||||
|
||||
void framebuffer_size_callback(GLFWwindow *window, int width, int height)
|
||||
{
|
||||
// we have to rescale the Texture and renderbuffer storage.
|
||||
window_height = height;
|
||||
window_width = width;
|
||||
glBindTexture(GL_TEXTURE_2D, screen_textureColorbuffer);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, window_width, window_height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, screen_rbo);
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, window_width, window_height);
|
||||
}
|
||||
|
||||
static inline void check_error(int status)
|
||||
{
|
||||
if (status < 0) {
|
||||
printf("mpv API error: %s\n", mpv_error_string(status));
|
||||
//exit(1);
|
||||
}
|
||||
}
|
||||
//
|
||||
///** Returns true on success, or false if there was an error */
|
||||
//bool SetSocketBlockingEnabled(int fd, bool blocking)
|
||||
//{
|
||||
// if (fd < 0) return false;
|
||||
//
|
||||
//#ifdef _WIN32
|
||||
// unsigned long mode = blocking ? 0 : 1;
|
||||
// return (ioctlsocket(fd, FIONBIO, &mode) == 0) ? true : false;
|
||||
//#else
|
||||
// int flags = fcntl(fd, F_GETFL, 0);
|
||||
// if (flags == -1) return false;
|
||||
// flags = blocking ? (flags & ~O_NONBLOCK) : (flags | O_NONBLOCK);
|
||||
// return (fcntl(fd, F_SETFL, flags) == 0) ? true : false;
|
||||
//#endif
|
||||
//}
|
||||
|
45
src/main.h
45
src/main.h
@ -9,19 +9,13 @@
|
||||
|
||||
#include "gfx/vao.h"
|
||||
#include "gfx/vbo.h"
|
||||
#include "gfx/player.h"
|
||||
#include "gfx/renderer.h"
|
||||
|
||||
//#include "danmaku/danmaku.h"
|
||||
|
||||
//#include <cstring>
|
||||
#include <unistd.h>
|
||||
#include "gfx/shader.h"
|
||||
#include "gfx/bitmap.h"
|
||||
|
||||
//#include "glm/glm.hpp"
|
||||
//#include <glm/gtc/matrix_transform.hpp>
|
||||
//#include <glm/gtx/transform.hpp>
|
||||
//#include <glm/gtc/type_ptr.hpp>
|
||||
|
||||
//#include <sys/socket.h>
|
||||
//#include <sys/types.h>
|
||||
//#include <netdb.h>
|
||||
@ -41,23 +35,16 @@
|
||||
//#define STB_IMAGE_IMPLEMENTATION
|
||||
//#include <stb/stb_image.h>
|
||||
|
||||
|
||||
int main(int argc, char const *argv[]);
|
||||
|
||||
int window_width = 1366;
|
||||
int window_height = 768;
|
||||
int fbo_width = 1366;
|
||||
int fbo_height = 768;
|
||||
int window_width = 1920;
|
||||
int window_height = 1080;
|
||||
|
||||
GLFWwindow *wwindow = NULL;
|
||||
mpv_handle *mpv;
|
||||
mpv_render_context *mpv_ctx;
|
||||
|
||||
unsigned int video_framebuffer;
|
||||
unsigned int video_textureColorbuffer;
|
||||
|
||||
unsigned int screen_framebuffer;
|
||||
unsigned int screen_textureColorbuffer;
|
||||
|
||||
unsigned int screen_rbo;
|
||||
unsigned int video_rbo;
|
||||
unsigned int quadVAO, quadVBO;
|
||||
@ -66,11 +53,14 @@ unsigned int cubeVAO, cubeVBO;
|
||||
struct VAO quadVAOTEST;
|
||||
struct VBO quadVBOTEST;
|
||||
|
||||
struct Player *player;
|
||||
struct Renderer *renderer;
|
||||
|
||||
float deltaTime, lastFrame;
|
||||
unsigned int fcount = 0;
|
||||
bool animation=true;
|
||||
|
||||
static void *get_proc_address(void *ctx, const char *name);
|
||||
//static void *get_proc_address(void *ctx, const char *name);
|
||||
void processGLFWInput(GLFWwindow *window, mpv_handle *);
|
||||
void framebuffer_size_callback(GLFWwindow *window, int width, int height);
|
||||
|
||||
@ -84,22 +74,13 @@ float imgVertices[] = {
|
||||
1.0f, -1.0f, 0.0f, 1.0f, 0.0f,
|
||||
1.0f, 1.0f, 0.0f, 1.0f, 1.0f};
|
||||
|
||||
float quadVertices[] = {
|
||||
// positions // texCoords
|
||||
-1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
|
||||
-1.0f, -1.0f, 0.0f , 0.0f, 0.0f,
|
||||
1.0f, -1.0f, 0.0f, 1.0f, 0.0f,
|
||||
|
||||
-1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
|
||||
1.0f, -1.0f, 0.0f, 1.0f, 0.0f,
|
||||
1.0f, 1.0f, 0.0f, 1.0f, 1.0f};
|
||||
//static void on_mpv_render_update(void *ctx);
|
||||
//static void on_mpv_events(void *ctx);
|
||||
|
||||
int wakeup = 0;
|
||||
extern int wakeup;
|
||||
|
||||
static void on_mpv_render_update(void *ctx);
|
||||
static void on_mpv_events(void *ctx);
|
||||
unsigned int wakeup = 0;
|
||||
|
||||
static inline void check_error(int);
|
||||
|
||||
bool SetSocketBlockingEnabled(int fd, bool blocking);
|
||||
|
||||
|
Can't render this file because it is too large.
|
Can't render this file because it is too large.
|
Can't render this file because it is too large.
|
Reference in New Issue
Block a user