options<\/em>. First we will create an empty scene element in the RealityServer database as follows.<\/p>\n\r\n[\r\n\t...\r\n\t\r\n\t{"jsonrpc": "2.0", "method": "create_scene", "params": {\r\n\t\t"scene_name" : "exScene"\r\n\t}, "id": 3}\r\n]\r\n<\/pre>\nYou will need to use the scene_name<\/em> often in future commands. Since the scene is created inside the scope you don’t need to ensure it is unique, as long as the scope is.<\/p>\nCreating the Options<\/h3>\n
The options element is basically a container for attributes that control various Iray rendering settings. These settings do not relate to specific elements but rather apply to the entire scene. Later we will attach attributes to the options to control the rendering. For now we just need to create the options and tell the scene to use them.<\/p>\n
\r\n[\r\n\t...\r\n\r\n\t{"jsonrpc": "2.0", "method": "create_element", "params": {\r\n\t\t"element_name" : "exOptions",\r\n\t\t"element_type" : "Options"\r\n\t}, "id": 4},\r\n\r\n\t{"jsonrpc": "2.0", "method": "scene_set_options", "params": {\r\n\t\t"scene_name" : "exScene",\r\n\t\t"options" : "exOptions"\r\n\t}, "id": 5}\r\n<\/pre>\nHere we call the create_element<\/em> command for the first time. With the exception of scenes (which use the special create_scene<\/em> command), the create_element<\/em> command is used to add new elements to the database. For a list of available element types refer to the documentation for the command.<\/p>\nCreating the Root Group<\/h3>\n
The root group is a container which holds references to all of the instances, geometry, lights and other groups which will be used to render the scene. Every scene needs a root group so let’s create an empty one to begin with.<\/p>\n
\r\n[\r\n\t...\r\n\r\n\t{"jsonrpc": "2.0", "method": "create_element", "params": {\r\n\t\t"element_name" : "exRootGroup",\r\n\t\t"element_type" : "Group"\r\n\t}, "id": 6},\r\n\r\n\t{"jsonrpc": "2.0", "method": "scene_set_rootgroup", "params": {\r\n\t\t"scene_name" : "exScene",\r\n\t\t"group" : "exRootGroup"\r\n\t}, "id": 7}\r\n]\r\n<\/pre>\nThis is the same process used for the options. For geometry to actually render it must be attached to the root group. We will cover this a bit later on.<\/p>\n
Creating the Camera<\/h3>\n
Now for something with a bit more complexity. We need to create a camera which will define the viewpoint for our rendering. The scene needs a camera instance rather than the camera itself so we will need to make that as well.<\/p>\n
\r\n[\r\n\t...\r\n\r\n\t{"jsonrpc": "2.0", "method": "create_element", "params": {\r\n\t\t"element_name" : "exCamera",\r\n\t\t"element_type" : "Camera"\r\n\t}, "id": 8},\r\n\r\n\t{"jsonrpc": "2.0", "method": "camera_set_resolution", "params": {\r\n\t\t"camera_name" : "exCamera",\r\n\t\t"resolution" : { "x" : 640, "y" : 480 }\r\n\t}, "id": 9},\r\n\r\n\t{"jsonrpc": "2.0", "method": "create_element", "params": {\r\n\t\t"element_name" : "exCameraInstance",\r\n\t\t"element_type" : "Instance"\r\n\t}, "id": 10},\r\n\r\n\t{"jsonrpc": "2.0", "method": "instance_set_world_to_obj", "params": {\r\n\t\t"instance_name" : "exCameraInstance",\r\n\t\t"transform" : {\r\n\t\t\t"xx": -1.0, "xy": 0.0, "xz": 0.0, "xw": 0.0,\r\n\t\t\t"yx": 0.0, "yy": 1.0, "yz": 0.20395425411200102, "yw": 0.0,\r\n\t\t\t"zx": 0.0, "zy": 0.20395425411200102, "zz": -1.0, "zw": 0.0,\r\n\t\t\t"wx": 8.0, "wy": -5.0, "wz": -25.0, "ww": 1.0\r\n\t\t}\r\n\t}, "id": 11},\r\n\r\n\t{"jsonrpc": "2.0", "method": "instance_attach", "params": {\r\n\t\t"instance_name" : "exCameraInstance",\r\n\t\t"item_name" : "exCamera"\r\n\t}, "id": 12},\r\n\r\n\t{"jsonrpc": "2.0", "method": "group_attach", "params": {\r\n\t\t"group_name" : "exRootGroup",\r\n\t\t"item_name" : "exCameraInstance"\r\n\t}, "id": 13},\r\n\r\n\t{"jsonrpc": "2.0", "method": "scene_set_camera_instance", "params": {\r\n\t\t"scene_name" : "exScene",\r\n\t\t"camera_instance" : "exCameraInstance"\r\n\t}, "id": 14}\r\n]\r\n<\/pre>\nFirst we create the actual camera. Immediately afterwards we call one of the specialised camera commands camera_set_resolution<\/em> to set the size of the image we want to render. You can find other camera commands in the camera<\/em> group of the command documentation. We use the defaults for focal length and aperture for now but there are commands to set these available.<\/p>\nOnce the camera is made we create a new instance element. Instances are special elements which reference something in the scene and allow you to position it by applying a transformation matrix. We do that here with the instance_set_world_to_obj<\/em> command which sets the 4×4 matrix representing the world to object space transform of the instance. In this case we are using it to move the camera along the Z-axis, raise it up the Y-axis and tilt it downwards.<\/p>\nFor the instance to actually reference the camera element we need to attach it using the instance_attach<\/em> command. We then place the instance in our root group with the group_attach<\/em> command. Finally with this all setup we can tell the scene which camera to use by calling the scene_set_camera_instance<\/em> command.<\/p>\nTurning on the Light<\/h3>\n
If we were to render the scene now we would just get a black image because there is no environment or light source. For this example we are going to setup a daylight environment which will be used both as the background and as the source of illumination in the scene. We use the physically based sun_and_sky<\/em> function provided by MDL for this. This function is provided in the MDL base<\/em> module. The base<\/em> module is a special case, even though we are going to call import_scene_elements<\/em> to load it from a file that file actually doesn’t exist anywhere. It is a special internal file, later when we load a material we will load a read MDL file from disk. Here are the commands for making the daylighting and turning it on.<\/p>\n\r\n[\r\n\t...\r\n\r\n\t{"jsonrpc": "2.0", "method": "import_scene_elements", "params": {\r\n\t\t"filename": "${shader}\/base.mdl"\r\n\t}, "id": 15},\r\n\r\n\t{"jsonrpc": "2.0", "method": "create_function_call_from_definition", "params": {\r\n\t\t"arguments" : {\r\n\t\t\t"multiplier" : 0.10132,\r\n\t\t\t"rgb_unit_conversion" : { \r\n\t\t\t\t"r" : 1.0,\r\n\t\t\t\t"g" : 1.0,\r\n\t\t\t\t"b" : 1.0\r\n\t\t\t},\r\n\t\t\t"sun_disk_intensity" : 1.0,\r\n\t\t\t"physically_scaled_sun" : true,\r\n\t\t\t"sun_direction" : { "x" : 0.0, "y" : 0.5, "z" : -1.0 }\r\n\t\t},\r\n\t\t"function_definition_name" : "mdl::base::sun_and_sky(bool,float,color,float,float,float,float,float,color,color,float3,float,float,float,bool,int,bool)",\r\n\t\t"function_name" : "exSunSky"\r\n\t}, "id": 16},\r\n\r\n\t{"jsonrpc": "2.0", "method": "element_set_attribute", "params": {\r\n\t\t"element_name" : "exOptions",\r\n\t\t"attribute_type" : "Ref",\r\n\t\t"attribute_name" : "environment_function",\r\n\t\t"attribute_value" : "exSunSky",\r\n\t\t"create" : true\r\n\t}, "id": 17}\r\n]\r\n<\/pre>\nSo there are three steps, first import the MDL module containing the function, then create a function call from the function definition and finally set an attribute on our options element to tell Iray which MDL function to use to generate the environment. You will note a few things about the\u00a0create_function_call_from_definition<\/em> command used above. Firstly, you can see that you can provide initial values for the various attributes of the function at the time of creation. If there are parameters which do not have defaults you will need to provide values for them here otherwise you will get an error.<\/p>\nSecondly, note the odd value for the function_definition_name<\/em> parameter. This is the function signature<\/em>. Since MDL supports overloading of functions (similar to various Object Oriented programming languages), the function needs to be referenced by its full signature. You can find the signatures of the loaded functions by calling\u00a0import_scene_elements with the “import_options” : { “list_elements” : true }<\/em> parameter. You can also call the\u00a0get_function_definition_overloads<\/em> command if you know the function name. This will give you an array of strings representing the function signatures.<\/p>\nWhen setting the environment_function<\/em> attribute on the options, we use the Ref<\/em> attribute type since while we are using a name this particular attribute expects a reference to a function.<\/p>\nSetting up Tonemapping<\/h3>\n
Now if we rendered the scene we wouldn’t get a black image, we would get a completely white image! Well that’s progress but really we want to see the sky we just created. For this we need to turn on the tonemapping functionality of Iray which controls how the physically correct values generated by Iray are mapped to the limited range of RGB colour values used to display images on computer screens.<\/p>\n
\r\n[\r\n\t...\r\n\r\n\t{"jsonrpc": "2.0", "method": "element_set_attributes", "params": {\r\n\t\t"create" : true,\r\n\t\t"element_name" : "exCamera",\r\n\t\t"attributes" : {\r\n\t\t\t"tm_tonemapper" : {\r\n\t\t\t\t"type" : "String",\r\n\t\t\t\t"value" : "mia_exposure_photographic"\r\n\t\t\t},\r\n\t\t\t"mip_cm2_factor" : {\r\n\t\t\t\t"type" : "Float32",\r\n\t\t\t\t"value" : 1.0\r\n\t\t\t},\r\n\t\t\t"mip_film_iso" : {\r\n\t\t\t\t"type" : "Float32",\r\n\t\t\t\t"value" : 100.0\r\n\t\t\t},\r\n\t\t\t"mip_camera_shutter" : {\r\n\t\t\t\t"type" : "Float32",\r\n\t\t\t\t"value" : 250.0\r\n\t\t\t},\r\n\t\t\t"mip_f_number" : {\r\n\t\t\t\t"type" : "Float32",\r\n\t\t\t\t"value" : 8.0\r\n\t\t\t},\r\n\t\t\t"mip_gamma" : {\r\n\t\t\t\t"type" : "Float32",\r\n\t\t\t\t"value" : 2.2\r\n\t\t\t}\r\n\t\t}\r\n\t}, "id": 18}\r\n]\r\n<\/pre>\nWe are using a new command here, element_set_attributes<\/em>, which is basically the same as element_set_attribute used earlier but allows us to set multiple attributes on an element in a single call. Since we are creating the attributes we must provide the type as well as the value for each. The attributes created above are attached to the camera (not the camera instance). You can find more details on how tone mapping works in the RealityServer documentation.<\/p>\nGeometry<\/h3>\n
The scene would now render with a sky and horizon but no objects which is a bit boring so we’ll add some geometry to the scene. We will use a command that was introduced in RealityServer 4.4 for this, generate_extrusion<\/em>.<\/p>\n\r\n[\r\n\t...\r\n\r\n\t{"jsonrpc": "2.0", "method": "generate_extrusion", "params": {\r\n\t\t"name" : "exObject",\r\n\t\t"profile" : [\r\n\t\t\t{ "x" : 0.0, "y" : 0.0 },\r\n\t\t\t{ "x" : 4.0, "y" : 0.0 },\r\n\t\t\t{ "x" : 4.0, "y" : 6.0 },\r\n\t\t\t{ "x" : 8.0, "y" : 1.0 },\r\n\t\t\t{ "x" : 12.0, "y" : 6.0 },\r\n\t\t\t{ "x" : 12.0, "y" : 0.0 },\r\n\t\t\t{ "x" : 16.0, "y" : 0.0 },\r\n\t\t\t{ "x" : 16.0, "y" : 12.0 },\r\n\t\t\t{ "x" : 12.0, "y" : 12.0 },\r\n\t\t\t{ "x" : 8.0, "y" : 7.0 },\r\n\t\t\t{ "x" : 4.0, "y" : 12.0 },\r\n\t\t\t{ "x" : 0.0, "y" : 12.0 }\r\n\t\t],\r\n\t\t"length" : 12.0\r\n\t}, "id": 19},\r\n\r\n\t{"jsonrpc": "2.0", "method": "element_set_attribute", "params": {\r\n\t\t"element_name" : "exObject",\r\n\t\t"attribute_type" : "Boolean",\r\n\t\t"attribute_name" : "visible",\r\n\t\t"attribute_value" : true,\r\n\t\t"create" : true\r\n\t}, "id": 20},\r\n\r\n\t{"jsonrpc": "2.0", "method": "create_element", "params": {\r\n\t\t"element_name" : "exObjectInstance",\r\n\t\t"element_type" : "Instance"\r\n\t}, "id": 21},\r\n\r\n\t{"jsonrpc": "2.0", "method": "instance_attach", "params": {\r\n\t\t"instance_name" : "exObjectInstance",\r\n\t\t"item_name" : "exObject"\r\n\t}, "id": 22},\r\n\r\n\t{"jsonrpc": "2.0", "method": "group_attach", "params": {\r\n\t\t"group_name" : "exRootGroup",\r\n\t\t"item_name" : "exObjectInstance"\r\n\t}, "id": 23}\r\n]\r\n<\/pre>\nWe give the generate_extrusion<\/em> command a list of points defining an M<\/em> shape from which it can build a nice mesh for us to render. The geometry created by this command has no attributes assigned to it and by default objects are not visible so we need to call element_set_attribute<\/em> to set the visible<\/em> attribute to true so we can see it.<\/p>\nIn order to actually place the object in the scene we need to first create an instance to reference it, then as we did with the camera we attach the object to the instance and add the instance to the root group. At this point we could render the scene and we would get a big M with a funny pink material.<\/p>\n
Defining a Material<\/h3>\n
The M renders pink because we haven’t defined a material for it yet. RealityServer ships with some materials you can use and setup so we’ll import one of those and change its parameters to suit our needs.<\/p>\n
\r\n[\r\n\t...\r\n\r\n\t{"jsonrpc": "2.0", "method": "import_scene_elements", "params": {\r\n\t\t"filename": "${shader}\/material_examples\/architectural.mdl"\r\n\t}, "id": 24},\r\n\r\n\t{"jsonrpc": "2.0", "method": "create_material_instance_from_definition", "params": {\r\n\t\t"arguments": {\r\n\t\t\t"diffuse" : { "r" : 0.8, "g" : 0.1, "b" : 0.25 },\r\n\t\t\t"reflectivity" : 0.5,\r\n\t\t\t"refl_gloss" : 0.3\r\n\t\t},\r\n\t\t"material_definition_name": "mdl::material_examples::architectural::architectural",\r\n\t\t"material_name": "exMaterial"\r\n\t}, "id": 25},\r\n\r\n\t{"jsonrpc": "2.0", "method": "instance_set_material", "params": {\r\n\t\t"instance_name" : "exObjectInstance",\r\n\t\t"material_name" : "exMaterial"\r\n\t}, "id": 26}\r\n]\r\n<\/pre>\nBefore making an instance of the MDL material we need to load its definition from disk. We use import_scene_elements<\/em> for this purpose. The ${shader}<\/em> path causes RealityServer to look in all MDL search paths for the file specified. With the MDL file loaded we can now call\u00a0create_material_instance_from_definition<\/em> to create a material within our scene based on the definition contained in the MDL file. In a similar way to when we made the function for the environment, we can set the initial values of any arguments we want. Here we make the material bit red and setup a glossy reflection.<\/p>\nFinally we call the instance_set_material<\/em> command (this was introduced in RealityServer 4.4 build 1527.40) to actually assign the material to the instance of our M object. If we render the scene now we will get a nice red M lit by daylight, however it will look like it is floating in space, so let’s fix that next.<\/p>\nTurning on the Ground<\/h3>\n
Iray has a nice feature called the implicit ground plane. This is a special option you can enable which creates an automatic ground surface in the scene which can catch shadows and reflections from objects in the scene. The beauty of this feature is you just turn it on and everything is automatic, there is no need to model very large planes or surface. We turn it on simply by setting attributes on our options element.<\/p>\n
\r\n[\r\n\t...\r\n\r\n\t{"jsonrpc": "2.0", "method": "element_set_attributes", "params": {\r\n\t\t"element_name" : "exOptions",\r\n\t\t"create" : true,\r\n\t\t"attributes" : {\r\n\t\t\t"environment_dome_ground" : {\r\n\t\t\t\t"type" : "Boolean",\r\n\t\t\t\t"value" : true\r\n\t\t\t},\r\n\t\t\t"environment_dome_ground_reflectivity" : {\r\n\t\t\t\t"type" : "Color",\r\n\t\t\t\t"value" : { "r" : 0.4, "g" : 0.4, "b" : 0.4 }\r\n\t\t\t},\r\n\t\t\t"environment_dome_ground_glossiness" : {\r\n\t\t\t\t"type" : "Float32",\r\n\t\t\t\t"value" : 1000.0\r\n\t\t\t},\r\n\t\t\t"environment_dome_ground_shadow_intensity" : {\r\n\t\t\t\t"type" : "Float32",\r\n\t\t\t\t"value" : 0.8\r\n\t\t\t}\r\n\t\t}\r\n\t}, "id": 27}\r\n]\r\n<\/pre>\nIn this case we turn on the ground, then give it a reflectivity, glossiness and slightly reduce the shadow intensity. We use the element_set_attributes<\/em> command again to set multiple attributes in one go. At this stage we now have a complete scene which we can render to produce the image shown at the start of this article.<\/p>\nPutting it All Together<\/h3>\n
So we broke down all of the commands needed to make the scene above, now let’s put it all together in a single call we can make to RealityServer to generate the scene. There are 27 commands in all and here they are in one go. You can cut and past this into a tool like Postman and send it a post request to RealityServer and it will create the scene for you and it will reside in the scope. After reviewing the full scene creation request below we will finally make one more request to do the actual rendering. Here is the complete scene generation request. Click the box below to show the full source.<\/p>\n