mirror of https://github.com/bjornbytes/lovr.git
More font rendering;
This commit is contained in:
parent
02386af34f
commit
f80e3e5a13
|
@ -10,22 +10,24 @@ Font* lovrFontCreate(FontData* fontData) {
|
|||
Font* font = lovrAlloc(sizeof(Font), lovrFontDestroy);
|
||||
if (!font) return NULL;
|
||||
|
||||
font->fontData = fontData;
|
||||
vec_init(&font->vertices);
|
||||
|
||||
// Atlas
|
||||
int padding = 1;
|
||||
font->atlas.x = padding;
|
||||
font->atlas.y = padding;
|
||||
font->atlas.width = 64;
|
||||
font->atlas.height = 64;
|
||||
font->atlas.rowHeight = 0;
|
||||
font->atlas.offsetX = 0;
|
||||
font->atlas.extentX = 0;
|
||||
font->atlas.extentY = 0;
|
||||
font->atlas.padding = padding;
|
||||
map_init(&font->atlas.glyphs);
|
||||
|
||||
font->fontData = fontData;
|
||||
font->texture = NULL;
|
||||
lovrFontCreateTexture(font);
|
||||
vec_init(&font->vertices);
|
||||
// Texture
|
||||
TextureData* textureData = lovrTextureDataGetBlank(font->atlas.width, font->atlas.height, 0x0, FORMAT_RG);
|
||||
font->texture = lovrTextureCreate(textureData);
|
||||
lovrTextureSetWrap(font->texture, WRAP_CLAMP, WRAP_CLAMP);
|
||||
int swizzle[4] = { GL_RED, GL_RED, GL_RED, GL_GREEN };
|
||||
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzle);
|
||||
|
||||
return font;
|
||||
}
|
||||
|
@ -39,40 +41,47 @@ void lovrFontDestroy(const Ref* ref) {
|
|||
free(font);
|
||||
}
|
||||
|
||||
void lovrFontDataDestroy(FontData* fontData) {
|
||||
// TODO
|
||||
free(fontData);
|
||||
}
|
||||
|
||||
void lovrFontPrint(Font* font, const char* str) {
|
||||
FontAtlas* atlas = &font->atlas;
|
||||
vec_reserve(&font->vertices, strlen(str) * 30);
|
||||
vec_clear(&font->vertices);
|
||||
|
||||
// Cursor
|
||||
float x = 0;
|
||||
float y = 0;
|
||||
float u = atlas->width;
|
||||
float v = atlas->height;
|
||||
|
||||
for (unsigned int i = 0; i < strlen(str); i++) {
|
||||
if (str[i] == '\n') {
|
||||
x = 0;
|
||||
y -= font->fontData->size;
|
||||
continue;
|
||||
}
|
||||
|
||||
Glyph* glyph = lovrFontGetGlyph(font, str[i]);
|
||||
|
||||
if (glyph->w > 0 || glyph->h > 0) {
|
||||
float s = glyph->x / (float) atlas->width;
|
||||
float t = glyph->y / (float) atlas->height;
|
||||
float w = glyph->w;
|
||||
float h = glyph->h;
|
||||
float s2 = (glyph->x + w) / (float) atlas->width;
|
||||
float t2 = (glyph->y + h) / (float) atlas->height;
|
||||
float ox = x + glyph->ox;
|
||||
float oy = -y - glyph->oy;
|
||||
int gx = glyph->x;
|
||||
int gy = glyph->y;
|
||||
int gw = glyph->w;
|
||||
int gh = glyph->h;
|
||||
|
||||
if (gw > 0 && gh > 0) {
|
||||
float x1 = x + glyph->dx;
|
||||
float y1 = y + glyph->dy;
|
||||
float x2 = x1 + gw;
|
||||
float y2 = y1 - gh;
|
||||
float s1 = gx / u;
|
||||
float t1 = gy / v;
|
||||
float s2 = (gx + gw) / u;
|
||||
float t2 = (gy + gh) / v;
|
||||
|
||||
float v[30] = {
|
||||
ox, -oy, 0, s, t,
|
||||
ox, -oy - h, 0, s, t2,
|
||||
ox + w, -oy, 0, s2, t,
|
||||
ox + w, -oy, 0, s2, t,
|
||||
ox, -oy - h, 0, s, t2,
|
||||
ox + w, -oy - h, 0, s2, t2
|
||||
x1, y1, 0, s1, t1,
|
||||
x1, y2, 0, s1, t2,
|
||||
x2, y1, 0, s2, t1,
|
||||
x2, y1, 0, s2, t1,
|
||||
x1, y2, 0, s1, t2,
|
||||
x2, y2, 0, s2, t2
|
||||
};
|
||||
|
||||
vec_pusharr(&font->vertices, v, 30);
|
||||
|
@ -91,77 +100,74 @@ Glyph* lovrFontGetGlyph(Font* font, char character) {
|
|||
vec_glyph_t* glyphs = &atlas->glyphs;
|
||||
Glyph* glyph = map_get(glyphs, key);
|
||||
|
||||
// Add the glyph to the atlas if it isn't there
|
||||
if (!glyph) {
|
||||
|
||||
// Load the new glyph and add it to the cache
|
||||
Glyph g;
|
||||
lovrFontDataLoadGlyph(font->fontData, character, &g);
|
||||
map_set(glyphs, key, g);
|
||||
glyph = map_get(glyphs, key);
|
||||
|
||||
// Exit early if the glyph is empty to save texture space
|
||||
if (glyph->w == 0 && glyph->h == 0) {
|
||||
return glyph;
|
||||
}
|
||||
|
||||
// If the glyph does not fit, you must acquit
|
||||
int tooWide = 0, tooTall = 0;
|
||||
do {
|
||||
|
||||
// New row
|
||||
if ((tooWide = atlas->x + glyph->w > atlas->width - 2 * atlas->padding) == 1) {
|
||||
atlas->x = atlas->offsetX + atlas->padding;
|
||||
atlas->y += atlas->rowHeight + atlas->padding;
|
||||
atlas->rowHeight = 0;
|
||||
}
|
||||
|
||||
// +---+ +---+---+ +---+---+
|
||||
// | | -> | | | -> | | |
|
||||
// +---+ +---+---+ +---+---+
|
||||
// | |
|
||||
// +-------+
|
||||
if ((tooTall = atlas->y + glyph->h > atlas->height - 2 * atlas->padding) == 1) {
|
||||
if (atlas->width == atlas->height) {
|
||||
atlas->offsetX = atlas->extentX;
|
||||
atlas->x = atlas->offsetX + atlas->padding;
|
||||
atlas->y = atlas->padding;
|
||||
atlas->rowHeight = 0;
|
||||
atlas->width <<= 1;
|
||||
} else {
|
||||
atlas->extentX = 0;
|
||||
atlas->offsetX = 0;
|
||||
atlas->height <<= 1;
|
||||
}
|
||||
}
|
||||
} while (tooWide || tooTall);
|
||||
|
||||
// Keep track of glyph position in atlas
|
||||
glyph->x = atlas->x;
|
||||
glyph->y = atlas->y;
|
||||
|
||||
// Paste glyph into texture
|
||||
lovrGraphicsBindTexture(font->texture);
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, atlas->x, atlas->y, glyph->w, glyph->h, GL_RG, GL_UNSIGNED_BYTE, glyph->data);
|
||||
|
||||
// Advance atlas cursor
|
||||
atlas->x += glyph->w + atlas->padding;
|
||||
atlas->rowHeight = MAX(atlas->rowHeight, glyph->h);
|
||||
atlas->extentX = MAX(atlas->extentX, atlas->x);
|
||||
atlas->extentY = MAX(atlas->extentY, atlas->y + atlas->rowHeight);
|
||||
lovrFontAddGlyph(font, glyph);
|
||||
}
|
||||
|
||||
return glyph;
|
||||
}
|
||||
|
||||
void lovrFontCreateTexture(Font* font) {
|
||||
if (font->texture) {
|
||||
lovrRelease(&font->texture->ref);
|
||||
void lovrFontAddGlyph(Font* font, Glyph* glyph) {
|
||||
FontAtlas* atlas = &font->atlas;
|
||||
|
||||
// Don't waste space on empty glyphs
|
||||
if (glyph->w == 0 && glyph->h == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
FontAtlas* atlas = &font->atlas;
|
||||
TextureData* textureData = lovrTextureDataGetBlank(atlas->width * 4, atlas->height * 4, 0x0, FORMAT_RG);
|
||||
font->texture = lovrTextureCreate(textureData);
|
||||
lovrTextureSetWrap(font->texture, WRAP_CLAMP, WRAP_CLAMP);
|
||||
int swizzle[4] = { GL_RED, GL_RED, GL_RED, GL_GREEN };
|
||||
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzle);
|
||||
// If the glyph does not fit, you must acquit (new row)
|
||||
if (atlas->x + glyph->w > atlas->width - 2 * atlas->padding) {
|
||||
atlas->x = atlas->padding;
|
||||
atlas->y += atlas->rowHeight + atlas->padding;
|
||||
atlas->rowHeight = 0;
|
||||
}
|
||||
|
||||
// Expand the texture if needed. Expanding the texture re-adds all the glyphs, so we can return.
|
||||
if (atlas->y + glyph->h > atlas->height - 2 * atlas->padding) {
|
||||
if (atlas->width == atlas->height) {
|
||||
atlas->width <<= 1;
|
||||
} else {
|
||||
atlas->height <<= 1;
|
||||
}
|
||||
lovrFontExpandTexture(font);
|
||||
return;
|
||||
}
|
||||
|
||||
// Keep track of glyph's position in the atlas
|
||||
glyph->x = atlas->x;
|
||||
glyph->y = atlas->y;
|
||||
|
||||
// Paste glyph into texture
|
||||
lovrGraphicsBindTexture(font->texture);
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, atlas->x, atlas->y, glyph->w, glyph->h, GL_RG, GL_UNSIGNED_BYTE, glyph->data);
|
||||
|
||||
// Advance atlas cursor
|
||||
atlas->x += glyph->w + atlas->padding;
|
||||
atlas->rowHeight = MAX(atlas->rowHeight, glyph->h);
|
||||
}
|
||||
|
||||
void lovrFontExpandTexture(Font* font) {
|
||||
FontAtlas* atlas = &font->atlas;
|
||||
|
||||
// Resize the texture storage
|
||||
lovrTextureDataResize(font->texture->textureData, atlas->width, atlas->height, 0x0);
|
||||
lovrTextureRefresh(font->texture);
|
||||
|
||||
// Reset the cursor
|
||||
atlas->x = atlas->padding;
|
||||
atlas->y = atlas->padding;
|
||||
atlas->rowHeight = 0;
|
||||
|
||||
// Re-pack all the glyphs
|
||||
const char* key;
|
||||
map_iter_t iter = map_iter(&atlas->glyphs);
|
||||
while ((key = map_next(&atlas->glyphs, &iter)) != NULL) {
|
||||
Glyph* glyph = map_get(&atlas->glyphs, key);
|
||||
lovrFontAddGlyph(font, glyph);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,15 +8,16 @@
|
|||
|
||||
typedef struct {
|
||||
void* rasterizer;
|
||||
int size;
|
||||
} FontData;
|
||||
|
||||
typedef struct {
|
||||
int x;
|
||||
int y;
|
||||
int ox;
|
||||
int oy;
|
||||
int w;
|
||||
int h;
|
||||
int dx;
|
||||
int dy;
|
||||
int advance;
|
||||
uint8_t* data;
|
||||
} Glyph;
|
||||
|
@ -29,9 +30,6 @@ typedef struct {
|
|||
int width;
|
||||
int height;
|
||||
int rowHeight;
|
||||
int offsetX;
|
||||
int extentX;
|
||||
int extentY;
|
||||
int padding;
|
||||
vec_glyph_t glyphs;
|
||||
} FontAtlas;
|
||||
|
@ -46,7 +44,7 @@ typedef struct {
|
|||
|
||||
Font* lovrFontCreate(FontData* fontData);
|
||||
void lovrFontDestroy(const Ref* ref);
|
||||
void lovrFontDataDestroy(FontData* fontData);
|
||||
void lovrFontPrint(Font* font, const char* str);
|
||||
Glyph* lovrFontGetGlyph(Font* font, char character);
|
||||
void lovrFontCreateTexture(Font* font);
|
||||
void lovrFontAddGlyph(Font* font, Glyph* glyph);
|
||||
void lovrFontExpandTexture(Font* font);
|
||||
|
|
|
@ -195,7 +195,10 @@ void lovrGraphicsBindTexture(Texture* texture) {
|
|||
texture = state.defaultTexture;
|
||||
}
|
||||
|
||||
lovrTextureBind(texture);
|
||||
if (texture != state.activeTexture) {
|
||||
state.activeTexture = texture;
|
||||
glBindTexture(GL_TEXTURE_2D, texture->id);
|
||||
}
|
||||
}
|
||||
|
||||
mat4 lovrGraphicsGetProjection() {
|
||||
|
|
|
@ -50,6 +50,7 @@ typedef struct {
|
|||
Shader* skyboxShader;
|
||||
Shader* fullscreenShader;
|
||||
Font* activeFont;
|
||||
Texture* activeTexture;
|
||||
Texture* defaultTexture;
|
||||
float transforms[MAX_TRANSFORMS][16];
|
||||
CanvasState* canvases[MAX_CANVASES];
|
||||
|
|
|
@ -19,14 +19,9 @@ Texture* lovrTextureCreate(TextureData* textureData) {
|
|||
Texture* texture = lovrAlloc(sizeof(Texture), lovrTextureDestroy);
|
||||
if (!texture) return NULL;
|
||||
|
||||
int w = textureData->width;
|
||||
int h = textureData->height;
|
||||
GLenum format = getGLFormat(textureData->format);
|
||||
|
||||
texture->textureData = textureData;
|
||||
glGenTextures(1, &texture->id);
|
||||
lovrTextureBind(texture);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, format, w, h, 0, format, GL_UNSIGNED_BYTE, textureData->data);
|
||||
lovrTextureRefresh(texture);
|
||||
lovrTextureSetFilter(texture, FILTER_LINEAR, FILTER_LINEAR);
|
||||
lovrTextureSetWrap(texture, WRAP_REPEAT, WRAP_REPEAT);
|
||||
|
||||
|
@ -104,10 +99,6 @@ void lovrTextureDataDestroy(TextureData* textureData) {
|
|||
free(textureData);
|
||||
}
|
||||
|
||||
void lovrTextureBind(Texture* texture) {
|
||||
glBindTexture(GL_TEXTURE_2D, texture->id);
|
||||
}
|
||||
|
||||
void lovrTextureBindFramebuffer(Texture* texture) {
|
||||
if (!texture->framebuffer) {
|
||||
error("Texture cannot be used as a canvas");
|
||||
|
@ -154,6 +145,15 @@ void lovrTextureResolveMSAA(Texture* texture) {
|
|||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||
}
|
||||
|
||||
void lovrTextureRefresh(Texture* texture) {
|
||||
TextureData* textureData = texture->textureData;
|
||||
int w = textureData->width;
|
||||
int h = textureData->height;
|
||||
GLenum format = getGLFormat(textureData->format);
|
||||
lovrGraphicsBindTexture(texture);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, format, w, h, 0, format, GL_UNSIGNED_BYTE, textureData->data);
|
||||
}
|
||||
|
||||
int lovrTextureGetHeight(Texture* texture) {
|
||||
return texture->textureData->height;
|
||||
}
|
||||
|
@ -170,7 +170,7 @@ void lovrTextureGetFilter(Texture* texture, FilterMode* min, FilterMode* mag) {
|
|||
void lovrTextureSetFilter(Texture* texture, FilterMode min, FilterMode mag) {
|
||||
texture->filterMin = min;
|
||||
texture->filterMag = mag;
|
||||
lovrTextureBind(texture);
|
||||
lovrGraphicsBindTexture(texture);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag);
|
||||
}
|
||||
|
@ -183,7 +183,7 @@ void lovrTextureGetWrap(Texture* texture, WrapMode* horizontal, WrapMode* vertic
|
|||
void lovrTextureSetWrap(Texture* texture, WrapMode horizontal, WrapMode vertical) {
|
||||
texture->wrapHorizontal = horizontal;
|
||||
texture->wrapVertical = vertical;
|
||||
lovrTextureBind(texture);
|
||||
lovrGraphicsBindTexture(texture);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, horizontal);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, vertical);
|
||||
}
|
||||
|
|
|
@ -57,7 +57,6 @@ Texture* lovrTextureCreate(TextureData* textureData);
|
|||
Texture* lovrTextureCreateWithFramebuffer(TextureData* textureData, TextureProjection projection, int msaa);
|
||||
void lovrTextureDestroy(const Ref* ref);
|
||||
void lovrTextureDataDestroy(TextureData* textureData);
|
||||
void lovrTextureBind(Texture* texture);
|
||||
void lovrTextureBindFramebuffer(Texture* texture);
|
||||
void lovrTextureResolveMSAA(Texture* texture);
|
||||
void lovrTextureRefresh(Texture* texture);
|
||||
|
|
|
@ -148,7 +148,7 @@ Headset* viveInit() {
|
|||
|
||||
viveRefreshControllers(vive);
|
||||
|
||||
TextureData* textureData = lovrTextureDataGetEmpty(vive->renderWidth, vive->renderHeight);
|
||||
TextureData* textureData = lovrTextureDataGetEmpty(vive->renderWidth, vive->renderHeight, FORMAT_RGBA);
|
||||
vive->texture = lovrTextureCreateWithFramebuffer(textureData, PROJECTION_PERSPECTIVE, 4);
|
||||
|
||||
return headset;
|
||||
|
|
|
@ -6,60 +6,71 @@
|
|||
|
||||
static FT_Library ft = NULL;
|
||||
|
||||
FontData* lovrFontDataCreate(void* data, int size) {
|
||||
FontData* lovrFontDataCreate(void* data, int size, int height) {
|
||||
if (!ft && FT_Init_FreeType(&ft)) {
|
||||
error("Error initializing FreeType");
|
||||
}
|
||||
|
||||
FontData* fontData = malloc(sizeof(FontData));
|
||||
if (FT_New_Memory_Face(ft, data, size, 0, (FT_Face*)&fontData->rasterizer)) {
|
||||
error("Error loading font");
|
||||
}
|
||||
fontData->size = height;
|
||||
|
||||
if (FT_Set_Pixel_Sizes(fontData->rasterizer, 0, 64)) {
|
||||
error("Problem setting font size");
|
||||
FT_Error err = FT_Err_Ok;
|
||||
err = err || FT_New_Memory_Face(ft, data, size, 0, (FT_Face*)&fontData->rasterizer);
|
||||
err = err || FT_Set_Pixel_Sizes(fontData->rasterizer, 0, height);
|
||||
|
||||
if (err) {
|
||||
error("Problem loading font\n");
|
||||
}
|
||||
|
||||
return fontData;
|
||||
}
|
||||
|
||||
void lovrFontDataDestroy(FontData* fontData) {
|
||||
FT_Done_Face(fontData->rasterizer);
|
||||
free(fontData);
|
||||
}
|
||||
|
||||
void lovrFontDataLoadGlyph(FontData* fontData, uint32_t character, Glyph* glyph) {
|
||||
FT_Face face = fontData->rasterizer;
|
||||
FT_Error err = FT_Err_Ok;
|
||||
FT_Glyph ftGlyph;
|
||||
FT_Bitmap ftBitmap;
|
||||
FT_BitmapGlyph ftBitmapGlyph;
|
||||
FT_Glyph slot;
|
||||
FT_Bitmap bitmap;
|
||||
FT_BitmapGlyph bmglyph;
|
||||
FT_Glyph_Metrics* metrics;
|
||||
|
||||
err |= FT_Load_Glyph(face, FT_Get_Char_Index(face, character), FT_LOAD_DEFAULT);
|
||||
err |= FT_Get_Glyph(face->glyph, &ftGlyph);
|
||||
err |= FT_Glyph_To_Bitmap(&ftGlyph, FT_RENDER_MODE_NORMAL, 0, 1);
|
||||
// FreeType stuff
|
||||
err = err || FT_Load_Glyph(face, FT_Get_Char_Index(face, character), FT_LOAD_DEFAULT);
|
||||
err = err || FT_Get_Glyph(face->glyph, &slot);
|
||||
err = err || FT_Glyph_To_Bitmap(&slot, FT_RENDER_MODE_NORMAL, 0, 1);
|
||||
|
||||
if (err) {
|
||||
error("Error loading glyph\n");
|
||||
}
|
||||
|
||||
ftBitmapGlyph = (FT_BitmapGlyph) ftGlyph;
|
||||
ftBitmap = ftBitmapGlyph->bitmap;
|
||||
bmglyph = (FT_BitmapGlyph) slot;
|
||||
bitmap = bmglyph->bitmap;
|
||||
metrics = &face->glyph->metrics;
|
||||
|
||||
FT_Glyph_Metrics* metrics = &face->glyph->metrics;
|
||||
// Initialize glyph
|
||||
glyph->x = 0;
|
||||
glyph->y = 0;
|
||||
glyph->ox = metrics->horiBearingX >> 6;
|
||||
glyph->oy = metrics->horiBearingY >> 6;
|
||||
glyph->w = metrics->width >> 6;
|
||||
glyph->h = metrics->height >> 6;
|
||||
glyph->dx = metrics->horiBearingX >> 6;
|
||||
glyph->dy = metrics->horiBearingY >> 6;
|
||||
glyph->advance = metrics->horiAdvance >> 6;
|
||||
glyph->data = malloc(2 * glyph->w * glyph->h);
|
||||
glyph->data = malloc(glyph->w * glyph->h * 2 * sizeof(uint8_t));
|
||||
|
||||
// Transform data into an OpenGL-friendly format
|
||||
int i = 0;
|
||||
uint8_t* row = ftBitmap.buffer;
|
||||
uint8_t* row = bitmap.buffer;
|
||||
for (int y = 0; y < glyph->h; y++) {
|
||||
for (int x = 0; x < glyph->w; x++) {
|
||||
glyph->data[i++] = 0xff;
|
||||
glyph->data[i++] = row[x];
|
||||
}
|
||||
row += ftBitmap.pitch;
|
||||
row += bitmap.pitch;
|
||||
}
|
||||
|
||||
FT_Done_Glyph(ftGlyph);
|
||||
FT_Done_Glyph(slot);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include "graphics/font.h"
|
||||
#include <stdint.h>
|
||||
|
||||
FontData* lovrFontDataCreate(void* data, int size);
|
||||
FontData* lovrFontDataCreate(void* data, int size, int height);
|
||||
void lovrFontDataDestroy(FontData* fontData);
|
||||
void lovrFontDataLoadGlyph(FontData* fontData, uint32_t characer, Glyph* glyph);
|
||||
|
|
|
@ -28,15 +28,23 @@ TextureData* lovrTextureDataGetBlank(int width, int height, uint8_t value, Textu
|
|||
return textureData;
|
||||
}
|
||||
|
||||
TextureData* lovrTextureDataGetEmpty(int width, int height) {
|
||||
TextureData* lovrTextureDataGetEmpty(int width, int height, TextureFormat format) {
|
||||
TextureData* textureData = malloc(sizeof(TextureData));
|
||||
if (!textureData) return NULL;
|
||||
|
||||
int channels = 0;
|
||||
switch (format) {
|
||||
case FORMAT_RED: channels = 1; break;
|
||||
case FORMAT_RG: channels = 2; break;
|
||||
case FORMAT_RGB: channels = 3; break;
|
||||
case FORMAT_RGBA: channels = 4; break;
|
||||
}
|
||||
|
||||
textureData->data = NULL;
|
||||
textureData->width = width;
|
||||
textureData->height = height;
|
||||
textureData->channels = 4;
|
||||
textureData->format = FORMAT_RGBA;
|
||||
textureData->channels = channels;
|
||||
textureData->format = format;
|
||||
|
||||
return textureData;
|
||||
}
|
||||
|
@ -72,3 +80,11 @@ TextureData* lovrTextureDataFromOpenVRModel(OpenVRModel* vrModel) {
|
|||
textureData->format = FORMAT_RGBA;
|
||||
return textureData;
|
||||
}
|
||||
|
||||
void lovrTextureDataResize(TextureData* textureData, int width, int height, uint8_t value) {
|
||||
int size = sizeof(uint8_t) * width * height * textureData->channels;
|
||||
textureData->width = width;
|
||||
textureData->height = height;
|
||||
textureData->data = realloc(textureData->data, size);
|
||||
memset(textureData->data, value, size);
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include <stdint.h>
|
||||
|
||||
TextureData* lovrTextureDataGetBlank(int width, int height, uint8_t value, TextureFormat format);
|
||||
TextureData* lovrTextureDataGetEmpty(int width, int height);
|
||||
TextureData* lovrTextureDataGetEmpty(int width, int height, TextureFormat format);
|
||||
TextureData* lovrTextureDataFromFile(void* data, int size);
|
||||
TextureData* lovrTextureDataFromOpenVRModel(OpenVRModel* vrModel);
|
||||
void lovrTextureDataResize(TextureData* textureData, int width, int height, uint8_t value);
|
||||
|
|
|
@ -625,13 +625,15 @@ int l_lovrGraphicsNewBuffer(lua_State* L) {
|
|||
|
||||
int l_lovrGraphicsNewFont(lua_State* L) {
|
||||
const char* path = luaL_checkstring(L, 1);
|
||||
//float size = luaL_optnumber(L, 2, 16);
|
||||
float fontSize = luaL_optnumber(L, 2, 12);
|
||||
|
||||
int fileSize;
|
||||
void* data = lovrFilesystemRead(path, &fileSize);
|
||||
if (!data) {
|
||||
luaL_error(L, "Could not load font '%s'", path);
|
||||
}
|
||||
FontData* fontData = lovrFontDataCreate(data, fileSize);
|
||||
|
||||
FontData* fontData = lovrFontDataCreate(data, fileSize, fontSize);
|
||||
Font* font = lovrFontCreate(fontData);
|
||||
luax_pushtype(L, Font, font);
|
||||
return 1;
|
||||
|
@ -725,7 +727,7 @@ int l_lovrGraphicsNewTexture(lua_State* L) {
|
|||
int height = luaL_checknumber(L, 2);
|
||||
TextureProjection* projection = luax_optenum(L, 3, "2d", &TextureProjections, "projection");
|
||||
int msaa = luaL_optnumber(L, 4, 0);
|
||||
TextureData* textureData = lovrTextureDataGetEmpty(width, height);
|
||||
TextureData* textureData = lovrTextureDataGetEmpty(width, height, FORMAT_RGBA);
|
||||
texture = lovrTextureCreateWithFramebuffer(textureData, *projection, msaa);
|
||||
}
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ const luaL_Reg lovrTexture[] = {
|
|||
|
||||
int l_lovrTextureBind(lua_State* L) {
|
||||
Texture* texture = luax_checktype(L, 1, Texture);
|
||||
lovrTextureBind(texture);
|
||||
lovrGraphicsBindTexture(texture);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue