diff options
Diffstat (limited to 'src/libjin/Graphics')
30 files changed, 1137 insertions, 325 deletions
diff --git a/src/libjin/Graphics/Bitmap.h b/src/libjin/Graphics/Bitmap.h index ab84388..af7f376 100644 --- a/src/libjin/Graphics/Bitmap.h +++ b/src/libjin/Graphics/Bitmap.h @@ -1,6 +1,6 @@ #ifndef __LIBJIN_BITMAP_H #define __LIBJIN_BITMAP_H -#include "../modules.h" +#include "../jin_configuration.h" #if LIBJIN_MODULES_RENDER #include "../Math/Vector2.hpp" @@ -16,6 +16,7 @@ namespace graphics public: static Bitmap* createBitmap(const void* imgData, size_t size); static Bitmap* createBitmap(int w, int h, Color color = Color::BLACK); + static void destroyBitmap(Bitmap* bitmap); static Bitmap* clone(const Bitmap* bitmap); ~Bitmap(); @@ -42,8 +43,8 @@ namespace graphics }; -} -} +} // graphics +} // jin #endif #endif
\ No newline at end of file diff --git a/src/libjin/Graphics/Canvas.cpp b/src/libjin/Graphics/Canvas.cpp index efcd12d..d34731a 100644 --- a/src/libjin/Graphics/Canvas.cpp +++ b/src/libjin/Graphics/Canvas.cpp @@ -1,4 +1,4 @@ -#include "../modules.h" +#include "../jin_configuration.h" #if LIBJIN_MODULES_RENDER #include "../utils/macros.h" @@ -26,36 +26,26 @@ namespace graphics Canvas::Canvas(int w, int h) : Drawable(w, h) { - vertCoord[0] = 0; vertCoord[1] = 0; - vertCoord[2] = 0; vertCoord[3] = h; - vertCoord[4] = w; vertCoord[5] = h; - vertCoord[6] = w; vertCoord[7] = 0; - - textCoord[0] = 0; textCoord[1] = 1; - textCoord[2] = 0; textCoord[3] = 0; - textCoord[4] = 1; textCoord[5] = 0; - textCoord[6] = 1; textCoord[7] = 1; - GLint current_fbo; glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, ¤t_fbo); /* generate a new render buffer object */ - glGenFramebuffers(1, &fbo); - glBindFramebuffer(GL_FRAMEBUFFER, fbo); + fbo = gl.genFrameBuffer(); + gl.bindFrameBuffer(fbo); /* generate texture save target */ - glGenTextures(1, &texture); - glBindTexture(GL_TEXTURE_2D, texture); + texture = gl.genTexture(); + gl.bindTexture(texture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); - glBindTexture(GL_TEXTURE_2D, 0); + gl.texImage(GL_RGBA8, w, h, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + gl.bindTexture(0); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0); GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); /* unbind framebuffer */ - glBindFramebuffer(GL_FRAMEBUFFER, current_fbo); + gl.bindFrameBuffer(current_fbo); } Canvas::~Canvas() @@ -74,25 +64,12 @@ namespace graphics { if (isBinded(canvas)) return; current = canvas; - glBindFramebuffer(GL_FRAMEBUFFER, canvas->fbo); - + gl.bindFrameBuffer(canvas->fbo); int w = canvas->size.w; int h = canvas->size.h; /* set view port to canvas */ glViewport(0, 0, w, h); - - /* set projection matrix */ - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glLoadIdentity(); - glOrtho(0, w, h, 0, -1, 1); - - /* set (model*view) matrix */ - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glLoadIdentity(); - - /* ready to draw */ + gl.ProjectionMatrix.setOrtho(0, w, 0, h, -1, 1); } /** @@ -107,25 +84,16 @@ namespace graphics current = DEFAULT_CANVAS; /* get window size as viewport */ Window* wnd = Window::get(); - int ww = wnd->getW(); - int wh = wnd->getH(); + int w = wnd->getW(); + int h = wnd->getH(); glBindFramebuffer(GL_FRAMEBUFFER, DEFAULT_CANVAS->fbo); - glViewport(0, 0, ww, wh); - - /* set projection matrix */ - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glLoadIdentity(); - glOrtho(0, ww, wh, 0, -1, 1); - - /* set (model*view) matrix */ - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glLoadIdentity(); - - /* ready to draw */ + /* set viewport on screen */ + glViewport(0, 0, w, h); + + gl.ProjectionMatrix.setOrtho(0, w, h, 0, -1, 1); + } } // render diff --git a/src/libjin/Graphics/Canvas.h b/src/libjin/Graphics/Canvas.h index a6a52ea..09ae7aa 100644 --- a/src/libjin/Graphics/Canvas.h +++ b/src/libjin/Graphics/Canvas.h @@ -1,6 +1,6 @@ #ifndef __LIBJIN_CANVAS_H #define __LIBJIN_CANVAS_H -#include "../modules.h" +#include "../jin_configuration.h" #if LIBJIN_MODULES_RENDER #include "drawable.h" @@ -29,6 +29,7 @@ namespace graphics GLuint fbo; + }; } // render diff --git a/src/libjin/Graphics/Color.h b/src/libjin/Graphics/Color.h index a5bc5d0..6f9e887 100644 --- a/src/libjin/Graphics/Color.h +++ b/src/libjin/Graphics/Color.h @@ -3,7 +3,7 @@ */ #ifndef __LIBJIN_COLOR_H #define __LIBJIN_COLOR_H -#include "../modules.h" +#include "../jin_configuration.h" #if LIBJIN_MODULES_RENDER #include "../utils/endian.h" @@ -13,6 +13,8 @@ namespace jin namespace graphics { + typedef unsigned char Channel; + class Color { public: @@ -46,6 +48,14 @@ namespace graphics a = c.a; } + void set(unsigned char _r, unsigned char _g, unsigned char _b, unsigned char _a) + { + r = _r; + g = _g; + b = _b; + a = _a; + } + void operator = (const Color& c) { r = c.r; @@ -64,7 +74,7 @@ namespace graphics return !(r == c.r && g == c.g && b == c.b && a == c.a); } - unsigned char r, g, b, a; + Channel r, g, b, a; //#if LIBJIN_BYTEORDER == LIBJIN_BIG_ENDIAN // unsigned char r, g, b, a; diff --git a/src/libjin/Graphics/Drawable.cpp b/src/libjin/Graphics/Drawable.cpp index 675c54d..9f52f0a 100644 --- a/src/libjin/Graphics/Drawable.cpp +++ b/src/libjin/Graphics/Drawable.cpp @@ -1,6 +1,7 @@ -#include "../modules.h" +#include "../jin_configuration.h" #if LIBJIN_MODULES_RENDER +#include "Shader.h" #include "drawable.h" #include "../math/matrix.h" #include <stdlib.h> @@ -15,6 +16,15 @@ namespace graphics , size(w, h) , anchor(0, 0) { + vertex_coords[0] = 0; vertex_coords[1] = 0; + vertex_coords[2] = 0; vertex_coords[3] = h; + vertex_coords[4] = w; vertex_coords[5] = h; + vertex_coords[6] = w; vertex_coords[7] = 0; + + texture_coords[0] = 0; texture_coords[1] = 0; + texture_coords[2] = 0; texture_coords[3] = 1; + texture_coords[4] = 1; texture_coords[5] = 1; + texture_coords[6] = 1; texture_coords[7] = 0; } Drawable::~Drawable() @@ -30,31 +40,17 @@ namespace graphics void Drawable::draw(int x, int y, float sx, float sy, float r) { - /* Must set textCoord and vertCoord before renderring */ - if (! textCoord||! vertCoord) return; - - static jin::math::Matrix t; - t.setTransformation(x, y, r, sx, sy, anchor.x, anchor.y); - - glBindTexture(GL_TEXTURE_2D, texture); - - /* push modle matrix */ - glPushMatrix(); - glMultMatrixf((const GLfloat*)t.getElements()); - - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - glTexCoordPointer(2, GL_FLOAT, 0, textCoord); - glVertexPointer(2, GL_FLOAT, 0, vertCoord); - glDrawArrays(GL_QUADS, 0, 4); - glDisableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - - /* pop the model matrix */ - glPopMatrix(); - - /* bind texture to default screen */ - glBindTexture(GL_TEXTURE_2D, 0); + gl.ModelMatrix.setTransformation(x, y, r, sx, sy, anchor.x, anchor.y); + + Shader* shader = Shader::getCurrentJSL(); + shader->sendMatrix4(Shader::MODEL_MATRIX, &gl.ModelMatrix); + shader->sendMatrix4(Shader::PROJECTION_MATRIX, &gl.ProjectionMatrix); + shader->bindVertexPointer(2, GL_FLOAT, 0, vertex_coords); + shader->bindUVPointer(2, GL_FLOAT, 0, texture_coords); + + gl.bindTexture(texture); + gl.drawArrays(GL_QUADS, 0, 4); + gl.bindTexture(0); } } // render diff --git a/src/libjin/Graphics/Drawable.h b/src/libjin/Graphics/Drawable.h index ff82365..c77068c 100644 --- a/src/libjin/Graphics/Drawable.h +++ b/src/libjin/Graphics/Drawable.h @@ -1,10 +1,10 @@ #ifndef __LIBJIN_DRAWABLE #define __LIBJIN_DRAWABLE -#include "../modules.h" +#include "../jin_configuration.h" #if LIBJIN_MODULES_RENDER #include "../math/Vector2.hpp" -#include "../3rdparty/GLee/GLee.h" +#include "OpenGL.h" namespace jin { @@ -27,12 +27,13 @@ namespace graphics static const int DRAWABLE_V_SIZE = 8; GLuint texture; + GLuint vbo; /* TODO: vertex buffer object */ /* GLuint vbo; */ jin::math::Vector2<unsigned int> size; jin::math::Vector2<int> anchor; - float vertCoord[DRAWABLE_V_SIZE]; - float textCoord[DRAWABLE_V_SIZE]; + float vertex_coords[DRAWABLE_V_SIZE]; + float texture_coords[DRAWABLE_V_SIZE]; }; diff --git a/src/libjin/Graphics/Font.cpp b/src/libjin/Graphics/Font.cpp index bb767db..a3a46dd 100644 --- a/src/libjin/Graphics/Font.cpp +++ b/src/libjin/Graphics/Font.cpp @@ -1,24 +1,28 @@ -#include "../modules.h" +#include "../jin_configuration.h" #if LIBJIN_MODULES_RENDER +#include "OpenGL.h" #include "font.h" #include <stdio.h> -#define STB_TRUETYPE_IMPLEMENTATION -#include "../3rdparty/stb/stb_truetype.h" #include "color.h" +#include "Shader.h" +#include "../Common/Array.hpp" namespace jin { namespace graphics { + #include "Shaders/font.shader.h" + using namespace std; using namespace jin::math; - + const int Font::TEXTURE_WIDTHS[] = { 128, 256, 256, 512, 512, 1024, 1024 }; const int Font::TEXTURE_HEIGHTS[] = { 128, 128, 256, 256, 512, 512, 1024 }; - static const char *ttf_utf8toCodepoint(const char *p, unsigned *res) { + /* utf8 byte string to unicode codepoint */ + static const char* utf8toCodepoint(const char *p, unsigned *res) { unsigned x, mask, shift; switch (*p & 0xf0) { case 0xf0: mask = 0x07; shift = 18; break; @@ -31,7 +35,6 @@ namespace graphics } x = (*p & mask) << shift; do { - /* Return early if we reach an unexpected NULL */ if (*(++p) == '\0') { *res = x; return p; @@ -43,80 +46,322 @@ namespace graphics return p + 1; } - /*static*/ Font* Font::createFont(const char* font, size_t size) + /* little endian unicode */ + static const char* unicodeLittleEndian(const char* p, unsigned* res) { } - /*static*/ Font* Font::createFont(const char* file) + /*static*/ Font* Font::createFont(FontData* fontData, unsigned int fontSzie) { - + Font* font; + try + { + font = new Font(fontData, fontSzie); + } + catch (...) + { + return nullptr; + } + return font; } - Font::Font() - : textureLevel(TEXTURE_SIZE_LEVEL_MAX) + void Font::destroyFont(Font* font) + { + if (font != nullptr) + delete font; + } + + Font::Font(FontData* f, unsigned int fontSize) + : cursor(0, 0) + , font(f) + , fontsize(fontSize) { - + font->pushFontsize(fontsize); + font->getVMetrics(&baseline, &descent); + estimateSize(); + font->popFontsize(); + /* create a default texture */ + createAtlas(); } - bool Font::createTexture() + /* estimate the size of atlas texture */ + void Font::estimateSize() { - GLuint t; - glGenTextures(1, &t); - glBindTexture(GL_TEXTURE_2D, t); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - /*Initialize the texture, attempting smaller sizes if initialization fails.*/ - bool initialized = false; - while (textureLevel >= 0) + for (int level = 0; level <= TEXTURE_SIZE_LEVEL_MAX; ++level) { - /*clear errors before initializing*/ - while (glGetError() != GL_NO_ERROR); - textureWidth = TEXTURE_WIDTHS[textureLevel]; - textureHeight = TEXTURE_HEIGHTS[textureLevel]; - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, textureWidth, textureHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); - initialized = (glGetError() == GL_NO_ERROR); - if (initialized || textureLevel <= 0) + if (descent * (descent*0.8) * 96 <= TEXTURE_WIDTHS[level] * TEXTURE_HEIGHTS[level]) + { + textureWidth = TEXTURE_WIDTHS[level]; + textureHeight = TEXTURE_HEIGHTS[level]; break; - --textureLevel; + } } - if (!initialized) + } + + Font::~Font() + { + map<unsigned int, Glyph*>::iterator it = glyphs.begin(); + for (; it != glyphs.end(); ++it) + { + delete it->second; + } + } + + GLuint Font::createAtlas() + { + GLuint t; + gl.flushError(); + t = gl.genTexture(); + gl.bindTexture(t); + gl.setTexParameter(GL_TEXTURE_MAG_FILTER, GL_LINEAR); + gl.setTexParameter(GL_TEXTURE_MIN_FILTER, GL_LINEAR); + gl.setTexParameter(GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + gl.setTexParameter(GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + gl.texImage(GL_RGBA8, textureWidth, textureHeight, GL_RGBA, GL_UNSIGNED_BYTE); + if (glGetError() != GL_NO_ERROR) { glDeleteTextures(1, &t); - glBindTexture(GL_TEXTURE_2D, 0); - return false; + gl.bindTexture(0); + return 0; } - textures.push_back(t); - glBindTexture(GL_TEXTURE_2D, 0); - return true; + atlases.push_back(t); + gl.bindTexture(0); + return t; + } + + void Font::print(const char* t, int x, int y, int lineheight, int spacing) + { + Page* page = typeset(t, lineheight, spacing); + print(page, x, y); + delete page; } - void Font::print(const char* text, int x, int y) + Page* Font::typeset(const char* text, int lineheight, int spacing) { - int len = strlen(text); - /* xy and uv list */ - vector<GlyphVertex> glyphvertices(len*4); - /* texture binded along with glyphvertices */ - vector<GlyphArrayDrawInfo> glyphinfolist; - float dx = 0; - float dy = 0; - //float lineheihgt = ; + // typesetting, for reducing draw call + const char* t = text; + Page* page = new Page(); + vector<GlyphArrayDrawInfo>& glyphinfolist = page->glyphinfolist; + vector<GlyphVertex>& glyphvertices = page->glyphvertices; + Vector2<int> p(0, 0); + Codepoint c; + int texture = -1; + Glyph* glyph = nullptr; + GlyphVertex vertex; + for (int i = 0; *t != NULL; i += 4) + { + t = utf8toCodepoint(t, &c); + if (c == 0x0D) + { + i -= 4; + continue; + } + /* new line */ + if (c == 0x0A) + { + p.y += lineheight; + p.x = 0; + i -= 4; + continue; + } + glyph = findGlyph(c); + if (texture != glyph->atlas) + { + GlyphArrayDrawInfo info; + info.start = i; + info.count = 0; + info.texture = glyph->atlas; + texture = glyph->atlas; + glyphinfolist.push_back(info); + } + glyphinfolist[glyphinfolist.size() - 1].count += 4; + Glyph::Bbox& bbox = glyph->bbox; + // 1 + vertex.x = p.x; vertex.y = p.y; + vertex.u = bbox.x; vertex.v = bbox.y; + glyphvertices.push_back(vertex); + // 2 + vertex.x = p.x; vertex.y = p.y + glyph->height; + vertex.u = bbox.x; vertex.v = bbox.y + bbox.height; + glyphvertices.push_back(vertex); + // 3 + vertex.x = p.x + glyph->width; vertex.y = p.y + glyph->height; + vertex.u = bbox.x + bbox.width; vertex.v = bbox.y + bbox.height; + glyphvertices.push_back(vertex); + // 4 + vertex.x = p.x + glyph->width; vertex.y = p.y; + vertex.u = bbox.x + bbox.width; vertex.v = bbox.y; + glyphvertices.push_back(vertex); + + p.x += glyph->width + spacing; + } + getTextBox(text, &page->width, &page->height, lineheight, spacing); + return page; } - /** - * unicodeȾļtextureϣglyphs - */ - Glyph* Font::addGlyph(unsigned int character) + void Font::print(const Page* page, int x, int y) { - GLuint texture = textures.back(); + Shader* shader = Shader::getCurrentJSL(); + const vector<GlyphArrayDrawInfo>& glyphinfolist = page->glyphinfolist; + const vector<GlyphVertex>& glyphvertices = page->glyphvertices; + gl.ModelMatrix.setTransformation(x, y, 0, 1, 1, 0, 0); + shader->sendMatrix4(Shader::MODEL_MATRIX, &gl.ModelMatrix); + shader->sendMatrix4(Shader::PROJECTION_MATRIX, &gl.ProjectionMatrix); + for (int i = 0; i < glyphinfolist.size(); ++i) + { + const GlyphArrayDrawInfo& info = glyphinfolist[i]; + shader->bindVertexPointer(2, GL_INT, sizeof(GlyphVertex), &glyphvertices[info.start].x); + shader->bindUVPointer(2, GL_FLOAT, sizeof(GlyphVertex), &glyphvertices[info.start].u); + gl.bindTexture(info.texture); + gl.drawArrays(GL_QUADS, 0, info.count); + gl.bindTexture(0); + } + } + int Font::getCharWidth(int c) + { + int adw, lsb; + font->pushFontsize(fontsize); + font->getHMetrics(c, &adw, &lsb); + font->popFontsize(); + return adw; } - Glyph* Font::findGlyph(unsigned int character) + int Font::getCharHeight(int c) + { + return descent; + } + + int Font::getTextWidth(const char* t, int spacing) + { + font->pushFontsize(fontsize); + int res = 0; + int tmp = 0; + const char *p = t; + while (*p) { + unsigned c; + p = utf8toCodepoint(p, &c); + if (*p == 0x0D) + continue; + if (*p == 0x0A) + { + tmp = 0; + continue; + } + tmp += getCharWidth(c) + spacing; + if (tmp > res) res = tmp; + } + font->popFontsize(); + return res; + } + + int Font::getTextHeight(const char* t, int lineheight) + { + font->pushFontsize(fontsize); + int res = 0; + bool newline = true; + while (*t) + { + unsigned c; + t = utf8toCodepoint(t, &c); + if (*t == 0x0A) + newline = true; + else if (*t == 0x0D); + else if (newline) + { + newline = false; + res += lineheight; + } + } + font->popFontsize(); + return res; + } + + void Font::getTextBox(const char* text, int* w, int* h, int lineheight, int spacing) + { + font->pushFontsize(fontsize); + *w = 0; + *h = 0; + int tmp = 0; + const char* p = text; + const char* pt = nullptr; + bool nl = true; + while (*p) { + unsigned c; + pt = p; + p = utf8toCodepoint(p, &c); + if (*pt == 0x0D) + continue; + if (*pt == 0x0A) + { + tmp = 0; + nl = true; + continue; + } + else if(nl) + { + nl = false; + *h += lineheight; + } + tmp += getCharWidth(c) + spacing; + if (tmp > *w) *w = tmp; + } + font->popFontsize(); + } + + Glyph* Font::bakeGlyph(unsigned int character) { + Glyph* glyph = (Glyph*)malloc(sizeof(Glyph)); + int w, h, xoff, yoff; + font->pushFontsize(fontsize); + GLuint atlas = atlases.back(); + const Color* bitmap = font->getCodepointBitmap(character, &w, &h, &xoff, &yoff); + int adw, lsb; + { + font->getHMetrics(character, &adw, &lsb); + font->popFontsize(); + if (cursor.x + adw > textureWidth ) + { + cursor.x = 0; + cursor.y += descent; + if (cursor.y + descent * 2 > textureHeight) + { + /* create new atlas */ + atlas = createAtlas(); + cursor.y = 0; + } + } + gl.bindTexture(atlas); + gl.texSubImage(cursor.x + xoff, cursor.y + yoff + baseline, w, h, GL_RGBA, GL_UNSIGNED_BYTE, bitmap); + gl.bindTexture(); + delete[] bitmap; + } + glyph->atlas = atlas; + glyph->bbox.x = cursor.x / (float)textureWidth; + glyph->bbox.y = cursor.y / (float)textureHeight; + glyph->bbox.width = adw / (float)textureWidth; + glyph->bbox.height = descent / (float)textureHeight; + glyph->width = adw; + glyph->height = descent; + glyphs.insert(std::pair<unsigned int, Glyph*>(character, glyph)); + cursor.x += adw; + return glyph; + } + + Glyph* Font::findGlyph(unsigned int character) + { + map<unsigned int, Glyph*>::iterator it = glyphs.find(character); + if (it != glyphs.end()) + { + return it->second; + } + else + { + Glyph* glyph = bakeGlyph(character); + return glyph; + } } } // graphics diff --git a/src/libjin/Graphics/Font.h b/src/libjin/Graphics/Font.h index 10fd242..2bd51a5 100644 --- a/src/libjin/Graphics/Font.h +++ b/src/libjin/Graphics/Font.h @@ -1,79 +1,100 @@ #ifndef __LIBJIN_FONT_H #define __LIBJIN_FONT_H -#include "../modules.h" +#include "../jin_configuration.h" #if LIBJIN_MODULES_RENDER #include <vector> #include <map> #include "drawable.h" -#include "../3rdparty/stb/stb_truetype.h" +#include "FontData.h" #include "../math/quad.h" namespace jin { namespace graphics { - /** - * original from love2d font and graphics modules - * the basic idea is storing glyphs in several mipmap - * http://www.ruanyifeng.com/blog/2007/10/ascii_unicode_and_utf-8.html - */ - + struct GlyphVertex { - float x, y; // screen coordinates - float u, v; // texture coordinates + int x, y; // screen coordinates + float u, v; // texture uv }; - /* track when to change texutre binded in render array */ - /* casue switch texture is expensive */ - /* std::vector<GlyphVertex> list */ struct GlyphArrayDrawInfo { - GLuint texture; - int startvertex; - int vertexcount; + GLuint texture; // atlas + unsigned int start; // glyph vertex indecies + unsigned int count; // glyph vertex count }; - /* glyph texture */ struct Glyph { - GLuint texture; // texture where this glyph rendered - int spacing; // spacing of glyph - GlyphVertex vertices[4]; // quad of glyph render region + GLuint atlas; + /* normalized coordinates */ + struct Bbox + { + float x, y; + float width, height; + } bbox; + /* glyph size in pixel */ + unsigned int width, height; + }; + + struct Page + { + std::vector<GlyphArrayDrawInfo> glyphinfolist; + std::vector<GlyphVertex> glyphvertices; + int width, height; }; class Font { - public: - static Font* createFont(const char* file); - static Font* createFont(const char* data, size_t size); + public: + typedef unsigned int Codepoint; + + static Font* createFont(FontData* fontData, unsigned int fontSzie); + static void destroyFont(Font* font); - void print(const char* text, int x, int y); + Page* typeset(const char* text, int lineheight, int spacing); + void print(const char* text, int x, int y, int lineheight, int spacing = 0); + void print(const Page* page, int x, int y); + //Bitmap* bake(const char* text); +#if defined(font_debug) + void drawAtlas(); +#endif + ~Font(); private: - /* font atlas levels */ static const int TEXTURE_SIZE_LEVELS_COUNT = 7; static const int TEXTURE_SIZE_LEVEL_MAX = TEXTURE_SIZE_LEVELS_COUNT - 1; static const int TEXTURE_WIDTHS[TEXTURE_SIZE_LEVELS_COUNT]; static const int TEXTURE_HEIGHTS[TEXTURE_SIZE_LEVELS_COUNT]; - static const int SPACES_PER_TAB = 4; - - /* create a new mipmap to render glyph and push it on textures */ - bool createTexture(); - /* create a glyph for a unicode and return it */ - Glyph* addGlyph(unsigned int character); - /* find glyph by unicode */ - Glyph* findGlyph(unsigned int character); - - /* list of textures where glyphs rendered, always operate the last one */ - /* map character to its render area */ - std::vector<GLuint> textures; - std::map<unsigned int, Glyph*> glyphs; - /* mipmap size level */ - int textureLevel; - int textureWidth; + + Font(FontData* font, Codepoint fontSize); + + void estimateSize(); + GLuint createAtlas(); + Glyph* bakeGlyph(Codepoint character); + Glyph* findGlyph(Codepoint character); + + int getCharWidth(int c); + int getCharHeight(int c); + int getTextWidth(const char* text, int spacing = 0); + int getTextHeight(const char* text, int lineheight); + void getTextBox(const char* text, int* w, int* h, int lineheight, int spacing = 0); + + int textureWidth; int textureHeight; + std::vector<GLuint> atlases; + /* map unicode codepoint to glyph */ + std::map<Codepoint, Glyph*> glyphs; + FontData* font; + const unsigned int fontsize; + int baseline; + int descent; + + /* cursor helped render to texture */ + math::Vector2<float> cursor; }; diff --git a/src/libjin/Graphics/FontData.cpp b/src/libjin/Graphics/FontData.cpp new file mode 100644 index 0000000..1b66b12 --- /dev/null +++ b/src/libjin/Graphics/FontData.cpp @@ -0,0 +1,115 @@ +#include "FontData.h" +#define STB_TRUETYPE_IMPLEMENTATION +#include "../3rdparty/stb/stb_truetype.h" +#include <stdio.h> + +namespace jin +{ +namespace graphics +{ + + FontData* FontData::createFontData(const unsigned char* data, unsigned int size) + { + FontData* font = nullptr; + try + { + font = new FontData(data, size); + return font; + } + catch (...) + { + return nullptr; + } + } + + FontData::FontData(const unsigned char* d, unsigned int s) + { + raw.size = s; + raw.data = (unsigned char*)malloc(s); + memcpy(raw.data, d, s); + if (!stbtt_InitFont(&info, (const unsigned char*)raw.data, 0)) + { + delete raw.data; + throw 0; + } + /* push default fontsize */ + pushFontsize(FONT_SIZE); + } + + FontData::~FontData() + { + free(raw.data); + } + + /* + * (0, 0) + * +--------------+ ascent + * | +--------+ | + * | | | | + * | | bitmap | | + * +--|--------|--+ baseline + * | +--------+ | + * +--|-----------+ decent + * | | + * leftSideBearing | + * | + * advanceWidth + */ + void FontData::getVMetrics(int* baseline, int* descent) + { + float scale = scales.back(); + int ascent; + stbtt_GetFontVMetrics(&info, &ascent, descent, 0); + *baseline = (int)(ascent*scale) + 1; // slight adjustment + *descent = *baseline - (int)(*descent*scale) + 1; + } + + void FontData::getHMetrics(unsigned int codepoint, int* advanceWidth, int* leftSideBearing) + { + float scale = scales.back(); + int adw, lsb; + stbtt_GetCodepointHMetrics(&info, codepoint, &adw, &lsb); + *advanceWidth = (int)(adw*scale); + *leftSideBearing = (int)(lsb*scale); + } + + void FontData::pushFontsize(unsigned int fs) + { + float sc = stbtt_ScaleForPixelHeight(&info, fs); + scales.push_back(sc); + } + + void FontData::popFontsize() + { + /* always keep default font size on the bottom of stack */ + if(scales.size() > 1) + scales.pop_back(); + } + + Channel* FontData::getCodepointBitmapAlpha(unsigned int codepoint, int* width, int* height, int* xoff, int* yoff) const + { + float scale = scales.back(); + Channel* bitmap = stbtt_GetCodepointBitmap(&info, scale, scale, codepoint, width, height, xoff, yoff); + return bitmap; + } + + Color* FontData::getCodepointBitmap(unsigned int codepoint, int* width, int* height, int* xoff, int* yoff) const + { + float scale = scales.back(); + Channel* bitmap = stbtt_GetCodepointBitmap(&info, scale, scale, codepoint, width, height, xoff, yoff); + int w = *width, h = *height; + //int xo = *xoff, yo = *yoff; + Color* bitmap32 = new Color[w*h]; + for (int y = 0; y < h; ++y) + { + for (int x = 0; x < w; ++x) + { + bitmap32[x + y * w].set(0xff, 0xff, 0xff, bitmap[x + y * w]); + } + } + free(bitmap); + return bitmap32; + } + +} +}
\ No newline at end of file diff --git a/src/libjin/Graphics/FontData.h b/src/libjin/Graphics/FontData.h new file mode 100644 index 0000000..c75b9a1 --- /dev/null +++ b/src/libjin/Graphics/FontData.h @@ -0,0 +1,45 @@ +#ifndef __LIBJIN_FONTDATA_H +#define __LIBJIN_FONTDATA_H +#include "../3rdparty/stb/stb_truetype.h" +#include "Color.h" +#include <vector> + +namespace jin +{ +namespace graphics +{ + + class FontData + { + public: + static FontData* createFontData(const unsigned char* data, unsigned int size); + + ~FontData(); + + void pushFontsize(unsigned int fontsize); + void popFontsize(); + + Channel* getCodepointBitmapAlpha(unsigned int codepoint, int* width, int* height, int* xoff, int* yoff) const; + Color* getCodepointBitmap(unsigned int codepoint, int* width, int* height, int* xoff, int* yoff) const; + void getVMetrics(int* baseline, int* descent); + void getHMetrics(unsigned int codepoint, int* advanceWidth, int* leftSideBearing); + + private: + static const unsigned int FONT_SIZE = 12; + + FontData(const unsigned char* data, unsigned int size); + + stbtt_fontinfo info; + struct + { + unsigned char* data; + unsigned int size; + } raw; + std::vector<float> scales; + + }; + +} +} + +#endif
\ No newline at end of file diff --git a/src/libjin/Graphics/Graphics.h b/src/libjin/Graphics/Graphics.h index dfd6048..a4bf98b 100644 --- a/src/libjin/Graphics/Graphics.h +++ b/src/libjin/Graphics/Graphics.h @@ -1,11 +1,12 @@ #ifndef __LIBJIN_GRAPHICS_H #define __LIBJIN_GRAPHICS_H -#include "../modules.h" +#include "../jin_configuration.h" #if LIBJIN_MODULES_RENDER #include "canvas.h" #include "color.h" -#include "font.h" +#include "FontData.h" +#include "Font.h" #include "Shapes.h" #include "texture.h" #include "Shader.h" diff --git a/src/libjin/Graphics/Mesh.cpp b/src/libjin/Graphics/Mesh.cpp new file mode 100644 index 0000000..503a189 --- /dev/null +++ b/src/libjin/Graphics/Mesh.cpp @@ -0,0 +1,11 @@ +#include "Mesh.h" + +namespace jin +{ +namespace graphics +{ + + + +} +}
\ No newline at end of file diff --git a/src/libjin/Graphics/Mesh.h b/src/libjin/Graphics/Mesh.h new file mode 100644 index 0000000..d0bb93e --- /dev/null +++ b/src/libjin/Graphics/Mesh.h @@ -0,0 +1,17 @@ +#ifndef __LIBJIN_MESH_H +#define __LIBJIN_MESH_H + +namespace jin +{ +namespace graphics +{ + + class Mesh + { + + }; + +} +} + +#endif
\ No newline at end of file diff --git a/src/libjin/Graphics/OpenGL.cpp b/src/libjin/Graphics/OpenGL.cpp new file mode 100644 index 0000000..f7bed9f --- /dev/null +++ b/src/libjin/Graphics/OpenGL.cpp @@ -0,0 +1,12 @@ +#define OGL2D_IMPLEMENT +#include "OpenGL.h" + +namespace jin +{ +namespace graphics +{ + + OpenGL gl; + +} +} diff --git a/src/libjin/Graphics/OpenGL.h b/src/libjin/Graphics/OpenGL.h new file mode 100644 index 0000000..51395ba --- /dev/null +++ b/src/libjin/Graphics/OpenGL.h @@ -0,0 +1,29 @@ +#ifndef __LIBJIN_OPENGL_H +#define __LIBJIN_OPENGL_H +#include "../3rdparty/GLee/GLee.h" +#include "../3rdparty/ogl/OpenGL.h" +#include "../Math/Matrix.h" + +namespace jin +{ +namespace graphics +{ + + class OpenGL : public ogl2d::OpenGL + { + public: + math::Matrix ProjectionMatrix; + math::Matrix ModelMatrix; + + OpenGL() : ogl2d::OpenGL() + { + } + + }; + + extern OpenGL gl; + +} +} + +#endif
\ No newline at end of file diff --git a/src/libjin/Graphics/Shader.cpp b/src/libjin/Graphics/Shader.cpp index e882d35..6c8e3b5 100644 --- a/src/libjin/Graphics/Shader.cpp +++ b/src/libjin/Graphics/Shader.cpp @@ -1,6 +1,9 @@ -#include "../modules.h" +#include <regex> +#include "../jin_configuration.h" #if LIBJIN_MODULES_RENDER +#include <iostream> + #include "../utils/macros.h" #include "Shader.h" #include "../Filesystem/Buffer.h" @@ -10,6 +13,7 @@ namespace graphics { using namespace jin::filesystem; + using namespace std; /** * default_texture @@ -17,7 +21,14 @@ namespace graphics * SHADER_FORMAT_SIZE * formatShader */ - #include "base.shader.h" + #include "Shaders/base.shader.h" + #include "Shaders/default.shader.h" + + const char* Shader::PROJECTION_MATRIX = "_projectionMatrix_"; + const char* Shader::MODEL_MATRIX = "_modelMatrix_"; + const char* Shader::MAIN_TEXTURE = "_main_texture_"; + const char* Shader::VERTEX_COORDS = "_vert_coord_"; + const char* Shader::TEXTURE_COORDS = "_tex_coord_"; /** * https://stackoverflow.com/questions/27941496/use-sampler-without-passing-through-value @@ -44,46 +55,84 @@ namespace graphics */ const int DEFAULT_TEXTURE_UNIT = 0; - /*static*/ JSLProgram* JSLProgram::currentJSLProgram = nullptr; + /*static*/ Shader* Shader::currentShader = nullptr; - JSLProgram* JSLProgram::createJSLProgram(const char* program) + Shader* Shader::createShader(const string& program) { - JSLProgram* jsl = nullptr; + Shader* shader = nullptr; try { - jsl = new JSLProgram(program); + shader = new Shader(program); } catch(...) { return nullptr; } - return jsl; + return shader; } - JSLProgram::JSLProgram(const char* program) + Shader::Shader(const string& program) : currentTextureUnit(DEFAULT_TEXTURE_UNIT) { - Buffer b = Buffer(strlen(program) + SHADER_FORMAT_SIZE); - formatShader((char*)b.data, program); - GLuint shader = glCreateShader(GL_FRAGMENT_SHADER); - glShaderSource(shader, 1, (const GLchar**)&b.data, NULL); - glCompileShader(shader); + if (!compile(program)) + throw 0; + } + + Shader::~Shader() + { + if (currentShader == this) + unuse(); + } + + bool Shader::compile(const string& program) + { + int loc_VERTEX_SHADER = program.find("#VERTEX_SHADER"); + int loc_END_VERTEX_SHADER = program.find("#END_VERTEX_SHADER"); + int loc_FRAGMENT_SHADER = program.find("#FRAGMENT_SHADER"); + int loc_END_FRAGMENT_SHADER = program.find("#END_FRAGMENT_SHADER"); + if (loc_VERTEX_SHADER == string::npos + || loc_END_VERTEX_SHADER == string::npos + || loc_FRAGMENT_SHADER == string::npos + || loc_END_FRAGMENT_SHADER == string::npos + ) + return false; + int p = loc_VERTEX_SHADER + strlen("#VERTEX_SHADER"); + string vertex_shader = program.substr(p, loc_END_VERTEX_SHADER - p); + Buffer vbuffer = Buffer(vertex_shader.length() + BASE_VERTEX_SHADER_SIZE); + formatVertexShader((char*)vbuffer.data, vertex_shader.c_str()); + p = loc_FRAGMENT_SHADER + strlen("#FRAGMENT_SHADER"); + string fragment_shader = program.substr(p, loc_END_FRAGMENT_SHADER - p); + Buffer fbuffer = Buffer(fragment_shader.length() + BASE_FRAGMENT_SHADER_SIZE); + formatFragmentShader((char*)fbuffer.data, fragment_shader.c_str()); + /* compile */ GLint success; - glGetShaderiv(shader, GL_COMPILE_STATUS, &success); + GLuint vshader = glCreateShader(GL_VERTEX_SHADER); + glShaderSource(vshader, 1, (const GLchar**)&vbuffer.data, NULL); + glCompileShader(vshader); + glGetShaderiv(vshader, GL_COMPILE_STATUS, &success); + //std::cout << (char*)vbuffer.data << std::endl; + //Buffer log = Buffer(1024); + //int len; + //glGetShaderInfoLog(vshader, sizeof(log), &len, (GLchar*)log.data); + //std::cout << (char*)log.data << std::endl; if (success == GL_FALSE) - throw 0; + return false; + GLuint fshader = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(fshader, 1, (const GLchar**)&fbuffer.data, NULL); + glCompileShader(fshader); + glGetShaderiv(fshader, GL_COMPILE_STATUS, &success); + //std::cout << (char*)fbuffer.data << std::endl; + if (success == GL_FALSE) + return false; pid = glCreateProgram(); - glAttachShader(pid, shader); + glAttachShader(pid, vshader); + glAttachShader(pid, fshader); glLinkProgram(pid); glGetProgramiv(pid, GL_LINK_STATUS, &success); + //glGetProgramInfoLog(pid, 1024, &len, (GLchar*)log.data); + //std::cout << (char*)log.data << std::endl; if (success == GL_FALSE) - throw 0; - } - - JSLProgram::~JSLProgram() - { - if (currentJSLProgram == this) - unuse(); + throw false; } static inline GLint getMaxTextureUnits() @@ -93,22 +142,20 @@ namespace graphics return maxTextureUnits; } - void JSLProgram::use() + void Shader::use() { glUseProgram(pid); - currentJSLProgram = this; - /* bind default texture */ - int loc = glGetUniformLocation(pid, default_texture); - glUniform1i(loc, DEFAULT_TEXTURE_UNIT); + currentShader = this; + sendInt(Shader::MAIN_TEXTURE, DEFAULT_TEXTURE_UNIT); } - /*static*/ void JSLProgram::unuse() + /*static*/ void Shader::unuse() { glUseProgram(0); - currentJSLProgram = nullptr; + currentShader = nullptr; } - GLint JSLProgram::claimTextureUnit(const std::string& name) + GLint Shader::claimTextureUnit(const std::string& name) { std::map<std::string, GLint>::iterator unit = textureUnits.find(name); if (unit != textureUnits.end()) @@ -121,10 +168,17 @@ namespace graphics } #define checkJSL() \ - if (currentJSLProgram != this) \ + if (currentShader != this) \ return - void JSLProgram::sendFloat(const char* variable, float number) + void Shader::sendInt(const char* name, int value) + { + checkJSL(); + int loc = glGetUniformLocation(pid, name); + glUniform1i(loc, value); + } + + void Shader::sendFloat(const char* variable, float number) { checkJSL(); int loc = glGetUniformLocation(pid, variable); @@ -145,7 +199,7 @@ namespace graphics * TextureUnit textureUnits[GL_MAX_TEXTURE_IMAGE_UNITS] * GLuint currentTextureUnit = 0; */ - void JSLProgram::sendTexture(const char* variable, const Texture* tex) + void Shader::sendTexture(const char* variable, const Texture* tex) { checkJSL(); GLint location = glGetUniformLocation(pid, variable); @@ -157,14 +211,13 @@ namespace graphics // TODO: 쳣 return; } + gl.activeTexUnit(unit); glUniform1i(location, unit); - glActiveTexture(GL_TEXTURE0 + unit); - glBindTexture(GL_TEXTURE_2D, tex->getTexture()); - - glActiveTexture(GL_TEXTURE0); + gl.bindTexture(tex->getTexture()); + gl.activeTexUnit(0); } - void JSLProgram::sendCanvas(const char* variable, const Canvas* canvas) + void Shader::sendCanvas(const char* variable, const Canvas* canvas) { checkJSL(); GLint location = glGetUniformLocation(pid, variable); @@ -178,33 +231,33 @@ namespace graphics } glUniform1i(location, unit); glActiveTexture(GL_TEXTURE0 + unit); - glBindTexture(GL_TEXTURE_2D, canvas->getTexture()); + gl.bindTexture(canvas->getTexture()); glActiveTexture(GL_TEXTURE0); } - void JSLProgram::sendVec2(const char* name, float x, float y) + void Shader::sendVec2(const char* name, float x, float y) { checkJSL(); int loc = glGetUniformLocation(pid, name); glUniform2f(loc, x, y); } - void JSLProgram::sendVec3(const char* name, float x, float y, float z) + void Shader::sendVec3(const char* name, float x, float y, float z) { checkJSL(); int loc = glGetUniformLocation(pid, name); glUniform3f(loc, x, y, z); } - void JSLProgram::sendVec4(const char* name, float x, float y, float z, float w) + void Shader::sendVec4(const char* name, float x, float y, float z, float w) { checkJSL(); int loc = glGetUniformLocation(pid, name); glUniform4f(loc, x, y, z, w); } - void JSLProgram::sendColor(const char* name, const Color* col) + void Shader::sendColor(const char* name, const Color* col) { checkJSL(); int loc = glGetUniformLocation(pid, name); @@ -216,6 +269,26 @@ namespace graphics ); } + void Shader::sendMatrix4(const char* name, const math::Matrix* mat4) + { + int loc = glGetUniformLocation(pid, name); + glUniformMatrix4fv(loc, 1, GL_FALSE, mat4->getElements()); + } + + void Shader::bindVertexPointer(int n, GLenum type, GLsizei stride, const GLvoid * pointers) + { + GLint loc = glGetAttribLocation(pid, VERTEX_COORDS); + glEnableVertexAttribArray(0); + glVertexAttribPointer(loc, n, type, GL_FALSE, stride, pointers); + } + + void Shader::bindUVPointer(int n, GLenum type, GLsizei stride, const GLvoid * pointers) + { + GLint loc = glGetAttribLocation(pid, TEXTURE_COORDS); + glEnableVertexAttribArray(1); + glVertexAttribPointer(loc, n, type, GL_FALSE, stride, pointers); + } + } // graphics } // jin diff --git a/src/libjin/Graphics/Shader.h b/src/libjin/Graphics/Shader.h index 83a2831..2ea9e04 100644 --- a/src/libjin/Graphics/Shader.h +++ b/src/libjin/Graphics/Shader.h @@ -1,6 +1,6 @@ #ifndef __LIBJIN_JSL_H #define __LIBJIN_JSL_H -#include "../modules.h" +#include "../jin_configuration.h" #if LIBJIN_MODULES_RENDER #include <string> @@ -15,30 +15,42 @@ namespace jin namespace graphics { - /* Jin Shader Language Program*/ - class JSLProgram + /* Jin Shading Language Program*/ + class Shader { public: - static JSLProgram* createJSLProgram(const char* program); - static inline JSLProgram* getCurrentJSL() { return currentJSLProgram; } + static Shader* createShader(const std::string& program); + static inline Shader* getCurrentJSL() { return currentShader; } static void unuse(); - virtual ~JSLProgram(); + static const char* PROJECTION_MATRIX; + static const char* MODEL_MATRIX; + static const char* MAIN_TEXTURE; + static const char* VERTEX_COORDS; + static const char* TEXTURE_COORDS; + + virtual ~Shader(); void use(); void sendFloat(const char* name, float number); void sendTexture(const char* name, const Texture* image); + void sendInt(const char* name, int value); void sendVec2(const char* name, float x, float y); void sendVec3(const char* name, float x, float y, float z); void sendVec4(const char* name, float x, float y, float z, float w); void sendCanvas(const char* name, const Canvas* canvas); void sendColor(const char* name, const Color* col); + void sendMatrix4(const char* name, const math::Matrix* mat4); + + void bindVertexPointer(int n, GLenum type, GLsizei stride, const GLvoid * pointers); + void bindUVPointer(int n, GLenum type, GLsizei stride, const GLvoid * pointers); protected: - static JSLProgram* currentJSLProgram; + static Shader* currentShader; GLint claimTextureUnit(const std::string& name); - JSLProgram(const char* program); + Shader(const std::string& program); + bool compile(const std::string& program); GLuint pid; GLint currentTextureUnit; diff --git a/src/libjin/Graphics/Shaders/base.shader.h b/src/libjin/Graphics/Shaders/base.shader.h new file mode 100644 index 0000000..3790a47 --- /dev/null +++ b/src/libjin/Graphics/Shaders/base.shader.h @@ -0,0 +1,104 @@ +/* + * https://stackoverflow.com/questions/10868958/what-does-sampler2d-store + * The sampler2D is bound to a texture unit. The glUniform call binds it to texture + * unit zero. The glActiveTexture call is only needed if you are going to use multiple + * texture units (because GL_TEXTURE0 is the default anyway). +*/ +/* +#VERTEX_SHADER + +vertex vert(vertex v) +{ + return v; +} + +#END_VERTEX_SHADER + +#FRAGMENT_SHADER + +vec4 frag(vec4 color, Texture tex, vertex v) +{ + return Texel(tex, v.uv); +} + +#END_FRAGMENT_SHADER + +*/ + +static const char* base_shared = R"( +#define Number float +#define Texture sampler2D +#define Canvas sampler2D +#define Color vec4 +#define Vec2 vec2 +#define Vec3 vec3 +#define Vec4 vec4 + +#define texel texture2D + +struct Vertex +{ + vec2 xy; + vec2 uv; +}; + +)"; + +static const int BASE_SHARED_SIZE = strlen(base_shared); + +static const char* base_vertex = R"( +#version 130 core + +%s + +uniform mat4 _projectionMatrix_; +uniform mat4 _modelMatrix_; + +in vec2 _vert_coord_; +in vec2 _tex_coord_; + +out vec4 _color; +out vec2 _xy; +out vec2 _uv; + +%s + +void main() +{ + vec4 v = _modelMatrix_ * vec4(_vert_coord_, 0, 1.0); + Vertex _v = vert(Vertex(v.xy, _tex_coord_)); + gl_Position = _projectionMatrix_ * vec4(_v.xy, 0, 1.0f); + _color = gl_Color; + _xy = _v.xy; + _uv = _v.uv; +} +)"; + +static const int BASE_VERTEX_SHADER_SIZE = strlen(base_vertex) + BASE_SHARED_SIZE; + +#define formatVertexShader(buf, program) sprintf(buf,base_vertex, base_shared, program) + +static const char* base_fragment = R"( +#version 130 core + +%s + +uniform Texture _main_texture_; + +in vec4 _color; +in vec2 _xy; +in vec2 _uv; + +out vec4 _outColor_; + +%s + +void main() +{ + _outColor_ = frag(_color, _main_texture_, Vertex(_xy, _uv)); +} +)"; + +static const int BASE_FRAGMENT_SHADER_SIZE = strlen(base_fragment) + BASE_SHARED_SIZE; + +#define formatFragmentShader(buf, program) sprintf(buf, base_fragment, base_shared, program) diff --git a/src/libjin/Graphics/Shaders/default.shader.h b/src/libjin/Graphics/Shaders/default.shader.h new file mode 100644 index 0000000..f0175d7 --- /dev/null +++ b/src/libjin/Graphics/Shaders/default.shader.h @@ -0,0 +1,21 @@ +// Ĭshader +static const char* default_shader = R"( + +#VERTEX_SHADER + +Vertex vert(Vertex v) +{ + return v; +} + +#END_VERTEX_SHADER + +#FRAGMENT_SHADER + +Color frag(Color col, Texture tex, Vertex v) +{ + return col; +} + +#END_FRAGMENT_SHADER +)";
\ No newline at end of file diff --git a/src/libjin/Graphics/Shaders/font.shader.h b/src/libjin/Graphics/Shaders/font.shader.h new file mode 100644 index 0000000..e04c225 --- /dev/null +++ b/src/libjin/Graphics/Shaders/font.shader.h @@ -0,0 +1,21 @@ +// shader +static const char* font_shader = R"( + +#VERTEX_SHADER + +Vertex vert(Vertex v) +{ + return v; +} + +#END_VERTEX_SHADER + +#FRAGMENT_SHADER + +Color frag(Color col, Texture tex, Vertex v) +{ + return Color(col.rgb, texel(tex, v.uv).a); +} + +#END_FRAGMENT_SHADER +)";
\ No newline at end of file diff --git a/src/libjin/Graphics/Shaders/texture.shader.h b/src/libjin/Graphics/Shaders/texture.shader.h new file mode 100644 index 0000000..d1fc86f --- /dev/null +++ b/src/libjin/Graphics/Shaders/texture.shader.h @@ -0,0 +1,21 @@ +// ͼshader +static const char* texture_shader = R"( + +#VERTEX_SHADER + +Vertex vert(Vertex v) +{ + return v; +} + +#END_VERTEX_SHADER + +#FRAGMENT_SHADER + +Color frag(Color col, Texture tex, Vertex v) +{ + return col * texel(tex, v.uv); +} + +#END_FRAGMENT_SHADER +)";
\ No newline at end of file diff --git a/src/libjin/Graphics/Shapes.cpp b/src/libjin/Graphics/Shapes.cpp index 2cb33a2..cf47e00 100644 --- a/src/libjin/Graphics/Shapes.cpp +++ b/src/libjin/Graphics/Shapes.cpp @@ -1,6 +1,7 @@ -#include "../modules.h" +#include "../jin_configuration.h" #if LIBJIN_MODULES_RENDER +#include "Shader.h" #include "Shapes.h" #include "../math/matrix.h" #include "../math/constant.h" @@ -11,21 +12,30 @@ namespace jin namespace graphics { + using namespace math; + void point(int x, int y) { - float vers[] = { x + 0.5f , y + 0.5f }; - glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(2, GL_FLOAT, 0, (GLvoid*)vers); + float verts[] = { x + 0.5f , y + 0.5f }; + + Shader* shader = Shader::getCurrentJSL(); + shader->bindVertexPointer(2, GL_FLOAT, 0, verts); + gl.ModelMatrix.setIdentity(); + shader->sendMatrix4(Shader::MODEL_MATRIX, &gl.ModelMatrix); + shader->sendMatrix4(Shader::PROJECTION_MATRIX, &gl.ProjectionMatrix); + glDrawArrays(GL_POINTS, 0, 1); - glDisableClientState(GL_VERTEX_ARRAY); } void points(int n, GLshort* p) { - glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(2, GL_SHORT, 0, (GLvoid*)p); - glDrawArrays(GL_POINTS, 0, n); - glDisableClientState(GL_VERTEX_ARRAY); + Shader* shader = Shader::getCurrentJSL(); + shader->bindVertexPointer(2, GL_SHORT, 0, p); + gl.ModelMatrix.setIdentity(); + shader->sendMatrix4(Shader::MODEL_MATRIX, &gl.ModelMatrix); + shader->sendMatrix4(Shader::PROJECTION_MATRIX, &gl.ProjectionMatrix); + + glDrawArrays(GL_POINTS, 0, n); } void line(int x1, int y1, int x2, int y2) @@ -34,11 +44,14 @@ namespace graphics x1, y1, x2, y2 }; - - glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(2, GL_FLOAT, 0, (const GLvoid*)verts); - glDrawArrays(GL_LINES, 0, 2); - glDisableClientState(GL_VERTEX_ARRAY); + + Shader* shader = Shader::getCurrentJSL(); + shader->bindVertexPointer(2, GL_FLOAT, 0, verts); + gl.ModelMatrix.setIdentity(); + shader->sendMatrix4(Shader::MODEL_MATRIX, &gl.ModelMatrix); + shader->sendMatrix4(Shader::PROJECTION_MATRIX, &gl.ProjectionMatrix); + + glDrawArrays(GL_LINES, 0, 2); } void circle(RenderMode mode, int x, int y, int r) @@ -80,10 +93,13 @@ namespace graphics void polygon_line(float* p, int count) { - glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(2, GL_FLOAT, 0, (const GLvoid*)p); + Shader* shader = Shader::getCurrentJSL(); + gl.ModelMatrix.setIdentity(); + shader->sendMatrix4(Shader::MODEL_MATRIX, &gl.ModelMatrix); + shader->sendMatrix4(Shader::PROJECTION_MATRIX, &gl.ProjectionMatrix); + shader->bindVertexPointer(2, GL_FLOAT, 0, p); + glDrawArrays(GL_LINE_LOOP, 0, count); - glDisableClientState(GL_VERTEX_ARRAY); } void polygon(RenderMode mode, float* p, int count) @@ -94,10 +110,13 @@ namespace graphics } else if (mode == FILL) { - glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(2, GL_FLOAT, 0, (const GLvoid*)p); + Shader* shader = Shader::getCurrentJSL(); + gl.ModelMatrix.setIdentity(); + shader->sendMatrix4(Shader::MODEL_MATRIX, &gl.ModelMatrix); + shader->sendMatrix4(Shader::PROJECTION_MATRIX, &gl.ProjectionMatrix); + shader->bindVertexPointer(2, GL_FLOAT, 0, p); + glDrawArrays(GL_POLYGON, 0, count); - glDisableClientState(GL_VERTEX_ARRAY); } } diff --git a/src/libjin/Graphics/Shapes.h b/src/libjin/Graphics/Shapes.h index dc9f272..b248cca 100644 --- a/src/libjin/Graphics/Shapes.h +++ b/src/libjin/Graphics/Shapes.h @@ -1,6 +1,6 @@ #ifndef __LIBJIN_GEOMETRY_H #define __LIBJIN_GEOMETRY_H -#include "../modules.h" +#include "../jin_configuration.h" #if LIBJIN_MODULES_RENDER #include "color.h" diff --git a/src/libjin/Graphics/Texture.cpp b/src/libjin/Graphics/Texture.cpp index 9958935..5a39f77 100644 --- a/src/libjin/Graphics/Texture.cpp +++ b/src/libjin/Graphics/Texture.cpp @@ -1,4 +1,4 @@ -#include "../modules.h" +#include "../jin_configuration.h" #if LIBJIN_MODULES_RENDER #include <fstream> @@ -15,35 +15,23 @@ namespace graphics /*static*/ Texture* Texture::createTexture(Bitmap* bitmap) { - Texture* tex = new Texture(); - const Color* pixels = bitmap->getPixels(); - tex->size.w = bitmap->getWidth(); - tex->size.h = bitmap->getHeight(); - unsigned int w = tex->size.w; - unsigned int h = tex->size.h; - - glGenTextures(1, &tex->texture); - glBindTexture(GL_TEXTURE_2D, tex->texture); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); - - tex->vertCoord[0] = 0; tex->vertCoord[1] = 1; - tex->vertCoord[2] = 0; tex->vertCoord[3] = h; - tex->vertCoord[4] = w; tex->vertCoord[5] = h; - tex->vertCoord[6] = w; tex->vertCoord[7] = 1; - - tex->textCoord[0] = 0; tex->textCoord[1] = 0; - tex->textCoord[2] = 0; tex->textCoord[3] = 1; - tex->textCoord[4] = 1; tex->textCoord[5] = 1; - tex->textCoord[6] = 1; tex->textCoord[7] = 0; - + Texture* tex = new Texture(bitmap); return tex; } - Texture::Texture() - : Drawable() + Texture::Texture(const Bitmap* bitmap) + : Drawable(bitmap->getWidth(), bitmap->getHeight()) { + unsigned int w = size.w; + unsigned int h = size.h; + const Color* pixels = bitmap->getPixels(); + + texture = gl.genTexture(); + gl.bindTexture(texture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + gl.texImage(GL_RGBA8, w, h, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + gl.bindTexture(0); } Texture::~Texture() diff --git a/src/libjin/Graphics/Texture.h b/src/libjin/Graphics/Texture.h index f2e45f0..8498666 100644 --- a/src/libjin/Graphics/Texture.h +++ b/src/libjin/Graphics/Texture.h @@ -1,6 +1,6 @@ #ifndef __LIBJIN_IMAGE_H #define __LIBJIN_IMAGE_H -#include "../modules.h" +#include "../jin_configuration.h" #if LIBJIN_MODULES_RENDER #include "../3rdparty/GLee/GLee.h" @@ -20,7 +20,7 @@ namespace graphics ~Texture(); private: - Texture(); + Texture(const Bitmap* bitmap); }; diff --git a/src/libjin/Graphics/Utf8.cpp b/src/libjin/Graphics/Utf8.cpp new file mode 100644 index 0000000..1a79d43 --- /dev/null +++ b/src/libjin/Graphics/Utf8.cpp @@ -0,0 +1,68 @@ +#include <stdlib.h> +#include <string.h> +#include "Utf8.h" + +namespace jin +{ +namespace graphics +{ + + /* utf8 byte string to unicode codepoint */ + static const char *utf8toCodepoint(const char *p, unsigned *res) { + unsigned x, mask, shift; + switch (*p & 0xf0) { + case 0xf0: mask = 0x07; shift = 18; break; + case 0xe0: mask = 0x0f; shift = 12; break; + case 0xc0: + case 0xd0: mask = 0x1f; shift = 6; break; + default: + *res = *p; + return p + 1; + } + x = (*p & mask) << shift; + do { + if (*(++p) == '\0') { + *res = x; + return p; + } + shift -= 6; + x |= (*p & 0x3f) << shift; + } while (shift); + *res = x; + return p + 1; + } + + Utf8::Utf8(const char* raw, unsigned int length) + { + _length = length; + _raw = (char*)calloc(1, length); + memcpy(_raw, raw, length); + } + + Utf8::Iterator Utf8::getIterator() + { + return Iterator(*this); + } + + Utf8::~Utf8() + { + free(_raw); + _raw = nullptr; + _length = 0; + } + + Utf8::Iterator::Iterator(const Utf8& utf8) + : _utf8(utf8) + { + _p = utf8._raw; + } + + Codepoint Utf8::Iterator::get() + { + Codepoint c; + _p = utf8toCodepoint(_p, &c); + return c; + } + +} +}
\ No newline at end of file diff --git a/src/libjin/Graphics/Utf8.h b/src/libjin/Graphics/Utf8.h new file mode 100644 index 0000000..d2d11fb --- /dev/null +++ b/src/libjin/Graphics/Utf8.h @@ -0,0 +1,44 @@ +#ifndef __LIBJIN_UTF8_H +#define __LIBJIN_UTF8_H + +namespace jin +{ +namespace graphics +{ + + typedef unsigned int Codepoint; + + class Utf8 + { + public: + class Iterator + { + public: + /* unicode codepoint */ + Codepoint get(); + + private: + friend class Utf8; + Iterator(const Utf8&); + + const char* _p; + const Utf8& _utf8; + }; + + /* rawıսij */ + Utf8(const char* raw, unsigned int length); + Iterator getIterator(); + + private: + friend class Utf8::Iterator; + ~Utf8(); + + char* _raw; + unsigned int _length; + + }; + +} +} + +#endif
\ No newline at end of file diff --git a/src/libjin/Graphics/Window.cpp b/src/libjin/Graphics/Window.cpp index 1fb60cc..6ebc9f9 100644 --- a/src/libjin/Graphics/Window.cpp +++ b/src/libjin/Graphics/Window.cpp @@ -1,10 +1,11 @@ -#include "../modules.h" +#include "../jin_configuration.h" #if LIBJIN_MODULES_RENDER #include <iostream> #include "window.h" -#include "../3rdparty/GLee/GLee.h" +#include "OpenGL.h" #include "canvas.h" +#include "Shader.h" #include "../utils/utils.h" #include "../audio/sdl/SDLAudio.h" #include "../utils/log.h" @@ -68,23 +69,24 @@ namespace graphics SDL_GL_SetSwapInterval(vsync ? 1 : 0); SDL_GL_MakeCurrent(wnd, ctx); /* default configuration */ - glClearColor(0.f, 0.f, 0.f, 1.f); - glColor4f(1, 1, 1, 1); - glEnable(GL_BLEND); - glEnable(GL_TEXTURE_2D); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + gl.setClearColor(0, 0, 0, 0xff); + gl.pushColor(0xff, 0xff, 0xff, 0xff); + gl.enable(GL_BLEND); + gl.enable(GL_TEXTURE_2D); + gl.setBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); /* avoid white screen blink on windows */ swapBuffers(); /* bind to default canvas */ Canvas::unbind(); + Shader::unuse(); return true; } void Window::quitSystem() { /* disable opengl */ - glDisable(GL_BLEND); - glDisable(GL_TEXTURE_2D); + gl.disable(GL_BLEND); + gl.disable(GL_TEXTURE_2D); /* close window */ SDL_DestroyWindow(wnd); SDL_Quit(); diff --git a/src/libjin/Graphics/Window.h b/src/libjin/Graphics/Window.h index 6b247a6..301b0b5 100644 --- a/src/libjin/Graphics/Window.h +++ b/src/libjin/Graphics/Window.h @@ -1,6 +1,6 @@ #ifndef __LIBJIN_RENDER_WINDOW #define __LIBJIN_RENDER_WINDOW -#include "../modules.h" +#include "../jin_configuration.h" #if LIBJIN_MODULES_RENDER #include "SDL2/SDL.h" diff --git a/src/libjin/Graphics/base.shader.h b/src/libjin/Graphics/base.shader.h deleted file mode 100644 index 080e27e..0000000 --- a/src/libjin/Graphics/base.shader.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * https://stackoverflow.com/questions/10868958/what-does-sampler2d-store - * The sampler2D is bound to a texture unit. The glUniform call binds it to texture - * unit zero. The glActiveTexture call is only needed if you are going to use multiple - * texture units (because GL_TEXTURE0 is the default anyway). -*/ - -static const char* default_texture = "_tex0_"; - -static const char* base_shader = R"( -#define number float -#define Texture sampler2D -#define Canvas sampler2D -#define Color vec4 -#define Texel texture2D -#define extern uniform -#define Vec2 vec2 -#define Vec3 vec3 -#define Vec4 vec4 -#define Number number -#define Image Texture - -extern Texture %s; -%s -void main() -{ - gl_FragColor = effect(gl_Color, %s, gl_TexCoord[0].xy, gl_FragCoord.xy); -} -)"; - -static const int SHADER_FORMAT_SIZE = strlen(base_shader) + strlen(default_texture) * 2; - -#define formatShader(buf, program)\ - sprintf(buf, base_shader, default_texture, program, default_texture) |