Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I've done some shader programming some time ago but only simple stuff. I'm especially interested in how do you manage shaders? Do you just write one of each kind, or do you need more of them? If so, how exactly do you split and managed them?

Also I've recently read that all the transformation matrix operations I used in OpenGL(glPushMatrix, etc) are now deprecated and you need to manage your own matrices.Is that something you do in a vertex shader and how would I go about doing it correctly?

Suggestions for books about this topic will be highly appreciated.

Thank you.

share|improve this question
    
What do you mean, "one of each kind"? What "kind" of shaders are you talking about that someone might write one of? –  Nicol Bolas Jul 14 '11 at 0:41
    
Do you write one vertex shader and one pixel shader? Or do you have more of each and you load them separately based on what effect you're trying to accomplish? –  adivasile Jul 14 '11 at 8:40
add comment

1 Answer 1

up vote 3 down vote accepted

I'll answer your second querstion first: both vertex and pixel shaders can treat part of (4 constants) their assigned constant memory (basically an array of 4D vectors, which can also be interpreted as integers or booleans with more modern shader versions) as a matrix in row-major format. It's up to you to upload the "right" transformation matrix for a job. So for example, for a standard 3D transform you'd upload this: Matrix mFullTransform = mProj * mView * mWorld, to transform a rigid vertex from object space. Get a basic (may just as well be dated) book about programming the post-fixed-pipe graphics pipeline. I have an old nVidia book called the CG tutorial lying around that covers this quite well.

As for multiple shaders, depending on your application design it might be a good idea to split up vertex and pixel shaders. From there on a common challenge is to write a shader that transforms/renders geometry based on a material. The material likely imposes small differences in the shader code. Now you can choose to upload these parameters (for a modern model) to constants and branch at runtime. This is not a very speedy approach though so it might be a good idea to take a different one. An often used strategy is to 'build' (or splice) and compile shaders at compiletime (or, in some simpler or runtime cases on initialization) and pair them up with the corresponding (material) data. Tailor your solution to your needs: for simple games and graphics demos it usually suffices to write all the shaders by hand and perhaps take a small hit left or right for a runtime parameter or 2.

Anyway hope it helps, been out of this game for a while.

[EDIT] Look at the first comment as well, has a good point about an important difference between D3D (which I mistakenly assumed, force of habit..) and OpenGL.

share|improve this answer
    
"both vertex and pixel shaders can treat part of (4 constants) their assigned constant memory (basically an array of 4D vectors, which can also be interpreted as integers or booleans with more modern shader versions) as a matrix in row-major format." The tag and post stated "OpenGL", not Direct3D. In OpenGL, UBOs work similarly to that, but they can use whatever orientation of matrix you want (row-vs-column). –  Nicol Bolas Jul 15 '11 at 2:38
    
Good point there, thank you :) But if one assumes column-major in OpenGL, I still take it that a transpose has to take place somewhere down the line as the shader units don't expose a different instruction set. So either the matrix is transposed on upload or the shader compiler generates different instructions for V'=V*M, taking the different layout into account? That would incur quite a penalty (unless somewhere 4 transforms are done parallel, so it can be done "vertical transform"-style, common in SIMD optimizations). Just wondering, hope you can shed some light on that! –  njdw Jul 15 '11 at 17:52
    
Also I'd like to add that this whole shader parameter thing isn't as one-dimensional as I make it out to be. Apart from fully static parameters that can be generated using the material data, there may be parameters that are dynamic (i.e you want to be able to turn them on and off based on a runtime situation). For those you can once again precalculate multiple shaders, stash them in data and select the right one -- or perhaps choose to make it a constant-driven parameter the shader itself takes care of. Bah, I've spent too much time on this at work to keep it brief ;) –  njdw Jul 15 '11 at 17:57
    
All matrices in GLSL are column-major. Period. You can provide matrices from external code in row-major order, but GLSL will transpose them on upload. For UBOs, you can tell GLSL whether a particular matrix is column-major in storage, but the compiler will make the adjustments necessary for the rest of the GLSL code to treat them as column-major. This could be reversing the order of certain math operations, doing a transpose, or something else. But it's all transparent. GLSL follows math conventions, so it's a = M * v. –  Nicol Bolas Jul 15 '11 at 18:11
    
I think I get it, but I'm going to take a look at it tonight. My OGL/GLSL exp. is almost absent, obviously :) What just puzzled me is that a shader unit can't perform v'=m*v (that's the right order in my book as well) using dot4s (the most optimal way) if the matrix is "physically" stored differently in the constant registers right (I literally mean the difference as it would be in RAM)? Or am I over- or underthinking this... (don't mean to hijack this question, just interested!) –  njdw Jul 15 '11 at 18:19
show 2 more comments

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.