Deformation Motion Blur
The motion blur tutorial illustrates how to apply the motion blur effect in rendering.
In RPR, you can define a per-vertex motion blur.
In this deformed cube demo, we only move a few vertices of the cube. This is defined inside the cube_data_motionBlur
data.
To create the motion, we set the RPR_MESH_MOTION_DIMENSION property to 2, thus defining the vertices at exposure = 0.0 and exposure = 1.0.
More key times can be used if needed, for example, RPR_MESH_MOTION_DIMENSION = 3 would mean we define vertices at exposures = 0.0; 0.5; 1.0.
With no movement, this cube is usually defined by 24 unique vertices. However, with RPR_MESH_MOTION_DIMENSION = 2, we need to give 24*2 = 48 vertices to rprContextCreateMeshEx2().
Once this moving cube is created, you need to set the exposure: rprCameraSetExposure(camera,1.0). This means that the renderer is going to interpolate from vertices set of exposure = 0.0 to the set of exposure = 1.0.
Note that if you only need to have a motion of the transform matrix, with constant vertices data, you should rather use rprShapeSetMotionTransform() and rprShapeSetMotionTransformCount().
// Cube geometry
vertex cube_data_motionBlur[cube_NumberOfVertices*numberOfBlurKeyTime] =
{
// Vertices at camera exposure = 0.0.
{ -1.0f, 1.0f, -1.0f, 0.f, 1.f, 0.f, 0.f, 0.f },
{ 1.0f, 1.0f, -1.0f, 0.f, 1.f, 0.f, 1.f, 0.f },
{ 1.0f, 1.0f, 1.0f , 0.f, 1.f, 0.f, 1.f, 1.f },
{ -1.0f, 1.0f, 1.0f , 0.f, 1.f, 0.f, 0.f, 1.f},
{ -1.0f, -1.0f, -1.0f , 0.f, -1.f, 0.f, 0.f, 0.f },
{ 1.0f, -1.0f, -1.0f , 0.f, -1.f, 0.f, 1.f, 0.f },
{ 1.0f, -1.0f, 1.0f , 0.f, -1.f, 0.f, 1.f, 1.f },
{ -1.0f, -1.0f, 1.0f , 0.f, -1.f, 0.f, 0.f, 1.f },
{ -1.0f, -1.0f, 1.0f , -1.f, 0.f, 0.f, 0.f, 0.f },
{ -1.0f, -1.0f, -1.0f , -1.f, 0.f, 0.f, 1.f, 0.f },
{ -1.0f, 1.0f, -1.0f , -1.f, 0.f, 0.f, 1.f, 1.f },
{ -1.0f, 1.0f, 1.0f , -1.f, 0.f, 0.f, 0.f, 1.f },
{ 1.0f, -1.0f, 1.0f , 1.f, 0.f, 0.f, 0.f, 0.f },
{ 1.0f, -1.0f, -1.0f , 1.f, 0.f, 0.f, 1.f, 0.f },
{ 1.0f, 1.0f, -1.0f , 1.f, 0.f, 0.f, 1.f, 1.f },
{ 1.0f, 1.0f, 1.0f , 1.f, 0.f, 0.f, 0.f, 1.f },
{ -1.0f, -1.0f, -1.0f , 0.f, 0.f, -1.f , 0.f, 0.f },
{ 1.0f, -1.0f, -1.0f , 0.f, 0.f, -1.f , 1.f, 0.f },
{ 1.0f, 1.0f, -1.0f , 0.f, 0.f, -1.f, 1.f, 1.f },
{ -1.0f, 1.0f, -1.0f , 0.f, 0.f, -1.f, 0.f, 1.f },
{ -1.0f, -1.0f, 1.0f , 0.f, 0.f, 1.f, 0.f, 0.f },
{ 1.0f, -1.0f, 1.0f , 0.f, 0.f, 1.f, 1.f, 0.f },
{ 1.0f, 1.0f, 1.0f , 0.f, 0.f, 1.f, 1.f, 1.f },
{ -1.0f, 1.0f, 1.0f , 0.f, 0.f, 1.f, 0.f, 1.f },
// Vertices at camera exposure = 1.0: slightly deform the cube
{ -1.0f+shiftX, 1.0f, -1.0f, 0.f, 1.f, 0.f, 0.f, 0.f },
{ 1.0f+shiftX, 1.0f+shiftY, -1.0f, 0.f, 1.f, 0.f, 1.f, 0.f },
{ 1.0f+shiftX, 1.0f+shiftY, 1.0f , 0.f, 1.f, 0.f, 1.f, 1.f },
{ -1.0f+shiftX, 1.0f, 1.0f , 0.f, 1.f, 0.f, 0.f, 1.f},
{ -1.0f, -1.0f, -1.0f , 0.f, -1.f, 0.f, 0.f, 0.f },
{ 1.0f, -1.0f, -1.0f , 0.f, -1.f, 0.f, 1.f, 0.f },
{ 1.0f, -1.0f, 1.0f , 0.f, -1.f, 0.f, 1.f, 1.f },
{ -1.0f, -1.0f, 1.0f , 0.f, -1.f, 0.f, 0.f, 1.f },
{ -1.0f, -1.0f, 1.0f , -1.f, 0.f, 0.f, 0.f, 0.f },
{ -1.0f, -1.0f, -1.0f , -1.f, 0.f, 0.f, 1.f, 0.f },
{ -1.0f+shiftX, 1.0f, -1.0f , -1.f, 0.f, 0.f, 1.f, 1.f },
{ -1.0f+shiftX, 1.0f, 1.0f , -1.f, 0.f, 0.f, 0.f, 1.f },
{ 1.0f, -1.0f, 1.0f , 1.f, 0.f, 0.f, 0.f, 0.f },
{ 1.0f, -1.0f, -1.0f , 1.f, 0.f, 0.f, 1.f, 0.f },
{ 1.0f+shiftX, 1.0f+shiftY, -1.0f , 1.f, 0.f, 0.f, 1.f, 1.f },
{ 1.0f+shiftX, 1.0f+shiftY, 1.0f , 1.f, 0.f, 0.f, 0.f, 1.f },
{ -1.0f, -1.0f, -1.0f , 0.f, 0.f, -1.f , 0.f, 0.f },
{ 1.0f, -1.0f, -1.0f , 0.f, 0.f, -1.f , 1.f, 0.f },
{ 1.0f+shiftX, 1.0f+shiftY, -1.0f , 0.f, 0.f, -1.f, 1.f, 1.f },
{ -1.0f+shiftX, 1.0f, -1.0f , 0.f, 0.f, -1.f, 0.f, 1.f },
{ -1.0f, -1.0f, 1.0f , 0.f, 0.f, 1.f, 0.f, 0.f },
{ 1.0f, -1.0f, 1.0f , 0.f, 0.f, 1.f, 1.f, 0.f },
{ 1.0f+shiftX, 1.0f+shiftY, 1.0f , 0.f, 0.f, 1.f, 1.f, 1.f },
{ -1.0f+shiftX, 1.0f, 1.0f , 0.f, 0.f, 1.f, 0.f, 1.f },
};
// Create cube mesh
rpr_shape cube = nullptr;
{
// 0-terminated list of mesh extra properties (key + value)
rpr_mesh_info mesh_properties[16];
// First key: specify that we want to use mesh deformation on this rpr_shape
mesh_properties[0] = (rpr_mesh_info)RPR_MESH_MOTION_DIMENSION;
// 2 key times are used in cube_data_motionBlur (exposure = 0.0 and exposure = 1.0)
// More key times can be used if needed, for example, 3 key times would mean: exposure = 0.0; 0.5; 1.0
mesh_properties[1] = (rpr_mesh_info)numberOfBlurKeyTime;
mesh_properties[2] = (rpr_mesh_info)0; // key=0 means end of mesh properties.
const rpr_float* texcoords[] = { (rpr_float const*)((char*)&cube_data_motionBlur[0] + sizeof(rpr_float)*6) };
size_t num_texcoords[] = { cube_NumberOfVertices*numberOfBlurKeyTime };
rpr_int texcoord_stride[] = { sizeof(vertex) };
const rpr_int* texcoord_indices_[] = { indices };
rpr_int tidx_stride_[] = { sizeof(rpr_int) };
CHECK(rprContextCreateMeshEx2(context,
(rpr_float const*)&cube_data_motionBlur[0], cube_NumberOfVertices*numberOfBlurKeyTime, sizeof(vertex),
(rpr_float const*)((char*)&cube_data_motionBlur[0] + sizeof(rpr_float) * 3), cube_NumberOfVertices*numberOfBlurKeyTime, sizeof(vertex),
nullptr,0,0,
1, // using 1 texture coord layer.
texcoords, num_texcoords, texcoord_stride,
(rpr_int const*)indices, sizeof(rpr_int),
(rpr_int const*)indices, sizeof(rpr_int),
texcoord_indices_,tidx_stride_,
num_face_vertices, 12, mesh_properties, &cube));
// Add a cube to the scene
CHECK(rprSceneAttachShape(scene, cube));
// Create a transform: -2 unit along X axis and 1 unit up Y axis
RadeonProRender::matrix m = RadeonProRender::translation(RadeonProRender::float3(-2, 1, 0));
// Set the transform
CHECK(rprShapeSetTransform(cube, RPR_TRUE, &m.m00));
}
// Set exposure for motion blur
CHECK(rprCameraSetExposure(camera,1.0));