I am writing a 3D graphics engine.
I've heard that it is bad to use too much uniform variables in your shader program because it can cause slowdown.
On the other side, some say that re-using some built-in variables like gl_TextureMatrix is kind of bad practice.
How should I organize creating my shader programs ? Should I write plenty of uniforms for each mechanism or can I rely on those built-in variables ? For example, should I use built-in gl_LightSource or define o开发者_开发百科wn uniform array with light source informations, so I can have more lights on my scene? I also know about deferred rendering techniques but I want to do basic multiple lights first.
Or maybe, which built-in variables are 'OK' to reuse?
What are (dis)advantages of each of these practices?
I've never heard that uniforms can slowdown the shader, they are like compile time constants (or should be).
About using built-in variables, it's not recommended to use them, because they are deprecated in OpenGL 3.0 and with the OpenGL Core profile, they are not available. They were removed for sake of programmability. You can define your own variables for anything you want and that is fine.
So, it's just a matter of programmability, if you are learning and want to use them, it's also fine.
The point is that in modern 3D graphics programming, the API is making fewer assumptions about how to draw your scene and shifts more of the control to the developer. This is true of both OpenGL and Direct3D. Sure, most scenes use vertices, colors, normals, texture coordinates, etc., which all resulted in the fixed pipelines. However, what if I want to have starting positions and velocities for a particle engine? This would put gravity and time into uniform variables.
So, to answer your question, assuming you want to move into modern graphics development, stop using any predefined uniforms and define all your own. As of OpenGL 3, the predefined uniforms are gone anyway, and it rests upon you to define exactly what you need to render your scene. For veterans of the fixed pipeline, this often feels like a step backwards. "WHAT?? I have implement the matrices that were working fine already???" However, they quickly find that this pays off greatly when they see that they no longer have to make 500 different glEnable calls just to prep the rendering; the shader program defines precisely how they want to draw the scene.
In short, it's a bad idea to live in both worlds (using shaders and all the fixed pipeline functionality together). If the fixed pipeline does everything you need it to do, stick to OpenGL 2 and just get the job done the way you are currently familiar with. If you need advanced rendering tricks, dive into OpenGL 3+ and never look back.
In OpenGL-4 all those predefined uniforms are gone, but I usually just use the old names, so that I can reuse my old shaders.
It is a bad practice to use built-in uniforms, because:
- You start to use them, and they are enough for you.
- You need more, so you'll make a special logic for custom attributes.
- You can use custom attributes for everything, and they are supported, so why to keep obsolete built-in logic?
- You migrate on OpenGL 3+ core context / ES 2 and forget about built-ins.
I've come through these steps myself and conclude - life would be easier if I started with pure GL-3 initially.
A comment on the original question, about performance.
- If a built-in uniform has no 'special behavior' then there it is no faster than one that is defined by you. There's nothing in the pre-defined uniforms that you can't do.
- All of the built-in uniforms that I can think of have special behavior. For example, lights are transformed to eye space, lighting model coefficients are pre-multiplied. So the driver may have to do work to keep the uniforms that 'model' the fixed function pipeline in sync. I don't know what implementations will do this work always vs. skip this work when possible...ymmv.
- You may get better flexibility with custom uniforms. For example, you can't put the default uniforms in a UBO even if you want to.
- While a number of people have suggested not using the built-ins, the driver writers may have spent more time optimizing things like matrix transforms than your schedule permits; if you do remove built-ins for custom uniforms, audit performance to make sure your CPU-side performance is good enough.
Finally, when not using UBOs, the driver may have to update all uniforms when changing shaders. So more uniforms can slow down shader changes.
In all cases, unfortunately the only thing you can really do is take good measurements; the GL makes no guarantees as to what's optimized in the driver.
精彩评论