Paste number 29373: | OpenGL + SDL_ttf |
Pasted by: | swinchen |
When: | 15 years, 7 months ago |
Share: | Tweet this! | http://paste.lisp.org/+MNX |
Channel: | None |
Paste contents: |
#include <SDL/SDL.h>
#include <SDL/SDL_ttf.h>
#include <SDL/SDL_opengl.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#define PI 3.141592653589793238462643
typedef struct
{
int minx, maxx, miny, maxy, advance;
GLfloat texcoord[4];
GLuint texid;
} t_glyph;
typedef struct
{
int style, pointsize, height, ascent, descent, lineskip;
SDL_Color color;
t_glyph glyphs[128];
} t_font;
int build_font(char* filename, t_font* font);
void print_glstr(int x, int y, t_font* font, char* str);
void set_perspective(GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar);
void SDL_GL_Enter2DMode();
void SDL_GL_Leave2DMode();
static int power_of_two(int input);
GLuint SDL_GL_LoadTexture(SDL_Surface *surface, GLfloat *texcoord);
int main(int argc, char* argv[])
{
t_font font;
SDL_Surface* screen;
SDL_Color white = {0xFF, 0xFF, 0xFF, 0x00};
if ( SDL_Init(SDL_INIT_TIMER | SDL_INIT_VIDEO) < 0 )
{
fprintf(stderr, "ERROR Initializing SDL: %s\n", SDL_GetError());
return -1;
}
atexit(SDL_Quit);
if ( TTF_Init() < 0 )
{
fprintf(stderr, "ERROR Initializing TTF Engine: %s\n", TTF_GetError());
return -1;
}
atexit(TTF_Quit);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
screen = SDL_SetVideoMode(800, 600, 32, SDL_OPENGL);
if ( screen == NULL )
{
fprintf(stderr, "ERROR Couldn't set video mode: %s\n", SDL_GetError());
return -1;
}
glViewport(0, 0, screen->w, screen->h);
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
set_perspective(45.0f, (GLdouble) screen->w / screen->h, 1.0f, 100.0f);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glShadeModel(GL_SMOOTH);
glClearColor(0.0, 0.0, 0.0, 1.0);
font.pointsize = 20;
font.style = TTF_STYLE_NORMAL;
memcpy(&(font.color), &white, sizeof(SDL_Color));
if ( build_font("MONACO.TTF",&font) < 0)
{
fprintf(stderr, "ERROR building font: %s\n", TTF_GetError());
return -1;
}
while ( SDL_GetTicks() < 5000 )
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslated(0.0, 0.0, -5.0);
glBegin(GL_POINTS);
glVertex3d(0.0,0.0,0.0);
glEnd();
SDL_GL_Enter2DMode();
print_glstr(100, 500, &font, "abcdefghijklmnopqrstuvwxyz");
SDL_GL_Leave2DMode();
SDL_GL_SwapBuffers();
}
SDL_FreeSurface(screen);
return 0;
}
int build_font(char* filename, t_font* font)
{
TTF_Font* ttffont;
SDL_Surface* surf;
int i;
GLenum gl_error;
ttffont = TTF_OpenFont(filename, font->pointsize);
if (ttffont == NULL)
{
TTF_SetError("ERROR opening font: %s\n", TTF_GetError());
return -1;
}
TTF_SetFontStyle(ttffont, font->style);
font->ascent = TTF_FontAscent(ttffont);
font->descent = TTF_FontDescent(ttffont);
font->height = TTF_FontHeight(ttffont);
font->lineskip = TTF_FontLineSkip(ttffont);
for ( i = ' '; i <= '~'; i++ )
{
surf = TTF_RenderGlyph_Blended(ttffont, i, font->color);
if ( surf == NULL )
{
TTF_SetError("ERROR rendering glyph %c: %s\n", (char)i,
TTF_GetError());
TTF_CloseFont(ttffont);
return -1;
}
TTF_GlyphMetrics(ttffont, i, &(font->glyphs[i].minx),
&(font->glyphs[i].maxx), &(font->glyphs[i].miny),
&(font->glyphs[i].maxy), &(font->glyphs[i].advance));
font->glyphs[i].texid = SDL_GL_LoadTexture(surf,
font->glyphs[i].texcoord);
if ( (gl_error = glGetError()) != GL_NO_ERROR ) {
/* If this failed, the text may exceed texture size limits */
TTF_SetError("Warning: Couldn't create texture: 0x%x\n", gl_error);
SDL_FreeSurface(surf);
TTF_CloseFont(ttffont);
return -1;
}
SDL_FreeSurface(surf);
}
TTF_CloseFont(ttffont);
return 0;
}
void print_glstr(int x, int y, t_font* font, char* str)
{
int texMinX, texMaxX, texMinY, texMaxY, i, w, h;
while (*str != 0)
{
i = (int)*str;
texMinX = font->glyphs[i].texcoord[0];
texMinY = font->glyphs[i].texcoord[1];
texMaxX = font->glyphs[i].texcoord[2];
texMaxY = font->glyphs[i].texcoord[3];
w = font->glyphs[i].maxx;
h = font->glyphs[i].maxy;
glBindTexture(GL_TEXTURE_2D, font->glyphs[i].texid);
glBegin(GL_TRIANGLE_STRIP);
glTexCoord2f(texMinX, texMinY); glVertex2i(x, y );
glTexCoord2f(texMaxX, texMinY); glVertex2i(x+w, y );
glTexCoord2f(texMinX, texMaxY); glVertex2i(x, y+h);
glTexCoord2f(texMaxX, texMaxY); glVertex2i(x+w, y+h);
glEnd();
x += font->glyphs[i].advance;
str++;
}
}
void set_perspective(GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar)
{
GLdouble ymax;
ymax = zNear * tan(fovy * PI / 360.0f);
glFrustum(-ymax*aspect, ymax*aspect, -ymax, ymax, zNear, zFar);
}
void SDL_GL_Enter2DMode()
{
SDL_Surface *screen = SDL_GetVideoSurface();
/* Note, there may be other things you need to change,
depending on how you have your OpenGL state set up.
*/
glPushAttrib(GL_ENABLE_BIT);
glDisable(GL_DEPTH_TEST);
glDisable(GL_CULL_FACE);
glEnable(GL_TEXTURE_2D);
/* This allows alpha blending of 2D textures with the scene */
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glViewport(0, 0, screen->w, screen->h);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glOrtho(0.0, (GLdouble)screen->w, (GLdouble)screen->h, 0.0, 0.0, 1.0);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
}
void SDL_GL_Leave2DMode()
{
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glPopAttrib();
}
/* Quick utility function for texture creation */
static int power_of_two(int input)
{
int value = 1;
while ( value < input ) {
value <<= 1;
}
return value;
}
GLuint SDL_GL_LoadTexture(SDL_Surface *surface, GLfloat *texcoord)
{
GLuint texture;
int w, h;
SDL_Surface *image;
SDL_Rect area;
Uint32 saved_flags;
Uint8 saved_alpha;
/* Use the surface width and height expanded to powers of 2 */
w = power_of_two(surface->w);
h = power_of_two(surface->h);
texcoord[0] = 0.0f; /* Min X */
texcoord[1] = 0.0f; /* Min Y */
texcoord[2] = (GLfloat)surface->w / w; /* Max X */
texcoord[3] = (GLfloat)surface->h / h; /* Max Y */
image = SDL_CreateRGBSurface(
SDL_SWSURFACE,
w, h,
32,
#if SDL_BYTEORDER == SDL_LIL_ENDIAN /* OpenGL RGBA masks */
0x000000FF,
0x0000FF00,
0x00FF0000,
0xFF000000
#else
0xFF000000,
0x00FF0000,
0x0000FF00,
0x000000FF
#endif
);
if ( image == NULL ) {
return 0;
}
/* Save the alpha blending attributes */
saved_flags = surface->flags&(SDL_SRCALPHA|SDL_RLEACCELOK);
saved_alpha = surface->format->alpha;
if ( (saved_flags & SDL_SRCALPHA) == SDL_SRCALPHA ) {
SDL_SetAlpha(surface, 0, 0);
}
/* Copy the surface into the GL texture image */
area.x = 0;
area.y = 0;
area.w = surface->w;
area.h = surface->h;
SDL_BlitSurface(surface, &area, image, &area);
/* Restore the alpha blending attributes */
if ( (saved_flags & SDL_SRCALPHA) == SDL_SRCALPHA ) {
SDL_SetAlpha(surface, saved_flags, saved_alpha);
}
/* Create an OpenGL texture for the image */
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, 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_RGBA,
w, h,
0,
GL_RGBA,
GL_UNSIGNED_BYTE,
image->pixels);
SDL_FreeSurface(image); /* No longer needed */
return texture;
}
This paste has no annotations.