SDL_ttf: Proposed extension for precreated surfaces

Hello again,

Bob Pendleton wrote:

I have never been able to make TTF_RenderText_Blended work for me. And,
yes, I am using the latest SDL_ttf from cvs. Don’t know what the problem
is, I just can’t make it work. Could you post code that uses it and
makes it work?

I should have been more clear, makes it work with OpenGL.

Ah, perfect! Koshmaar, I hope you don’t mind, but I pinched your code and
adapted it to OpenGL, since I wanted to try out the glSubTexture2D thing.

So, here it is. It also demonstrates a nice blending effect, and tinting.
It worked as of today using the SDL_ttf from Debian unstable, I can’t
really say more than that, sorry. Oh, and you’ll have to adapt the font
and rotation speed.

Hope this helps!

Benjamin

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>

#include <SDL.h>
#include <SDL_ttf.h>
#include <GL/gl.h>
#include <GL/glu.h>

int main( int argc, char* argv[] ) {

if( SDL_Init(SDL_INIT_VIDEO)==(-1) ) {
printf(“Could not initialize SDL: %s.\n”, SDL_GetError());
exit(-1);
}

SDL_Surface *screen;

int WINWIDTH = 800, WINHEIGHT = 600, BPP = 32;
screen = SDL_SetVideoMode( WINWIDTH,WINHEIGHT, BPP, SDL_HWSURFACE | SDL_DOUBLEBUF | SDL_OPENGL | SDL_FULLSCREEN );

if( screen == NULL ) {
fprintf(stderr, “Couldn’t set %ix%ix%i video mode: %s\n”, WINWIDTH,WINHEIGHT,BPP, SDL_GetError());
SDL_Quit();
exit(1);
}

// Setup OpenGL
glShadeModel(GL_SMOOTH);
glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glClearColor(0, 0, 0, 0);
glViewport(0, 0, WINWIDTH, WINHEIGHT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-WINWIDTH/2.0, WINWIDTH/2.0, WINHEIGHT/2.0, -WINHEIGHT/2.0, 1.0, -1.0); // note inverted y axis!
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

glClear(GL_COLOR_BUFFER_BIT);

TTF_Init();
TTF_Font *fnt = TTF_OpenFont( “Vera.ttf”, 72 );

SDL_Color foreground = {255,255,255,255}; // White with full alpha

SDL_Surface *sText = TTF_RenderText_Blended( fnt, “Test Blended”, foreground);
//SDL_BlitSurface( sText,NULL, screen,&rcDest );

int texWidth=1, texHeight=1;
while (texWidth < sText->w) texWidth *= 2;
while (texHeight < sText->h) texHeight *= 2;

unsigned char texture;
texture = (unsigned char
) malloc (texWidthtexHeight4);
memset(texture, 0, texWidthtexHeight4); // Black with transparent alpha

GLuint tex_id;
glGenTextures(1, &tex_id);
glBindTexture(GL_TEXTURE_2D, tex_id);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, 4, texWidth, texHeight, 0, GL_RGBA,
GL_UNSIGNED_BYTE, texture);
glTexSubImage2D(GL_TEXTURE_2D, 0, (texWidth - sText->w)/2, (texHeight - sText->h)/2,
sText->w, sText->h, GL_RGBA, GL_UNSIGNED_BYTE, sText->pixels);

fprintf(stderr, " Width: %i Height: %i\n", sText->w, sText->h);
fprintf(stderr, " TexWidth: %i TexHeight: %i\n", texWidth, texHeight);

SDL_Event event;
GLfloat alpha = 0.0;
while (1) {
if ( SDL_PollEvent ( &event ) ) {
if ( event.type == SDL_KEYDOWN ) break ;
}

 glClear(GL_COLOR_BUFFER_BIT);

 glDisable(GL_TEXTURE_2D); // For square
 glPushMatrix();
 glRotatef(-alpha, 0.0, 0.0, 1.0);
 glBegin(GL_QUADS);
   glColor4f(1.0, 0.0, 0.0, 1.0); glVertex3f(-200.0, -200.0, 0.0);
   glColor4f(0.0, 1.0, 0.0, 1.0); glVertex3f( 200.0, -200.0, 0.0);
   glColor4f(0.0, 0.0, 1.0, 1.0); glVertex3f( 200.0,  200.0, 0.0);
   glColor4f(1.0, 1.0, 0.0, 1.0); glVertex3f(-200.0,  200.0, 0.0);
 glEnd();
 glPopMatrix();

 glEnable(GL_TEXTURE_2D); // For text
 glPushMatrix();
 glTranslatef(8.0, 8.0, 0.0);
 glRotatef(alpha, 0.0, 0.0, 1.0);
 glColor4f(0.0, 0.0, 0.0, 0.25);
 glBegin(GL_QUADS);
   glTexCoord2f(0.0, 0.0); glVertex3f(-(sText->w)/2.0, -(sText->h)/2.0, 0.0);
   glTexCoord2f(1.0, 0.0); glVertex3f( (sText->w)/2.0, -(sText->h)/2.0, 0.0);
   glTexCoord2f(1.0, 1.0); glVertex3f( (sText->w)/2.0,  (sText->h)/2.0, 0.0);
   glTexCoord2f(0.0, 1.0); glVertex3f(-(sText->w)/2.0,  (sText->h)/2.0, 0.0);
 glEnd();
 glPopMatrix();


 glPushMatrix();
 glRotatef(alpha, 0.0, 0.0, 1.0);
 glColor4f(alpha/360.0, 1.0-alpha/360.0, 0.0, 1.0);
 glBegin(GL_QUADS);
   glTexCoord2f(0.0, 0.0); glVertex3f(-(sText->w)/2.0, -(sText->h)/2.0, 0.0);
   glTexCoord2f(1.0, 0.0); glVertex3f( (sText->w)/2.0, -(sText->h)/2.0, 0.0);
   glTexCoord2f(1.0, 1.0); glVertex3f( (sText->w)/2.0,  (sText->h)/2.0, 0.0);
   glTexCoord2f(0.0, 1.0); glVertex3f(-(sText->w)/2.0,  (sText->h)/2.0, 0.0);
 glEnd();
 glPopMatrix();

 alpha += 0.01; if (alpha >= 360.0) alpha = 0.0;

 SDL_GL_SwapBuffers();

}

SDL_FreeSurface( sText );
TTF_CloseFont( fnt );
TTF_Quit();
SDL_Quit();
return 0;
}

Martin Storsj? wrote:

Until OpenGL 2.0 becomes widespread, any OpenGL texture must have a
height and a width which are a power of 2. But the SDL_Surfaces
created by the TTF_Render functions usually aren’t. So to place the
text in a texture, I’d have to create a new, power-of-2 conforming
SDL_Surface, blit the TTF-created one into it, and free the original.
Or I could create a suitable memory area and “blit” by hand.

One solution is to create the texture with glTexImage2D as usual, but
supplying NULL for the pixels parameter. Then you can update rectangles
of any size of this texture using glTexSubImage2D.

iirc glTexSubImage2D was buggy on some cards/drivers…
is that still true or is it considered safe these days?
because I’d like to use this technique as an optimization myself…

glTexSubImage2D would indeed be a great optimization. But at least the latest
nVidia drivers have a bug in there. I know of a race condition inside this
function which causes it to hang under certain circumstances until the opengl
context is no longer displayed (window is iconified or something like that).
It’s a nasty one that showed up on a couple of different cards and on both
Linux and Windows drivers.

GregorOn Wednesday 08 December 2004 10:10, Jonathan Atkins wrote:

On Wed, 8 Dec 2004, Benjamin Deutsch wrote:

Ah, perfect! Koshmaar, I hope you don’t mind, but I pinched your code and
adapted it to OpenGL, since I wanted to try out the glSubTexture2D thing.

Sure, no problem :wink:

So, here it is. It also demonstrates a nice blending effect, and tinting.
It worked as of today using the SDL_ttf from Debian unstable, I can’t
really say more than that, sorry. Oh, and you’ll have to adapt the font
and rotation speed.

Looks nice, and - what’s more important - works perfectly on my old computer, including blending etc. Also, it’s very efficient, in windowed mode it take no more then 20% of cpu cycles along with Winamp, 2x web browser windows, VS NET, 2x DevC++ and other misc things…

Koshmaar

Hello again,

Bob Pendleton wrote:

I have never been able to make TTF_RenderText_Blended work for me. And,
yes, I am using the latest SDL_ttf from cvs. Don’t know what the problem
is, I just can’t make it work. Could you post code that uses it and
makes it work?

I should have been more clear, makes it work with OpenGL.

Ah, perfect! Koshmaar, I hope you don’t mind, but I pinched your code and
adapted it to OpenGL, since I wanted to try out the glSubTexture2D thing.

So, here it is. It also demonstrates a nice blending effect, and tinting.
It worked as of today using the SDL_ttf from Debian unstable, I can’t
really say more than that, sorry. Oh, and you’ll have to adapt the font
and rotation speed.

Hope this helps!

It did, I was failing to properly initialize alpha. Dumb ass bug that I
was never really motivated to find. Visually it produces exactly the
same effect as the code I originally posted using SDL_RenderText_Shaded
because of the way I was converting the 8 bits values to and alpha
value. I am glad to have both working now.

	Thank You Very Much

		Bob PendletonOn Thu, 2004-12-09 at 14:50, Benjamin Deutsch wrote:

Benjamin

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>

#include <SDL.h>
#include <SDL_ttf.h>
#include <GL/gl.h>
#include <GL/glu.h>

int main( int argc, char* argv[] ) {

if( SDL_Init(SDL_INIT_VIDEO)==(-1) ) {
printf(“Could not initialize SDL: %s.\n”, SDL_GetError());
exit(-1);
}

SDL_Surface *screen;

int WINWIDTH = 800, WINHEIGHT = 600, BPP = 32;
screen = SDL_SetVideoMode( WINWIDTH,WINHEIGHT, BPP, SDL_HWSURFACE | SDL_DOUBLEBUF | SDL_OPENGL | SDL_FULLSCREEN );

if( screen == NULL ) {
fprintf(stderr, “Couldn’t set %ix%ix%i video mode: %s\n”, WINWIDTH,WINHEIGHT,BPP, SDL_GetError());
SDL_Quit();
exit(1);
}

// Setup OpenGL
glShadeModel(GL_SMOOTH);
glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glClearColor(0, 0, 0, 0);
glViewport(0, 0, WINWIDTH, WINHEIGHT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-WINWIDTH/2.0, WINWIDTH/2.0, WINHEIGHT/2.0, -WINHEIGHT/2.0, 1.0, -1.0); // note inverted y axis!
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

glClear(GL_COLOR_BUFFER_BIT);

TTF_Init();
TTF_Font *fnt = TTF_OpenFont( “Vera.ttf”, 72 );

SDL_Color foreground = {255,255,255,255}; // White with full alpha

SDL_Surface *sText = TTF_RenderText_Blended( fnt, “Test Blended”, foreground);
//SDL_BlitSurface( sText,NULL, screen,&rcDest );

int texWidth=1, texHeight=1;
while (texWidth < sText->w) texWidth *= 2;
while (texHeight < sText->h) texHeight *= 2;

unsigned char texture;
texture = (unsigned char
) malloc (texWidthtexHeight4);
memset(texture, 0, texWidthtexHeight4); // Black with transparent alpha

GLuint tex_id;
glGenTextures(1, &tex_id);
glBindTexture(GL_TEXTURE_2D, tex_id);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, 4, texWidth, texHeight, 0, GL_RGBA,
GL_UNSIGNED_BYTE, texture);
glTexSubImage2D(GL_TEXTURE_2D, 0, (texWidth - sText->w)/2, (texHeight - sText->h)/2,
sText->w, sText->h, GL_RGBA, GL_UNSIGNED_BYTE, sText->pixels);

fprintf(stderr, " Width: %i Height: %i\n", sText->w, sText->h);
fprintf(stderr, " TexWidth: %i TexHeight: %i\n", texWidth, texHeight);

SDL_Event event;
GLfloat alpha = 0.0;
while (1) {
if ( SDL_PollEvent ( &event ) ) {
if ( event.type == SDL_KEYDOWN ) break ;
}

 glClear(GL_COLOR_BUFFER_BIT);

 glDisable(GL_TEXTURE_2D); // For square
 glPushMatrix();
 glRotatef(-alpha, 0.0, 0.0, 1.0);
 glBegin(GL_QUADS);
   glColor4f(1.0, 0.0, 0.0, 1.0); glVertex3f(-200.0, -200.0, 0.0);
   glColor4f(0.0, 1.0, 0.0, 1.0); glVertex3f( 200.0, -200.0, 0.0);
   glColor4f(0.0, 0.0, 1.0, 1.0); glVertex3f( 200.0,  200.0, 0.0);
   glColor4f(1.0, 1.0, 0.0, 1.0); glVertex3f(-200.0,  200.0, 0.0);
 glEnd();
 glPopMatrix();

 glEnable(GL_TEXTURE_2D); // For text
 glPushMatrix();
 glTranslatef(8.0, 8.0, 0.0);
 glRotatef(alpha, 0.0, 0.0, 1.0);
 glColor4f(0.0, 0.0, 0.0, 0.25);
 glBegin(GL_QUADS);
   glTexCoord2f(0.0, 0.0); glVertex3f(-(sText->w)/2.0, -(sText->h)/2.0, 0.0);
   glTexCoord2f(1.0, 0.0); glVertex3f( (sText->w)/2.0, -(sText->h)/2.0, 0.0);
   glTexCoord2f(1.0, 1.0); glVertex3f( (sText->w)/2.0,  (sText->h)/2.0, 0.0);
   glTexCoord2f(0.0, 1.0); glVertex3f(-(sText->w)/2.0,  (sText->h)/2.0, 0.0);
 glEnd();
 glPopMatrix();


 glPushMatrix();
 glRotatef(alpha, 0.0, 0.0, 1.0);
 glColor4f(alpha/360.0, 1.0-alpha/360.0, 0.0, 1.0);
 glBegin(GL_QUADS);
   glTexCoord2f(0.0, 0.0); glVertex3f(-(sText->w)/2.0, -(sText->h)/2.0, 0.0);
   glTexCoord2f(1.0, 0.0); glVertex3f( (sText->w)/2.0, -(sText->h)/2.0, 0.0);
   glTexCoord2f(1.0, 1.0); glVertex3f( (sText->w)/2.0,  (sText->h)/2.0, 0.0);
   glTexCoord2f(0.0, 1.0); glVertex3f(-(sText->w)/2.0,  (sText->h)/2.0, 0.0);
 glEnd();
 glPopMatrix();

 alpha += 0.01; if (alpha >= 360.0) alpha = 0.0;

 SDL_GL_SwapBuffers();

}

SDL_FreeSurface( sText );
TTF_CloseFont( fnt );
TTF_Quit();
SDL_Quit();
return 0;
}


SDL mailing list
SDL at libsdl.org
http://www.libsdl.org/mailman/listinfo/sdl

±-------------------------------------+