PDA

View Full Version : [SOLVED] SDL surfaces...



pjpdev
14-11-2009, 01:05 PM
For PJPlib's graphics core I need to be able to get various data from the surfaces. But PSDL_Surface can't give me stuff like width, height and format. I need to use TSDL_Surface instead, but then I can't load images into it because the loading routines of JEDI-SDL return pointers.

For PJPlib I've decided to use OpenGL for graphics rendering, so I need to be able to convert the PSDL_Surface data to OpenGL textures.

Can any pointer-guru help me out here please?

Thanks in advance.

Stoney
14-11-2009, 08:30 PM
For PJPlib's graphics core I need to be able to get various data from the surfaces. But PSDL_Surface can't give me stuff like width, height and format. I need to use TSDL_Surface instead, but then I can't load images into it because the loading routines of JEDI-SDL return pointers.

After you've called a loading routine and assuming that the image has been loaded correctly, you can get the width of the surface with MySDL_Surface^.w and the height with MySDL_Surface^.h. (var MySDL_Surface: PSDL_Surface should be declared somewhere in your code.) As far as I know w and h are read-only, so don't try to change the values.



For PJPlib I've decided to use OpenGL for graphics rendering, so I need to be able to convert the PSDL_Surface data to OpenGL textures.

Basically you just need to write your own texture loader or use an existing one. :)

For example to convert a SDL_Surface into a texture to be used with OpenGL, you can use this little function (it also scales the surfaces that are not power of 2):


function CreateTexture(SDL_Surface: PSDL_Surface): Integer;
var Texture: TGLuInt;
Begin
Result := -1;
if Assigned(SDL_Surface) then
begin
glGenTextures(1, @Texture);
glBindTexture(GL_TEXTURE_2D, Texture);
if SDL_Surface.format.BytesPerPixel > 3 then glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, SDL_Surface^.w, SDL_Surface^.h,0, GL_RGBA, GL_UNSIGNED_BYTE, SDL_Surface^.pixels)
else glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, SDL_Surface^.w, SDL_Surface^.h,0, GL_RGB, GL_UNSIGNED_BYTE, SDL_Surface^.pixels);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
if SDL_Surface.format.BytesPerPixel > 3 then gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, SDL_Surface^.w, SDL_Surface^.h, GL_RGBA, GL_UNSIGNED_BYTE, SDL_Surface^.pixels)
else gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB, SDL_Surface^.w, SDL_Surface^.h, GL_RGB, GL_UNSIGNED_BYTE, SDL_Surface^.pixels);
SDL_FreeSurface(SDL_Surface);
Result := Texture;
end;
End;

...

var
MyTexture: GLuInt;
MySDL_Surface: PSDL_Surface;

begin
// SDL init and OpenGL init

glEnable(GL_TEXTURE_2D);

MySDL_Surface := IMG_Load(...);
MyTexture := CreateTexture(MySDL_Surface);

// Game Loop
while ... do
begin
glBindTexture(GL_TEXTURE_2D, Texture);
// Draw quad here

end;

end.

Alternatively, you can the easySDL texture loader from DelphiGL:
http://svn.delphigl.com/websvn/filedetails.php?repname=dglsdk_linux&path=%2Ftrunk%2Fheader%2FeasySDLTextures.pas&rev=174

pjpdev
15-11-2009, 08:43 AM
Thanks Stoney, it helped a lot.

pjpdev
15-11-2009, 11:44 AM
Now I just get a blank quad... I tried figuring it out, but it just won't work.

Here's my image loading code:


function TPJPImage.LoadImage(filename: PChar): Boolean;
var
surface: PSDL_Surface;
nOfColors: GLint;
begin
//Load the texture into memory
surface := IMG_Load(filename);
if (surface = nil) then
begin
Result := False;
Exit;
end;

//Process the surface
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);

glGenTextures(1, @texture);
glBindTexture(GL_TEXTURE_2D, texture);

glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);

glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTE R, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTE R, GL_NEAREST);

nOfColors := surface^.format^.BitsPerPixel;
if (nOfColors = 4) then //Texture has alpha channel
begin
glTexImage2D(GL_TEXTURE_2D, 0, 4, surface^.w, surface^.h, 0, GL_RGBA,
GL_UNSIGNED_BYTE, surface^.pixels);
gluBuild2DMipmaps(GL_TEXTURE_2D, 4, surface^.w, surface^.h, GL_RGBA,
GL_UNSIGNED_BYTE, surface^.pixels);
end
else if (nOfColors = 3) then //No alpha channel
begin
glTexImage2D(GL_TEXTURE_2D, 0, 3, surface^.w, surface^.h, 0, GL_RGB,
GL_UNSIGNED_BYTE, surface^.pixels);
gluBuild2DMipmaps(GL_TEXTURE_2D, 3, surface^.w, surface^.h, GL_RGB,
GL_UNSIGNED_BYTE, surface^.pixels);
end;

fWidth := surface^.w;
fHeight := surface^.h;

SDL_FreeSurface(surface);
Result := True;
end;


The texture variable belongs to the TPJPImage class and is a GLuint.

pjpdev
15-11-2009, 11:49 AM
Oh... never mind. I used BitsPerPixel instead of BytesPerPixel :-[

Problem solved.