Radeon ProRender

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));

See full code