12 Sep 2013, 16:10
Quote:// What uniform parameters does engine set ?There is a number of predefined uniforms that are directly set by the engine, defined in the Murl::IEnums::UniformItem enumeration:
http://murlengine.com/api/en/class_murl_...3379d7f52e
When we have the shader tutorials ready, we will give an overview of the available names. In the mean time, the actual variable name for each of these enum values can be retrieved by calling the static method Murl::IEnums::GetUniformItemName(). Some of these items also have an alternative name (specifically the array types), which can be queried using Murl::IEnums::GetUniformItemAlternativeName(). Both methods return a const Char* pointer; querying the alternative name may return a null pointer.
You can also check the necessary data type for each item (Murl::IEnums::UniformType) by calling Murl::IEnums::GetUniformItemDataType().
Quote://This part came from line 368-372Analogous to uniforms, there is also the Murl::IEnums::AttributeItem enum:
// geom->AddAttribute(...) API
attribute vec4 aPosition;
attribute vec3 aNormal;
attribute vec3 aBinormal;
attribute vec3 aTangent;
attribute vec2 aTexCoord0;
http://murlengine.com/api/en/class_murl_...334b27467c
together with the methods Murl::IEnums::GetAttributeItemName(), Murl::IEnums::GetAttributeItemAlternativeName() and Murl::IEnums::GetAttributeItemDataType().
Quote:// How to change them from code ?Most of the predefined variables cannot directly be set by the user, but there exist both the IEnums::UNIFORM_ITEM_CUSTOM and IEnums::ATTRIBUTE_ITEM_CUSTOM items, which can be used to specify your own variables from code, with whatever variable name you need.
// Is it possible to add our own uniform parameters ?
To do so, you need to group your custom uniforms in a suitable way using Graph::IGenericParameterGroup nodes (Actually, as a side note, for OpenGL ES 2.0 the actual grouping does not matter. However, for DirectX 11 and OpenGL ES 3.0, groups should be defined in such a way that each of them encapsulates uniforms with the same or similar update frequency). You can add individual uniform variables to each group you create, with desired variable name and data type.
Next, you need to put all desired groups into one Graph::IGenericParameters node, which can then be activated with a Graph::IParametersState node just like a Graph::IFixedParameters node. Here's a short snipped of how to do so from code:
// Create container for our sub-graph
Graph::INode* container = root->CreateNode("Node");
// Create parameter groups and add individual uniforms
UInt32 byteOffset;
Graph::IGenericParameterGroup* waterTransGroup = dynamic_cast<Graph::IGenericParameterGroup*>(root->CreateNode("GenericParameterGroup"));
waterTransGroup->SetName("cbWaterTrans");
byteOffset = 0;
SInt32 bumpTransIndex0 = waterTransGroup->AddUniform("uBumpTranslation0", IEnums::UNIFORM_TYPE_FLOAT_VECTOR_4, byteOffset);
SInt32 bumpTransIndex1 = waterTransGroup->AddUniform("uBumpTranslation1", IEnums::UNIFORM_TYPE_FLOAT_VECTOR_4, byteOffset);
Graph::IFloatVector4Uniform* bumpTransParam0 = waterTransGroup->GetFloatVector4Uniform(bumpTransIndex0);
Graph::IFloatVector4Uniform* bumpTransParam1 = waterTransGroup->GetFloatVector4Uniform(bumpTransIndex1);
container->AddChild(waterTransGroup->GetNodeInterface());
Graph::IGenericParameterGroup* waterScaleGroup = dynamic_cast<Graph::IGenericParameterGroup*>(root->CreateNode("GenericParameterGroup"));
waterScaleGroup->SetName("cbWaterScale");
byteOffset = 0;
SInt32 bumpScaleIndex0 = waterScaleGroup->AddUniform("uBumpScale0", IEnums::UNIFORM_TYPE_FLOAT_VECTOR_4, byteOffset);
SInt32 bumpScaleIndex1 = waterScaleGroup->AddUniform("uBumpScale1", IEnums::UNIFORM_TYPE_FLOAT_VECTOR_4, byteOffset);
Graph::IFloatVector4Uniform* bumpScaleParam0 = waterScaleGroup->GetFloatVector4Uniform(bumpScaleIndex0);
Graph::IFloatVector4Uniform* bumpScaleParam1 = waterScaleGroup->GetFloatVector4Uniform(bumpScaleIndex1);
container->AddChild(waterScaleGroup->GetNodeInterface());
// Create a parameters node to hold the two groups
Graph::IGenericParameters* waterParams = dynamic_cast<Graph::IGenericParameters*>(root->CreateNode("GenericParameters"));
waterParams->GetGenericParameterGroupNodeTarget()->SetNumberOfNodes(2);
waterParams->GetGenericParameterGroupNodeTarget()->SetNode(waterTransGroup, 0);
waterParams->GetGenericParameterGroupNodeTarget()->SetNode(waterScaleGroup, 1);
container->AddChild(waterParams->GetNodeInterface());
// Create a state object to activate the parameters for subsequent rendering
Graph::IParametersState* waterState = dynamic_cast<Graph::IParametersState*>(root->CreateNode("ParametersState"));
waterState->GetParametersNodeTarget()->SetNumberOfNodes(1);
waterState->GetParametersNodeTarget()->SetNode(waterParams->GetParametersInterface(), 0);
container->AddChild(waterState->GetNodeInterface());
// Add & init the container
root->InitGraph(container, mWaterParamContainer.GetNode());
// Set some values
Float val[] = { 42.0f, 2.0f, 3.0f, 1.0f };
bumpTransParam0->SetValue(val);
And here's how to use these uniforms in the shader:
uniform highp mat4 uModelMatrix;
uniform highp mat4 uCameraViewMatrix;
uniform highp mat4 uCameraProjectionMatrix;
uniform highp mat4 uCameraViewProjectionMatrix;
uniform highp vec4 uCameraPosition;
uniform mediump vec4 uBumpTranslation0;
uniform mediump vec4 uBumpScale0;
uniform mediump vec4 uBumpTranslation1;
uniform mediump vec4 uBumpScale1;
attribute highp vec4 aPosition;
varying mediump vec3 vWaterToEye;
varying mediump float vWaterToEyeLength;
varying mediump vec2 vBumpCoord0;
varying mediump vec2 vBumpCoord1;
void main()
{
highp vec4 worldPosition = (uModelMatrix * aPosition);
gl_Position = uCameraViewProjectionMatrix * worldPosition;
mediump vec2 texCoord = worldPosition.xz;
vBumpCoord0 = texCoord.xy * uBumpScale0.xy;
vBumpCoord0 += uBumpTranslation0.xy;
vBumpCoord1 = texCoord.xy * uBumpScale1.xy;
vBumpCoord1 += uBumpTranslation1.xy;
highp vec4 camPos = uCameraPosition;
vWaterToEye = camPos.xyz - worldPosition.xyz;
vWaterToEyeLength = length(vWaterToEye);
}
As I mentioned above, only most of the predefined uniforms cannot be set directly. The exception to this rule are the "uMaterial*" uniforms, which are regularly set via Graph::IFixedParameters nodes. If you want to use these uniforms in your shader together with a Graph::IGenericParameters node, you must manually add a Graph::IGenericParameterGroup with name (not ID!) "cbMaterial", and add the "uMaterial*" variables to that group.
Quote:// Why lighting uniforms are arrays of 2 while only first element was used ?In the sample, only 1 simultaneous light source is used, so this value might as well be set to 1.
Quote:// Is it possible to process multiple lights with vector of uLightPositionCurrently, 2 simultaneous light sources are supported. If you want more, you might use multi-pass rendering, which leads to your next question:
Quote:2. Multiple programs.Yes, this is possible, through the use of Graph::MultiMaterial, Graph::MultiParamerers, Graph::MultiTexture and Graph::MultiLight nodes. However, this is another big topic on its own. I'll try to create another sample that covers this, and post another answer when it's ready. Again, I have to ask you for a bit of patience, but I promise it won't take long this time
I understand in simple case engine uses IFixedProgram to render objects.
In our case we use IShaderProgram and SetNumberOfNodes(1), so only 1 program is used.
I wonder is it possible to attach several programs to material to execute one by one ? Or any other technique is available ?
Best regards,
Christopher