timesynk/engine/sdl/r_gl.c

153 lines
4.5 KiB
C

/******
SDL opengl renderer
******/
#include <SDL/SDL_opengl.h>
#include "../ui/elements.h"
#include "r_gl.h"
#include "interface.h"
void r_gl_Init() {
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
if ((screen = SDL_SetVideoMode(g_video_width, g_video_height, 32, SDL_HWSURFACE|SDL_OPENGL|SDL_RESIZABLE|g_video_fullscreen)) == NULL)
return; // TODO: handle error
glEnable( GL_TEXTURE_2D );
glClearColor( 0.0f, 0.0f, 0.0f, 0.0f );
glViewport( 0, 0, g_video_width, g_video_height);
glClear( GL_COLOR_BUFFER_BIT );
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
glOrtho(0.0f, g_video_width, g_video_height, 1.0f, -1.0f, 1.0f);
//glOrtho(0.0f, g_video_width, 0, g_video_height, -1.0f, 1.0f);
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
}
void r_gl_Reinit() {
}
void r_gl_clearScreen() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
void r_gl_renderScreen() {
SDL_GL_SwapBuffers();
}
void r_gl_renderElements(struct ElementList *list) {
struct Element *current = list->first;
while(current != NULL) {
struct Element *next = current->next;
r_gl_renderElement(current);
current = next;
}
}
void r_gl_renderElement(struct Element *element) {
if (element == NULL)
return;
if (element->flags & E_FLAG_HIDE || element->target == NULL)
return;
if (element->flags & E_FLAG_UPDATE) {
if (element->type == E_TYPE_TEXT) {
r_gl_renderText(element->font, ((struct TextElement*)element->data)->string, element->dimen.x, element->dimen.y);
}
}
}
void r_gl_renderText(struct Font *font, const char *string, int x, int y) {
if (font == NULL) {
printf("font is null\n");
return;
}
if (font->texture == 0) {
r_gl_createTexture(&font->texture, font->surface);
}
int i = 0;
int x_offset, y_offset;
int x_render = 0;
int y_render = 0;
/* get the width and height of each sprite in gl texture terms */
double sx = 1.0f/(font->surface->w / font->width);
double sy = 1.0f/(font->surface->h / font->height);
glBindTexture(GL_TEXTURE_2D, font->texture);
while(string[i] != '\0') {
switch(string[i]) {
case '\n':
y_render += font->height*font->scale_y;
x_render = 0;
break;
default:
y_offset = string[i] / 16;
x_offset = string[i] - (y_offset*16);
/* get the texture offsets for the target sprite */
double tx = (x_offset == 0 ? 0.0f : 1.0f/((float)(16.0f/x_offset)));
double ty = (y_offset == 0 ? 0.0f : 1.0f/(8.0f/y_offset));
/* draw a clipped portion of our font texture to a quad*/
glLoadIdentity();
glTranslated(x+x_render, y+y_render, 1.0f);
//glTranslated(font->width, y_render, 0.0f);
glBegin(GL_QUADS);
// tl
//glTexCoord2d(tx,ty+sy); glVertex2f(0,0);
glTexCoord2d(tx,ty); glVertex2f(0,0);
// tr
//glTexCoord2d(tx+sx,ty+sy); glVertex2f(font->width, 0);
glTexCoord2d(tx+sx,ty); glVertex2f(font->width*font->scale_x, 0);
// br
//glTexCoord2d(tx+sx,ty); glVertex2f(font->width, font->height);
glTexCoord2d(tx+sx,ty+sy); glVertex2f(font->width*font->scale_x, font->height*font->scale_y);
// bl
//glTexCoord2d(tx,ty); glVertex2f(0,font->height);
glTexCoord2d(tx,ty+sy); glVertex2f(0,font->height*font->scale_y);
glEnd();
x_render += font->width*font->scale_x;
break;
}
i++;
}
glLoadIdentity();
}
GLuint r_gl_createTexture(GLuint *texture, SDL_Surface *surface) {
GLenum format;
GLint colors = surface->format->BytesPerPixel;
if (colors == 4) { // with alpha
if (surface->format->Rmask == 0x000000ff) {
format = GL_RGBA;
} else {
format = GL_BGRA;
}
} else if (colors == 3) {
if (surface->format->Rmask == 0x000000ff) {
format = GL_RGB;
} else {
format = GL_BGR;
}
} else {
// non truecolor, handle error or convert
}
// generate texture handle
glGenTextures(1, texture);
// bind the texture object
glBindTexture(GL_TEXTURE_2D, *texture);
// set stretching properties
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
// get the appropriate endianness for data packing
int num = 1;
int pack_type = ( (*(char*)&num == 1) ? GL_UNSIGNED_INT_8_8_8_8 : GL_UNSIGNED_INT_8_8_8_8_REV);
// copy it over! :)
glTexImage2D(GL_TEXTURE_2D, 0, colors, surface->w, surface->h, 0, format, pack_type, surface->pixels);
return *texture;
}