Jump to content
The Dark Mod Forums
Sign in to follow this  
greebo

Background Image

Recommended Posts

I opened a new branch with the Overlay plugin, but I'm a bit stuck when it comes to do the actual OpenGL drawing.

 

Below is my render function. It basically creates a new displaylist and sends the quad coordinates.

	// OpenGLRenderable implementation, back-end render method
void render(RenderStateFlags state) const {
	// Create the temporary list 
	// (TODO: make this a class member and construct the list only once)
	int _displayList = glGenLists(1);

	glNewList(_displayList,  GL_COMPILE);

	glBegin(GL_QUADS);
	for (VertexList::const_iterator i = _quad.begin();
		 i != _quad.end();
		 ++i)
	{
		glNormal3f(i->normal[0], i->normal[1], i->normal[2]);
		glColor3f(1.f, 0.f, 0.f);
		//glTexCoord2f(i->texcoord[0], i->texcoord[1]);
		glVertex3fv(Vector3(i->vertex));
	}
	glEnd();

	glEndList();

	glCallList(_displayList);

	// Delete the list
	glDeleteLists (_displayList, 1);
}

The vertices, normals and texcoords (in this order) are stored in a std::list of ArbitraryMeshVertex structure:

_quad.push_back(ArbitraryMeshVertex(Vertex3f(-100,-100,0), Vector3(0,0,1), TexCoord2f(0, 1)));
_quad.push_back(ArbitraryMeshVertex(Vertex3f(+100,-100,0), Vector3(0,0,1), TexCoord2f(1, 1)));
_quad.push_back(ArbitraryMeshVertex(Vertex3f(+100,+100,0), Vector3(0,0,1), TexCoord2f(1, 0)));
_quad.push_back(ArbitraryMeshVertex(Vertex3f(-100,+100,0), Vector3(0,0,1), TexCoord2f(0, 0)));

Problem is, I don't see anything. There must be something I miss and I don't know what it could be. These changes are already committed to the overlay branch - could you give me a hint what to do next?

Share this post


Link to post
Share on other sites

First of all, don't bother with display lists for this, since you are only drawing a single quad the use of DLs won't help (and may make things worse). I'm not sure your list is valid in this case anyway, because it depends on non-GL program code (the list iterator bit) which cannot be stored in a DL.

 

When it comes to testing, it is best to start by hardcoding the values first off. Just try drawing a fixed quad in a single colour, then try binding a texture to it[1], then try parameterising the size (I presume this is why you are storing coordinates).

 

If you can't get it to render a single quad, you would then need to extend the examination to things like whether your function is actually being called, and what matrices are being set before hand which could affect the rendering.

 

[1] The problem you will likely have, is that the 2D ortho views may not have textures enabled at all, since nothing else draws textures in them. You might need to look further afield at the renderer code to get this enabled.

Share this post


Link to post
Share on other sites

This is my progress so far, I've been able to overlay an arbitrary shader image over the background (currently, it's stretched to fit the window dimensions, which the user will be able to change via the preference settings).

 

overlay15md.th.jpg

 

If things go well, I will be able to finish this soon.

Share this post


Link to post
Share on other sites

I've implemented the blend functions for the image overlay, the image's transparency can now be adjusted as well:

 

overlay21as.th.jpg

Share this post


Link to post
Share on other sites

Cool, I was going to suggest the alpha blending but wasn't sure how difficult it would be.

 

I don't know how far along you are with the GUI interface for this function, but I would suggest a dialog accessed from the View menu, with an option to browse for an image and a slider bar to configure the opacity.

Share this post


Link to post
Share on other sites

This is already implemented :), although at the moment only valid shaders (those in the material files) are allowed.

 

I'll have to figure out how to create actual Shader objects out of image files chosen from a file dialog (which I have to create as well with a Registry Connection for the Preference Dialog).

Share this post


Link to post
Share on other sites
I'll have to figure out how to create actual Shader objects out of image files chosen from a file dialog (which I have to create as well with a Registry Connection for the Preference Dialog).

 

Look at the way notex.bmp is loaded in the shaders plugin, this is a GL texture created from a bitmap on disk. Presumably you could use a similar technique.

Share this post


Link to post
Share on other sites

Ok.

 

Shall I merge the current version with the trunk or do you suggest to wait until it's feature-complete?

Share this post


Link to post
Share on other sites

Now, this is getting tiresome! I've tried to figure out for 2 hours now how to load a image, but the damn thing just doesn't get loaded...

 

The GlobalTextures().capture() method returns an q_texture object with texture_number 0 and tells me that "the image couldn't be loaded", but still returns a non-NULL pointer, which makes it hard for the calling function to determine whether the operation was successful or not.

 

It's really frustrating - there are tons of capture(), realise() and whatever methods calling each other and most of them are buried within some cpp-File without a proper interface. And this is giving me the creeps:

typedef HashedCache<TextureKey, qtexture_t, TextureKeyHashNoCase, TextureKeyEqualNoCase, TextureConstructor> qtextures_t;

 

I think I will expand the IShader interface by methods to create new shaders. The only place where Shader objects are allocated is the Shaders plugin (of course), but other plugins don't get a real chance to do it, or I'm missing something vital.

Share this post


Link to post
Share on other sites
It's really frustrating - there are tons of capture(), realise() and whatever methods calling each other and most of them are buried within some cpp-File without a proper interface. And this is giving me the creeps:

typedef HashedCache<TextureKey, qtexture_t, TextureKeyHashNoCase, TextureKeyEqualNoCase, TextureConstructor> qtextures_t;

 

Yep, that's Radiant for you. Welcome to "Not Invented Here" syndrome -- that HashedCache crap is just a stupid reimplementation of std::map (except that it's unsorted, so perhaps marginally faster in theory but not by much).

 

I think I will expand the IShader interface by methods to create new shaders. The only place where Shader objects are allocated is the Shaders plugin (of course), but other plugins don't get a real chance to do it, or I'm missing something vital.

 

I don't think you need an IShader, just a texture (qtexture_t) object, with a GL number. You would be better off extending the GlobalTextures module to accept new textures, however this might be tricky because there is loads of ancient crap in there (void* callbacks etc). This probably needs to be done anyway to accomodate addnormals() and other map expressions that create new textures.

Share this post


Link to post
Share on other sites

Thanks guys :)

 

I wouldn't call it a major update (from looking at the things Orbweaver does to the code), but obviously it's a popular one, which is nice. B)

Share this post


Link to post
Share on other sites

Orbweaver, do you know if the GlobalFileSystem() is capable of loading files outside of the actual Project folder (i.e. C:/games/doom3/darkmod/)?

 

I could successfully load the file if the path is specified relatively to the mod root directory, but everything else doesn't seem to work.

Share this post


Link to post
Share on other sites

I'm pretty sure all of the VFS methods deal only with stuff underneath the Doom 3 directory and in .pk4 files. It might be necessary to load the image yourself, and extend the TexturesCache module interface with another method to insert a new image into the cache, e.g. virtual void insertImage(const std::string& name, const Image* img)

 

It looks like an Image object is just an interface which defines, amongst other things, methods to return the height and width of the image and a pointer to an array of bytes, which you can presumably get through GDK's image loading functionality. Inserting it into the textures cache might be dirtier, because there is some stuff about LoadImageCallbacks that you would have to deal with but I think there is a default you can use for this. Oh, and there is that horrible HashedCache again.

 

If you were feeling particularly energetic, you might find that splitting out the TexturesCache into a separate module would make things easier, and it might even be possible to get rid of the image callback stuff altogether, depending on whether anything is actually using it.

Share this post


Link to post
Share on other sites
I'm pretty sure all of the VFS methods deal only with stuff underneath the Doom 3 directory and in .pk4 files. It might be necessary to load the image yourself, and extend the TexturesCache module interface with another method to insert a new image into the cache, e.g. virtual void insertImage(const std::string& name, const Image* img)

I was afraid I would have to do this, but there seems to be no other way around it.

 

If you were feeling particularly energetic, you might find that splitting out the TexturesCache into a separate module would make things easier, and it might even be possible to get rid of the image callback stuff altogether, depending on whether anything is actually using it.

That was my plan ^_^

Share this post


Link to post
Share on other sites

I think I found another way, but I'm still stuck. What I did is the following:

 

The image modules expect to have an ArchiveFile& reference passed to them. These modules are cycled through by the QERApp_LoadImage method that passes the ArchiveFile* pointers to them.

 

I placed a check after cycling through the modules whether the returned Image* pointer is being NULL or not (if it's NULL, the file could not be opened through the GlobalFileSystem().openFile() method). If that is the case, I try to open the file myself by creating a DirectoryArchiveFile with the direct path to the file, which was successful. The good thing is, that the DirectoryArchiveFile derives from ArchiveFile which is required by the image modules.

 

(The slicing that happens when passing it by reference is not a problem, I already checked that.)

 

Now if I pass that DirectoryArchiveFile& to the JPEG image module (which succeeds, the size of the passed buffer is shown correctly in the JPEG module), they try to create a ScopedArchiveBuffer from it, and this is where the problem starts, because the resulting buffer does not get filled correctly. The ScopedArchiveBuffer stays at size 0, and I don't know why. The buffer should be filled by an fread() function that returns as result the length of read bytes, but this is 0 somehow.

 

How can I check for I/O errors when using fread()?

 

Another question, if that turns out to be hopeless: if I create a GdkPixBuf from a file on disk, how would I get the image data into an Image structure?

 

I think I will try to accomplish this with a GdkPixBuf*

Share this post


Link to post
Share on other sites

I played around a bit more with the image modules and now it's getting weird, because if I specify a BMP, the image gets loaded fine, but that's the only format that is successfully loaded. All the others (TGA, JPG, DDS) fail to load and can't seem to fill their ScopedArchiveBuffer properly. This bugs me...

 

edit: I found the problem, it seemed that the ScopedArchiveBuffer cannot be used more than once as the filepointer doesn't get reset to the start of the inputfile. I can work my way around this, I think. Still, I could implement an own imageloader making use of GdkPixBuf as well.

Share this post


Link to post
Share on other sites

I recommend staying away from the legacy Radiant stuff like ArchiveBuffer, and instead use GdkPixbufs like you originally suggested. I have a (very) future task to remove all of that archive stuff and just have the VFS return a std::istream& with the content of the file, since the current implementation is, like most legacy Radiant code, unnecessarily complex and home-grown.

 

Note that anything called "Scoped" is probably a smart pointer of some sort, and will destroy its owned content when it leaves scope (the end of { }).

Share this post


Link to post
Share on other sites

Ok, I wrote my own GdkImageLoader now and it works. It's slow as I transfer the RGBA values one by one (takes about 1 sec. for a 8 megapixel image on my system, so I guess it's ok).

 

Where should I put this loader? Should I attach it to the existing image modules and name it "GDK", so that other modules can make use of it as well? Or should I leave it as helper class in the Overlay plugin?

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this  

×
×
  • Create New...