Jump to content

  • Log In with Google      Sign In   
  • Create Account


PAndersson

Member Since 14 Dec 2009
Offline Last Active Dec 22 2013 08:55 AM

Topics I've Started

Tools for proving things for multithreaded systems

09 February 2013 - 06:50 PM

I have finalized the intiial threading model for a program I'm working on, and due to the nature of its enviroment I have to allow deadlocks to occur or loose much of the benift from multithreading. Fortunatly, it also enables easy detection and resolution of deadlocks without rolling anything back; except for one special case though the programmer has to go out of his way to make that one possible and those can still easily be detected though not resolved.

 

Anyway, I do not think there are any more cases where deadlocking can occur but I'm not 100% certain either. So I'm wondering if there are any good tools or methods for proving that deadlocking is impossible (other than that onbe case I mentioned) in a system of unknown size? The only method I'm aware of is petri nets, though I do not know if that method can be adapted to work with a model of unknown size or not.


Designing an asset loading system

02 January 2013 - 02:08 PM

So I'm working on my first hobby game where I have to implement a proper asset loading system, in my previous projects I have had no problem fitting everything in memory at once. In this, I have estimated that VRAM will most likely be a limiting factor that makes that approach impossible. Though fitting it all in system RAM should not be an issue.

 

Now, I do not need every art asset loaded at once of course, and determining and limiting what needs to be loaded and what does not is not really what I wonder here. Instead I'm unsure on how to go about designing a proper asset loading system.

 

While I try to eliminate loading screens, beyond an initial, altogether by being smart about what is loaded and what is not the game still nicely needs to handle the sudden need for an unloaded art asset. Perhaps an object that requires it is suddenly spawned by an in-game event. The way I would like to handle this from the users perspective is to simply pause the game until it is loaded and pop up a "Loading" text on the screen.

 

I have two possible implementations in mind for this:

 

1. Finish executing the current frame, render the game state with the "Loading" text and do not do another update until the asset(s) are done loading asynchoniously. This does pose the limitation that any assets cannot be used in the frame they are requested as they may not have loaded yet, which can be an issue as the heaviest of them are both used for graphical and gameplay data.

 

2. Have the game-loop execute in a seperate thread, and pause that thread whenever an unloaded asset is used. The seperate rendering thread needs to handle this correctly (note that I already have a seperate rendering thread). This should pose few issues, but feels overly complicated for such a task.

 

So how do games usually do this?

 

Finally, I'm wondering if it is a good idea to have each State (ie startup menu, game running and the like) provide a seperate "loading state" that they enter when they want to show the user that they are loading something? It feels like it should not be their concern, but each state may need to show different loading screens and at least one of the different "loading screens" will need graphical information for the current game state.

 


Cube map troubles

23 November 2012 - 02:54 PM

Hey all, I'm having a bit of trouble trying to get a cubemap to work with OpenGL and GLSL. It seems to upload it just fine, at least GlIntercept outputs the cubemap texture in the way I would expect it too. However, when I try to sample the texture all I seem to get is just plain black no matter which coordinates I use to sample. The source texture has essentially no black at all.

I have been tearing my hair over this for the past few days and I'm wondering if any of you could spot the likely stupid mistake I've made?

Texture loading code:
[source lang="cpp"]namespace { SDL_Surface* createCubeMapFace(SDL_Surface* in, int faceStartX, int faceStartY, int width, int height) { #if SDL_BYTEORDER == SDL_LIL_ENDIAN SDL_Surface* bufferSurface = SDL_CreateRGBSurface(0, width, height, 32, 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000); #else SDL_Surface* bufferSurface = SDL_CreateRGBSurface(0, width, height, 32, 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF); #endif SDL_Rect rect; rect.w = width; rect.h = height; rect.x = faceStartX; rect.y = faceStartY; SDL_Rect dest; dest.x = 0; dest.y = 0; SDL_FillRect(bufferSurface, &dest, SDL_MapRGBA(bufferSurface->format, 0, 0xFF, 0, 0xFF)); SDL_BlitSurface(in, &rect, bufferSurface, &dest); return bufferSurface; } void uploadCubeMapFace(GLenum cubeMapFace, SDL_Surface* face, bool generateMipMaps) { glTexImage2D(cubeMapFace, 0, GL_RGBA, face->w, face->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, face->pixels ); tryLogError(); if (generateMipMaps) gluBuild2DMipmaps(cubeMapFace, GL_RGBA, face->w , face->h, GL_RGBA,GL_UNSIGNED_BYTE, face->pixels); tryLogError(); } GLuint uploadFaceSet(SDL_Surface*left, SDL_Surface* front, SDL_Surface* right, SDL_Surface* far, SDL_Surface* top, SDL_Surface* bottom, bool mipmapped) { GLuint id; glGenTextures(1, &id); glEnable(GL_TEXTURE_CUBE_MAP); glBindTexture(GL_TEXTURE_CUBE_MAP, id); tryLogError(); // Upload texture glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_MIRRORED_REPEAT); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); //Create cube map uploadCubeMapFace(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, left, mipmapped); uploadCubeMapFace(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, front, mipmapped); uploadCubeMapFace(GL_TEXTURE_CUBE_MAP_POSITIVE_X, right, mipmapped); uploadCubeMapFace(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, far, mipmapped); uploadCubeMapFace(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, top, mipmapped); uploadCubeMapFace(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, bottom, mipmapped); glBindTexture(GL_TEXTURE_CUBE_MAP, 0); return id; } // Loads a Texture into VideoRAM and returns a texture id GLuint loadCubeMapTextureIntoVRAM(Image* image, bool generateMipMaps) { assert(image->getWidth() % 4 == 0); assert(image->getHeight() % 3 == 0); assert(image->getWidth()/4 == image->getHeight()/3); int sideWidth = image->getWidth()/4; int sideHeight = image->getHeight()/3; auto left = createCubeMapFace(image->getInternalSurface(), sideWidth*0, sideHeight*1, sideWidth, sideHeight); auto front = createCubeMapFace(image->getInternalSurface(), sideWidth*1, sideHeight*1, sideWidth, sideHeight); auto right = createCubeMapFace(image->getInternalSurface(), sideWidth*2, sideHeight*1, sideWidth, sideHeight); auto far = createCubeMapFace(image->getInternalSurface(), sideWidth*3, sideHeight*1, sideWidth, sideHeight); auto top = createCubeMapFace(image->getInternalSurface(), sideWidth*1, sideHeight*0, sideWidth, sideHeight); auto bottom = createCubeMapFace(image->getInternalSurface(), sideWidth*1, sideHeight*2, sideWidth, sideHeight); auto retVal = uploadFaceSet(left, front, right, far, top, bottom, generateMipMaps); SDL_FreeSurface(left); SDL_FreeSurface(front); SDL_FreeSurface(right); SDL_FreeSurface(far); SDL_FreeSurface(top); SDL_FreeSurface(bottom); return retVal; } }[/source]

Code used to sent the cubemap id to the shader program, I have checked that the id is correct and that the part of the of the code is executed as it should as well as having a unique sampler number.

[source lang="cpp"]void ShaderProgram::setTexture(String variableName, int samplerNo, ICubeMap* texture) { assert(this->programId == activeProgram); assert(samplerNo >= 0); glEnable(GL_TEXTURE_CUBE_MAP); glBindTexture(GL_TEXTURE_CUBE_MAP, texture->getOpenGLId()); glActiveTexture(GL_TEXTURE0 + samplerNo); GLuint loc = glGetUniformLocation(this->programId, variableName.getStringUtf8()); glUniform1i(loc, samplerNo); }[/source]

Finally, the minimimalistic test fragment shader:

[source lang="cpp"]#version 330uniform samplerCube cubeMapTexture;in vec4 rawNormal;out vec4 fragmentColour;void main(void){ fragmentColour = texture(cubeMapTexture, vec3(rawNormal.xyz)); }[/source]
The vertex shader works as it should, if I hard set the colour in the fragment shader the object appears as expected.

I would be thankful for any help.

Efficent semi-procedual terrain in GLSL?

19 October 2012 - 11:52 AM

I'm curious about how one would best go about procedually generating terrain in a GLSL fragment shader. I'm not intrested in generating the vertices, as that is a solved problem for me. Actually generating the terrain is not very hard, but I'm unsure how I would best go about it when it comes to efficency. The terrain fragment shader will be fairly heavily used, and large inefficencies may lead to below acceptable performance (something I have encountered while playing around with it before, though in a less serious manner), I must admit that I have not measured how it would be in this instance, but I also ask becouse I want to understand how to best work on a GPU.

The terrain in the project needs to be changeable at runtime and in some cases guided by human design, I think it would be for the best to send a texture containing information about terrain types but not how it actually looks as that is what I want to generate procedually.
Presuming I associate a single terrain type with a unique value, how would I best go about actually using it?
Should I calculate the color for each terrain type, and the multiply it by either 0 or 1 depending on whether I want to use it or not and then simply adding them all together in the end resulting in only one color being used. If so, should I use branching statements to select the 'multiplication'
value or should I use some bitmanipulation or other method?
Or would the more straightforward if, else if, else if, ..... , else construct be roughly equal?

A given draw-call is unlikely to use more than half the availible terrain types, does that change anything?

Another option would be to create a new texture for each terrain type (where each pixel is effectivly a boolean, use or do not use) and do a new draw call for each of them with thier own shader program, this would mean terrain type selection would effecivly be handled by the CPU but that may not be efficient as the textures need to be quite large. For that reason, it would be difficult to cache these between draw calls as well.

Fixing terrain tearing

07 October 2012 - 04:56 AM

What you see in the attached screenshot, besides an early test of my GUI system, is a an equadistance point sphere with a heightmapped applied to it. Tearing artifacts are highly visible (at least in motion :P) and I would like some suggestions in how I would go about eliminating them.

The sphere is essentially a cube with its vertices remapped into a spherical shape, and the cube is constructed from 6 quads each consisting of n*n points. These quads are then attached together into a single mesh before the remapping. The tearing appears at the 'seams' of the six quads, as they do not actually share any vertices. Having the quads share vertices solves the tearing issue, but introduces problems when it comes to texture coordinates. I was thinking about detecting overlapping vertices and creating quads to patch these up. While detecting overlapping vertices are easy enough, I'm unsure about the best way to actually create indices for them without teh result being massive and overcomplicated code.

Attached File  tearing.png   146.87KB   63 downloads

PARTNERS