Making a Graphics Engine

Started by Noodles, August 10, 2013, 18:04:47

Previous topic - Next topic

quew8

It is kind for possible - and certainly much more efficient than updating VBOs the whole time, now I think about it.

Firstly by dynamic, do you mean dynamic sized or just changeable? The second is simple, the first is more difficult.

Essentially you can think of GLSL as C without pointers or memory allocation (Probably a few other things less as well). If you don't know about C, you can only create arrays with a compile-time constant length. Thus, to make dynamic arrays you dynamically assign memory, but GLSL doesn't have this second bit, so only fixed length arrays. The solution to this is to create a texture (which you can obviously choose whatever size for on creation (within hardware limits) ). You fill this texture with the data and access it in the shader via a sampler. Another benefit to this is that you don't have to re-upload the matrices the whole time if they are the same. (you can update them with glTexSubImageXD() ) (The obvious drawback of this is that you are using more video memory as well). I never use this method since it seems hacky so I'm always worried that some video cards will mess with the data to "optimize" it but since it isn't texture data will mess it up. However I HAVE NEVER HEARD OF THIS HAPPENING and if you think about it, it's stupid anyway.

So my alternate solution is to create a fixed sized array large enough for the maximum requirement I will ever have for it, fill it up as required and also pass up how many elements I've used if that is relevant.

Anyway, some code. To change a uniform variable, you must first get its location with glGetUniformLocation() :

int shaderProgramId = ... //your shader program's id.
int location = glGetUniformLocation(shaderProgramId, "aUniformVariableName"); //And yes, you literally put the variable's name.
//Essentially you name the variable exactly as you would in code, so for the 5th element of an array:
int arrayLoc = glGetUniformLocation(shaderProgramId, "aUniformVariableArray[5]");
//And for the "foo" field in a uniform structure:
int structLoc = glGetUniformLocation(shaderProgramId, "aUniformVariableStruct.foo");


Easy as pie. Then to upload your matrix (I'm only going to show you the matrix stuff):

FloatBuffer matrixBuff = ... //The float buffer containing your matrix.
boolean shouldTranspose = ... //Whether OpenGL should transpose the matrix as it loads it. Put false if you're unsure.
glUniformMatrix4f(location, shouldTranspose, matrixBuff); //Location is the variable from the previous snippet.


And that's it. If you're going to go with the texture route, then it obviously depends how you want to store the matrix in a texture. I would recommend a 1D texture but that's completely down to ease of use. I have no idea in general but especially no idea if that is the quickest / most efficient.

I'm sorry - I know I have waffled more than a little. Congratulations if you managed to get this far in one go.

Noodles

Well by dynamic I actually ment both,
/*Solution 1*/but now that I think about it your solution of making an array with a fixed maximum length should suffice.

/*Solution 2*/Do you think the Texture way would be more efficient?
Since I hav to change the matrices every render-Cicle, which means, I could have all the Textures saved which would be enormous amounts of Memory.
Or I would have to save a Texture each rendercicle just to acces it from the graphics memory, which I imagine is extremely inefficient.
But tell me do you think this would be at all more efficient than solution number 1.

Well thanks for the answer anyway.

quew8

I can't say for sure - especially since I have never used that approach, but what I do know is this. Uniform Variables are designed to be updated frequently. Textures aren't really. Presumably, you will be using all of the uniform array a lot / all of the time so that isn't even a question of wasting memory.

I think the question you need to ask is, do I need truly dynamic arrays? Ie. can I be sure of the maximum size I will need at the shader's compile time or can't I?

Noodles

Since this array will be storing just one matrix for every joint in a animated body, I would guess between 64 and 256 would be enough, depending on how accurate I want to animate.

Well thanks I appreciate the consultancy.