FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

SDL2 and SDLImage

 
Post new topic   Reply to topic     Forum Index -> Derelict
View previous topic :: View next topic  
Author Message
ste3e



Joined: 08 Apr 2012
Posts: 17
Location: New Zealand

PostPosted: Fri Apr 27, 2012 3:38 pm    Post subject: SDL2 and SDLImage Reply with quote

So far I have SDL2 and GL3 running with shaders and am trying to add textures. I have tried both SDL and DevIl and both object when I try to load them:

Code:
import derelict.sdl2.sdl;
import derelict.opengl3.gl3;
import derelict.sdl2.image;
.
.
.
pragma(lib, "DerelictUtil.lib");
pragma(lib, "DerelictSDL2.lib");
pragma(lib, "DerelictGL3.lib");

.
.
.
try{
        DerelictSDL2.load();
    }catch(Exception e){
        writeln("Error loading SDL2 lib");
      return false;
    }
    try{
        DerelictGL3.load();
    }catch(Exception e){
        writeln("Error loading GL3 lib");
      return false;
    }
    try{
        DerelictSDL2Image.load();
    }catch(Exception e){
        writeln("Error loading SDL2 Image lib");
      return false;
    }


I get "Error loading SDL2 Image lib" printed to the console when I try to run the program so I am having an issue loading DerelictSDL2Image. If I convert the code to the DevIl I get the same problem. Does anyone have some working syntax they could share or have I missed something?
Back to top
View user's profile Send private message Visit poster's website
aldacron



Joined: 05 May 2004
Posts: 1322
Location: Seoul, South Korea

PostPosted: Fri Apr 27, 2012 11:09 pm    Post subject: Reply with quote

Your code is fine. The issue is that there's an error happening when you attempt to load the shared library. Rather than eating the exception and printing your own error message, you should print the exception. That will give you a clue as to what the problem is.
_________________
The One With D | The One With Aldacron | D Bits
Back to top
View user's profile Send private message Send e-mail Visit poster's website
ste3e



Joined: 08 Apr 2012
Posts: 17
Location: New Zealand

PostPosted: Sat Apr 28, 2012 1:31 am    Post subject: Reply with quote

I figured that out with the DevIl thing which I am chasing in parallel. The error I get is:

libderelict.util.exception.SharedLibLoadException@..\import\derelict\util\exception.d(38): Failed to load one or more shared libraries:
SDL2_image.dll - The specified module could not be found.
----------------
437E1C
437C93
456EF0

I do not understand this one because I have a copy of SDL2_image.dll sitting in the windows\bin dir along with the SDL2.dll, in fact, in every directory where I have a copy of SDL2.dll I also have a copy of SDL2_image.dll.
Back to top
View user's profile Send private message Visit poster's website
aldacron



Joined: 05 May 2004
Posts: 1322
Location: Seoul, South Korea

PostPosted: Sat Apr 28, 2012 11:02 pm    Post subject: Reply with quote

ste3e wrote:
I figured that out with the DevIl thing which I am chasing in parallel. The error I get is:

libderelict.util.exception.SharedLibLoadException@..\import\derelict\util\exception.d(3Cool: Failed to load one or more shared libraries:
SDL2_image.dll - The specified module could not be found.
----------------
437E1C
437C93
456EF0

I do not understand this one because I have a copy of SDL2_image.dll sitting in the windows\bin dir along with the SDL2.dll, in fact, in every directory where I have a copy of SDL2.dll I also have a copy of SDL2_image.dll.


You mean windows\bin in the DMD directory? It shouldn't be there. The Windows system loader, which Derelict uses internally, has no idea about that path. The best thing to do is to make sure all of the DLLs you use are in the same directory as your executable.
_________________
The One With D | The One With Aldacron | D Bits
Back to top
View user's profile Send private message Send e-mail Visit poster's website
ste3e



Joined: 08 Apr 2012
Posts: 17
Location: New Zealand

PostPosted: Sun Apr 29, 2012 5:04 pm    Post subject: Reply with quote

Sorted the DevIl side of things by following your advice. I am still having issues with SDLImage. It is now claiming "libjpeg-8.dll was not found. Part of the issue here, I suspect, is that I never compiled the SDL2 dll files but sourced them off the net (I don't have VC08/10).

The question remaining is that given the main window of the app is SDL2, is there any advantage using SDL2Image rather than DevIl for constructing openGL textures. Basically the only thing the image software is being used for is to pull the format and pixel data out of image files.
Back to top
View user's profile Send private message Visit poster's website
aldacron



Joined: 05 May 2004
Posts: 1322
Location: Seoul, South Korea

PostPosted: Sun Apr 29, 2012 11:11 pm    Post subject: Reply with quote

ste3e wrote:
Sorted the DevIl side of things by following your advice. I am still having issues with SDLImage. It is now claiming "libjpeg-8.dll was not found. Part of the issue here, I suspect, is that I never compiled the SDL2 dll files but sourced them off the net (I don't have VC08/10).


When does the error come... when you call SDL2Image.load or when you attempt to load a .jpeg image? If it's the former (which I doubt), it means your SDL2_image.dll is linked with the libjpeg import library. If that's the case, you'll likely need not only libjpeg, but other libraries, too (like libpng). If it's the latter (which I assume it is), then it means SDL_image is loading libjpeg lazily and all you need to do is put libjpeg-8.dll in the same directory as your executable. Unlike DevIL, SDL_image does not link statically to the other libraries it uses.

I'm using SDL2_image in my BorderWatch project to load PNG images, so I also need to include libpng.dll. But since I'm not loading JPEGs, I don't need libjpeg.

Quote:

The question remaining is that given the main window of the app is SDL2, is there any advantage using SDL2Image rather than DevIl for constructing openGL textures. Basically the only thing the image software is being used for is to pull the format and pixel data out of image files.


If you aren't using the SDL2 renderer, then it really doesn't matter.
_________________
The One With D | The One With Aldacron | D Bits
Back to top
View user's profile Send private message Send e-mail Visit poster's website
ste3e



Joined: 08 Apr 2012
Posts: 17
Location: New Zealand

PostPosted: Mon Apr 30, 2012 6:21 pm    Post subject: Reply with quote

It is the former. The following code throws the exception:


Code:
import std.stdio;
import derelict.sdl2.sdl;
import derelict.sdl2.image;
import derelict.devil.il;;
import derelict.opengl3.gl3;

pragma(lib, "DerelictUtil.lib");
pragma(lib, "DerelictSDL2.lib");
pragma(lib, "DerelictGL3.lib");
pragma(lib, "DerelictIL.lib");


int main(){
   try{
        DerelictSDL2.load();
    }catch(Exception e){
        writeln("Error loading SDL2 lib");
      return false;
    }
    try{
        DerelictGL3.load();
    }catch(Exception e){
        writeln("Error loading GL3 lib");
      return false;
    }
   try{
        DerelictSDL2Image.load();
    }catch(Exception e){
        writeln("Error loading SDL2 image lib ", e);
      return false;
    }
    try{
        DerelictIL.load();
    }catch(Exception e){
        writeln("Error loading DevIl image lib ", e);
      return false;
    }

   writeln("Drop through OK");

   return 0;
}


Is it not possible to create a folder somewhere, stick all the required c.dll files in it, and tell DMD to look there rather than dumping the dll files into the current project?
Back to top
View user's profile Send private message Visit poster's website
aldacron



Joined: 05 May 2004
Posts: 1322
Location: Seoul, South Korea

PostPosted: Mon Apr 30, 2012 8:21 pm    Post subject: Reply with quote

ste3e wrote:
It is the former.


Hmm. That's not what I expected. SDL_image is supposed to be loading stuff lazy. Where did you download the DLL?

Quote:

Is it not possible to create a folder somewhere, stick all the required c.dll files in it, and tell DMD to look there rather than dumping the dll files into the current project?


DMD has nothing to do with it. When you say project, I assume that means you are using an IDE. What I typically do in that case is to create a 'bin' directory, go to the project settings and configure that directory as the working directory, and dump all of my dlls and resource directories there.
_________________
The One With D | The One With Aldacron | D Bits
Back to top
View user's profile Send private message Send e-mail Visit poster's website
ste3e



Joined: 08 Apr 2012
Posts: 17
Location: New Zealand

PostPosted: Mon Apr 30, 2012 8:38 pm    Post subject: Reply with quote

SDL_gfx DevPak

This DevPak was created by Rob Loach (http://www.robloach.net).

Please visit www.robloach.net for more information.


Was where I got it. Could you suggest another copy?
Back to top
View user's profile Send private message Visit poster's website
aldacron



Joined: 05 May 2004
Posts: 1322
Location: Seoul, South Korea

PostPosted: Tue May 01, 2012 1:51 am    Post subject: Reply with quote

ste3e wrote:
SDL_gfx DevPak

This DevPak was created by Rob Loach (http://www.robloach.net).

Please visit www.robloach.net for more information.


Was where I got it.


Well, I don't see anything on his site about SDL. I googled SDL_gfx Devpak. The only thing I could find was seven years old and didn't inlcude a copy of the SDL_image DLL. If it had, it would have been the wrong version anyway. Regardless, because of the nature of your error, I'm going to assume that your problem is precisely that -- an older version of SDL_image (which DerelictSDL2Image shouldn't even be able to load, given that it's looking for SDL2_image.dll and not SDL_image.dll).

Quote:
Could you suggest another copy?


There have been no official releases of either SDL2 or SDL2_image and I don't know of any third party sites that have made precompiled binaries available. So, to make sure you have exactly what you need, I've uploaded copies of both SDL2 and SDL2_image to the Downloads section of the Derelict3 repository. I built them myself. The SDL2 dll was compiled from the source snapshot released on Feb. 20. The SDL2_image dll was compiled from a checkout of the repository around the same time period. I use both in a couple of projects, so I know they work.
_________________
The One With D | The One With Aldacron | D Bits
Back to top
View user's profile Send private message Send e-mail Visit poster's website
ste3e



Joined: 08 Apr 2012
Posts: 17
Location: New Zealand

PostPosted: Tue May 01, 2012 6:11 pm    Post subject: Reply with quote

Thankyou for the dlls. I found I still had to paste a copy of libpng15-15.dll and zlib1.dll to the project bin before calling any SDL2_image functions, but now it is all go. Just to round this post off and make it easier for those who follow I have posted the working code below (it contains a cool snip of code for flipping images to get them proper with openGL by tito http://stackoverflow.com/questions/5862097/sdl-opengl-screenshot-is-black).

First a brief rundown of what I found to be required and where (I am using XP):

1) a built version of Derelict3 with sc.ini properly configured (http://www.sjonesart.com/gl.php)

2) driver files SDL2.dll and SDL2_Image.dll both of which aldacron has provided as binaries as linked to in the previous post These files need to be placed in the same folder as your compiled .exe

3) I also required libpng15-15.dll and zlib1.dll be placed alongside the SDL2 dlls.


Code:
import std.stdio;      //required libpng15-15.dll + zlib1.dll placed in bin dir
import std.string;
import std.conv;
import std.path;
import std.file;
import derelict.sdl2.sdl;
import derelict.sdl2.image;
import derelict.opengl3.gl3;

pragma(lib, "DerelictUtil.lib");
pragma(lib, "DerelictSDL2.lib");
pragma(lib, "DerelictGL3.lib");

SDL_Window *win;
SDL_GLContext context;
int w=800, h=600;
bool running=true;
uint shader = 0, vao = 0, tid = 0, colLoc = 0;
int flags=SDL_WINDOW_OPENGL | SDL_WINDOW_BORDERLESS | SDL_WINDOW_SHOWN;

bool initSDL_GL(){
   if(SDL_Init(SDL_INIT_VIDEO) < 0){
      writefln("Error initializing SDL");
      return false;
   }
   SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
   SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
   SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
   SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);

   win=SDL_CreateWindow("3Doodle", SDL_WINDOWPOS_CENTERED,
   SDL_WINDOWPOS_CENTERED, w, h, flags);
    if(!win){
        writefln("Error creating SDL window");
      SDL_Quit();
      return false;
     }

    context=SDL_GL_CreateContext(win);
    SDL_GL_SetSwapInterval(1);
   
   glClearColor(0.0, 0.0, 0.0, 1.0);
   glViewport(0, 0, w, h);

    DerelictGL3.reload();

    return true;
}


bool initShaders(){
   const string vshader="
   #version 330
   layout(location = 0) in vec3 pos;
   layout(location = 1) in vec2 texCoords;

   out vec2 coords;

   void main(void)
   {
      coords=texCoords.st;

       gl_Position = vec4(pos, 1.0);
   }
   ";
   const string fshader="
   #version 330

   uniform sampler2D colMap;

   in vec2 coords;

   void main(void)
   {
      vec3 col=texture2D(colMap, coords.st).xyz;

      gl_FragColor = vec4((coords.yyx + col), 1.0);
   }
   ";

   shader=glCreateProgram();
   if(shader == 0){
      writeln("Error: GL did not assigh main shader program id");
      return false;
   }
   int vshad=glCreateShader(GL_VERTEX_SHADER);
   const char *vptr=toStringz(vshader);
   glShaderSource(vshad, 1, &vptr, null);
   glCompileShader(vshad);   
   int status, len;
   glGetShaderiv(vshad, GL_COMPILE_STATUS, &status);
   if(status==GL_FALSE){
      glGetShaderiv(vshad, GL_INFO_LOG_LENGTH, &len);
      char[] error=new char[len];
      glGetShaderInfoLog(vshad, len, null, cast(char*)error);
      writeln(error);
      return false;
   }
   int fshad=glCreateShader(GL_FRAGMENT_SHADER);
   const char *fptr=toStringz(fshader);
   glShaderSource(fshad, 1, &fptr, null);
   glCompileShader(fshad);   
   glGetShaderiv(vshad, GL_COMPILE_STATUS, &status);
   if(status==GL_FALSE){
      glGetShaderiv(fshad, GL_INFO_LOG_LENGTH, &len);
      char[] error=new char[len];
      glGetShaderInfoLog(fshad, len, null, cast(char*)error);
      writeln(error);
      return false;
   }
   glAttachShader(shader, vshad);
   glAttachShader(shader, fshad);
   glLinkProgram(shader);
   glGetShaderiv(shader, GL_LINK_STATUS, &status);
   if(status==GL_FALSE){
      glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &len);
      char[] error=new char[len];
      glGetShaderInfoLog(shader, len, null, cast(char*)error);
      writeln(error);
      return false;
   }


   return true;
}

bool initVAO(){
   uint vbov, vboc;
   const float[] v = [   -0.75f, -0.75f, 0.0f,
                  0.75f, 0.75f, 0.0f,
                  -0.75f, 0.75f, 0.0f];
   const float[] c = [   0.0f, 0.0f,
                  1.0f, 1.0f,
                  0.0f, 1.0f];
   glGenVertexArrays(1, &vao);
   assert(vao > 0);

   glBindVertexArray(vao);

   glGenBuffers(1, &vbov);
   assert(vbov > 0);
   glBindBuffer(GL_ARRAY_BUFFER, vbov);
   glBufferData(GL_ARRAY_BUFFER, v.length * GL_FLOAT.sizeof, v.ptr, GL_STATIC_DRAW);
   glEnableVertexAttribArray(0);
   glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, null);         
   glBindBuffer(GL_ARRAY_BUFFER, 0);

   glGenBuffers(1, &vboc);
   assert(vboc > 0);
   glBindBuffer(GL_ARRAY_BUFFER, vboc);
   glBufferData(GL_ARRAY_BUFFER, c.length * GL_FLOAT.sizeof, c.ptr, GL_STATIC_DRAW);
   glEnableVertexAttribArray(1);
   glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, null);         
   glBindBuffer(GL_ARRAY_BUFFER, 0);

   glBindVertexArray(0);   

   return true;
}

bool initUniforms(){
   colLoc=glGetUniformLocation(shader, "colMap");
   if(colLoc == -1){writeln("Error: main shader did not assign id to sampler2D colMap"); return false;}

      glUseProgram(shader);
      glUniform1i(colLoc, 0);
      glUseProgram(0);

   return true;
}

bool initTex(){
   assert(exists("MaoriPartyTransforms.png"));
   SDL_Surface *s=IMG_Load("MaoriPartyTransforms.png");
   assert(s);

   glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
   glGenTextures(1, &tid);
   assert(tid > 0);
   glBindTexture(GL_TEXTURE_2D, tid);

   int mode = GL_RGB;
   if(s.format.BytesPerPixel == 4) mode=GL_RGBA;
   
   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);   
   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

   glTexImage2D(GL_TEXTURE_2D, 0, mode, s.w, s.h, 0, mode, GL_UNSIGNED_BYTE, flip(s).pixels);

   SDL_FreeSurface(s);
   return true;
}

//thanks to tito http://stackoverflow.com/questions/5862097/sdl-opengl-screenshot-is-black
SDL_Surface* flip(SDL_Surface* sfc)
{
     SDL_Surface* result = SDL_CreateRGBSurface(sfc.flags, sfc.w, sfc.h,
         sfc.format.BytesPerPixel * 8, sfc.format.Rmask, sfc.format.Gmask,
         sfc.format.Bmask, sfc.format.Amask);
     ubyte* pixels = cast(ubyte*) sfc.pixels;
     ubyte* rpixels = cast(ubyte*) result.pixels;
     uint pitch = sfc.pitch;
     uint pxlength = pitch*sfc.h;
     assert(result != null);

     for(uint line = 0; line < sfc.h; ++line) {
         uint pos = line * pitch;
         rpixels[pos..pos+pitch] =
             pixels[(pxlength-pos)-pitch..pxlength-pos];
     }

     return result;
}


int main(){
   try{
        DerelictSDL2.load();
    }catch(Exception e){
        writeln("Error loading SDL2 lib");
      return false;
    }
    try{
        DerelictGL3.load();
    }catch(Exception e){
        writeln("Error loading GL3 lib");
      return false;
    }
   try{
        DerelictSDL2Image.load();
    }catch(Exception e){
        writeln("Error loading SDL image lib ", e);
      return false;
    }
   
   writeln("Init SDL_GL: ", initSDL_GL());
   writeln("Init shaders: ", initShaders());
   writeln("Init VAO: ", initVAO());
   writeln("Init uniforms: ", initUniforms());
   writeln("Init textures: ", initTex());
   
   while(running){
      SDL_Event e;
      while(SDL_PollEvent(&e)){
         switch(e.type){
            case SDL_KEYDOWN:
            running=false;
            break;
            default:
            break;
         }
      }
      glClear(GL_COLOR_BUFFER_BIT);

      glUseProgram(shader);      

      glBindVertexArray(vao);

      glActiveTexture(GL_TEXTURE0);
      glBindTexture(GL_TEXTURE_2D, tid);

      glDrawArrays(GL_TRIANGLES, 0, 6);

      glBindTexture(GL_TEXTURE_2D, 0);
      glBindVertexArray(0);
      glUseProgram(0);

      SDL_GL_SwapWindow(win);
   }

   SDL_GL_DeleteContext(context);
   SDL_DestroyWindow(win);
   SDL_Quit();

   return 0;
}
Back to top
View user's profile Send private message Visit poster's website
aldacron



Joined: 05 May 2004
Posts: 1322
Location: Seoul, South Korea

PostPosted: Wed May 02, 2012 2:03 am    Post subject: Reply with quote

ste3e wrote:
Thankyou for the dlls. I found I still had to paste a copy of libpng15-15.dll and zlib1.dll to the project bin before calling any SDL2_image functions, but now it is all go.


Of, course! You are loading a .png image. SDL2_image uses libpng to load them, so it has to be on your path. And libpng has a dependency on zlib, so you need that on the path as well. The difference is that older versions of SDL_image linked with the import libraries for every third-party library it used, which required all of those DLLs to be available when any app using SDL_image started up. Now, SDL2_image no longer links with those import libraries. Instead, when you try to load an image that requires a third-party library, SDL2_image will load the appropriate DLL via system calls (the same way Derelict loads DLLs). That means you only need to have the libraries for the image types you need and any dependencies they have.

Quote:
1) a built version of Derelict3 with sc.ini properly configured (http://www.sjonesart.com/gl.php)


Well, I just looked over the steps on that site and I have to say he's making it much more difficult than it is. There's never any need to cut/copy stuff around, or to modify sc.ini. Ever. And it's really not a good idea to modify sc.ini at all, because you'll have to do so every time you download a new version of DMD. I've got three different DMD configurations active on my system and two different versions of Derelict that I compile with and never once have I modified any sc.ini. I suppose one of these days I'll have to write up a tutorial on downloading and using Derelict myself. It really is simple.

Quote:

3) I also required libpng15-15.dll and zlib1.dll be placed alongside the SDL2 dlls.


This is only necessary if you need to load PNG images. Take a look at the SDL_image project page and you'll see this (which is essentially what I explained above):

Quote:
As of SDL_image 1.2.5, JPEG, PNG, TIFF, and WEBP image loading libraries are dynamically loaded, so if you don't need to load those formats, you don't need to include those shared libraries. libpng depends on libz, and libtiff depends on both libz and libjpeg.

_________________
The One With D | The One With Aldacron | D Bits
Back to top
View user's profile Send private message Send e-mail Visit poster's website
ste3e



Joined: 08 Apr 2012
Posts: 17
Location: New Zealand

PostPosted: Wed May 02, 2012 4:31 am    Post subject: Reply with quote

Quote:
I found I still had to paste a copy of libpng15-15.dll and zlib1.dll to the project bin before calling any SDL2_image functions, but now it is all go.


What I meant to say was that before I had included any code that called upon SDL to load any image I had to have libpng15-15.dll and zlib1.dll in place, otherwise I ended with errors like the one over the missing jpeg dll when using the first SDL2Image.dll.

Quote:
I suppose one of these days I'll have to write up a tutorial on downloading and using Derelict myself. It really is simple.


Everything is simple when you already know how to do it! When you do not know how to do it, and there is no working code about that you might play with, it is quite a different story.
Back to top
View user's profile Send private message Visit poster's website
Display posts from previous:   
Post new topic   Reply to topic     Forum Index -> Derelict All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group