RAMSES Documentation  27.0.130
Information for RAMSES users and developers
Exemplary API snippets

RAMSES API Usage by Example

Note: The following example code snippets

  • omit error checking to keep code snippets small
  • do not represent full applications

The full source code of the examples is available in examples section of this document.

Minimal

This client implements the minimal requirements for a client to provide content within the RAMSES distributed system.

// register at RAMSES daemon
ramses::RamsesFramework framework(argc, argv);
ramses::RamsesClient& ramses(*framework.createClient("ramses-example-minimal"));
framework.connect();
// create a scene and register it at RAMSES daemon
ramses::Scene* scene = ramses.createScene(ramses::sceneId_t(123u));
// signal the scene it is in a state that can be rendered
scene->flush();
// distribute the scene to RAMSES
scene->publish();
// application logic
uint32_t loops = 100;
while (--loops)
{
std::this_thread::sleep_for(std::chrono::seconds(1));
}
// unregister and destroy scene
scene->unpublish();
ramses.destroy(*scene);
// disconnect from RAMSES daemon
framework.disconnect();
Entry point of RAMSES client API.
Definition: RamsesClient.h:34
Class representing ramses framework components that are needed to initialize an instance of ramses cl...
Definition: RamsesFramework.h:35
The Scene holds a scene graph. It is the essential class for distributing content to the ramses syste...
Definition: Scene.h:83
status_t unpublish()
Unpublish the scene from the ramses system.
status_t publish(EScenePublicationMode publicationMode=EScenePublicationMode_LocalAndRemote)
Publishes the scene to the ramses system.
status_t flush(sceneVersionTag_t sceneVersionTag=InvalidSceneVersionTag)
Commits all changes done to the scene since the last flush or since scene creation....
Helper class to create strongly typed values out of various types.
Definition: StronglyTypedValue.h:23
The RAMSES namespace contains all client side objects and functions used to implement RAMSES applicat...
Definition: AnimatedProperty.h:15

Basic Geometry

This code creates a simple geometry.

// IMPORTANT NOTE: For simplicity and readability the example code does not check return values from API calls.
// This should not be the case for real applications.
// prepare triangle geometry: vertex position array and index array
float vertexPositionsArray[] = { -1.f, 0.f, -1.f, 1.f, 0.f, -1.f, 0.f, 1.f, -1.f };
ramses::ArrayResource* vertexPositions = scene->createArrayResource(ramses::EDataType::Vector3F, 3, vertexPositionsArray);
// create an appearance for red triangle
effectDesc.setVertexShaderFromFile("res/ramses-example-basic-geometry.vert");
effectDesc.setFragmentShaderFromFile("res/ramses-example-basic-geometry.frag");
const ramses::Effect* effect = scene->createEffect(effectDesc, ramses::ResourceCacheFlag_DoNotCache, "glsl shader");
ramses::Appearance* appearance = scene->createAppearance(*effect, "triangle appearance");
// set vertex positions directly in geometry
ramses::GeometryBinding* geometry = scene->createGeometryBinding(*effect, "triangle geometry");
ramses::AttributeInput positionsInput;
effect->findAttributeInput("a_position", positionsInput);
geometry->setInputBuffer(positionsInput, *vertexPositions);
// get input data of appearance and bind required data
effect->findUniformInput("color", colorInput);
appearance->setInputValueVector4f(colorInput, 1.0f, 0.0f, 0.0f, 1.0f);
// create a mesh node to define the triangle with chosen appearance
ramses::MeshNode* meshNode = scene->createMeshNode("triangle mesh node");
meshNode->setAppearance(*appearance);
meshNode->setIndexCount(3);
meshNode->setGeometryBinding(*geometry);
// mesh needs to be added to a render group that belongs to a render pass with camera in order to be rendered
renderGroup->addMeshNode(*meshNode);
The Appearance describes how an object should look like. This includes GLSL uniform values,...
Definition: Appearance.h:34
status_t setInputValueVector4f(const UniformInput &input, float x, float y, float z, float w)
Sets value of the input.
The ArrayResource stores a data array of a given type. The data is immutable. The resource can be use...
Definition: ArrayResource.h:26
The AttributeInput is a description of an attribute effect input.
Definition: AttributeInput.h:22
An effect description holds all necessary information for an effect to be created.
Definition: EffectDescription.h:21
status_t setVertexShaderFromFile(const char *shaderSourceFileName)
Reads and sets vertex shader source from file.
status_t setUniformSemantic(const char *inputName, EEffectUniformSemantic semanticType)
Sets an uniform semantic. Used for uniforms which are not locally available on the client,...
status_t setFragmentShaderFromFile(const char *shaderSourceFileName)
Reads and sets fragment shader source from file.
An effect describes how an object will be rendered to the screen.
Definition: Effect.h:26
status_t findUniformInput(const char *inputName, UniformInput &uniformInput) const
Finds uniform input by input name.
status_t findAttributeInput(const char *inputName, AttributeInput &attributeInput) const
Finds attribute input by input name.
A geometry binding together with an appearance describe how an object will be rendered to the screen.
Definition: GeometryBinding.h:25
status_t setInputBuffer(const AttributeInput &attributeInput, const ArrayResource &arrayResource, uint32_t instancingDivisor=0)
Assign a data array resource to a given effect attribute input.
The MeshNode holds all information which is needed to render an object to the screen.
Definition: MeshNode.h:25
status_t setAppearance(Appearance &appearance)
Sets the Appearance of the MeshNode.
status_t setGeometryBinding(GeometryBinding &geometry)
Sets the GeometryBinding of the MeshNode.
status_t setIndexCount(uint32_t indexCount)
Sets the number of indices that will be used for rendering.
MeshNode * createMeshNode(const char *name=nullptr)
Creates a scene graph MeshNode. MeshNode is a Node with additional properties and bindings that repre...
Effect * createEffect(const EffectDescription &effectDesc, resourceCacheFlag_t cacheFlag=ResourceCacheFlag_DoNotCache, const char *name=nullptr)
Create a new Effect by parsing a GLSL shader described by an EffectDescription instance....
GeometryBinding * createGeometryBinding(const Effect &effect, const char *name=nullptr)
Creates a new GeometryBinding.
ArrayResource * createArrayResource(EDataType type, uint32_t numElements, const void *arrayData, resourceCacheFlag_t cacheFlag=ResourceCacheFlag_DoNotCache, const char *name=nullptr)
Create a new ArrayResource. It makes a copy of the given data of a certain type as a resource,...
Appearance * createAppearance(const Effect &effect, const char *name=nullptr)
Creates a new Appearance.
The UniformInput is a description of an uniform effect input.
Definition: UniformInput.h:22
@ ModelViewProjectionMatrix
Model-view-projection matrix 4x4.
@ Vector3F
three components of type float per data element
constexpr const resourceCacheFlag_t ResourceCacheFlag_DoNotCache
Requests the render to not cache a resource. This is the default value.
Definition: RamsesFrameworkTypes.h:212

Basic Scene Graph

This code creates a simple scene graph with multiple nodes.

// IMPORTANT NOTE: For simplicity and readability the example code does not check return values from API calls.
// This should not be the case for real applications.
// create node as root
ramses::Node* group = scene->createNode("group of triangles");
// create grid of triangles
for (int row = 0; row < 2; ++row)
{
for (int column = 0; column < 3; ++column)
{
// create a mesh node to define the triangle with chosen appearance
ramses::MeshNode* meshNode = scene->createMeshNode("triangle mesh node");
meshNode->setAppearance(*appearance);
meshNode->setGeometryBinding(*geometry);
meshNode->setTranslation(column * 0.2f, row * 0.2f, 0.0f);
meshNode->setParent(*group);
// mesh needs to be added to a render group that belongs to a render pass with camera in order to be rendered
renderGroup->addMeshNode(*meshNode);
}
}
The Node is the base class of all nodes and provides scene graph functionality which propagates to it...
Definition: Node.h:23
status_t setParent(Node &node)
Sets parent Node for this node.
status_t setTranslation(float x, float y, float z)
Sets the absolute translation the absolute values.
Node * createNode(const char *name=nullptr)
Creates a scene graph node. The basic purpose of Node is to define topology in scene graph by links t...

Basic Animation

This code creates a simple animation of a color of an appearance.

// IMPORTANT NOTE: For simplicity and readability the example code does not check return values from API calls.
// This should not be the case for real applications.
// create animation system, provide creation flag
// EAnimationSystemFlags_LiveUpdates to get live updates of animated properties
// create spline with animation keys
ramses::SplineLinearFloat* colorSpline = animationSystem->createSplineLinearFloat("color spline");
colorSpline->setKey(0u, 0.f);
colorSpline->setKey(5000u, 1.f);
colorSpline->setKey(10000u, 0.f);
// get handle to appearance input
effect->findUniformInput("color", colorInput);
appearance->setInputValueVector4f(colorInput, 1.f, 0.f, 0.f, 1.f);
// create animated property for color input with single component animation (green color channel is referred to via Z component)
ramses::AnimatedProperty* colorAnimProperty = animationSystem->createAnimatedProperty(colorInput, *appearance, ramses::EAnimatedPropertyComponent_Y);
// create animation
ramses::Animation* animation = animationSystem->createAnimation(*colorAnimProperty, *colorSpline, "color animation");
// create animation sequence and add animation
ramses::AnimationSequence* sequence = animationSystem->createAnimationSequence();
sequence->addAnimation(*animation);
// set animation properties (optional)
sequence->setAnimationLooping(*animation);
// start sequence
sequence->setPlaybackSpeed(5.f);
sequence->startAt(0u);
// signal the scene it is in a state that can be rendered
scene->flush();
// distribute the scene to RAMSES
scene->publish();
// application logic
float x;
float y;
float z;
float w;
for (uint64_t timeStamp = 0u; timeStamp < 10000u; timeStamp += 20u)
{
animationSystem->setTime(timeStamp);
// print current value of animated property
appearance->getInputValueVector4f(colorInput, x, y, z, w);
printf("%f %f %f %f\n", x, y, z, w);
// signal the scene it is in a state that can be rendered
scene->flush();
std::this_thread::sleep_for(std::chrono::milliseconds(20));
}
The AnimatedProperty holds a reference to data that can be animated.
Definition: AnimatedProperty.h:20
The AnimationSequence is a container for multiple animations. AnimationSequence has its own virtual t...
Definition: AnimationSequence.h:26
status_t addAnimation(const Animation &animation, sequenceTimeStamp_t startTimeInSequence=0u, sequenceTimeStamp_t stopTimeInSequence=0u)
Add animation to the sequence. Animation will be placed on to sequence time line at given time stamp ...
status_t setPlaybackSpeed(float playbackSpeed)
Sets sequence playback speed affecting all animations within the sequence. Default sequence playback ...
status_t setAnimationLooping(const Animation &animation, timeMilliseconds_t loopDuration=0)
Enables animation looping. When animation reaches last spline key (or loopDuration passes) it begins ...
status_t startAt(globalTimeStamp_t timeStamp)
Starts the sequence of animations at given time.
The AnimationSystem holds all animation related data.
Definition: AnimationSystem.h:57
AnimationSequence * createAnimationSequence(const char *name=nullptr)
Creates AnimationSequence that can hold references to multiple animations and control them together.
SplineLinearFloat * createSplineLinearFloat(const char *name=nullptr)
Creates a spline in this animation system using float data type and linear interpolation.
AnimatedProperty * createAnimatedProperty(const Node &propertyOwner, EAnimatedProperty property, EAnimatedPropertyComponent propertyComponent=EAnimatedPropertyComponent_All, const char *name=nullptr)
Create a new animated property for Node.
Animation * createAnimation(const AnimatedProperty &animatedProperty, const Spline &spline, const char *name=nullptr)
Creates Animation that can animate given property using given spline.
status_t setTime(globalTimeStamp_t timeStamp)
Sets the animation system to a given time. Any unsigned integral values that are used in an increment...
The Animation combines spline with one or more AnimatedProperty instances and allows control of the a...
Definition: Animation.h:22
status_t getInputValueVector4f(const UniformInput &input, float &x, float &y, float &z, float &w) const
Gets the value of the input.
AnimationSystem * createAnimationSystem(uint32_t flags=EAnimationSystemFlags_Default, const char *name=nullptr)
Create a new animation system. The animation system will be updated on renderer side after calls to A...
The SplineLinearFloat stores spline keys of type float that can be used for animation with linear int...
Definition: SplineLinearFloat.h:21
status_t setKey(splineTimeStamp_t timeStamp, float value)
Sets a spline key at given time with given value.
@ EAnimatedPropertyComponent_Y
Definition: AnimatedProperty.h:67
@ EAnimationSystemFlags_ClientSideProcessing
Definition: AnimationSystemEnums.h:20

Basic Realtime Animation

This code creates a simple realtime animation sequence with three triangles.

// IMPORTANT NOTE: For simplicity and readability the example code does not check return values from API calls.
// This should not be the case for real applications.
// create real time animation system, provide creation flag
// EAnimationSystemFlags_ClientSideProcessing to get live updates of animated properties
// create splines with animation keys
ramses::SplineLinearFloat* spline1 = animationSystem->createSplineLinearFloat("spline1");
spline1->setKey(0u, 0.f);
spline1->setKey(5000u, -1.f);
spline1->setKey(10000u, 0.f);
ramses::SplineLinearFloat* spline2 = animationSystem->createSplineLinearFloat("spline2");
spline2->setKey(0u, 0.f);
spline2->setKey(5000u, 1.f);
spline2->setKey(10000u, 0.f);
// create animated property for each translation node with single component animation
// create three animations
ramses::Animation* animation1 = animationSystem->createAnimation(*animProperty1, *spline1, "animation1");
ramses::Animation* animation2 = animationSystem->createAnimation(*animProperty2, *spline2, "animation2");
ramses::Animation* animation3 = animationSystem->createAnimation(*animProperty3, *spline1, "animation3"); // we can reuse spline1 for animating Y component of the third translation node
// create animation sequence
ramses::AnimationSequence* animSequence = animationSystem->createAnimationSequence();
// add animations to a sequence
animSequence->addAnimation(*animation1);
animSequence->addAnimation(*animation2);
animSequence->addAnimation(*animation3);
// set animation properties (optional)
animSequence->setAnimationLooping(*animation1);
animSequence->setAnimationLooping(*animation2);
animSequence->setAnimationLooping(*animation3);
// set sequence playback speed
animSequence->setPlaybackSpeed(5.f);
// start animation sequence
animationSystem->updateLocalTime();
animSequence->startAt(animationSystem->getTime());
// signal the scene it is in a state that can be rendered
scene->flush();
// distribute the scene to RAMSES
scene->publish();
// no application logic is needed here
// real time animation system is updated automatically on renderer every frame using system time
float x;
float y;
float z;
for (int ii = 0; ii < 500; ++ii)
{
// with RealTimeAnimationSystem, updateLocalTime() has to be called
// to get up-to-date animated values
animationSystem->updateLocalTime();
// print current value of animated property
meshNode1->getTranslation(x, y, z);
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
// however local client animation system should be updated before any change is made
animationSystem->updateLocalTime();
animSequence->setPlaybackSpeed(10.f);
for (int ii = 0; ii < 500; ++ii)
{
// with RealTimeAnimationSystem, updateLocalTime() has to be called
// to get up-to-date animated values
animationSystem->updateLocalTime();
// print current value of animated property
meshNode1->getTranslation(x, y, z);
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
The AnimationSystemRealTime is a special version of AnimationSystem that is designed to use system ti...
Definition: AnimationSystemRealTime.h:33
status_t updateLocalTime(globalTimeStamp_t systemTime=0u)
Sets the local animation system to a given time. The time used should always be system time,...
globalTimeStamp_t getTime() const
Gets the current animation system time. The time stamp retrieved is the time stamp that was previousl...
AnimationSystemRealTime * createRealTimeAnimationSystem(uint32_t flags=EAnimationSystemFlags_Default, const char *name=nullptr)
Create a new animation system that is designed to work with system time. The animation system will be...
@ EAnimatedPropertyComponent_X
Definition: AnimatedProperty.h:66
@ EAnimatedProperty_Translation
Definition: AnimatedProperty.h:76

Basic Texturing

This code creates a simple scene demonstrating basic usage of textures.

// IMPORTANT NOTE: For simplicity and readability the example code does not check return values from API calls.
// This should not be the case for real applications.
// prepare triangle geometry: vertex position array and index array
float vertexPositionsArray[] = { -0.5f, 0.f, -1.f, 0.5f, 0.f, -1.f, -0.5f, 1.f, -1.f, 0.5f, 1.f, -1.f };
ramses::ArrayResource* vertexPositions = scene->createArrayResource(ramses::EDataType::Vector3F, 4, vertexPositionsArray);
float textureCoordsArray[] = { 0.f, 1.f, 1.f, 1.f, 0.f, 0.f, 1.f, 0.f};
ramses::ArrayResource* textureCoords = scene->createArrayResource(ramses::EDataType::Vector2F, 4, textureCoordsArray);
uint16_t indicesArray[] = { 0, 1, 2, 2, 1, 3 };
// texture
ramses::Texture2D* texture = ramses::RamsesUtils::CreateTextureResourceFromPng("res/ramses-example-basic-texturing-texture.png", *scene);
*texture);
effectDesc.setVertexShaderFromFile("res/ramses-example-basic-texturing.vert");
effectDesc.setFragmentShaderFromFile("res/ramses-example-basic-texturing.frag");
ramses::Effect* effectTex = scene->createEffect(effectDesc, ramses::ResourceCacheFlag_DoNotCache, "glsl shader");
ramses::Appearance* appearance = scene->createAppearance(*effectTex, "triangle appearance");
// set vertex positions directly in geometry
ramses::GeometryBinding* geometry = scene->createGeometryBinding(*effectTex, "triangle geometry");
geometry->setIndices(*indices);
ramses::AttributeInput positionsInput;
ramses::AttributeInput texcoordsInput;
effectTex->findAttributeInput("a_position", positionsInput);
effectTex->findAttributeInput("a_texcoord", texcoordsInput);
geometry->setInputBuffer(positionsInput, *vertexPositions);
geometry->setInputBuffer(texcoordsInput, *textureCoords);
ramses::UniformInput textureInput;
effectTex->findUniformInput("textureSampler", textureInput);
appearance->setInputTexture(textureInput, *sampler);
// create a mesh node to define the triangle with chosen appearance
ramses::MeshNode* meshNode = scene->createMeshNode("textured triangle mesh node");
meshNode->setAppearance(*appearance);
meshNode->setGeometryBinding(*geometry);
// mesh needs to be added to a render group that belongs to a render pass with camera in order to be rendered
renderGroup->addMeshNode(*meshNode);
status_t setInputTexture(const UniformInput &input, const TextureSampler &textureSampler)
Sets texture sampler to the input.
status_t setIndices(const ArrayResource &indicesResource)
Assign a data array with data type UInt16 or UInt32 to be used when accessing vertex data.
static Texture2D * CreateTextureResourceFromPng(const char *pngFilePath, Scene &scene, const TextureSwizzle &swizzle={}, const char *name=nullptr)
Creates a Texture from the given png file.
TextureSampler * createTextureSampler(ETextureAddressMode wrapUMode, ETextureAddressMode wrapVMode, ETextureSamplingMethod minSamplingMethod, ETextureSamplingMethod magSamplingMethod, const Texture2D &texture, uint32_t anisotropyLevel=1, const char *name=nullptr)
Creates a texture sampler object.
Texture represents a 2-D texture resource.
Definition: Texture2D.h:24
The TextureSampler holds a texture and its sampling parameters.
Definition: TextureSampler.h:29
@ ETextureSamplingMethod_Linear
Definition: TextureEnums.h:21
@ ETextureAddressMode_Repeat
Definition: TextureEnums.h:33
@ Vector2F
two components of type float per data element
@ UInt16
one component of type uint16_t per data element

Basic Blending

This code creates a simple scene consisting of three triangles with alpha blending.

// IMPORTANT NOTE: For simplicity and readability the example code does not check return values from API calls.
// This should not be the case for real applications.
// set blending states for alpha blending
appearanceRed->setBlendingOperations(ramses::EBlendOperation_Add, ramses::EBlendOperation_Add);
appearanceGreen->setBlendingOperations(ramses::EBlendOperation_Add, ramses::EBlendOperation_Add);
appearanceBlue->setBlendingOperations(ramses::EBlendOperation_Add, ramses::EBlendOperation_Add);
// set appearances to mesh nodes
meshNodeRed->setAppearance(*appearanceRed);
meshNodeGreen->setAppearance(*appearanceGreen);
meshNodeBlue->setAppearance(*appearanceBlue);
// set same geometry to all mesh nodes
meshNodeRed->setGeometryBinding(*geometry);
meshNodeGreen->setGeometryBinding(*geometry);
meshNodeBlue->setGeometryBinding(*geometry);
// mesh needs to be added to a render group that belongs to a render pass with camera in order to be rendered
// set render order so that triangles are rendered back to front
renderGroup->addMeshNode(*meshNodeRed, 0);
renderGroup->addMeshNode(*meshNodeGreen, 1);
renderGroup->addMeshNode(*meshNodeBlue, 2);
@ EBlendFactor_OneMinusSrcAlpha
Definition: AppearanceEnums.h:74
@ EBlendFactor_One
Definition: AppearanceEnums.h:72
@ EBlendFactor_SrcAlpha
Definition: AppearanceEnums.h:73
@ EBlendOperation_Add
Definition: AppearanceEnums.h:58

Basic GLSL Import

This code creates an appearance by importing GLSL ES 2.0 shader code files. The appearance is then used to render a simple geometry.

// IMPORTANT NOTE: For simplicity and readability the example code does not check return values from API calls.
// This should not be the case for real applications.
// create an appearance for red triangle
effectDesc.setVertexShaderFromFile("res/ramses-example-basic-effect-from-glsl.vert");
effectDesc.setFragmentShaderFromFile("res/ramses-example-basic-effect-from-glsl.frag");
const ramses::Effect* effect = scene->createEffect(effectDesc, ramses::ResourceCacheFlag_DoNotCache, "glsl shader");
ramses::Appearance* appearance = scene->createAppearance(*effect, "triangle appearance");
// set vertex positions directly in geometry
ramses::GeometryBinding* geometry = scene->createGeometryBinding(*effect, "triangle geometry");
geometry->setIndices(*indices);
ramses::AttributeInput positionsInput;
effect->findAttributeInput("a_position", positionsInput);
geometry->setInputBuffer(positionsInput, *vertexPositions);
ramses::UniformInput scaleAndShearInput;
effect->findUniformInput("u_transformations", scaleAndShearInput);
float scaleAndShearArrayData[] = { 0.3f, 0.6f, 0.0f, 0.0f, 0.3f, 0.6f, 0.0f, 0.0f };
appearance->setInputValueVector4f(scaleAndShearInput, 2, scaleAndShearArrayData);
// create a mesh node to define the triangle with chosen appearance
ramses::MeshNode* meshNode = scene->createMeshNode("triangle mesh node");
meshNode->setAppearance(*appearance);
meshNode->setGeometryBinding(*geometry);
// mesh needs to be added to a render group that belongs to a render pass with camera in order to be rendered
renderGroup->addMeshNode(*meshNode);
effect->findUniformInput("color", colorInput);
appearance->setInputValueVector4f(colorInput, 0.1f, 0.5f, 0.2f, 1.0);

Basic Render Groups Handling

This code shows the usage of (nested) render groups. Render groups are containing renderables which are rendered within the render pass the render group is added to. The renderables inside one render group have an order in which they are rendered. A render group can also contain other nested render groups with their renderables. The example shows a render group containing two elements, a mesh and a nested render group with two further meshes.

// IMPORTANT NOTE: For simplicity and readability the example code does not check return values from API calls.
// This should not be the case for real applications.
// every render pass needs a camera to define rendering parameters
// create camera with perspective projection
ramses::PerspectiveCamera* camera = scene->createPerspectiveCamera("perspective camera of renderpass");
camera->setTranslation(0.0f, 0.0f, 5.0f);
camera->setFrustum(45.f, 640.f / 480.f, 1.f, 100.f);
// use left side of the viewport
camera->setViewport(0u, 0u, 640u, 480u);
// create render pass
ramses::RenderPass* renderPass = scene->createRenderPass("renderpass");
// set valid camera for the pass
renderPass->setCamera(*camera);
// create render group and add it to render pass
ramses::RenderGroup* renderGroup = scene->createRenderGroup("rendergroup");
renderPass->addRenderGroup(*renderGroup);
// create another render group and add it to first one as nested render group with render order '3'
ramses::RenderGroup* nestedRenderGroup= scene->createRenderGroup("nested rendergroup");
renderGroup->addRenderGroup(*nestedRenderGroup, 3);
ramses::Appearance* appearanceA = scene->createAppearance(*effectTex, "triangle appearance");
ramses::Appearance* appearanceB = scene->createAppearance(*effectTex, "triangle appearance");
ramses::Appearance* appearanceC = scene->createAppearance(*effectTex, "triangle appearance");
// set vertex positions directly in geometry
ramses::GeometryBinding* geometry = scene->createGeometryBinding(*effectTex, "triangle geometry");
geometry->setIndices(*indices);
ramses::AttributeInput positionsInput;
effectTex->findAttributeInput("a_position", positionsInput);
geometry->setInputBuffer(positionsInput, *vertexPositions);
// use three appearances, each with a different color for distinguishing the meshes
effectTex->findUniformInput("color", color);
appearanceA->setInputValueVector4f(color, 1.0f,0.0f,0.0f,1.0f);
appearanceB->setInputValueVector4f(color, 0.0f,1.0f,0.0f,1.0f);
appearanceC->setInputValueVector4f(color, 0.0f,0.0f,1.0f,1.0f);
ramses::MeshNode* meshNodeA = scene->createMeshNode("red triangle mesh node");
meshNodeA->setAppearance(*appearanceA);
meshNodeA->setGeometryBinding(*geometry);
ramses::MeshNode* meshNodeB = scene->createMeshNode("green triangle mesh node");
meshNodeB->setAppearance(*appearanceB);
meshNodeB->setGeometryBinding(*geometry);
meshNodeB->setTranslation(0.5f, 0.5f, 0.0f);
ramses::MeshNode* meshNodeC = scene->createMeshNode("blue triangle mesh node");
meshNodeC->setAppearance(*appearanceC);
meshNodeC->setGeometryBinding(*geometry);
meshNodeC->setTranslation(0.75f, -0.25f, 0.0f);
// Add meshA with render order '1' to the render group where already the nested render group with render order '3' was added.
// So meshA is rendered before every other element of the nested render group.
renderGroup->addMeshNode(*meshNodeA, 1);
// Add meshB and meshC to the nested render group with render order '2' and '1'.
// This order is only relevant inside the nested render group. So C is rendered before B but both are rendered after A.
nestedRenderGroup->addMeshNode(*meshNodeB, 2);
nestedRenderGroup->addMeshNode(*meshNodeC, 1);
status_t setViewport(int32_t x, int32_t y, uint32_t width, uint32_t height)
Sets the viewport to be used when rendering with this camera.
The PerspectiveCamera is a local camera which defines a perspective view into the scene.
Definition: PerspectiveCamera.h:23
status_t setFrustum(float fov, float aspectRatio, float nearPlane, float farPlane)
An alternative method (see ramses::Camera::setFrustum) to set the perspective view frustum of the cam...
The RenderGroup is a container used to collect renderables which are supposed to be rendered together...
Definition: RenderGroup.h:31
status_t addMeshNode(const MeshNode &mesh, int32_t orderWithinGroup=0)
Add a mesh to this RenderGroup. If a mesh is already contained in this RenderGroup only its render or...
status_t addRenderGroup(const RenderGroup &renderGroup, int32_t orderWithinGroup=0)
Add a RenderGroup to this RenderGroup. If a RenderGroup is already contained in this RenderGroup only...
The RenderPass is a container used to collect meshes which are supposed to be rendered together.
Definition: RenderPass.h:31
status_t setCamera(const Camera &camera)
Set the camera to use for rendering the objects of this renderpass.
status_t setClearFlags(uint32_t clearFlags)
Set the clear flags which enable/disable the clearing of the render target assigned to this RenderPas...
status_t addRenderGroup(const RenderGroup &renderGroup, int32_t orderWithinPass=0)
Add a RenderGroup to this RenderPass for rendering.
RenderPass * createRenderPass(const char *name=nullptr)
Create a render pass in the scene.
RenderGroup * createRenderGroup(const char *name=nullptr)
Create a RenderGroup instance in the scene.
PerspectiveCamera * createPerspectiveCamera(const char *name=nullptr)
Creates a Perspective Camera in this Scene.
@ EClearFlags_None
Definition: RamsesFrameworkTypes.h:257

Render Pass and Camera Setup

This code shows the usage of renderpasses and cameras. Each renderpass needs to have a valid camera assigned. The example creates two renderpasses, each with a camera using different projection and viewport parameters. In order for a mesh to be rendered it must be added to a renderpass.

// IMPORTANT NOTE: For simplicity and readability the example code does not check return values from API calls.
// This should not be the case for real applications.
// every render pass needs a camera to define rendering parameters
// create camera with perspective projection
ramses::Node* cameraTranslate = scene->createNode();
cameraTranslate->setTranslation(0.0f, 0.0f, 5.0f);
ramses::PerspectiveCamera* cameraA = scene->createPerspectiveCamera("perspective camera of renderpass A");
cameraA->setParent(*cameraTranslate);
cameraA->setFrustum(45.f, 640.f / 480.f, 0.1f, 100.f);
// use left side of the viewport
cameraA->setViewport(0u, 0u, 640u, 480u);
// create camera with orthographic projection
ramses::OrthographicCamera* cameraB = scene->createOrthographicCamera("ortho camera of renderpass B");
cameraB->setParent(*cameraTranslate);
cameraB->setFrustum(-2.f, 2.f, -2.f, 2.f, 0.1f, 100.f);
// use right side of the viewport
cameraB->setViewport(640u, 0u, 640u, 480u);
// create two renderpasses
ramses::RenderPass* renderPassA = scene->createRenderPass("renderpass A");
ramses::RenderPass* renderPassB = scene->createRenderPass("renderpass B");
// set valid cameras for the passes
renderPassA->setCamera(*cameraA);
renderPassB->setCamera(*cameraB);
// create render group for each renderpass
ramses::RenderGroup* renderGroupA = scene->createRenderGroup("rendergroup A");
ramses::RenderGroup* renderGroupB = scene->createRenderGroup("rendergroup B");
renderPassA->addRenderGroup(*renderGroupA);
renderPassB->addRenderGroup(*renderGroupB);
ramses::Appearance* appearanceA = scene->createAppearance(*effectTex, "triangle appearance");
ramses::Appearance* appearanceB = scene->createAppearance(*effectTex, "triangle appearance");
// set vertex positions directly in geometry
ramses::GeometryBinding* geometry = scene->createGeometryBinding(*effectTex, "triangle geometry");
geometry->setIndices(*indices);
ramses::AttributeInput positionsInput;
effectTex->findAttributeInput("a_position", positionsInput);
geometry->setInputBuffer(positionsInput, *vertexPositions);
// use two appearances, each with a different color for distinguishing the meshes
effectTex->findUniformInput("color", color);
appearanceA->setInputValueVector4f(color, 1.0f,0.0f,0.0f,1.0f);
appearanceB->setInputValueVector4f(color, 0.0f,1.0f,0.0f,1.0f);
ramses::MeshNode* meshNodeA = scene->createMeshNode("red triangle mesh node");
meshNodeA->setAppearance(*appearanceA);
meshNodeA->setGeometryBinding(*geometry);
ramses::MeshNode* meshNodeB = scene->createMeshNode("green triangle mesh node");
meshNodeB->setAppearance(*appearanceB);
meshNodeB->setGeometryBinding(*geometry);
// add each mesh to one pass
renderGroupA->addMeshNode(*meshNodeA);
renderGroupB->addMeshNode(*meshNodeB);
status_t setFrustum(float leftPlane, float rightPlane, float bottomPlane, float topPlane, float nearPlane, float farPlane)
Sets camera frustum planes of the Camera.
The OrthographicCamera is a local camera which defines an orthographic view into the scene.
Definition: OrthographicCamera.h:22
OrthographicCamera * createOrthographicCamera(const char *name=nullptr)
Creates a Orthographic Camera in this Scene.

Basic Render Target Handling

This code shows the usage of a render target in combination with render passes. A render target can be assigned to a render pass, so the pass renders its meshes into a render target. The render target can be then used as texture input in a following render pass.

// IMPORTANT NOTE: For simplicity and readability the example code does not check return values from API calls.
// This should not be the case for real applications.
// every render pass needs a camera to define rendering parameters
// usage of a custom perspective camera for the render pass assigned to the render target
ramses::Node* cameraTranslate = scene->createNode();
cameraTranslate->setTranslation(0.0f, 0.0f, 5.0f);
ramses::PerspectiveCamera* cameraA = scene->createPerspectiveCamera("camera of renderpass A");
cameraA->setParent(*cameraTranslate);
cameraA->setFrustum(-0.1f, 0.1f, -0.1f, 0.1f, 1.f, 10.f);
// we want to render to the full extent of render target which has the resolution 64x64 (created later)
cameraA->setViewport(0u, 0u, 64u, 64u);
// use another camera for the resolving render pass
auto* cameraB = scene->createPerspectiveCamera("camera of resolving renderpass B");
cameraB->setViewport(0, 0, 1280u, 480u);
cameraB->setFrustum(19.f, 1280.f / 480.f, 0.1f, 1500.f);
cameraB->setParent(*cameraTranslate);
// create the renderpasses
ramses::RenderPass* renderPassA = scene->createRenderPass("renderpass A");
ramses::RenderPass* renderPassB = scene->createRenderPass("renderpass B");
renderPassA->setClearColor(1.f, 1.f, 1.f, 1.f);
// set valid cameras for the passes
renderPassA->setCamera(*cameraA);
renderPassB->setCamera(*cameraB);
// create render group for each renderpass
ramses::RenderGroup* renderGroupA = scene->createRenderGroup("rendergroup A");
ramses::RenderGroup* renderGroupB = scene->createRenderGroup("rendergroup B");
renderPassA->addRenderGroup(*renderGroupA);
renderPassB->addRenderGroup(*renderGroupB);
// create a render target and assign it to renderpass A
rtDesc.addRenderBuffer(*renderBuffer);
ramses::RenderTarget* renderTarget = scene->createRenderTarget(rtDesc);
renderPassA->setRenderTarget(renderTarget);
// create triangle appearance, get input data and bind required data
ramses::Appearance* appearanceA = scene->createAppearance(*triangleEffect, "triangle appearance");
{
triangleEffect->findUniformInput("color", color);
appearanceA->setInputValueVector4f(color, 1.0f, 0.0f, 0.0f, 1.0f);
}
ramses::GeometryBinding* geometryA = scene->createGeometryBinding(*triangleEffect, "triangle geometry");
{
geometryA->setIndices(*indicesTriangle);
ramses::AttributeInput positionsInput;
triangleEffect->findAttributeInput("a_position", positionsInput);
geometryA->setInputBuffer(positionsInput, *vertexPositionsTriangle);
}
// create quad appearance, get input data and bind required data
ramses::Appearance* appearanceB = scene->createAppearance(*quadEffect, "quad appearance");
{
// create texture sampler with render target
*renderBuffer);
// set render target sampler as input
ramses::UniformInput textureInput;
quadEffect->findUniformInput("textureSampler", textureInput);
appearanceB->setInputTexture(textureInput, *sampler);
}
ramses::GeometryBinding* geometryB = scene->createGeometryBinding(*quadEffect, "quad geometry");
{
geometryB->setIndices(*indicesQuad);
ramses::AttributeInput positionsInput;
ramses::AttributeInput texcoordsInput;
quadEffect->findAttributeInput("a_position", positionsInput);
quadEffect->findAttributeInput("a_texcoord", texcoordsInput);
geometryB->setInputBuffer(positionsInput, *vertexPositionsQuad);
geometryB->setInputBuffer(texcoordsInput, *textureCoords);
}
// create meshs
ramses::MeshNode* meshNodeA = scene->createMeshNode("red triangle mesh node");
meshNodeA->setAppearance(*appearanceA);
meshNodeA->setGeometryBinding(*geometryA);
ramses::MeshNode* meshNodeB = scene->createMeshNode("texture quad mesh node");
meshNodeB->setAppearance(*appearanceB);
meshNodeB->setGeometryBinding(*geometryB);
// add triangle mesh to first pass and quad to second one
renderGroupA->addMeshNode(*meshNodeA);
renderGroupB->addMeshNode(*meshNodeB);
RenderBuffer can be used with RenderTarget as buffer for writing or with TextureSampler as buffer for...
Definition: RenderBuffer.h:25
status_t setRenderTarget(RenderTarget *renderTarget)
Set the render target for the render pass to render into.
status_t setClearColor(float r, float g, float b, float a)
Set the clear color for the RenderPass (default: [0,0,0,0])
RenderTargetDescription holds all necessary information for a RenderTarget to be created.
Definition: RenderTargetDescription.h:22
status_t addRenderBuffer(const RenderBuffer &renderBuffer)
Adds a RenderBuffer to the RenderTargetDescription.
The RenderTarget can be used as an output for a RenderPass.
Definition: RenderTarget.h:20
RenderBuffer * createRenderBuffer(uint32_t width, uint32_t height, ERenderBufferType bufferType, ERenderBufferFormat bufferFormat, ERenderBufferAccessMode accessMode, uint32_t sampleCount=0u, const char *name=nullptr)
Create a RenderBuffer to be used with RenderTarget for rendering into and TextureSampler for sampling...
RenderTarget * createRenderTarget(const RenderTargetDescription &rtDesc, const char *name=nullptr)
Create a render target providing a set of RenderBuffers.
@ ERenderBufferFormat_RGBA8
Definition: TextureEnums.h:141
@ ETextureSamplingMethod_Nearest
Definition: TextureEnums.h:20
@ ERenderBufferType_Color
Definition: TextureEnums.h:129
@ ERenderBufferAccessMode_ReadWrite
RenderBuffer with this access can be used both in RenderTarget and TextureSampler.
Definition: TextureEnums.h:171

Basic Compositing

This code creates a stream-texture that consists of a fallback texture and an id for mapping to a render-target. The renderer can replace the fallback texture by the content of a render-target, when the render-target is connected to the renderer. The id is an integer to identify the render-target.

// IMPORTANT NOTE: For simplicity and readability the example code does not check return values from API calls.
// This should not be the case for real applications.
// texture
ramses::Texture2D* texture =
ramses::RamsesUtils::CreateTextureResourceFromPng("res/ramses-example-basic-compositing-texture.png", *scene);
// use Texture2D as fallback for StreamTexture
ramses::StreamTexture* streamTexture = scene->createStreamTexture(*texture, surfaceId, "streamTexture");
StreamTexture * createStreamTexture(const Texture2D &fallbackTexture, waylandIviSurfaceId_t source, const char *name=nullptr)
Create a Stream Texture.
StreamTexture is a special kind of texture, which holds a reference to a "fallback texture" and a str...
Definition: StreamTexture.h:25

Data Buffers (vertices)

This example creates a scene with a shape. Some of the shape's vertices are changed every frame and thus translated around the scene.

The first part of the example shows the setup of the data buffer objects. In contrast to ressources, data buffers get created via the scene (and are owned by the scene).

//
// IMPORTANT NOTE: For simplicity and readability the example code does not check return values from API calls.
// This should not be the case for real applications.
// Create the DataBuffers
// The data buffers need more information about size
const uint32_t NumVertices = 16u;
const uint32_t NumIndices = 42u;
// then create the buffers via the _scene_
ramses::ArrayBuffer* vertices = scene->createArrayBuffer( ramses::EDataType::Vector3F, NumVertices, "some varying vertices");
ramses::ArrayBuffer* indices = scene->createArrayBuffer( ramses::EDataType::UInt16, NumIndices, "some varying indices");
// finally set/update the data
vertices->updateData(0u, NumVertices, vertexPositions);
indices->updateData( 0u, NumIndices, indexData);
The ArrayBuffer is a data object used to provide vertex or index data to ramses::GeometryBinding::set...
Definition: ArrayBuffer.h:27
status_t updateData(uint32_t firstElement, uint32_t numElements, const void *bufferData)
Update data of the ArrayBuffer object.
ArrayBuffer * createArrayBuffer(EDataType dataType, uint32_t maxNumElements, const char *name=nullptr)
Create a new ramses::ArrayBuffer. The created object is a mutable buffer object that can be used as i...

The second part of the example shows the application logic. A loop cycling over some of the vertices and changing their positions. These positions get applied to the data buffer by using setData. With setData you can set either the whole data buffer or just do partial updates using the optional offset parameter.

const std::vector<uint32_t> ridges = { 1, 7, 8, 14 };
const std::vector<uint32_t> notches = { 3, 4, 11, 12 };
float updatedValues[3];
for (uint64_t timeStamp = 0u; timeStamp < 10000u; timeStamp += 20u)
{
for(auto i: ridges)
{
translateVertex(updatedValues, i, timeStamp, 0.25f);
vertices->updateData(i, 1, updatedValues);
}
for(auto i: notches)
{
translateVertex(updatedValues, i, timeStamp, -0.4f);
vertices->updateData(i, 1, updatedValues);
}
// signal the scene it is in a state that can be rendered
scene->flush();
std::this_thread::sleep_for(std::chrono::milliseconds(20));
}

Data Buffers (textures)

This example creates a scene with two quads. Each quad is showing the same texture. The difference between both quads is, that they are are showing different mipmap levels of the same texture. The texture's content within each mipmap layer is changed every frame.

The first part of the example shows the setup of the data buffer objects. In contrast to client resources, data buffers get created via the scene (and are owned by the scene).

// IMPORTANT NOTE: For simplicity and readability the example code does not check return values from API calls.
// This should not be the case for real applications.
// Create the Texture2DBuffer via the scene
ramses::Texture2DBuffer* texture = scene->createTexture2DBuffer(format, textureWidthLevel0, textureHeightLevel0, 2u, "A varying texture");
// Whith Texture2DBuffer::setData you can pass a buffer for a specific mipmap level
texture->updateData(0, 0, 0, textureWidthLevel0, textureHeightLevel0, textureDataLevel0.data());
texture->updateData(1, 0, 0, textureWidthLevel1, textureHeightLevel1, textureDataLevel1.data());
// Just like resources or render buffers you add it via createTextureSampler
*texture);
Texture2DBuffer * createTexture2DBuffer(ETextureFormat textureFormat, uint32_t width, uint32_t height, uint32_t mipLevelCount, const char *name=nullptr)
Create a new Texture2DBuffer. The created object is a mutable buffer object that can be used as a tex...
The Texture2DBuffer is a mutable texture buffer used to hold texture data with the possibility to per...
Definition: Texture2DBuffer.h:26
status_t updateData(uint32_t mipLevel, uint32_t offsetX, uint32_t offsetY, uint32_t width, uint32_t height, const void *data)
Update a subregion of the data of Texture2DBuffer. The caller is responsible to check that the data h...
@ ETextureAddressMode_Clamp
Definition: TextureEnums.h:32

To change the data in the two mipmap levels, two data arrays (regionDataLevel0 and regionDataLevel1) have been created. The size of these arrays is the size of the area to be changed (regionWidth and regionHeight).

In the following example you see a for-loop that calculates new pixel data for the two arrays. The array-data is then used with setData to update the data buffer. Other parameters in the setData call are the target mipmap level, and the dimensions.

Finally a scene->flush() is called to send the updated data to the renderer.

// application logic
for(uint32_t i=0; i < 100; ++i)
{
// The IndexIterator is just a helper class calculating the needed indices and positions
// With regard to the example it's not important how these values are calculated.
IndexIterator<textureWidthLevel0, textureHeightLevel0, regionOffsetXLevel0, regionOffsetYLevel0, regionWidthLevel0, regionHeightLevel0> regionIndicesLevel0;
IndexIterator<textureWidthLevel1, textureHeightLevel1, regionOffsetXLevel1, regionOffsetYLevel1, regionWidthLevel1, regionHeightLevel1> regionIndicesLevel1;
// cycleOffset is used to shift the calculated positions, thus creating the cycle effect
const float cycleOffset = static_cast<float>(i) / 10.f;
// iterate over the values you want to update in mipmap level 0
for(; !regionIndicesLevel0.isAtEnd(); ++regionIndicesLevel0)
{
const uint32_t index = regionIndicesLevel0.getIndexLocal() * 3;
// calculate new color values for the updated texture
// these values can be stored in some new array, which is not necessarily the original
// data array. This new array has to have the correct dimensions for the updated region
// (i.e. might be just as small as the region you need to update)
regionDataLevel0.begin()[index+0] = convertToUInt8(regionIndicesLevel0.getPositionXLocal(cycleOffset));
regionDataLevel0.begin()[index+1] = 0;
regionDataLevel0.begin()[index+2] = convertToUInt8(regionIndicesLevel0.getPositionYLocal(cycleOffset));
}
// iterate over the values you want to update in mipmap level 1
for(; !regionIndicesLevel1.isAtEnd(); ++regionIndicesLevel1)
{
const uint32_t index = regionIndicesLevel1.getIndexLocal() * 3;
regionDataLevel1.begin()[index+0] = 0;
regionDataLevel1.begin()[index+1] = convertToUInt8(regionIndicesLevel1.getPositionXLocal(cycleOffset+0.5f));
regionDataLevel1.begin()[index+2] = convertToUInt8(regionIndicesLevel1.getPositionYLocal(cycleOffset+0.3f));
}
// with Texture2DBuffer::setData you can pass the updated array data to the data buffer
texture->updateData(0, regionOffsetXLevel0, regionOffsetYLevel0, regionWidthLevel0, regionHeightLevel0, regionDataLevel0.data());
texture->updateData(1, regionOffsetXLevel1, regionOffsetYLevel1, regionWidthLevel1, regionHeightLevel1, regionDataLevel1.data());
scene->flush();
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}

Basic File/Asset Loading

This code loads an asset (a serialized ramses scene).

// IMPORTANT NOTE: For simplicity and readability the example code does not check return values from API calls.
// This should not be the case for real applications.
ramses::Scene* loadedScene = ramses.loadSceneFromFile("tempfile.ramses");
// make changes to loaded scene
ramses::RamsesObject* loadedObject = loadedScene->findObjectByName("scale node");
ramses::Node* loadedScaleNode = ramses::RamsesUtils::TryConvert<ramses::Node>(*loadedObject);
The RamsesObject is a base class for all client API objects owned by the framework.
Definition: RamsesObject.h:21
const RamsesObject * findObjectByName(const char *name) const
Get an object from the scene by name.

Render Once Render Pass

This code shows the usage of a render pass that is rendered only once into a render target. A heavy content that is mostly static can benefit from this feature where it is rendered only once or with low frequency and the result in form of a render buffer is used every frame in the main scene.

// IMPORTANT NOTE: For simplicity and readability the example code does not check return values from API calls.
// This should not be the case for real applications.
// create the render once renderpass
ramses::RenderPass* renderPassRT = scene->createRenderPass("renderpass to render target");
renderPassRT->setClearColor(1.f, 1.f, 1.f, 1.f);
renderPassRT->setCamera(*cameraA);
renderPassRT->setRenderOnce(true);
status_t setRenderOnce(bool enable)
Set/unset render once flag - rendering of the render pass only once.
@ EClearFlags_All
Definition: RamsesFrameworkTypes.h:263
while (--loops)
{
// change color once per second
// this will re-render the mesh to the render target only once per color change
std::this_thread::sleep_for(std::chrono::seconds(1));
appearanceA->setInputValueVector4f(color, (loops % 2 ? 1.0f : 0.0f), 0.0f, (loops % 2 ? 0.0f : 1.0f), 1.0f);
renderPassRT->retriggerRenderOnce();
scene->flush();
}
status_t retriggerRenderOnce()
Will re-render a render once pass.

Geometry Instancing

This code demonstrates usage of geometry instancing via ramses apis.

// IMPORTANT NOTE: For simplicity and readability the example code does not check return values from API calls.
// This should not be the case for real applications.
// prepare triangle geometry: vertex position array and index array
float vertexPositionsArray[] = { -1.f, 0.f, -1.f, 1.f, 0.f, -1.f, 0.f, 1.f, -1.f };
ramses::ArrayResource* vertexPositions = scene->createArrayResource(ramses::EDataType::Vector3F, 3, vertexPositionsArray);
uint16_t indicesArray[] = { 0, 1, 2 };
// ------- Instancing with uniforms --------
// create an appearance for red triangles
ramses::EffectDescription effectDescUniform;
effectDescUniform.setVertexShaderFromFile("res/ramses-example-geometry-instancing-uniform.vert");
effectDescUniform.setFragmentShaderFromFile("res/ramses-example-geometry-instancing-uniform.frag");
const ramses::Effect* uniformEffect = scene->createEffect(effectDescUniform, ramses::ResourceCacheFlag_DoNotCache, "uniform-instancing");
ramses::Appearance* uniformAppearance = scene->createAppearance(*uniformEffect, "triangle_uniforms");
// get input data of appearance and bind required data
ramses::UniformInput uniformInstanceTranslationInput;
uniformEffect->findUniformInput("translations", uniformInstanceTranslationInput);
float translations[30];
ramses::UniformInput uniformInstanceColorInput;
uniformEffect->findUniformInput("colors", uniformInstanceColorInput);
float colors[40];
// set vertex positions directly in geometry
ramses::GeometryBinding* uniformGeometry = scene->createGeometryBinding(*uniformEffect, "triangle geometry uniforms");
uniformGeometry->setIndices(*indices);
ramses::AttributeInput uniformPositionInput;
uniformEffect->findAttributeInput("a_position", uniformPositionInput);
uniformGeometry->setInputBuffer(uniformPositionInput, *vertexPositions);
// create a mesh node to define the triangle with chosen appearance
ramses::MeshNode* uniformMeshNode = scene->createMeshNode("uniform-instanced triangle");
uniformMeshNode->setAppearance(*uniformAppearance);
uniformMeshNode->setGeometryBinding(*uniformGeometry);
uniformMeshNode->setInstanceCount(10u);
// mesh needs to be added to a render group that belongs to a render pass with camera in order to be rendered
renderGroup->addMeshNode(*uniformMeshNode);
// ------- Instancing with vertex arrays --------
// create an appearance for red triangles
ramses::EffectDescription effectDescVertex;
effectDescVertex.setVertexShaderFromFile("res/ramses-example-geometry-instancing-vertex.vert");
effectDescVertex.setFragmentShaderFromFile("res/ramses-example-geometry-instancing-vertex.frag");
const ramses::Effect* vertexEffect = scene->createEffect(effectDescVertex, ramses::ResourceCacheFlag_DoNotCache, "vertex-instancing");
ramses::Appearance* vertexAppearance = scene->createAppearance(*vertexEffect, "triangle_uniforms");
// set vertex positions directly in geometry
ramses::GeometryBinding* vertexGeometry = scene->createGeometryBinding(*vertexEffect, "triangle geometry uniforms");
vertexGeometry->setIndices(*indices);
ramses::AttributeInput vertexPositionInput;
vertexEffect->findAttributeInput("a_position", vertexPositionInput);
vertexGeometry->setInputBuffer(vertexPositionInput, *vertexPositions);
// prepare triangle geometry: vertex position array and index array
float vertexInstanceTranslationArray[] = {
-4.5f, .75f, -6.0f,
4.5f, .75f, -6.0f,
4.5f, -1.75f, -6.0f,
-4.5f, -1.75f, -6.0f
};
float vertexInstanceColorArray[] = {
1.0f, 0.0f, 0.0f, 1.0f,
0.0f, 1.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f
};
const ramses::ArrayResource* vertexTranslations = scene->createArrayResource(ramses::EDataType::Vector3F, 4, vertexInstanceTranslationArray);
const ramses::ArrayResource* vertexColors = scene->createArrayResource(ramses::EDataType::Vector4F, 4, vertexInstanceColorArray);
ramses::AttributeInput vertexTranslationInput;
vertexEffect->findAttributeInput("translation", vertexTranslationInput);
vertexGeometry->setInputBuffer(vertexTranslationInput, *vertexTranslations, 1u);
ramses::AttributeInput vertexColorInput;
vertexEffect->findAttributeInput("color", vertexColorInput);
vertexGeometry->setInputBuffer(vertexColorInput, *vertexColors, 1u);
// create a mesh node to define the triangle with chosen appearance
ramses::MeshNode* vertexMeshNode = scene->createMeshNode("vertex-instanced triangle");
vertexMeshNode->setAppearance(*vertexAppearance);
vertexMeshNode->setGeometryBinding(*vertexGeometry);
vertexMeshNode->setInstanceCount(4u);
// mesh needs to be added to a render group that belongs to a render pass with camera in order to be rendered
renderGroup->addMeshNode(*vertexMeshNode);
// distribute the scene to RAMSES
scene->publish();
// application logic
uint32_t t = 0;
while (t < 1000000)
{
// update translations of triangle instances
for (uint32_t i = 0; i < 10; i++)
{
translations[i * 3] = -3.0f + i * 0.7f;
translations[i * 3 + 1] = -0.5f + static_cast<float>(std::sin(i+0.05f*t));
translations[i * 3 + 2] = -5.0f;
}
uniformAppearance->setInputValueVector3f(uniformInstanceTranslationInput, 10, translations);
// update color of triangle instances
for (uint32_t i = 0; i < 10; i++)
{
colors[i * 4] = 1.0f;
colors[i * 4 + 1] = 0.75f * static_cast<float>(std::sin(i+0.05f*t));
colors[i * 4 + 2] = 0.2f;
colors[i * 4 + 3] = 1.0f;
}
uniformAppearance->setInputValueVector4f(uniformInstanceColorInput, 10, colors);
scene->flush();
t++;
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
status_t setInputValueVector3f(const UniformInput &input, float x, float y, float z)
Sets value of the input.
status_t setInstanceCount(uint32_t instanceCount)
Sets the number of instances that will be drawn for this mesh by the renderer.
@ Vector4F
four components of type float per data element

Geometry Shaders

This code demonstrates usage of geometry shaders in ramses.

// create an appearance for red triangle
effectDesc.setVertexShaderFromFile("res/ramses-example-local-geometry-shaders.vert");
effectDesc.setFragmentShaderFromFile("res/ramses-example-local-geometry-shaders.frag");
effectDesc.setGeometryShaderFromFile("res/ramses-example-local-geometry-shaders.geom");
const ramses::Effect* effect = clientScene->createEffect(effectDesc, ramses::ResourceCacheFlag_DoNotCache, "glsl shader");
ramses::Appearance* appearance = clientScene->createAppearance(*effect, "triangle appearance");
ramses::GeometryBinding* geometry = clientScene->createGeometryBinding(*effect, "triangle geometry");
geometry->setIndices(*indices);
ramses::AttributeInput positionsInput;
effect->findAttributeInput("a_position", positionsInput);
geometry->setInputBuffer(positionsInput, *vertexPositions);
effect->findUniformInput("color", colorInput);
ramses::UniformInput xMultiplierInput;
effect->findUniformInput("x_multiplier", xMultiplierInput);
status_t setDrawMode(EDrawMode mode)
Sets the draw mode indicating by which primitive the mesh will be rendered Default draw mode is Trian...
status_t setGeometryShaderFromFile(const char *shaderSourceFileName)
Reads and sets geometry shader source from file.
@ EDrawMode_Points
Definition: AppearanceEnums.h:176

Interleaved vertex attributes

This code demonstrates usage of interleaved vertex attributes via ramses apis.

// IMPORTANT NOTE: For simplicity and readability the example code does not check return values from API calls.
// This should not be the case for real applications.
// prepare triangle geometry: interleaved position and color data for each vertex
const float vertexData[] = {
-1.f, 0.f, -1.f, 1.f, //vertex 1 position vec4
1.f, 0.f, 0.f, //vertex 1 color vec3
1.f, 0.f, -1.f, 1.f, //vertex 2 position vec4
0.f, 1.f, 0.f, //vertex 2 color vec3
0.f, 1.f, -1.f, 1.f, //vertex 3 position vec4
0.f, 0.f, 1.f, //vertex 3 color vec3
};
ramses::ArrayBuffer* vertexDataBuffer = scene->createArrayBuffer(ramses::EDataType::ByteBlob, sizeof(vertexData));
vertexDataBuffer->updateData(0u, sizeof(vertexData), vertexData);
// create an appearance for triangle
effectDesc.setVertexShaderFromFile("res/ramses-example-interleaved-vertex-buffers.vert");
effectDesc.setFragmentShaderFromFile("res/ramses-example-interleaved-vertex-buffers.frag");
const ramses::Effect* effect = scene->createEffect(effectDesc, ramses::ResourceCacheFlag_DoNotCache, "glsl shader");
ramses::Appearance* appearance = scene->createAppearance(*effect, "appearance");
// set vertex positions and color in geometry
ramses::GeometryBinding* geometry = scene->createGeometryBinding(*effect, "geometry");
ramses::AttributeInput positionsInput;
effect->findAttributeInput("a_position", positionsInput);
effect->findAttributeInput("a_color", colorsInput);
//positions have Zero offset
constexpr uint16_t positionsOffset = 0u;
//colors have offset equal to size of 4 floats, because for every vertex color data starts (directly) after position which is vec4
constexpr uint16_t colorsOffset = 4 * sizeof(float);
//Stride is equal to size of 7 floats (vec4 position + vec3 color)
constexpr uint16_t stride = 7 * sizeof(float);
//HINT:
//In this "specific" example another way to safely calculate offsets and stride would be to add the size of the previous data type to previous offset:
//constexpr uint16_t positionsOffset = 0u + 0u; //vertex data starts by position
//constexpr uint16_t colorsOffset = positionsOffset + uint16_t(ramses::GetSizeOfDataType(ramses::EDataType::Vector4F));
//constexpr uint16_t stride = colorsOffset + uint16_t(ramses::GetSizeOfDataType(ramses::EDataType::Vector3F));
geometry->setInputBuffer(positionsInput, *vertexDataBuffer, positionsOffset, stride);
geometry->setInputBuffer(colorsInput, *vertexDataBuffer, colorsOffset, stride);
// create a mesh node to define the triangle with chosen appearance
ramses::MeshNode* meshNode = scene->createMeshNode("triangle mesh node");
meshNode->setAppearance(*appearance);
meshNode->setIndexCount(3);
meshNode->setGeometryBinding(*geometry);
@ ByteBlob
array of raw bytes which gets typed later (e.g. interleaved vertex buffer) where one element is alway...

Multiple Displays

This code creates a renderer with two displays and shows how a scene can be mapped to a display.

// IMPORTANT NOTE: For simplicity and readability the example code does not check return values from API calls.
// This should not be the case for real applications.
// Create displays and map scenes to them
ramses::DisplayConfig displayConfig1(argc, argv);
const ramses::displayId_t display1 = renderer.createDisplay(displayConfig1);
sceneControlAPI.setSceneMapping(sceneId1, display1);
sceneControlAPI.setSceneState(sceneId1, ramses::RendererSceneState::Rendered);
sceneControlAPI.flush();
ramses::DisplayConfig displayConfig2(argc, argv);
//ivi surfaces must be unique for every display
displayConfig2.setWaylandIviSurfaceID(ramses::waylandIviSurfaceId_t(displayConfig1.getWaylandIviSurfaceID().getValue() + 1));
const ramses::displayId_t display2 = renderer.createDisplay(displayConfig2);
renderer.flush();
sceneControlAPI.setSceneMapping(sceneId2, display2);
sceneControlAPI.setSceneState(sceneId2, ramses::RendererSceneState::Rendered);
sceneControlAPI.flush();
The DisplayConfig holds a set of parameters to be used to initialize a display.
Definition: DisplayConfig.h:22
@ Rendered
Scene is being rendered.

Data Linking

This code creates two scenes, maps them to a display and shows how transformation data can be linked from one scene to the other.

Client side configuration:

// IMPORTANT NOTE: For simplicity and readability the example code does not check return values from API calls.
// This should not be the case for real applications.
// Transformation links
ramses::dataProviderId_t transformationProviderId(14u);
ramses::dataConsumerId_t transformationConsumerId(12u);
ramses::dataConsumerId_t transformationConsumerId2(87u);
triangleScene->createTransformationDataProvider(*providerNode, transformationProviderId);
quadScene->createTransformationDataConsumer(*consumerNode, transformationConsumerId);
quadScene2->createTransformationDataConsumer(*consumerNode2, transformationConsumerId2);
//Data links
ramses::dataProviderId_t dataProviderId(100u);
ramses::dataConsumerId_t dataConsumerId(101u);
triangleScene->createDataConsumer(*triangleInfo->colorData, dataConsumerId);
quadScene->createDataProvider(*quadInfo->colorData, dataProviderId);
//Texture links
ramses::dataProviderId_t textureProviderId(200u);
ramses::dataConsumerId_t textureConsumerId(201u);
triangleScene->createTextureProvider(*triangleInfo->textures[0], textureProviderId);
quadScene2->createTextureConsumer(*quadInfo2->textureSampler, textureConsumerId);
triangleScene->flush();
quadScene->flush();
quadScene2->flush();

Renderer side link creation:

// link transformation
sceneControlAPI.linkData(triangleSceneId, transformationProviderId, quadSceneId, transformationConsumerId);
sceneControlAPI.linkData(triangleSceneId, transformationProviderId, quadSceneId2, transformationConsumerId2);
// link data
sceneControlAPI.linkData(quadSceneId, dataProviderId, triangleSceneId, dataConsumerId);
// link texture
sceneControlAPI.linkData(triangleSceneId, textureProviderId, quadSceneId2, textureConsumerId);

Viewport Linking

This code creates two scenes with content and a master scene. The master scene is only used to control position and size of the other two scenes (in 2D) using data linking - it links viewport parameters to the other scenes' cameras. The master scene has no knowledge of the other scenes except for their camera viewport data consumer IDs.

Content side setup:

// IMPORTANT NOTE: For simplicity and readability the example code does not check return values from API calls.
// This should not be the case for real applications.
// Bind data objects to scene's camera viewport offset/size and mark as data consumers
const auto vpOffsetData = clientScene->createDataVector2i("vpOffset");
const auto vpSizeData = clientScene->createDataVector2i("vpSize");
vpOffsetData->setValue(0, 0);
vpSizeData->setValue(VPWidth, VPHeight);
camera->bindViewportOffset(*vpOffsetData);
camera->bindViewportSize(*vpSizeData);
clientScene->createDataConsumer(*vpOffsetData, VPOffsetConsumerId);
clientScene->createDataConsumer(*vpSizeData, VPSizeConsumerId);
status_t bindViewportOffset(const DataVector2i &offsetData)
Binds a ramses::DataObject to be used as source for viewport offset values.
status_t bindViewportSize(const DataVector2i &sizeData)
Binds a ramses::DataObject to be used as source for viewport size values.

Master scene side setup:

// In master scene create data objects and mark them as providers to control other scenes' viewports
const auto vp1offset = clientScene->createDataVector2i("vp1offset");
const auto vp1size = clientScene->createDataVector2i("vp1size");
const auto vp2offset = clientScene->createDataVector2i("vp2offset");
const auto vp2size = clientScene->createDataVector2i("vp2size");
vp1offset->setValue(0, 0);
vp1size->setValue(DispWidth, DispHeight);
vp2offset->setValue(0, 0);
vp2size->setValue(DispWidth, DispHeight);
clientScene->createDataProvider(*vp1offset, VP1OffsetProviderId);
clientScene->createDataProvider(*vp1size, VP1SizeProviderId);
clientScene->createDataProvider(*vp2offset, VP2OffsetProviderId);
clientScene->createDataProvider(*vp2size, VP2SizeProviderId);

Linking together:

// Link master scene's data objects to other scenes cameras' viewports
sceneControlAPI.linkData(sceneIdMaster, VP1OffsetProviderId, sceneId1, VPOffsetConsumerId);
sceneControlAPI.linkData(sceneIdMaster, VP1SizeProviderId, sceneId1, VPSizeConsumerId);
sceneControlAPI.linkData(sceneIdMaster, VP2OffsetProviderId, sceneId2, VPOffsetConsumerId);
sceneControlAPI.linkData(sceneIdMaster, VP2SizeProviderId, sceneId2, VPSizeConsumerId);
sceneControlAPI.flush();

Offscreen Buffer

This code creates a consumer scene with two quads next to each other and two texture consumers. Then a provider scene with a quad is created twice while one is rendered into an offscreen buffer and the other one into a multisampled offscreen buffer. The two offscreen buffers are then linked to the consumer scene so that they are used as textures on the two quads and the difference between multisampled and regular offscreen buffer becomes visible. On top the offscreen buffers are periodically linked and unlinked from their consumers so the fallback Texture/RenderBuffer is shown.

// IMPORTANT NOTE: For simplicity and readability the example code does not check return values from API calls.
// This should not be the case for real applications.
// Create texture consumer that will use multi sampled offscreen buffer to sample from
const ramses::dataConsumerId_t samplerConsumerIdMS(456u);
consumerScene->createTextureConsumer(*textureSamplerConsumerMS, samplerConsumerIdMS);
// flush with version tag and wait for flush applied to make sure consumer is created
ramses::sceneVersionTag_t versionTagMS{ 42 };
consumerScene->flush(versionTagMS);
eventHandler.waitForFlush(consumerSceneId, versionTagMS);
// Create second texture consumer that will use non-MS offscreen buffer to sample from to visually compare MS vs non-MS
const ramses::dataConsumerId_t samplerConsumerId(457u);
consumerScene->createTextureConsumer(*textureSamplerConsumer, samplerConsumerId);
// flush with version tag and wait for flush applied to make sure consumer is created
ramses::sceneVersionTag_t versionTag{ 43 };
consumerScene->flush(versionTag);
eventHandler.waitForFlush(consumerSceneId, versionTag);
// Create the two offscreen buffers - have to be on the same display where both the scene to be rendered into it is mapped and the scene to consume it is mapped
const ramses::displayBufferId_t offscreenBufferMS = renderer.createOffscreenBuffer(display, ObWidth, ObHeight, SampleCount);
const ramses::displayBufferId_t offscreenBuffer = renderer.createOffscreenBuffer(display, ObWidth, ObHeight);
renderer.flush();
eventHandler.waitForOffscreenBufferCreated(offscreenBufferMS);
eventHandler.waitForOffscreenBufferCreated(offscreenBuffer);
// Assign the provider scenes to the offscreen buffers
// This means the providerscenes are not going to be rendered on the display but to the offscreen buffer they are assigned to instead
sceneControlAPI.setSceneDisplayBufferAssignment(providerSceneId, offscreenBufferMS);
sceneControlAPI.setSceneDisplayBufferAssignment(providerSceneId2, offscreenBuffer);
sceneControlAPI.flush();
// Link the offscreen buffers scene texture samplers so that the provided content will be used as texture
sceneControlAPI.linkOffscreenBuffer(offscreenBufferMS, consumerSceneId, samplerConsumerIdMS);
sceneControlAPI.linkOffscreenBuffer(offscreenBuffer, consumerSceneId, samplerConsumerId);
sceneControlAPI.flush();
eventHandler.waitForOffscreenBufferLinkedToConsumingScene(consumerSceneId);
// Now both the consumer scene and the provider scenes can be rendered at the same time
sceneControlAPI.setSceneState(consumerSceneId, ramses::RendererSceneState::Rendered);
sceneControlAPI.setSceneState(providerSceneId, ramses::RendererSceneState::Rendered);
sceneControlAPI.setSceneState(providerSceneId2, ramses::RendererSceneState::Rendered);
sceneControlAPI.flush();
// Unlink the offscreen buffer scenes every other second and show the fallback texture (sampler2D) and fallback buffer (sampler2DMS)
bool link = false;
// Start at 1 so texture samplers are not unlinked immediately
uint64_t timeStamp = 1u;
float rotationZ = 0.f;
ramses::Node* rotationNode = ramses::RamsesUtils::TryConvert<ramses::Node>(*providerScene->findObjectByName("rotationNode"));
ramses::Node* rotationNodeMS = ramses::RamsesUtils::TryConvert<ramses::Node>(*providerScene2->findObjectByName("rotationNodeMS"));
while (!eventHandler.isWindowClosed())
{
renderer.dispatchEvents(eventHandler);
//Rotate the quads of the provider scenes
rotationNode->setRotation(0.f, 0.f, rotationZ, ramses::ERotationConvention::ZYX);
providerScene->flush();
rotationNodeMS->setRotation(0.f, 0.f, rotationZ, ramses::ERotationConvention::ZYX);
providerScene2->flush();
if (timeStamp % 200 == 0)
{
if (link)
{
sceneControlAPI.linkOffscreenBuffer(offscreenBuffer, consumerSceneId, samplerConsumerId);
sceneControlAPI.linkOffscreenBuffer(offscreenBufferMS, consumerSceneId, samplerConsumerIdMS);
}
else
{
sceneControlAPI.unlinkData(consumerSceneId, samplerConsumerId);
sceneControlAPI.unlinkData(consumerSceneId, samplerConsumerIdMS);
}
sceneControlAPI.flush();
link = !link;
}
++rotationZ;
++timeStamp;
std::this_thread::sleep_for(std::chrono::milliseconds{ 15u });
}
status_t setRotation(float x, float y, float z)
Sets the absolute rotation in all three directions for left-handed rotation using Euler ZYX rotation ...
@ ZYX
rotates around X then Y then Z axis
uint64_t sceneVersionTag_t
Scene version tag used to refer to content versions of a scene. A scene version may be updated along ...
Definition: RamsesFrameworkTypes.h:49
constexpr ramses::sceneId_t consumerSceneId(2u)
constexpr ramses::sceneId_t providerSceneId(1u)

Pick Handling

This code creates a scene with two triangles and two pickable objects exactly covering these two triangles. The pickable objects use the scenes camera. This is needed for the intersection algorithm to unproject the pick ray in the same space as the object in the scene, that should be picked. When the user clicks on either of the two triangles in the renderer window the triangles change color.

// use triangle's vertex position array as PickableObject geometry
// the two PickableObjects are exactly covering the two triangles
ramses::ArrayBuffer* pickableGeometryBuffer = clientScene->createArrayBuffer(ramses::EDataType::Vector3F, 3u, "geometryBuffer");
pickableGeometryBuffer->updateData(0u, 3, vertexPositionsArray);
ramses::PickableObject* pickableObject1 = clientScene->createPickableObject(*pickableGeometryBuffer, ramses::pickableObjectId_t(1), "pickableObject");
pickableObject1->setParent(*meshNode);
// use the scenes camera for calculating the right intersection point with the PickableObject
pickableObject1->setCamera(*perspectiveCamera);
ramses::PickableObject* pickableObject2 = clientScene->createPickableObject(*pickableGeometryBuffer, ramses::pickableObjectId_t(2), "pickableObject2");
pickableObject2->setParent(*meshNode2);
pickableObject2->setCamera(*orthographicCamera);
clientScene->publish();
clientScene->flush();
SceneStateEventHandler eventHandler(sceneControlAPI, *appearanceA, *appearanceB, colorInput);
// show the scene on the renderer
sceneControlAPI.setSceneMapping(sceneId, display);
sceneControlAPI.setSceneState(sceneId, ramses::RendererSceneState::Rendered);
sceneControlAPI.flush();
while (!eventHandler.isWindowClosed())
{
std::this_thread::sleep_for(std::chrono::milliseconds(15));
renderer.dispatchEvents(eventHandler);
sceneControlAPI.dispatchEvents(eventHandler);
// signal the scene it is in a state that can be rendered
clientScene->flush();
sceneControlAPI.flush();
Definition: main.cpp:48
PickableObject provides a way to specify a 'pickable' area.
Definition: PickableObject.h:44
status_t setCamera(const Camera &camera)
Set the camera to be used to unproject geometry.

Basic Text

This code creates a basic text using a text API.

// IMPORTANT NOTE: For simplicity and readability the example code does not check return values from API calls.
// This should not be the case for real applications.
// Text is rendered in a screen-space pixel precise coordinate system
// To achieve a texel-to-pixel ratio of 1 when rendering the text, it has to be
// rendered with an orthographic camera with planes matching the display size (pixel buffer)
const uint32_t displayWidth(1280);
const uint32_t displayHeight(480);
ramses::RamsesFramework framework(argc, argv);
ramses::RamsesClient& client(*framework.createClient("ExampleTextBasic"));
ramses::Scene* scene = client.createScene(ramses::sceneId_t(123u));
// create font registry to hold font memory and text cache to cache text meshes
ramses::FontRegistry fontRegistry;
ramses::TextCache textCache(*scene, fontRegistry, 1024u, 1024u);
framework.connect();
// Create orthographic camera, so that text pixels will match screen pixels
camera->setFrustum(0.0f, static_cast<float>(displayWidth), 0.0f, static_cast<float>(displayHeight), 0.1f, 1.f);
camera->setViewport(0, 0, displayWidth, displayHeight);
// create render pass
ramses::RenderPass* renderPass = scene->createRenderPass();
renderPass->setCamera(*camera);
ramses::RenderGroup* renderGroup = scene->createRenderGroup();
renderPass->addRenderGroup(*renderGroup);
// create appearance to be used for text
effectDesc.setVertexShaderFromFile("res/ramses-example-text-basic-effect.vert");
effectDesc.setFragmentShaderFromFile("res/ramses-example-text-basic-effect.frag");
ramses::Effect* textEffect = scene->createEffect(effectDesc, ramses::ResourceCacheFlag_DoNotCache, "simpleTextShader");
// create font instance
ramses::FontId font = fontRegistry.createFreetype2Font("res/ramses-example-text-basic-Roboto-Bold.ttf");
const int32_t fontSize = 64;
ramses::FontInstanceId fontInstance = fontRegistry.createFreetype2FontInstance(font, fontSize);
// load rasterized glyphs for each character
const std::u32string string = U"Hello World!";
ramses::GlyphMetricsVector positionedGlyphs = textCache.getPositionedGlyphs(string, fontInstance);
ramses::GlyphMetricsVector trackedPositionedGlyphs = textCache.getPositionedGlyphs(string, fontInstance);
// add some character tracking (unit is em --> relative to fontSize)
// that reduces the spaces between the individual glyphs
ramses::TextCache::ApplyTrackingToGlyphs(trackedPositionedGlyphs, -50, fontSize);
// create RAMSES meshes/texture page to hold the glyphs and text geometry
const ramses::TextLineId textId = textCache.createTextLine(positionedGlyphs, *textEffect);
ramses::TextLine* textLine = textCache.getTextLine(textId);
const ramses::TextLineId trackedTextId = textCache.createTextLine(trackedPositionedGlyphs, *textEffect);
ramses::TextLine* trackedTextLine = textCache.getTextLine(trackedTextId);
// add the text meshes to the render pass to show them
textLine->meshNode->setTranslation(20.0f, 100.0f, -0.5f);
renderGroup->addMeshNode(*textLine->meshNode);
trackedTextLine->meshNode->setTranslation(20.0f, 20.0f, -0.5f);
renderGroup->addMeshNode(*trackedTextLine->meshNode);
// apply changes
scene->flush();
status_t setBlendingOperations(EBlendOperation operationColor, EBlendOperation operationAlpha)
Sets blending operation for color and alpha. Blending factors need to be set as well in order to enab...
status_t setBlendingFactors(EBlendFactor srcColor, EBlendFactor destColor, EBlendFactor srcAlpha, EBlendFactor destAlpha)
Sets blending factors for source/destination color/alpha. Blending operations need to be set as well ...
status_t setAttributeSemantic(const char *inputName, EEffectAttributeSemantic semanticType)
Sets an attribute semantic. Used to mark attributes as special inputs (eg. text specific inputs)....
Font registry can be used to load Freetype2 fonts and create font instances (optionally with Harfbuzz...
Definition: FontRegistry.h:22
FontInstanceId createFreetype2FontInstance(FontId fontId, uint32_t size, bool forceAutohinting=false)
Create Freetype2 font instance.
FontId createFreetype2Font(const char *fontPath)
Load Freetype2 font from file.
const Appearance * getAppearance() const
Returns the appearance.
Stores text data - texture atlas, meshes, glyph bitmap data. It is a cache because the content can be...
Definition: TextCache.h:84
static void ApplyTrackingToGlyphs(GlyphMetricsVector &glyphMetrics, int32_t trackingFactor, int32_t fontSize)
Apply character tracking (positive or negative) to each glyph in provided GlyphMetricsVector....
@ TextPositions
Text specific - vertex positions input. MUST be of type vec2.
@ TextTextureCoordinates
Text specific - texture coordinates input. MUST be of type vec2.
std::vector< GlyphMetrics > GlyphMetricsVector
Vector of GlyphMetrics elements.
Definition: GlyphMetrics.h:42
Groups the scene objects needed to render a text line.
Definition: TextLine.h:34
MeshNode * meshNode
Mesh node that represents the text.
Definition: TextLine.h:36

Text with multiple languages

This code creates a text using a text API containing several languages.

// create font instances
const ramses::FontId hebrewFont = fontRegistry.createFreetype2Font("res/ramses-example-text-languages-Arimo-Regular.ttf");
const ramses::FontId japaneseFont = fontRegistry.createFreetype2Font("res/ramses-example-text-languages-WenQuanYiMicroHei.ttf");
const ramses::FontId cyrillicFont = fontRegistry.createFreetype2Font("res/ramses-example-text-languages-Roboto-Regular.ttf");
const ramses::FontId arabicFont = fontRegistry.createFreetype2Font("res/ramses-example-text-languages-DroidKufi-Regular.ttf");
const ramses::FontInstanceId cyrillicFontInst = fontRegistry.createFreetype2FontInstance(cyrillicFont, 40);
const ramses::FontInstanceId japaneseFontInst = fontRegistry.createFreetype2FontInstance(japaneseFont, 40);
const ramses::FontInstanceId hebrewFontInst = fontRegistry.createFreetype2FontInstance(hebrewFont, 40);
const ramses::FontInstanceId arabicFontInst = fontRegistry.createFreetype2FontInstance(arabicFont, 36);
const ramses::FontInstanceId arabicFontInst_shaped = fontRegistry.createFreetype2FontInstanceWithHarfBuzz(arabicFont, 36);
// Using UTF32 string to store translations of the word "chocolate" in different languages
const std::u32string cyrillicString = { 0x00000448, 0x0000043e, 0x0000043a, 0x0000043e, 0x0000043b, 0x00000430, 0x00000434 }; // "шоколад"
const std::u32string japaneseString = { 0x000030e7, 0x000030b3, 0x000030ec, 0x000030fc, 0x000030c8, }; // "チョコレート"
const std::u32string hebrewString = { 0x000005e9, 0x000005d5, 0x000005e7, 0x000005d5, 0x000005dc, 0x000005d3, }; // "שוקולד"
const std::u32string arabicString = { 0x00000634, 0x00000648, 0x00000643, 0x00000648, 0x00000644, 0x00000627, 0x0000062a, 0x00000629, }; //"شوكولاتة"
// create RAMSES meshes/texture page to hold the glyphs and text geometry
const ramses::TextLineId textId1 = textCache.createTextLine(textCache.getPositionedGlyphs(cyrillicString, cyrillicFontInst), *textEffect);
const ramses::TextLineId textId2 = textCache.createTextLine(textCache.getPositionedGlyphs(japaneseString, japaneseFontInst), *textEffect);
const ramses::TextLineId textId3 = textCache.createTextLine(textCache.getPositionedGlyphs(hebrewString, hebrewFontInst), *textEffect);
const ramses::TextLineId textId4 = textCache.createTextLine(textCache.getPositionedGlyphs(arabicString, arabicFontInst), *textEffect);
const ramses::TextLineId textId5 = textCache.createTextLine(textCache.getPositionedGlyphs(arabicString, arabicFontInst_shaped), *textEffect);
FontInstanceId createFreetype2FontInstanceWithHarfBuzz(FontId fontId, uint32_t size, bool forceAutohinting=false)
Create Freetype2 font instance with Harfbuzz shaping.

Local rendering of scenes

This code demonstrates creating a scene and rendering it locally via ramses apis. See example code in examples/ramses-example-local-client/src/main.cpp

Local rendering of scenes via DCSM

This code demonstrates creating a scene and rendering it locally via dcsm (on top of ramses apis) See example code in examples/ramses-example-local-client-dcsm/src/main.cpp

DCSM Provider

This code offers a small scene via DCSM and is able to resize it and run a hide/show animation. A renderer side application which is supposed to work with this example properly needs to understand the DCSM protocol. For the standalone renderer this can be enabled with the "-dcsm" command line parameter.

// first is to offer the content to a consumer listening
metadata.setPreviewDescription(std::u32string(U"example/пример/例"));
const auto& fileContents = loadPreviewImageFile();
metadata.setPreviewImagePng(fileContents.data(), fileContents.size());
m_dcsm.offerContentWithMetadata(m_contentID, m_categoryID, m_sceneToOffer, ramses::EDcsmOfferingMode::LocalAndRemote, metadata);
// wait for the consumer accepting the offer and sending the initial size
while (!m_sizeReceived)
{
m_dcsm.dispatchEvents(*this);
std::this_thread::sleep_for(std::chrono::milliseconds(16u));
}
Class to create DCSM metadata object to be used in DcsmProvider.
Definition: DcsmMetadataCreator.h:30
status_t setPreviewImagePng(const void *data, size_t dataLength)
Set preview image metadata entry. Data must point to a valid in memory representation of a PNG file f...
status_t setPreviewDescription(std::u32string previewDescription)
Set preview description metadata entry. Must be a valid utf32 string.

Scene referencing

This code creates two scenes with content and a master scene. The master scene is only used to control position and size of the other two scenes (in 2D) using data linking - it links viewport parameters to the other scenes' cameras. The master scene has no knowledge of the other scenes except for their camera viewport data consumer IDs. The example also shows how a client can control rendering states of other scenes without access to renderer API.

Create scene references and get the to a rendered state:

// create a scene reference for both scenes
ramses::SceneReference* sceneRef1 = masterScene->createSceneReference(refSceneId1);
ramses::SceneReference* sceneRef2 = masterScene->createSceneReference(refSceneId2);
// request scene references state to rendered, they will be brought to state rendered alongside with master scene
masterScene->flush();
The SceneReference object refers to another ramses scene using its sceneId.
Definition: SceneReference.h:37
status_t requestState(RendererSceneState requestedState)
Set a requested state for this scene reference.

Link viewport via scene referencing:

// wait for referenced scene to be available, before trying to data link
SceneReferenceEventHandler eventHandler(client);
eventHandler.waitForSceneRefState(refSceneId1, ramses::RendererSceneState::Ready);
eventHandler.waitForSceneRefState(refSceneId2, ramses::RendererSceneState::Ready);
// Link master scene's data objects to other scenes cameras' viewports
masterScene->linkData(nullptr, VP1OffsetProviderId, sceneRef1, VPOffsetConsumerId);
masterScene->linkData(nullptr, VP1SizeProviderId, sceneRef1, VPSizeConsumerId);
masterScene->linkData(nullptr, VP2OffsetProviderId, sceneRef2, VPOffsetConsumerId);
masterScene->linkData(nullptr, VP2SizeProviderId, sceneRef2, VPSizeConsumerId);
masterScene->flush();
@ Ready
Scene is ready to start rendering (its resources are uploaded).