aboutsummaryrefslogtreecommitdiff
path: root/src/libjin/Graphics
diff options
context:
space:
mode:
Diffstat (limited to 'src/libjin/Graphics')
-rw-r--r--src/libjin/Graphics/Bitmap.h7
-rw-r--r--src/libjin/Graphics/Canvas.cpp66
-rw-r--r--src/libjin/Graphics/Canvas.h3
-rw-r--r--src/libjin/Graphics/Color.h14
-rw-r--r--src/libjin/Graphics/Drawable.cpp48
-rw-r--r--src/libjin/Graphics/Drawable.h9
-rw-r--r--src/libjin/Graphics/Font.cpp349
-rw-r--r--src/libjin/Graphics/Font.h103
-rw-r--r--src/libjin/Graphics/FontData.cpp115
-rw-r--r--src/libjin/Graphics/FontData.h45
-rw-r--r--src/libjin/Graphics/Graphics.h5
-rw-r--r--src/libjin/Graphics/Mesh.cpp11
-rw-r--r--src/libjin/Graphics/Mesh.h17
-rw-r--r--src/libjin/Graphics/OpenGL.cpp12
-rw-r--r--src/libjin/Graphics/OpenGL.h29
-rw-r--r--src/libjin/Graphics/Shader.cpp161
-rw-r--r--src/libjin/Graphics/Shader.h28
-rw-r--r--src/libjin/Graphics/Shaders/base.shader.h104
-rw-r--r--src/libjin/Graphics/Shaders/default.shader.h21
-rw-r--r--src/libjin/Graphics/Shaders/font.shader.h21
-rw-r--r--src/libjin/Graphics/Shaders/texture.shader.h21
-rw-r--r--src/libjin/Graphics/Shapes.cpp59
-rw-r--r--src/libjin/Graphics/Shapes.h2
-rw-r--r--src/libjin/Graphics/Texture.cpp40
-rw-r--r--src/libjin/Graphics/Texture.h4
-rw-r--r--src/libjin/Graphics/Utf8.cpp68
-rw-r--r--src/libjin/Graphics/Utf8.h44
-rw-r--r--src/libjin/Graphics/Window.cpp20
-rw-r--r--src/libjin/Graphics/Window.h2
-rw-r--r--src/libjin/Graphics/base.shader.h34
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, &current_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)