From 5f4ffbc356d988c20c45ff3efd7f3db58bd13f42 Mon Sep 17 00:00:00 2001 From: Sian Cao Date: Wed, 23 Apr 2014 19:23:51 +0800 Subject: [PATCH] support simple text rendering mode restructure the code, to make it easier to swtich between text rendering and scene rendering modes. --- CMakeLists.txt | 4 +- actionmode.h | 19 +++ atlas.cc | 184 +++++++++++++++++++++++ atlas.h | 41 ++++++ atlas_frag.glsl | 10 ++ atlas_vertex.glsl | 7 + driver.cc | 188 ++---------------------- driver.h | 42 ++++++ glutil.cc | 86 +++++++++++ glutil.h | 16 ++ scene.cc | 89 +++++++++++ scene.h | 13 ++ fragment_shader.glsl => scene_frag.glsl | 0 vertex_shader.glsl => scene_vertex.glsl | 0 14 files changed, 520 insertions(+), 179 deletions(-) create mode 100644 actionmode.h create mode 100644 atlas.cc create mode 100644 atlas.h create mode 100644 atlas_frag.glsl create mode 100644 atlas_vertex.glsl create mode 100644 driver.h create mode 100644 glutil.cc create mode 100644 glutil.h create mode 100644 scene.cc create mode 100644 scene.h rename fragment_shader.glsl => scene_frag.glsl (100%) rename vertex_shader.glsl => scene_vertex.glsl (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index b3193f4..99f9dc7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,6 +14,7 @@ pkg_check_modules(GLESV2 REQUIRED glesv2) pkg_check_modules(LIBDRM REQUIRED libdrm) pkg_check_modules(EGL REQUIRED egl) pkg_check_modules(GBM REQUIRED gbm) +pkg_check_modules(FT2 REQUIRED freetype2) # Find includes in corresponding build directories set(CMAKE_INCLUDE_CURRENT_DIR ON) @@ -25,6 +26,7 @@ include_directories(${EGL_INCLUDE_DIRS}) include_directories(${GBM_INCLUDE_DIRS}) include_directories(${LIBDRM_INCLUDE_DIRS}) include_directories(${GLFW3_INCLUDE_DIRS}) +include_directories(${FT2_INCLUDE_DIRS}) configure_file(${PROJECT_SOURCE_DIR}/config.h.in ${PROJECT_BINARY_DIR}/config.h) @@ -34,4 +36,4 @@ file(GLOB SRCS "${PROJECT_SOURCE_DIR}/*.cc") add_executable(${target} ${SRCS}) target_link_libraries(${target} ${GLESV2_LIBRARIES} ${EGL_LIBRARIES} - ${GBM_LIBRARIES} ${LIBDRM_LIBRARIES}) + ${GBM_LIBRARIES} ${LIBDRM_LIBRARIES} ${FT2_LIBRARIES}) diff --git a/actionmode.h b/actionmode.h new file mode 100644 index 0000000..286a9ad --- /dev/null +++ b/actionmode.h @@ -0,0 +1,19 @@ +#ifndef _ACTION_MODE_H +#define _ACTION_MODE_H + +#include "glutil.h" + +class ActionMode { + public: + virtual bool init(int width, int height) = 0; + virtual void deinit() = 0; + virtual void render() = 0; + GLProcess& process() { return _proc; } + + protected: + struct GLProcess _proc; + int _screenWidth; + int _screenHeight; +}; + +#endif diff --git a/atlas.cc b/atlas.cc new file mode 100644 index 0000000..8c3b04b --- /dev/null +++ b/atlas.cc @@ -0,0 +1,184 @@ +#include +#include +#include + +#include "glutil.h" +#include "atlas.h" + +#include +#include +#include + +#include + +using namespace std; + +static FT_Library ft; +static FT_Face face; +static GLuint tex; + +static void init_ft() +{ + if (FT_Init_FreeType(&ft)) { + std::cerr << "init freetype failed" << std::endl; + exit(-1); + } + + if (FT_New_Face(ft, "/usr/share/fonts/microsoft/msyh.ttf", 0, &face)) { + std::cerr << "load face failed" << std::endl; + exit(-1); + } +} + +void TextMode::create_atlas(FT_Face face, int pointSize) +{ + FT_Set_Pixel_Sizes(face, 0, pointSize); + _atlas.point_size = pointSize; + FT_GlyphSlot slot = face->glyph; + for (unsigned char i = 32; i < 128; i++) { + if (FT_Load_Char(face, (char)i, FT_LOAD_RENDER)) { + std::cerr << "load " << i << " failed\n"; + continue; + } + + _atlas.infos[i] = { + (float)slot->bitmap_left, (float)slot->bitmap_top, + (float)slot->bitmap.width, (float)slot->bitmap.rows, + float(slot->advance.x >> 6), float(slot->advance.y >> 6), + _atlas.width + }; + + _atlas.height = std::max(_atlas.height, _atlas.infos[i].height); + _atlas.width += _atlas.infos[i].width + 10; + } + + //NOTE: transparent and `+10` above are anti rendering artifacts. + //since two chars in texture are close enough to blur each other's border. + GLubyte transparent[(int)_atlas.width * (int)_atlas.height]; + memset(transparent, 0, sizeof transparent); + glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, _atlas.width, _atlas.height, + 0, GL_ALPHA, GL_UNSIGNED_BYTE, transparent); + + for (unsigned char i = 32; i < 128; i++) { + if (FT_Load_Char(face, (char)i, FT_LOAD_RENDER)) { + std::cerr << "load " << i << " failed\n"; + continue; + } + glTexSubImage2D(GL_TEXTURE_2D, 0, _atlas.infos[i].offset, 0, _atlas.infos[i].width, + _atlas.infos[i].height, GL_ALPHA, GL_UNSIGNED_BYTE, slot->bitmap.buffer); + } +} + +void TextMode::render_text(const char *text, float x, float y, float sx, float sy) +{ + int len = strlen(text); + + struct point_t { + GLfloat x, y, s, t; + } points[6 * len]; + + for (int i = 0; i < len; ++i) { + int c = text[i]; + GLfloat x0 = x + _atlas.infos[c].left * sx; + GLfloat y0 = y + _atlas.infos[c].top * sy; + GLfloat w = _atlas.infos[c].width * sx, h = _atlas.infos[c].height * sy; + + float tw = _atlas.infos[c].width / _atlas.width; + float tx = _atlas.infos[c].offset / _atlas.width; + float ty = _atlas.infos[c].height / _atlas.height; + + int p = i * 6; + points[p++] = {x0, y0, tx, 0,}; + points[p++] = {x0 + w, y0, tx + tw, 0,}; + points[p++] = {x0, y0 - h, tx, ty,}; + + points[p++] = {x0, y0 - h, tx, ty,}; + points[p++] = {x0 + w, y0, tx + tw, 0,}; + points[p++] = {x0 + w, y0 - h, tx + tw, ty,}; + + x += _atlas.infos[c].ax * sx; + y += _atlas.infos[c].ay * sy; + } + + glBindBuffer(GL_ARRAY_BUFFER, _proc.vbo); + glBufferData(GL_ARRAY_BUFFER, sizeof points, points, GL_DYNAMIC_DRAW); + glDrawArrays(GL_TRIANGLES, 0, len * 6); + +} + +static timeval tv_start = {0, 0}; + +bool TextMode::init(int width, int height) +{ + _screenWidth = width, _screenHeight = height; + init_ft(); + GLProcess* proc = glprocess_create("atlas_vertex.glsl", "atlas_frag.glsl"); + if (!proc) return false; + _proc = *proc; + GLuint program = _proc.program; + glUseProgram(program); + + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glGenBuffers(1, &_proc.vbo); + glBindBuffer(GL_ARRAY_BUFFER, _proc.vbo); + + GLint pos_attrib = glGetAttribLocation(program, "position"); + glEnableVertexAttribArray(pos_attrib); + glVertexAttribPointer(pos_attrib, 4, GL_FLOAT, GL_FALSE, 0, NULL); + + glGenTextures(1, &tex); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, tex); + glUniform1i(glGetUniformLocation(program, "tex"), 0); + 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); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + + create_atlas(face, 28); + + glClearColor(1.0, 1.0, 1.0, 1.0); + return true; +} + +void TextMode::deinit() +{ + glprocess_release(&_proc); + _proc.program = 0; + //... +} + +void TextMode::render() +{ + glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); + + struct timeval tv; + gettimeofday(&tv, NULL); + if (!tv_start.tv_sec) tv_start = tv; + float t = (tv.tv_sec - tv_start.tv_sec) + (tv.tv_usec - tv_start.tv_usec) / 1000000.0; + + GLfloat bgcolor[] = { + float((glm::cos(t) + 1.0)/2.0), float((glm::sin(t)+1.0)/2.0), 0, 1 + }; + glUniform4fv(glGetUniformLocation(_proc.program, "bgcolor"), 1, bgcolor); + + float ps1 = 24.0, ps2 = 38.0; + float sx = 2.0 / _screenWidth, sy = 2.0 / _screenHeight; + + float x = -1.0, y = 1.0 - ps1 * sy; + render_text("this is freetype2 rendered text", x, y, sx, sy); + + x = -1.0, y = 1.0 - (ps1+ps2) * sy; + render_text("this is freetype2 rendered text again", x, y, sx, sy); + + GLfloat bgcolor2[] = { + 0, float((glm::cos(t) + 1.0)/2.0), float((glm::sin(t)+1.0)/2.0), 0.5 + }; + glUniform4fv(glGetUniformLocation(_proc.program, "bgcolor"), 1, bgcolor2); + x = -1.0 + 0.002, y = 1.0 - (ps1+ps2+ps2/3) * sy; + render_text("overrided transparent line", x, y, sx, sy); +} + diff --git a/atlas.h b/atlas.h new file mode 100644 index 0000000..162d431 --- /dev/null +++ b/atlas.h @@ -0,0 +1,41 @@ +#ifndef _ATLASH_H +#define _ATLASH_H + +#include "glutil.h" +#include "actionmode.h" + +#include +#include FT_FREETYPE_H + + +struct char_info_t { + float left, top; + float width, height; + float ax, ay; //advanced + float offset; // horizontal offset inside atlas +}; + +struct atlas_t { + float width, height; + struct char_info_t infos[128]; + int point_size; +}; + +struct text_mode_t { + struct atlas_t atlas; + GLProcess proc; +}; + +class TextMode: public ActionMode { + public: + bool init(int width, int height); + void deinit(); + void render(); + + private: + atlas_t _atlas; + void create_atlas(FT_Face face, int pointSize); + void render_text(const char *text, float x, float y, float sx, float sy); +}; + +#endif diff --git a/atlas_frag.glsl b/atlas_frag.glsl new file mode 100644 index 0000000..5a9cb78 --- /dev/null +++ b/atlas_frag.glsl @@ -0,0 +1,10 @@ +precision mediump float; +uniform vec4 bgcolor; +uniform sampler2D tex; + +varying vec2 texcoord; + +void main() +{ + gl_FragColor = vec4(1.0, 1.0, 1.0, texture2D(tex, texcoord).a) * bgcolor; +} diff --git a/atlas_vertex.glsl b/atlas_vertex.glsl new file mode 100644 index 0000000..8237ed4 --- /dev/null +++ b/atlas_vertex.glsl @@ -0,0 +1,7 @@ +attribute vec4 position; +varying vec2 texcoord; + +void main() { + gl_Position = vec4(position.xy, 0.0, 1.0); + texcoord = position.zw; +} diff --git a/driver.cc b/driver.cc index 4802882..7f5affe 100644 --- a/driver.cc +++ b/driver.cc @@ -13,44 +13,9 @@ using namespace std; -#include -#include - -#include -#include -#include - -#include - -#include -#include -#include - - -struct DisplayContext { - int fd; //drm device handle - EGLDisplay display; - EGLContext gl_context; - - GLuint vbo; - GLuint vertexShaderId, fragShaderId, program; - - drmModeModeInfo mode; - uint32_t conn; // connector id - uint32_t crtc; // crtc id - drmModeCrtc *saved_crtc; - - struct gbm_device *gbm; - struct gbm_surface *gbm_surface; - EGLSurface surface; - - struct gbm_bo *bo; - struct gbm_bo *next_bo; - uint32_t next_fb_id; - - bool pflip_pending; - bool cleanup; -}; +#include "scene.h" +#include "atlas.h" +#include "driver.h" static DisplayContext dc; @@ -63,135 +28,6 @@ static void err_quit(const char *fmt, ...) va_end(ap); } -static GLuint create_shader(GLenum type, const char *source) -{ - GLuint shader_id = glCreateShader(type); - if (!shader_id) { - return 0; - } - - glShaderSource(shader_id, 1, &source, NULL); - glCompileShader(shader_id); - - GLint compile_ret; - glGetShaderiv(shader_id, GL_COMPILE_STATUS, &compile_ret); - if (compile_ret == GL_FALSE) { - char buf[512]; - glGetShaderInfoLog(shader_id, sizeof buf - 1, NULL, buf); - fprintf(stderr, "%s\n", buf); - return 0; - } - - return shader_id; -} - - -static GLuint create_program(const char *vertexShader, const char *fragShader) -{ - dc.vertexShaderId = create_shader(GL_VERTEX_SHADER, vertexShader); - dc.fragShaderId = create_shader(GL_FRAGMENT_SHADER, fragShader); - if (dc.vertexShaderId == 0 || dc.fragShaderId == 0) { - err_quit("create_program failed\n"); - } - - GLuint program = glCreateProgram(); - glAttachShader(program, dc.vertexShaderId); - glAttachShader(program, dc.fragShaderId); - return program; -} - -static char* load_shader(const char* filename) -{ - string src; - string line; - ifstream ifs{filename}; - while (getline(ifs, line)) { - src += line + "\n"; - } - - // cerr << src << endl; - return strndup(src.c_str(), src.size()); -} - -static void init_gl(int argc, const char** argv) -{ - float width = dc.mode.hdisplay, height = dc.mode.vdisplay; - - char* vertex_shader = nullptr, *frag_shader = nullptr; - - if (argc == 3) { - vertex_shader = load_shader(argv[1]); - frag_shader = load_shader(argv[2]); - } else { - vertex_shader = load_shader("vertex_shader.glsl"); - frag_shader = load_shader("fragment_shader.glsl"); - } - - dc.program = create_program(vertex_shader, frag_shader); - free(vertex_shader); - free(frag_shader); - - glGenBuffers(1, &dc.vbo); - glBindBuffer(GL_ARRAY_BUFFER, dc.vbo); - - GLfloat vertex_data[] = { - -1.0, -1.0, - -1.0, 1.0, - 1.0, 1.0, - - 1.0, 1.0, - 1.0, -1.0, - -1.0, -1.0, - }; - - glBufferData(GL_ARRAY_BUFFER, sizeof vertex_data, vertex_data, GL_STATIC_DRAW); - - glLinkProgram(dc.program); - glUseProgram(dc.program); - - GLint pos_attrib = glGetAttribLocation(dc.program, "position"); - glEnableVertexAttribArray(pos_attrib); - glVertexAttribPointer(pos_attrib, 2, GL_FLOAT, GL_FALSE, 0, NULL); - - //projection - GLint projMId = glGetUniformLocation(dc.program, "projM"); - glm::mat4 projM = glm::perspective(60.0f, width / height, 1.0f, 10.0f); - glUniformMatrix4fv(projMId, 1, GL_FALSE, glm::value_ptr(projM)); - - //view - GLint viewMId = glGetUniformLocation(dc.program, "viewM"); - auto viewM = glm::lookAt( - glm::vec3(1.0f, 1.0f, 1.0f), - glm::vec3(0.0f, 0.0f, 0.0f), - glm::vec3(0.0f, 0.0f, 1.0f)); - glUniformMatrix4fv(viewMId, 1, GL_FALSE, glm::value_ptr(viewM)); - - auto resolution = glm::vec3(width, height, 1.0); - glUniform3fv(glGetUniformLocation(dc.program, "resolution"), - 1, glm::value_ptr(resolution)); - - glClearColor(0.0, 0.0, 0.0, 1.0); -} - -static struct timeval first_time = {0, 0}; - -static void render_scene(int width, int height) -{ - //glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); - glClear(GL_COLOR_BUFFER_BIT); - - struct timeval tm; - gettimeofday(&tm, NULL); - if (!first_time.tv_sec) first_time = tm; - - float timeval = (tm.tv_sec - first_time.tv_sec) + - (tm.tv_usec - first_time.tv_usec) / 1000000.0; - GLint time = glGetUniformLocation(dc.program, "time"); - glUniform1f(time, timeval); - - glDrawArrays(GL_TRIANGLES, 0, 6); -} - static void drm_fb_destroy_callback(struct gbm_bo *bo, void *data) { uint32_t fb_id = (uint32_t)(unsigned long)data; @@ -219,7 +55,7 @@ static void render() struct timeval tm_start, tm_end; gettimeofday(&tm_start ,NULL); - render_scene(dc.mode.hdisplay, dc.mode.vdisplay); + dc.action_mode->render(); if (!eglSwapBuffers(dc.display, dc.surface)) { printf("cannot swap buffers"); exit(-1); @@ -300,11 +136,6 @@ static void draw_loop() return; } else if (FD_ISSET(fd, &fds)) { - struct timeval tv_ev; - gettimeofday(&tv_ev, NULL); - float timeval = (tv_ev.tv_sec - first_time.tv_sec) + - (tv_ev.tv_usec - first_time.tv_usec) / 1000000.0; - std::cerr << "handle event at " << timeval << std::endl; drmHandleEvent(fd, &ev); } } @@ -467,10 +298,7 @@ static void setup_egl() static void cleanup() { - glDeleteBuffers(1, &dc.vbo); - glDeleteShader(dc.vertexShaderId); - glDeleteShader(dc.fragShaderId); - glDeleteProgram(dc.program); + dc.action_mode->deinit(); eglDestroySurface(dc.display, dc.surface); eglDestroyContext(dc.display, dc.gl_context); @@ -491,7 +319,11 @@ int main(int argc, const char* argv[]) { setup_drm(); setup_egl(); - init_gl(argc, argv); + + dc.action_mode = new TextMode; + if (!dc.action_mode->init(dc.mode.hdisplay, dc.mode.vdisplay)) { + return -1; + } if (!eglSwapBuffers(dc.display, dc.surface)) { printf("cannot swap buffers"); diff --git a/driver.h b/driver.h new file mode 100644 index 0000000..b7a04e7 --- /dev/null +++ b/driver.h @@ -0,0 +1,42 @@ +#ifndef _DRIVER_H +#define _DRIVER_H + +#include +#include + +//include gbm before gl header +#include +#include +#include + +#include + +#include "glutil.h" +#include "atlas.h" + + +struct DisplayContext { + int fd; //drm device handle + EGLDisplay display; + EGLContext gl_context; + + drmModeModeInfo mode; + uint32_t conn; // connector id + uint32_t crtc; // crtc id + drmModeCrtc *saved_crtc; + + struct gbm_device *gbm; + struct gbm_surface *gbm_surface; + EGLSurface surface; + + struct gbm_bo *bo; + struct gbm_bo *next_bo; + uint32_t next_fb_id; + + bool pflip_pending; + bool cleanup; + + ActionMode* action_mode; +}; + +#endif diff --git a/glutil.cc b/glutil.cc new file mode 100644 index 0000000..dc264c1 --- /dev/null +++ b/glutil.cc @@ -0,0 +1,86 @@ +#include +#include +#include + +using namespace std; + +#include "glutil.h" + +static string load_shader(const char* filename) +{ + ifstream ifs{filename}; + if (!ifs) { + cerr << "can not open file: " << filename << endl; + return ""; + } + + string src; + string line; + while (getline(ifs, line)) { + src += line + "\n"; + } + + return src; +} + +static GLuint create_shader(GLenum type, const char *source) +{ + GLuint shader_id = glCreateShader(type); + if (!shader_id) { + return 0; + } + + glShaderSource(shader_id, 1, &source, NULL); + glCompileShader(shader_id); + + GLint ret; + glGetShaderiv(shader_id, GL_COMPILE_STATUS, &ret); + if (ret == GL_FALSE) { + char buf[512]; + glGetShaderInfoLog(shader_id, sizeof buf - 1, NULL, buf); + cerr << buf << endl; + return 0; + } + + return shader_id; +} + +GLProcess* glprocess_create(const char *vertex_path, const char *frag_path) +{ + string vertex_shader = load_shader(vertex_path); + if (vertex_shader.empty()) { + return nullptr; + } + + string frag_shader = load_shader(frag_path); + if (frag_shader.empty()) { + return nullptr; + } + + + GLProcess* proc = new GLProcess; + proc->vertex_shader_id = create_shader(GL_VERTEX_SHADER, vertex_shader.c_str()); + proc->frag_shader_id= create_shader(GL_FRAGMENT_SHADER, frag_shader.c_str()); + if (proc->vertex_shader_id == 0 || proc->frag_shader_id == 0) { + delete proc; + return nullptr; + } + + GLuint program = glCreateProgram(); + glAttachShader(program, proc->vertex_shader_id); + glAttachShader(program, proc->frag_shader_id); + glLinkProgram(program); + //TODO: check link error + + + proc->program = program; + return proc; +} + +void glprocess_release(GLProcess* proc) +{ + glDeleteBuffers(1, &proc->vbo); + glDeleteShader(proc->vertex_shader_id); + glDeleteShader(proc->frag_shader_id); + glDeleteProgram(proc->program); +} diff --git a/glutil.h b/glutil.h new file mode 100644 index 0000000..3881279 --- /dev/null +++ b/glutil.h @@ -0,0 +1,16 @@ +#ifndef _GL_UTIL_H +#define _GL_UTIL_H + +#include +#include + +struct GLProcess { + GLuint program, vertex_shader_id, frag_shader_id; + GLuint vbo; +}; + +GLProcess* glprocess_create(const char *vertex_path, const char *frag_path); +void glprocess_release(GLProcess* proc); + + +#endif diff --git a/scene.cc b/scene.cc new file mode 100644 index 0000000..400c8ce --- /dev/null +++ b/scene.cc @@ -0,0 +1,89 @@ +#include +#include +#include +#include +#include + +#include +#include +#include + +using namespace std; + +#include "scene.h" + +#include +#include +#include + +bool SceneMode::init(int width, int height) +{ + _screenWidth = width, _screenHeight = height; + GLProcess* proc = glprocess_create("scene_vertex.glsl", "scene_frag.glsl"); + if (!proc) return false; + _proc = *proc; + + glGenBuffers(1, &_proc.vbo); + glBindBuffer(GL_ARRAY_BUFFER, _proc.vbo); + + GLfloat vertex_data[] = { + -1.0, -1.0, + -1.0, 1.0, + 1.0, 1.0, + + 1.0, 1.0, + 1.0, -1.0, + -1.0, -1.0, + }; + + glBufferData(GL_ARRAY_BUFFER, sizeof vertex_data, vertex_data, GL_STATIC_DRAW); + + glUseProgram(_proc.program); + + GLint pos_attrib = glGetAttribLocation(_proc.program, "position"); + glEnableVertexAttribArray(pos_attrib); + glVertexAttribPointer(pos_attrib, 2, GL_FLOAT, GL_FALSE, 0, NULL); + + //projection + GLint projMId = glGetUniformLocation(_proc.program, "projM"); + glm::mat4 projM = glm::perspective(60.0f, (float)_screenWidth / _screenHeight, 1.0f, 10.0f); + glUniformMatrix4fv(projMId, 1, GL_FALSE, glm::value_ptr(projM)); + + //view + GLint viewMId = glGetUniformLocation(_proc.program, "viewM"); + auto viewM = glm::lookAt( + glm::vec3(1.0f, 1.0f, 1.0f), + glm::vec3(0.0f, 0.0f, 0.0f), + glm::vec3(0.0f, 0.0f, 1.0f)); + glUniformMatrix4fv(viewMId, 1, GL_FALSE, glm::value_ptr(viewM)); + + auto resolution = glm::vec3(_screenWidth, _screenHeight, 1.0); + glUniform3fv(glGetUniformLocation(_proc.program, "resolution"), + 1, glm::value_ptr(resolution)); + + glClearColor(0.0, 0.0, 0.0, 1.0); + return true; +} + +void SceneMode::deinit() +{ + glprocess_release(&_proc); +} + +static struct timeval first_time = {0, 0}; +void SceneMode::render() +{ + glClear(GL_COLOR_BUFFER_BIT); + + struct timeval tm; + gettimeofday(&tm, NULL); + if (!first_time.tv_sec) first_time = tm; + + float timeval = (tm.tv_sec - first_time.tv_sec) + + (tm.tv_usec - first_time.tv_usec) / 1000000.0; + GLint time = glGetUniformLocation(_proc.program, "time"); + glUniform1f(time, timeval); + + glDrawArrays(GL_TRIANGLES, 0, 6); +} + diff --git a/scene.h b/scene.h new file mode 100644 index 0000000..67890dc --- /dev/null +++ b/scene.h @@ -0,0 +1,13 @@ +#ifndef _SCENE_H +#define _SCENE_H + +#include "actionmode.h" + +class SceneMode: public ActionMode { + public: + bool init(int width, int height); + void deinit(); + void render(); +}; + +#endif diff --git a/fragment_shader.glsl b/scene_frag.glsl similarity index 100% rename from fragment_shader.glsl rename to scene_frag.glsl diff --git a/vertex_shader.glsl b/scene_vertex.glsl similarity index 100% rename from vertex_shader.glsl rename to scene_vertex.glsl