# PBR ORMTexture.How to Merge Texture?

**URL:** https://discourse.vtk.org/t/pbr-ormtexture-how-to-merge-texture/14545
**Category:** Support
**Created:** [September 9, 2024, 3:53am UTC](https://discourse.vtk.org/t/pbr-ormtexture-how-to-merge-texture/14545 "2024-09-09T03:53:59Z")
**Posts on this page:** 1
**Page:** 1

<div class="post-metadata">

### Author: ![liukang](https://discourse.vtk.org/letter_avatar_proxy/v4/letter/l/e9c0ed/32.png) [@liukang](https://discourse.vtk.org/u/liukang)
#### Post date: [September 9, 2024, 3:54am UTC](https://discourse.vtk.org/t/pbr-ormtexture-how-to-merge-texture/14545/1 "2024-09-09T03:54:00Z")

</div>

Common PBR material package summary General insurance the following material types:

```auto
Concrete042C_2K_Color.jpg
Concrete042C_2K_AmbientOcclusion.jpg
Concrete042C_2K_Roughness.jpg
Concrete042C_2K_Metalness.jpg
Concrete042C_2K_NormalGL.jpg

```

 ![Concrete042C_2K_AmbientOcclusion](https://discourse.vtk.org/uploads/default/original/2X/6/6bd30ec9dca1f3d35d6c0d340c8bf949bbd89b8f.jpeg)

 ![Concrete042C_2K_Roughness](https://discourse.vtk.org/uploads/default/original/2X/f/fd68cf96d048598eb11a6c9610baba2dbfd7e175.jpeg)  
 ![Concrete042C_PREVIEW](https://discourse.vtk.org/uploads/default/original/2X/a/aff7b1b98abd6dae3d4b3eb1f2548131cb27c7fd.jpeg)  
Detailed data can be obtained from this address：

> **[Concrete 042 C on ambientCG](https://ambientcg.com/view?id=Concrete042C)**
>
> Asset 'Concrete 042 C' on ambientCG. Get this asset and 1000+ more PBR materials and textures for free under the Public Domain license.

In the ORMTexture description, Occlusion value, Roughness value and Metallic value are stored in the RGB component of the Texture. How to merge three 8-bit grayscale images into the required material of ORMTexture? The rendered effect after merging is quite different from the actual effect, is this the VTK rendering accuracy is not enough or I did something wrong?

 ![Snipaste_2024-09-09_12-38-23](https://discourse.vtk.org/uploads/default/original/2X/d/d7b4252cd96fffdc51bf4571a35301c245c20d50.jpeg)

Here is some code for my rendering:

```auto
 actor->GetProperty()->SetInterpolationToPBR();

 vtkSmartPointer<vtkImageData> redImage = vtkSmartPointer<vtkImageData>::New();
 ReadImageToTexture(m_material.ambientOcclusionPath, redImage.Get());

 vtkSmartPointer<vtkImageData> greenImage = vtkSmartPointer<vtkImageData>::New();
 ReadImageToTexture(m_material.roughnessPath, greenImage.Get());

 vtkSmartPointer<vtkImageData> blueImage = vtkSmartPointer<vtkImageData>::New();
 ReadImageToTexture(m_material.metalnessPath, blueImage.Get());

 int Dimensions[3];
 redImage->GetDimensions(Dimensions);

 vtkSmartPointer<vtkImageData> imageData = vtkSmartPointer<vtkImageData>::New();
 imageData->SetDimensions(Dimensions);
 imageData->AllocateScalars(VTK_UNSIGNED_CHAR, 3);

 int size = imageData->GetNumberOfPoints();

 unsigned char *pixels = static_cast<unsigned char *>(imageData->GetScalarPointer());
 unsigned char *pixels_r = static_cast<unsigned char *>(redImage->GetScalarPointer());
 unsigned char *pixels_g = static_cast<unsigned char *>(greenImage->GetScalarPointer());
 unsigned char *pixels_b = static_cast<unsigned char *>(blueImage->GetScalarPointer());
 for (int i = 0; i < Dimensions[0]; i++)
 {
     for (int j = 0; j < Dimensions[1]; j++)
     {
         pixels[(i * Dimensions[0] + j) * 3] = static_cast<unsigned char>(pixels_r[i * Dimensions[0] + j]); // R
         pixels[(i * Dimensions[0] + j) * 3 + 1] = static_cast<unsigned char>(pixels_g[i * Dimensions[0] + j]); // G
         pixels[(i * Dimensions[0] + j) * 3 + 2] = static_cast<unsigned char>(pixels_b[i * Dimensions[0] + j]); // B
     }
 }

 vtkSmartPointer<vtkTexture> material = vtkSmartPointer<vtkTexture>::New();
 material->InterpolateOn();
 material->MipmapOn();
 material->SetInputData(imageData);
 material->Update();

 vtkSmartPointer<vtkTexture> albedo = vtkSmartPointer<vtkTexture>::New();
 albedo->UseSRGBColorSpaceOn();
 albedo->InterpolateOn();
 ReadImageToTexture(m_material.baseColorPath, albedo);

 vtkSmartPointer<vtkTexture> normal = vtkSmartPointer<vtkTexture>::New();
 normal->InterpolateOn();
 ReadImageToTexture(m_material.normalPath, normal);

 vtkSmartPointer<vtkImageFlip> flip = vtkSmartPointer<vtkImageFlip>::New();
 ReadImageToImageFlip(m_material.normalPath, flip);
 flip->SetFilteredAxes(0);

 vtkSmartPointer<vtkTexture> coatNormal = vtkSmartPointer<vtkTexture>::New();
 coatNormal->InterpolateOn();
 coatNormal->SetInputConnection(flip->GetOutputPort());

 actor->GetProperty()->SetMetallic(1.0);
 actor->GetProperty()->SetRoughness(1.0);
 actor->GetProperty()->SetCoatColor(0.75,0.75,0.75);

 actor->GetProperty()->SetBaseColorTexture(albedo);
 actor->GetProperty()->SetORMTexture(material);
 actor->GetProperty()->SetNormalTexture(normal);
 actor->GetProperty()->SetCoatNormalTexture(coatNormal);

 vtkDataSet *dataSet = actor->GetMapper()->GetInput();
 vtkDataSetMapper *mapper = static_cast<vtkDataSetMapper *>(actor->GetMapper());

 vtkSmartPointer<vtkTextureMapToSphere> textureMap = vtkSmartPointer<vtkTextureMapToSphere>::New();
 textureMap->SetInputData(dataSet);
 textureMap->SetPreventSeam(false);
 textureMap->SetAutomaticSphereGeneration(true);
 textureMap->Update();

 vtkSmartPointer<vtkFloatArray> newTCoords = vtkSmartPointer<vtkFloatArray>::New();
 newTCoords->DeepCopy(textureMap->GetOutput()->GetPointData()->GetTCoords());
 dataSet->GetPointData()->SetTCoords(newTCoords);

 mapper->SetInputData(dataSet);
 mapper->SetScalarVisibility(false);
 mapper->Modified();

 actor->Modified();

```

I refer to the relevant example on [vtk.org](http://vtk.org):  
[https://examples.vtk.org/site/Cxx/Rendering/PBR\_Clear\_Coat/](https://examples.vtk.org/site/Cxx/Rendering/PBR_Clear_Coat/)
