|
The Vish Visualization Shell 0.3
Vish
|
The Render Anemone is an API that bundles everything together that is needed for rendering call such as OpenGL's glDrawArray, whereby it encapsulates the actual rendering API to allow independence from OpenGL.
The render Anemone is designed for caching of data transfers. The first step is to send data to an Anemone object:
This sets up an Anemone using virtual member functions from a VRenderContext, which may implement those via OpenGL or another graphics API. The second step is to actually invoke the rendering:
The Anemone will remember all properties (the so-called Tentacles) from the setup and subsequent code may just invoke the Anemone::wave() function to render again.
A Render Anemone may be created simply via the new operator as in
which is fine for code that only temporarily requires a Render Anemone during render time, but in general it is preferable to create a Render Anemone for more persistent usage across multiple rendering calls. This allows to setup the Render Anemone once while subsequent render calls merely invoke the Anemone::wave() function.
A VObject allows to define a local State object to hold context-dependent data. To place a RefPtr<Anemone> there will not work well because this State object will be destructed outside of the rendering thread without an OpenGL context available. Instead, the lifetime of an Anemone must be handled via an AnemoneCreator as in:
Then use the Anemone Creator with the Context Seagrass cache to store and handle the lifetime of the Render Anemone:
Note that the AnemoneCreator ceases to exist, then also the corresponding Anemone will cease to exist, but not immediately, rather at the next rendering call when the Seagrass Cache has the ability to manage its unused Anemones.
To add some shaders programs, GLSL source code may be conveniently defined in the C++ source code like this:
Basically shader code is just a string, but the GLSL_SHADER macro defines some line number information that is useful for debugging shaders. That context information is used by the GLSL_SOURCE macros when creating a GLProgram that can be used as a tentacle to be added to the Anemone:
Two groups of functions exist to send values to shader uniforms:
The second group of functions is more advanced: The Program maintains a set of variables with name, type and value. The Program::setValue() functions adds data there, but does not invoke any OpenGL (or similar) call yet. The Program::activateUniforms() call then sets all uniforms at once. However, this function does not need to be called explicitly but is performed by the Anemone::wave() when a Painter is activated. A major benefit is that the set of ProgramVariables may be updated any time, even without an OpenGL context being available or in the same thread, but the respective Program will always "see" the most recent values during drawing.
The most convenient way to set a uniform value in a shader via the setValue() API is provided by the array access, enabled by the Program's base class ProgramVariables:
The type of the uniform will be figured out automatically and implicitely ( using std::variant<> internally ), but must match the type used in the Program shader, including signedness of integers (int vs uint ).
The Render Stream API is an API in the Anemone library to allow coupling of VObject input parameters or functions with shader variables. It uses a syntax similar to the Standard C++ I/O Stream library.
Simplest verson: constant value.
Note that setting a boolean is enabling / disabling an OpenGL state:
(Remark: supported OpenGL flags are implemented in VGLRenderContext::Enable(), which is both a subset and extension of the full OpenGL functionality).
Couple a uniform variable with an object's input slot using the name of the input slot. Given an VObject's input slot:
this allows for a syntax such as:
(Note that in<> is a member template of Wizt::VSlotContainer::in which is available in child classes of VObject . Other classes require full class name specification. ).
The name of the shader variable must be identical to the name of the input slot. This name can also be specified explicitly to use a different name in the shader code than the object's input:
More complex version: via a context-relative member function:
Advanced version: transforming the value of an object's type slot:
Via a member function that adjust a value considering a Context
Couple a Vish Object's input slot with a uniform shader variable via some functor, for instance a function:
, allowing for the following syntax:
The functor's return type must correspond to the uniform shader variable, the functor's parameter must correspond to the input slot's type.
Finally, we can couple an Anemone's update function with a functor, in particular a lambda function:
Note the special syntax >> used here.