How to create a CgFx like effect system? - opengl

Seriouse graphics engine like CryEngine3, Unreal Engine 3 have their customized shader language and effect system. While trying to find some effect system for my small graphics framework, it looks like nvidia CgFx is the only choice (seems Khronos had a project called glFx, but the project page is 404 now).
I have several reasons to make a effect system of my own:
I need more control about how and when to pass the shader parameters.
In order to reuse shader snippets, I want to create some c++ macro like mechanism. It's also useful to use macro to do some conditional compilation, and that the way CryEngine used to produces various effects.
Looks like GLSL don't have such effect system
so I am wondering how to create a effect system? Do I need to write grammar parser from scratch or there's already some code/tools able to do this thing?
PS: I am using OpenGL with both GLSL and CG.

Back in the day when I was using HLSL, I developped a little shader system which allowed me to specify all my parameters through data, so that I could just edit a sort of XML file containing the list of parameters and the shader codes, and after saving, the engine would automatically reload it, rebind all parameters, etc.
It's nothing compared to what's found in the UDK, but pretty convenient, and I guess you're trying to implement something like that ?
I it is, then here are a few stuff to do. First, you need to create a class to abstract shader parameter handling (binding, setting, etc.) Something along these lines :
class IShaderParameter
{
protected:
IShaderParameter(const std::string & name)
: m_Uniform(-1)
, m_Name(name)
{}
GLuint m_Uniform;
std::string m_Name;
public:
virtual void Set(GLuint program) = 0;
};
Then, for static parameters, you can simply create an overload like this :
template < typename Type >
class StaticParameter
: public IShaderParameter
{
public:
StaticParameter(const std::string & name, const Type & value)
: IShaderParameter(name)
, m_Value(value)
{}
virtual void Set(GLuint program)
{
if (m_Uniform == -1)
m_Uniform = glGetUniformLocation(program, m_Name.c_str());
this->SetUniform(m_Value);
}
protected:
Type m_Value;
void SetUniform(float value) { glUniform1f(m_Uniform, value); }
// write all SetUniform specializations that you need here
// ...
};
And along the same idea, you can create a "dynamic shader parameter" type. For example, if you want to be able to bind a light's parameter to your shader, create a specialized parameter's type. In its constructor, pass the light's id so that it will know how to retrieve the light in the Set method. With a little work, you can have a whole bunch of parameters that you can then automatically bind to an entity of your engine (material parameters, light parameters, etc.)
The last thing to do is create a little custom file format (I used xml) to define your various parameters, and a loader. For example, in my case, it looked like this :
<shader>
<param type="vec3" name="lightPos">light_0_position</param>
<param type="vec4" name="diffuse">material_10_diffuse</param>
<vertexShader>
... a CDATA containing your shader code
</vertexShader>
</shader>
In my engine, "light_0_position" would mean a light parameter, 0 is the light's ID, and position is the parameter to get. Binding between the parameter and the actual value was done during loading so there was not much overhead.
Anyway, I don't if that answer your question, and don't take these sample codes too seriously (HLSL and OpenGL shaders work quite differently, and I'm no OpenGL expert ^^) but hopefully it'll give you a few leads :)

Could you elaborate on this? By working with OpenGL directly you have a full control over the parameters being passed to the GPU. What exactly are you missing?
(and 3.) GLSL does support re-using the code. You can have a library of shaders providing different functions. In order to use any function you just need to pre-declare it in the client shader (vec4 get_diffuse();) and attach the shader object implementing the function to the shader program before linking.

Related

load config file for game, singleton or passing down the tree or anything else?

I'm trying to create simple game in C++. At one point I want to have some setting, save and load from config file.
The config file should be read from the beginning, and should be accessible anywhere it needed.
So far I only see Singleton pattern as a solution.
Another way is to create an object an pass it down, but it can mess
up the current code.
I've also search and found something called Dependency Injection.
Is dependency injection useful in C++
Which design patterns can be applied to the configuration settings problem?
But I don't quite understand it, you still have to create an object in main and pass it down, right?
Singleton is quite simple, but some consider it antipattern, while pass it down the tree can mess up my current code. Is there any other Patterns?
P/S: I'm also curious how games load their setting.
I would suggest something simple as the following example, which circumvents any singleton-related or initialization order issue:
struct global_state
{
config _config;
};
struct game_state
{
global_state& _global_state;
};
int main()
{
global_state globals{load_config_from_file()};
game_state game{globals};
game.run();
}
Since _global_state is a member of game_state, it can be used in member functions without the need of explicitly passing it as a parameter:
void game_state::update_ui()
{
const float text_size = _global_state._config.get_float("text_size");
_some_text.set_size(text_size);
}

Drawing custom 3d shapes

I am attempting to create a custom object using Cinder C++ on windows with Visual Studio. I am hoping to find a solution that allows you to point to a object with BatchRef object, and which can be used in the same way as any other BatchRef.
I have already tried searching through the official websites tutorials and documentation, and while it does an excellent job of listing all the classes, functions, etc, it does a exceedingly slim job of covering the usage of most of those, with only the return type and arguments listed.
Ideally, we could call the custom shape something like myShape and it could be used in the following manner in my App::draw() override: (with mShader already defined someplace else)
gl::BatchRef bRef;
gl::pushModelMatrix();
bRef = gl::Batch::create( myShape() , mShader );
bRef -> draw();
gl::popModelMatrix();
If the documentation has instructions for this, feel free to point me that way. I was unable to find it, but that does not mean that it does not exist.

c++ best way to realise global switches/flags to control program behaviour without tying the classes to a common point

Let me elaborate on the title:
I want to implement a system that would allow me to enable/disable/modify the general behavior of my program. Here are some examples:
I could switch off and on logging
I could change if my graphing program should use floating or pixel coordinates
I could change if my calculations should be based upon some method or some other method
I could enable/disable certain aspects like maybe a extension api
I could enable/disable some basic integrated profiler (if I had one)
These are some made-up examples.
Now I want to know what the most common solution for this sort of thing is.
I could imagine this working with some sort of singelton class that gets instanced globally or in some other globally available object. Another thing that would be possible would be just constexpr or other variables floating around in a namespace, again globally.
However doing something like that, globally, feels like bad practise.
second part of the question
This might sound like I cant decide what I want, but I want a way to modify all these switches/flags or whatever they are actually called in a single location, without tying any of my classes to it. I don't know if this is possible however.
Why don't I want to do that? Well I like to make my classes somewhat reusable and I don't like tying classes together, unless its required by the DRY principle and or inheritance. I basically couldn't get rid of the flags without modifying the possible hundreds of classes that used them.
What I have tried in the past
Having it all as compiler defines. This worked reasonably well, however I didnt like that I couldnt make it so if the flag file was gone there were some sort of default settings that would make the classes themselves still operational and changeable (through these default values)
Having it as a class and instancing it globally (system class). Worked ok, however I didnt like instancing anything globally. Also same problem as above
Instancing the system class locally and passing it to the classes on construction. This was kinda cool, since I could make multiple instruction sets. However at the same time that kinda ruined the point since it would lead to things that needed to have one flag set the same to have them set differently and therefore failing to properly work together. Also passing it on every construction was a pain.
A static class. This one worked ok for the longest time, however there is still the problem when there are missing dependencies.
Summary
Basically I am looking for a way to have a single "place" where I can mess with some values (bools, floats etc.) and that will change the behaviour of all classes using them for whatever, where said values either overwrite default values or get replaced by default values if said "place" isnt defined.
If a Singleton class does not work for you , maybe using a DI container may fit in your third approach? It may help with the construction and make the code more testable.
There are some DI frameworks for c++, like https://github.com/google/fruit/wiki or https://github.com/boost-experimental/di which you can use.
If you decide to use switch/flags, pay attention for "cyclometric complexity".
If you do not change the skeleton of your algorithm but only his behaviour according to the objets in parameter, have a look at "template design pattern". This method allow you to define a generic algorithm and specify particular step for a particular situation.
Here's an approach I found useful; I don't know if it's what you're looking for, but maybe it will give you some ideas.
First, I created a BehaviorFlags.h file that declares the following function:
// Returns true iff the given feature/behavior flag was specified for us to use
bool IsBehaviorFlagEnabled(const char * flagName);
The idea being that any code in any of your classes could call this function to find out if a particular behavior should be enabled or not. For example, you might put this code at the top of your ExtensionsAPI.cpp file:
#include "BehaviorFlags.h"
static const enableExtensionAPI = IsBehaviorFlagEnabled("enable_extensions_api");
[...]
void DoTheExtensionsAPIStuff()
{
if (enableExtensionsAPI == false) return;
[... otherwise do the extensions API stuff ...]
}
Note that the IsBehaviorFlagEnabled() call is only executed once at program startup, for best run-time efficiency; but you also have the option of calling IsBehaviorFlagEnabled() on every call to DoTheExtensionsAPIStuff(), if run-time efficiency is less important that being able to change your program's behavior without having to restart your program.
As far as how the IsBehaviorFlagEnabled() function itself is implemented, it looks something like this (simplified version for demonstration purposes):
bool IsBehaviorFlagEnabled(const char * fileName)
{
// Note: a real implementation would find the user's home directory
// using the proper API and not just rely on ~ to expand to the home-dir path
std::string filePath = "~/MyProgram_Settings/";
filePath += fileName;
FILE * fpIn = fopen(filePath.c_str(), "r"); // i.e. does the file exist?
bool ret = (fpIn != NULL);
fclose(fpIn);
return ret;
}
The idea being that if you want to change your program's behavior, you can do so by creating a file (or folder) in the ~/MyProgram_Settings directory with the appropriate name. E.g. if you want to enable your Extensions API, you could just do a
touch ~/MyProgram_Settings/enable_extensions_api
... and then re-start your program, and now IsBehaviorFlagEnabled("enable_extensions_api") returns true and so your Extensions API is enabled.
The benefits I see of doing it this way (as opposed to parsing a .ini file at startup or something like that) are:
There's no need to modify any "central header file" or "registry file" every time you add a new behavior-flag.
You don't have to put a ParseINIFile() function at the top of main() in order for your flags-functionality to work correctly.
You don't have to use a text editor or memorize a .ini syntax to change the program's behavior
In a pinch (e.g. no shell access) you can create/remove settings simply using the "New Folder" and "Delete" functionality of the desktop's window manager.
The settings are persistent across runs of the program (i.e. no need to specify the same command line arguments every time)
The settings are persistent across reboots of the computer
The flags can be easily modified by a script (via e.g. touch ~/MyProgram_Settings/blah or rm -f ~/MyProgram_Settings/blah) -- much easier than getting a shell script to correctly modify a .ini file
If you have code in multiple different .cpp files that needs to be controlled by the same flag-file, you can just call IsBehaviorFlagEnabled("that_file") from each of them; no need to have every call site refer to the same global boolean variable if you don't want them to.
Extra credit: If you're using a bug-tracker and therefore have bug/feature ticket numbers assigned to various issues, you can creep the elegance a little bit further by also adding a class like this one:
/** This class encapsulates a feature that can be selectively disabled/enabled by putting an
* "enable_behavior_xxxx" or "disable_behavior_xxxx" file into the ~/MyProgram_Settings folder.
*/
class ConditionalBehavior
{
public:
/** Constructor.
* #param bugNumber Bug-Tracker ID number associated with this bug/feature.
* #param defaultState If true, this beheavior will be enabled by default (i.e. if no corresponding
* file exists in ~/MyProgram_Settings). If false, it will be disabled by default.
* #param switchAtVersion If specified, this feature's default-enabled state will be inverted if
* GetMyProgramVersion() returns any version number greater than this.
*/
ConditionalBehavior(int bugNumber, bool defaultState, int switchAtVersion = -1)
{
if ((switchAtVersion >= 0)&&(GetMyProgramVersion() >= switchAtVersion)) _enabled = !_enabled;
std::string fn = defaultState ? "disable" : "enable";
fn += "_behavior_";
fn += to_string(bugNumber);
if ((IsBehaviorFlagEnabled(fn))
||(IsBehaviorFlagEnabled("enable_everything")))
{
_enabled = !_enabled;
printf("Note: %s Behavior #%i\n", _enabled?"Enabling":"Disabling", bugNumber);
}
}
/** Returns true iff this feature should be enabled. */
bool IsEnabled() const {return _enabled;}
private:
bool _enabled;
};
Then, in your ExtensionsAPI.cpp file, you might have something like this:
// Extensions API feature is tracker #4321; disabled by default for now
// but you can try it out via "touch ~/MyProgram_Settings/enable_feature_4321"
static const ConditionalBehavior _feature4321(4321, false);
// Also tracker #4222 is now enabled-by-default, but you can disable
// it manually via "touch ~/MyProgram_Settings/disable_feature_4222"
static const ConditionalBehavior _feature4222(4222, true);
[...]
void DoTheExtensionsAPIStuff()
{
if (_feature4321.IsEnabled() == false) return;
[... otherwise do the extensions API stuff ...]
}
... or if you know that you are planning to make your Extensions API enabled-by-default starting with version 4500 of your program, you can set it so that Extensions API will be enabled-by-default only if GetMyProgramVersion() returns 4500 or greater:
static ConditionalBehavior _feature4321(4321, false, 4500);
[...]
... also, if you wanted to get more elaborate, the API could be extended so that IsBehaviorFlagEnabled() can optionally return a string to the caller containing the contents of the file it found (if any), so that you could do shell commands like:
echo "opengl" > ~/MyProgram_Settings/graphics_renderer
... to tell your program to use OpenGL for its 3D graphics, or etc:
// In Renderer.cpp
std::string rendererType;
if (IsDebugFlagEnabled("graphics_renderer", &rendererType))
{
printf("The user wants me to use [%s] for rendering 3D graphics!\n", rendererType.c_str());
}
else printf("The user didn't specify what renderer to use.\n");

Choosing between multiple shaders based on uniform variable

I want to choose from 2 fragment shaders based on the value of an uniform variable. I want to know how to do that.
I have onSurfaceCreated function which does compile and link to create program1 and glGetAttribLocation of that program1
In my onDrawFrame I do glUseProgram(program1). This function runs for every frame.
My problem is that, in the function onDrawFrame(), I get value of my uniform variable. There I have to choose between program1 or program2. But program1 is already compiled linked and all. How to do this? How will I change my program accordingly and use that since it is already done in onSurfaceCreated.?
Looks like you need to prepare both programs in your onSurfaceCreated function. I'll try to illustrate that with a sample code. Please organize it in a more accurate manner in your project:
// onSurfaceCreated function:
glCompileShader(/*shader1 for prog1*/);
glCompileShader(/*shader2 for prog1*/);
//...
glCompileShader(/*shadern for prog1*/);
glCompileShader(/*shader1 for prog2*/);
glCompileShader(/*shader2 for prog2*/);
//...
glCompileShader(/*shadern for prog2*/);
glLinkProgram(/*prog1*/);
glLinkProgram(/*prog2*/);
u1 = glGetUniformLocation(/*uniform in prog1*/);
u2 = glGetUniformLocation(/*uniform in prog2*/);
// onDrawFrame
if(I_need_prog1_condition) {
glUseProgram(prog1);
glUniform(/*set uniform using u1*/);
} else {
glUseProgram(prog2);
glUniform(/*set uniform using u2*/);
}
If you want to use the same set of uniforms form different programs (like in the code above), there exists a more elegant and up-to-date solution: uniform buffer objects! For example, you can create a buffer object with all variables that any of your shaders may need, but each of your shader programs can use only a subset of them. Moreover, you can determine unneeded (optimized-out) uniforms using glGetActiveUniform.
Also please note that the title of your question is a bit misleading. It looks like you want to choose an execution branch not in your host code (i.e. onDrawFrame function), but in your shader code. This approach is known as uber-shader technique. There are lots of discussions about them in the Internet like these:
http://www.gamedev.net/topic/659145-what-is-a-uber-shader/
http://www.shawnhargreaves.com/hlsl_fragments/hlsl_fragments.html
If you decide to do so, remember that GPU is not really good at handling if statements and other branching.

Using results from my own pass(not predefined pass) into next pass

I have created a pass that pathprofiles and then stores results in different data structures such as blocks corresponding to the paths, edges in paths etc.
I have different variables and data structures for each of these.
Is there a way to use these variables directly in another pass that i write?
If yes, how? (Im not sure if getAnalysisUsage works for this?)
Urgent help required
This answer might be late, but I had the same question, ran across your post and thanks to Oak was pointed into the right direction. So I wanted to share some code here.
Suppose you have two passes, the first one is your PathProfilePass and the second one is your DoSomethingPass. The first pass contains the data that you collect and share with the second path; nothing special needs to be done here:
/// Path profiling to gather heaps of data.
class PathProfilePass: public llvm::ModulePass {
public:
virtual bool runOnModule(llvm::Module &M) {
// Create goodness for edges and paths.
...
}
std::set<Edges> edges; ///< All the edges this pass collects.
std::set<Paths> paths; ///< All the paths this pass collects.
};
The interesting stuff happens in the second pass. Two things you need to do here:
Specify the dependency of the second pass on the first pass: see the getAnalysisUsage method.
Access the data from the first pass: see the getAnalysis method.
Code-wise it would look something like this for the second pass:
/// Doing something with edge and path informations.
class DoSomethingPass: public llvm::ModulePass {
public:
/// Specify the dependency of this pass on PathProfilePass.
virtual void getAnalysisUsage(llvm::AnalysisUsage &AU) const {
AU.addRequired<PathProfilePass>();
}
/// Use the data of the PathProfilePass.
virtual bool runOnModule(llvm::Module &M) {
PathProfilePass &PPP = getAnalysis<PathProfilePass>();
// Get the edges and paths from the first pass.
std::set<Edges> &edges = PPP.edges;
std::set<Paths> &paths = PPP.paths;
// Now you can noodle over that data.
...
}
};
Disclaimer: I haven't compiled this code, but this is an adaptation to your example of what works for me. Hope this is useful :-)
Set a dependency from the 2nd pass to the 1st pass (via overriding getAnalysisUsage and invoking getAnalysis - see the programmer's guide to writing a pass on how to do that). Once you get an instance of the 1st pass, you can use it just like any other C++ object.