Use Environment View Backgrounds and Reflection Effect

Andrew Markovich

October 20, 2022

Reflections for graphics scene objects can greatly improve rendering quality and realism, especially for architectural and mechanical models. Mirrors, glossy or metal surfaces, water, glass—all these materials look physically correct only if they accurately reflect the surrounding area.

Applying material reflections is typically not necessary during model editing, but they can greatly improve rendering quality when viewing a model at runtime (they are not designed for final scene rendering).

To create reflection effects for materials in a graphics scene, use environment map reflections or reflection planes. Both techniques require the WinGL ES2 or WinMetal vectorization module. Environment map reflections are realistic and do not impact rendering performance, but they are not physically correct. Reflection planes create physically-correct reflections, but they are an expensive operation for the CPU/GPU since it typically invokes ray tracing techniques, which are difficult for real-time rendering.

About Environment Map Reflections

Use environment maps to set up a texture that is used for an environment background and environment reflections together. For details about environment backgrounds, see Work with View Backgrounds. Environment reflections can be applied to many objects and materials inside a graphics scene without loss of rendering performance, and these "sky box" reflections create a realistic scene for simple graphic models and for less noticeable graphical objects. However, environment map reflections are an emulation of physically correct reflections—they provide a reflection of the background only and do not include reflections of objects inside the graphics scene.

cube map

Cube map background

cube map reflection

Cube map reflection

About Reflection Planes

Reflection planes can create a complete reflection effect of a graphics scene, including all visible objects in the scene. But since creation of each mirror plane requires the existing graphics scene to be rendered, this effect has a noticeable impact on rendering performance. It is not recommended to create a large number of reflection planes for an extensive graphic scene, since this can dramatically slow rendering (reflection plane mirrors are recomputed on each frame change, so it constantly influences real-time rendering performance).

reflection plane

 

Enable Material Reflections Using an Environment Map

To add environment map textures, use an OdDbRenderEnvironment object:

OdDbRenderEnvironmentPtr pEnv = ::oddbGetRenderEnvironmentObject(m_pDb, OdDb::kForWrite, true);
pEnv->setEnvironmentImageEnabled(true);
pEnv->setEnvironmentImageFileName(envImageFileName);

The image file name is stored in a .dwg/.dxf file when it is saved, so it is accessible the next time the file is opened. The image is used for environment backgrounds (if available) and for environment reflections (if a reflection isn't overridden by a material).

Set the Material for Environment Reflections

Use the "reflectivity" material property to enable a material reflection:

OdDbMaterialPtr pMaterial = ...;
pMaterial->setReflectivity(0.5);

The reflectivity coefficient is measured in the range 0-1 and specifies the percentage mix of reflection and diffuse material color:

  • 0.0 — No material reflection (default).
  • 0.5 — Half reflection and half diffuse material color (glossy surface).
  • 1.0 — Full reflection without mixing a material color (metallic surface).
reflectivity

 

By default, materials use an environment texture for the reflection effect (if it is set), but it is possible to override the reflection map per material:

OdGiMaterialMap reflectionMap;
reflectionMap.setSourceFileName(reflectionTextureFileName);
pMaterial->setReflection(reflectionMap);

Each material can have its own reflection texture. All material settings are stored inside the .dwg/.dxf file when it is saved, so client applications do not need additional customization to use environment map reflections.

Enable Reflection Plane Materials

Reflection planes aren't natively supported by .dwg databases and require customization. There are two ways to customize the behavior of materials in a .dwg database:

  • Create a custom material object based on the OdDbMaterial class.
  • Use overruling to modify the behavior of existing database material objects.

Creation of custom database objects is described in Drawing SDK documentation: Creating a Custom Entity. The next example is simpler, which uses overruling and shows the customization of material objects to support reflection plane rendering:

class MaterialDrawableOverrule : public OdStaticRxObject<OdGiDrawableOverrule>
{
public:
  MaterialDrawableOverrule()
  {
    OdRxOverrule::setIsOverruling(true);
    OdRxOverrule::addOverrule(OdDbMaterial::desc(), this);
  }
  ~MaterialDrawableOverrule()
  {
    OdRxOverrule::removeOverrule(OdDbMaterial::desc(), this);
    OdRxOverrule::setIsOverruling(false);
  }

  virtual bool isApplicable(const OdRxObject* pOverruledSubject) const
  {
    return true;
  }

  virtual OdUInt32 setAttributes(const OdGiDrawable* pSubject, OdGiDrawableTraits *traits)
  {
    OdUInt32 nFlags = OdGiDrawableOverrule::setAttributes(pSubject, traits);
    OdGiMaterialTraitsPtr pMatTraits = OdGiMaterialTraits::cast(traits);
    if (pMatTraits.isNull())
      return nFlags;
    if (OdDbMaterial::cast(pSubject)->name() == OD_T("Material 4"))
    { OdGiMaterialMap mMap;
      pMatTraits->setChannelFlags((OdGiMaterialTraits::ChannelFlags)(pMatTraits->channelFlags() | OdGiMaterialTraits::kUseReflection));
      pMatTraits->setReflectivity(0.5);
      OdGiMaterialMap matMap;
      matMap.setSource(OdGiMaterialMap::kScene);
      matMap.setTexture(OdGiSceneTexture::createObject());
      pMatTraits->setReflection(matMap);
    }
    return nFlags;
  }
};

The example overrule applies a reflection plane to the database material with the name “Material 4”. Similar to environment reflections, the reflectivity coefficient is set. The main difference from environment reflections is the use of the OdGiSceneTexture placeholder class as a material channel texture. This is a non-.dwg texture class; it is a special material channel to identify the difference from non-reflection plane materials.

Alternatively (instead of using overruling), an OdGiSceneTexture placeholder can be set to a database material directly:

OdDbMaterialPtr pMtl = OdDbDictionary::cast(pDb->getMaterialDictionaryId().safeOpenObject())->getAt(OD_T("Material 4"), OdDb::kForWrite);
pMtl->setChannelFlags((OdGiMaterialTraits::ChannelFlags)(pMtl->channelFlags() | OdGiMaterialTraits::kUseReflection));
pMtl->setReflectivity(0.5);
OdGiMaterialMap matMap;
matMap.setSource(OdGiMaterialMap::kScene);
matMap.setTexture(OdGiSceneTexture::createObject());
pMtl->setReflection(matMap);

This kind of texture can't be stored in .dwg/.dxf file formats, so a reflection plane can be applied to a scene material only at runtime. To save it to .dwg/.dxf file formats, client applications require implementation of custom material objects.

Softness Parameter of a Reflection Plane

To create a matte effect of a reflection surface, use the softness parameter of reflection plane materials and apply it to an OdGiSceneTexture object:

OdGiMaterialMap matMap;
matMap.setSource(OdGiMaterialMap::kScene);
OdGiSceneTexturePtr pTexture = OdGiSceneTexture::createObject();
pTexture->setSoftness(1);
matMap.setTexture(OdGiSceneTexture::createObject());

The softness parameter represents the blur amount (gaussian blur kernel size) that is applied to the generated scene texture before drawing it on a scene material surface. Larger blur amounts provide a more visible blur effect. Null softness (the default) means that no blur effect is applied.

 

softness
Apply Reflection Planes to Planar Surfaces

Reflection plane materials can be applied only to planar surfaces. Reflection planes are generated using the first face normal in the shell geometry primitive, and if the shell that represents a surface contains different normals, the final reflection effect is incorrect. On the other hand, if entity, for which reflection plane materials are applied, draws each face with different normal as separate shell geometry primitive - final reflection effect looks correct. However in this case, note that each separate reflection plane requires a large amount of GPU resources, since each reflection plane is represented as a separate GPU frame buffer, which holds GPU memory. Also, each reflection plane requires its own rendering pass, which reduces final frame rendering performance. Avoid applying reflection plane materials to a large surface set or non-planar surfaces, ensure that reflection plane materials aren't applied to other entities inside a drawing, and avoid using reflection plane materials for entities inside blocks.

To get more information please refer to ODA Documentation.