I'm going through all the Rastertek DirectX tutorials which by the way are very good, and the author tends to use multiple shaders for different things. In one of the later tutorials he even introduces a shader manager class.
Based on some other sources though I believe that it would be more efficient to use a single shader with multiple techniques instead. Are multiple shaders in the tutorials used for simplicity or are there some scenarios where using multiple shaders would be better then a single big one?
I guess in the tutorials they use them for simplicity.
Grouping them in techniques or separately is a design decision. There are scenarios where having multiple shaders is beneficial as you can combine them as you like.
As of DirectX 11 in Windows 8, D3DX Library is deprecated so you will find out that it changes. You can see an example of this in the source code of DirectX Tool Kit: http://directxtk.codeplex.com/ and how they handled their effects.
Normally you will have different Vertex Shader, Pixel Shaders, etc in memory; techniques tend to join them as one, so when you compile the Shader File, for that technique a specific Vertex and Pixel Shader is compiled. Your Effect Objects is handling what Vertex/Pixel Shader the device is been set when an X Technique with a Y Pass is chosen.
You could do this manually, for example, only compile the pixel shader and set it to the device.
Mostly answer would be : it depends.
Effects framework gives a big advantage that you can set your whole pipeline in one go using Pass->Apply, which can make things really easy, but can lead to pretty slow code if not used properly, which is probably why microsoft decided to deprecate it, but you can do as bad or even worse using multiple shaders, directxtk being a pretty good example of that actually (it's ok only for phone development).
In most cases effect framework will incur a few extra api calls that you could avoid using separate shaders (which i agree if you're draw call bound can be significant, but then you should look at optimizing that part with culling/instancing techniques). Using separate shaders you have to handle all state/constant buffer management yourself, and probably do it in a more efficient way if you know what you are doing.
What I really like about fx framework is the very nice reflection, and the use of semantics, which at a design stage can be really useful (for example, if you do float4x4 tP : PROJECTION, your engine can automatically bind camera projection to the shader).
Also layout validation at compile time between shader stages is really handy for authoring (fx framework).
One big advantage of separate shaders is you can easily swap only the stages you need, so you can save a decent amount of permutations, without touching the rest of the pipeline.
It is never a good idea to have multiple fx files loaded. Combine your fx files if you can and use globals when you can if it don't need to be in your VInput struct.
This way you can get the effects you need and pass it what you set up in your own Shader class to handle the rest include the technique passes.
Make yourself an abstract ShaderClass and an abstract ModelClass.
More precisely, have your shaders initialized within your Graphics class separate from your models.
If you create a TextureShader class with your texture.fx file, then there is no need to initialized another instance of it;
rather share the TextureShader object with the appropriate model(s) then
create a Renderer struct/class to hold on the both the Shader pointer and the (what ever)Model pointer using virtual when you need to.
Related
I am trying to write a rendering engine in C++ based on Vulkan. Vulkan is written in C, as a result it has some interesting conventions.
A recurring pattern I see in tutorials/code snippets from Vulkan apps is that most code is in 1 very big class. (right now my vulkan class is already about 2000 lines too). But to make a proper rendering engine, I will need to compartmentalize my code till some degree.
One of the aforementioned interesting bits is that it has something called a Logical Device, which is an abstract reference to the graphics card.
It is used everywhere, to create and allocate things in the following way:
Create structs with creation info
Create variable that the code will output into
Call the actual vkCreateSomething or vkAllocateSomething function, pass in the logical device,
the creation info and the reference to the variable to output to and check if it was a success.
on its own there is nothing wrong with this style I'd say. It's just that it's not really handy at all in OOP because it relies on the logical device being available everywhere.
How would I deal with this problem? Service locators and singletons are considered to be horrible solutions by many (which I can understand), so that seems like something I'd rather avoid.
Are there design patterns that deal with this?
The logical device is an actual dependency.
It has state, and its state needs to be available to work with the hardware.
You can use it as an argument to your operations, a value stored in pretty much every class, a global, or a monadic-esque "final" argument where every operation just returns something still needing the device to run on. You can replace a (pointer/reference to) it with a function returning a (pointer/reference to) it.
Consider if pure OOP is what you want to do; vulkan and rendering is more about operations than things being operated on. I would want to mix some functional programming patterns in, which makes the monad-like choice more reasonable.
Compose operations on buffers/data. These return operations, which also take buffers and data. The composition operation specifies which arguments are new inputs, and which are consumed by the next step. Doing this you can (at compile time) set up a type-safe graph of work to do, all without running anything.
The resulting composed operation would then have a setup (where you bind the logical device and anything you can do "early" before you need to have the expensive buffers ready), and an execute phase (where you feed it the expensive buffers and it generates output).
Or as another approach, find a compiler with coroutine support from c++2a and write it async yet procedurally.
Vulkan is a OOP API. It is not class-based, because it is C99 not C++. That can easily be fixed by using the official Vulkan-Hpp. You can consume it as vulkan.hpp which is part of the semi-official LunarG Vulkan SDK.
The usage would not be that different from vulkan.h though: you would probably have a member pointer/reference to a Device instance, or would have a VkDevice handle member in each object that needs it. Some higher level object would handle the lifetime of the Logical Device (e.g. your RenderingEngine class or such). The difference would be almost only esthetical: you would use device->command(...) instead of vkCommand(device, ...). vulkan.hpp does not seem to use proper RAII through constructors/destructors which is a shame.
Alternatively the user of your engine can manage the device. Though unlike OpenGL there is not much use for this. The user can make its own VkInstance and VkDevice if it also wishes to use Vulkan for something.
A recurring pattern I see in tutorials/code snippets from Vulkan apps is that most code is in 1 very big class.
That's not really specific to Vulkan. If you think about it, pretty much all C++ applications are one big class doing everything (only differences being how much the programmer bothers to delegate from it to some other class instances).
I have been looping through a game entity list and calling a virtual Render fn that uses: glBegin/glEnd. Recently I've learned that Vertex-Buffer-Arrays are the way to go (especially for ios/Android).
When I create a new entity into the world, I merely have to bind the entity's VAO to VBO, set its VAO id. Thus if I have N entities, I have N VAO/VBO's?
On the render function I don't need to re-bind anything, only call "glDrawArray/Element"?
Can I use both glBegin/glEnd-style OpenGL as well as VAO/VBO's in the render fn?
It seems that OpenGL hates OOP, but I need OOP for game programming... how do I solve this paradox?
Thus if I have N entities, I have N VAO/VBO's?
In decent game engine, if you have a thousands of objects with the same geometry (say, discarded bullet cases or something), there's only one instance (VAO/VBO/whatever) of that geometry/mesh loaded into game engine. Object and mesh used by that object are two different things. Multiple objects can use same mesh instance.
Can I use both glBegin/glEnd-style OpenGL as well as VAO/VBO's in the render fn?
Yes, although some people insist that because OpenGL 3/4 is available, you should avoid glBegin/glEnd and similar old-style functions. Still, it is up to you.
It seems that OpenGL hates OOP, but I need OOP for game programming... how do I solve this paradox?
It doesn't. Technically, integer IDs used by OpenGL are objects and function that operate on them are methods of those objects. It isn't that hard to wrap those integer ids into structures/classes, anyway.
On another hand, you don't have to use OOP. (opinion) Nowadays "OOP" is frequently overused. If you can solve your problem using simple structures/arrays, and the code will be readable/easy to maintain, there's no reason to go nuts and design full-blown object hierarchy for everything.
I am exploring the relatively new feature GL_ARB_separate_program_object.What I understand is I have to create a pipeline object which should contain shaders from stages which are mapped to there via
glUseProgramStages
This make me think about 2 possibilites of using multiple shaders:
1.Creating Multiple pipelines with variant Vertex/Fragment shaders couples(not using other shader types for now) coming from one time mapping to each pipeline.
2.Creating single pipeline and in runtime switch the mapping to different shaders using
glUseProgramStages
I am mostly concerned with performance.Which option is more performance wise ?
Your question cannot really be answered, as it would vary with driver implementations and such. However, the facts and history of the functionality should be informative.
EXT_separate_shader_objects was the first incarnation of this functionality. The biggest difference between them was this: you could not use user-defined varyings with the EXT version. You had to use the old compatibility input/outputs like gl_TexCoord.
Issue #2 in the EXT_separate_shader_objects specification attempts to justify this incomprehensible oversightexplains the reasoning for this as follows:
It is undesirable from a performance standpoint to attempt to support "rendezvous by name" for arbitrary separate shaders because the separate shaders won't be naturally compiled to match their varying inputs and outputs of the same name without a special link step. Such a special link would introduce an extra validation overhead to binding separate shaders. The link itself would have to be deferred until glBegin time since separate shaders won't match when transitioning from one set of consistent shaders to another. This special link would still create errors or undefined behavior when the names of input and output varyings matched but their types did not match.
This suggests that the reason not to rely on name matching, besides incompetence, was performance related (if you can't tell, I don't think very highly of EXT_SSO). The performance of "rendezvous by name" comes from having to do it at every draw call, rather than being able to do it once.
ARB_separate_shader_objects encapsulates the collection of programs in an object. Therefore, the object can store all of the "rendezvous" data. The first draw call may be slower, but subsequent uses of the same PPO will be fast, as long as you don't attach new programs to it.
So I would take that as evidence that PPOs should have programs set on them and then left alone. In general, modifying the attachments objects should be avoided whenever possible. That's why you're encouraged not to go adding or removing textures/renderbuffers from FBOs.
When I'm programming any kind of application with opengl, direct3d, sdl or any graphics api (games, in general) I have the habit of creating a class named Graphics that have everything needed to draw, load images, initialize window, etc. inside of it. There is an instance of this class inside another class, that is the main class of the program, or game, or anything that is going to use it.
As the years passed, I tried a lot of different approaches to using this, and I would like to know if you guys think some of these are good, or if everything is just useless crap and I should do it another way.
1 - Having an instance of Graphics inside the program class and having a function in the programs class that iterates the objects (game objects, like the player, for example) and call the Graphics methods to draw everything accordingly.
2 - Go passing pointer to Graphics to every single object so each one can have a Draw function and call the appropriate Graphics functions themselves by means of this pointer.
3 - Have everything inside Graphics to be static and eliminate the need of creating an instance of graphics. Then you can call every graphic functions from anywhere.(You would just have a Draw function to each object, just like topic 2)
Thank you.
Edit: And what if I make something similar to what iostream does with cout, like, just make a header with 'extern Graphics x;', declare x in a cpp file and, then, call everything from this x. Is this too bad? And if it is, why?
Well, I think that a "graphics" class can very well have a state, like, for example, a canvas it is drawing on. Therefore, making it a class is good; by creating a class you can make the same set of functions applicable to different types of "canvases" (opengl, directx, sdl, etc.)
Among your options, I think that option 1 would be the best, but option 2 would be the easiest (and option 3 is horrible, because it makes code dependent on global variables, eliminating reusability of your code - it is the hacker approach :D).
Option 1 is great, because you could write a graphics engine that does intelligent stuff with the things it draws: Assume that you have two objects that share the same textures, but use a different mesh. If programmed appropriately, the graphics engine can call the "draw mesh" functions of both objects with the same render settings, in this case the same texture, which speeds speeding up rendering. This is not possible with option 2, which usually groups draw functions for single object together, leading to more changes to the render settings.
Option 2, however, is easier to implement. If you do not need a lot of render speed, I would go for this one, as it is much less work, and leads to a more logical program structure. To realize option 1, like I explained, an object needs to have "render properties" or such, that need to be matched by the render engine, and different draw routines for different draw settings... very complicated in comparison to an object-draw function that just uses a central set of drawing functions like a Graphics class.
So if you opt for a "large project", choose option 1. For fast results, and if you do not need to draw a lot of things, option 2 is probably better. Usability for options 1 and 2 is similar.
PS: Sorry for the late edit, but my grammar was horrible in the previous version
I would opt for a fourth option, make Graphics a namespace, not a class.
It doesn't sound like a Graphics is a data type, just a collection of functions. That's exactly what namespaces are for.
I have trouble figuring out what a "Graphics" object is. An object in software is analogous to an object in real life, so what would a Graphics object represent?
The way I usually do it is not very different from a standard UI application: I have a Window class that can be instantiated multiple times and a MainWindow class that inherits from Window and is only instantiated once. In that MainWindow class I have all the graphics resources that will be used throughout execution (e.g. the Direct3D device object).
I'm currently getting to grips with OpenGL. I started out with GLUT but decided to "graduate" to the SFML libraries. SFML actually provides even less GL utilities than GLUT, but is portable and provides some other functionalities. So it's really just me, GL and GLU. Yes, I'm a sucker for punishment.
I wanted to ask about strategies that people have for managing things such as matrix changes, colour changes, material changes etc.
Currently I am rendering from a single thread following a "Naked Objects" design philosophy. ie. Every graphical object has a Render() function which does the work of drawing itself. These objects may themselves be aggregates of further objects, or aggregates of graphical primitives. When a particular Render() is called it has no information about what transformations/ material changes have been called before it (a good thing, surely).
As things have developed I have settled on certain strategies such as making every function promise to push then pop the matrices if they perform any transformations. With other settings, I explicitly set anything that needs setting before calling glBegin() and take nothing for granted. Problems creep in when one render function makes some changes to less common state variables, and I am starting to consider using some RAII to enforce the reversal of all state changes made in a scope. Using OpenGL sometimes reminds me alot of assembly programming.
To keep this all manageable, and to help with debugging, I find that I am practically developing my own openGL wrapper, so I figured it would be good to hear about strategies that others have used, or thoughts and considerations on the subject. Or maybe it's just time to switch to something like a scene graph library?
Update : 13/5/11
Having now looked into rendering with vertex/normal/colour arrays and VBO's I have decided to consolidate all actual openGL communication into a separate module. The rendering process will consist of getting a load of GL independent spatial/material data out of my objects and then conveying all this information to openGL in an interpretable format. This means all raw array handling and state manipulation will be consolidated into one area. It's adds an extra indirection, and a little computation overhead to the rendering process, but it means that I can use a single VBO / array for all my data and then pass it all at once, once per frame to openGL.
So it's really just me, GL and GLU
I see nothing bad in that. I'd even get rid of GLU, if possible.
With other settings, I explicitly set
anything that needs setting before
calling glBegin() and take nothing for
granted.
Also this is a good strategy, but of course you should keep expensive state switches to a minimum. Instead of immediate mode (glBegin / glEnd) you should migrate to using vertex arrays and if available vertex buffer objects.
Problems creep in when one render
function makes some changes to less
common state variables, and I am
starting to consider using some RAII
to enforce the reversal of all state
changes made in a scope.
Older versions of OpenGL provide you the attribute stack with accessing functions glPushAttrib / glPopAttrib and glPushClientAttrib / glPopClientAttrib for the client states.
But yes, the huge state space of older OpenGL versions was one of the major reasons to slimming down OpenGL-3; what's been covered by a lot of fixed function pipeline states now is configured and accessed through shaders, where each shader encapsulates what would have been dozens of OpenGL state variable values.
Using OpenGL sometimes reminds me alot
of assembly programming.
This not a suprise at all, as the very first incarnation of OpenGL was designed assuming some abstract machine (the implementation) on which OpenGL calls are kind of the Operation Codes of that machine.
First, try not to use glBegin/glEnd calls for new development. They are deprecated in OpenGL 3 and simply don't work in OpenGL ES (iOS, WebOS, Android). Instead, use vertex arrays and VBOs to consolidate your drawing.
Second, instead of writing your own wrapper, take a look at some recent open source ones to see how they do things. For example, check out the Visualization Library (http://www.visualizationlibrary.com/jetcms/). It's a fairly thin wrapper around OpenGL, so it's worth a look.