├── .gitignore
├── README.md
├── Web.config
├── chest.html
├── chest.js
├── envmaps
└── Yokohama
│ ├── negx.jpg
│ ├── negy.jpg
│ ├── negz.jpg
│ ├── posx.jpg
│ ├── posy.jpg
│ ├── posz.jpg
│ └── readme.md
├── fire-hydrant.html
├── fire-hydrant.js
├── index.css
├── index.html
├── libs
└── three.js
│ ├── OBJLoader.js
│ └── r82dev
│ ├── controls
│ └── OrbitControls.js
│ ├── three.js
│ └── three.min.js
├── models
├── Chest
│ ├── Chest.obj
│ ├── chest_albedo.png
│ ├── chest_ao.png
│ ├── chest_metalness.png
│ ├── chest_normal.png
│ └── chest_roughness.png
├── FireHydrant
│ ├── FireHydrantMesh.obj
│ ├── fire_hydrant_Base_Color.png
│ ├── fire_hydrant_Metallic.png
│ ├── fire_hydrant_Mixed_AO.png
│ ├── fire_hydrant_Normal_OpenGL.png
│ └── fire_hydrant_Roughness.png
└── NormalTangentTest
│ ├── NormalTangentTestPlatform.mtl
│ ├── NormalTangentTestPlatform.obj
│ ├── NormalTangentTestPlatform_high.mtl
│ ├── NormalTangentTestPlatform_high.obj
│ ├── NormalTangentTest_BaseColor.png
│ ├── NormalTangentTest_Metallic.png
│ ├── NormalTangentTest_Normal.png
│ ├── NormalTangentTest_Occlusion.png
│ ├── NormalTangentTest_OcclusionRoughnessMetallic.png
│ ├── NormalTangentTest_Roughness.png
│ └── UV_label_alpha.png
├── normal-tangent-readme.html
├── normal-tangent-test.html
├── normal-tangent-test.js
├── screenshots
├── FireHydrant.png
└── NormalTangentTest
│ ├── BlenderApplyNormalMap.png
│ ├── BlenderNormalMapImportButton.png
│ ├── ExampleOfCorrectNormalMap.png
│ ├── ExampleOfDirectXNormalsUsedInBlender.png
│ ├── ExampleOfUVDirections.png
│ ├── ExampleOfWrongBehavior.png
│ ├── OffAxis.png
│ └── UV_Positions_Arrows.png
└── style.css
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | Thumbs.db
3 | Desktop.ini
4 | *.suo
5 | *.blend1
6 | node_modules
7 | npm-debug.log
8 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Physically Based Rendering (PBR) Tests
2 |
3 | Click the link for more info:
4 |
5 | https://emackey.github.io/testing-pbr/
6 |
--------------------------------------------------------------------------------
/Web.config:
--------------------------------------------------------------------------------
1 |
2 |
13 | @emackey - 14 | source code 15 |
16 | 17 |18 | These are some quick tests of PBR using 19 | THREE.MeshStandardMaterial. 21 |
22 |28 | The mesh came from Substance Share 29 | and is covered by the 30 | Creative Commons 4.0 license. 31 | The textures were (mostly) procedurally generated in Substance Painter 2.3.1. The model has some visible polygon 32 | edges on the side hose hookups that were not visible in Substance Painter, but these may be artifacts from 33 | a sub-optimal conversion process I used. Also, the yellow paint looks shinier in Three.js than it did in 34 | Substance Painter. 35 |
36 | 37 |38 |
39 | 40 | 41 | 42 | 43 | 44 |50 | I believe this is a demo object from Luxology Modo. A detail map was removed such that the model 51 | can work just from the primary PBR maps. 52 |
53 | 54 |55 | Zoom in on one of the brass bumps on the front of the chest. Note that you can see the reflection 56 | of the environment in the brass, and again on the metal buckles. The reflection map is not 57 | part of the Chest model, it came from the host application's scene. I believe that glTF loaders 58 | will need to provide an API for the host app to supply a reflection map to the model being loaded. 59 | The reflection map cannot be included in a glTF model if the model is to be loaded into a larger 60 | scene. 61 |
62 | 63 |64 |
65 | 66 | 67 | 68 | 69 | 70 |76 | It's normal-mapping time. Do you know where your tangent vectors are? 77 |
78 |13 | @emackey - 14 | source code - 15 | other pbr models 16 |
17 | 18 |19 | It's normal-mapping time. Do you know where your tangent vectors are? 20 |
21 |27 | I created this model to test how normal, tangent, and bi-tangent vectors behave in various 28 | applications and engines. The tiles on the left are hemisphere-on-plane shaped geometry, 29 | and the tiles to the right of those are individual quads, which will contain normal-mapped 30 | versions of the same geometry (as calculated by Substance Painter 2.4). 31 | I've spun the UV maps around in 5 different directions, 32 | to cause the tangent vectors to go all different ways. 33 |
34 | 35 |
36 |
37 |
38 |
41 | I don't expect the normal-mapped versions to work off-axis, as the hemisphere 42 | geometry is quite large: 43 |
44 | 45 |
46 |
47 |
50 | But, when viewed directly face-on (orthographic or nearly so), I expect the normal map 51 | to closely replicate the geometry, regardless of the orientation of the 52 | normal-mapped quad in UV (texture coordinate) space. 53 |
54 | 55 |
56 |
57 | Loading the normal map into Blender 2.77's texture image panel appears straightforward, there's even
58 | a mapping called "Norm" that sounds correct. But the default behavior here is to take the luminance
59 | of the incoming image and treat it as a height map, which is not what we want at all. So while this
60 | is a needed step, it is not enough on its own.
61 |
64 |
65 | I didn't build this model just to test Blender, of course. There are several combinations of engines
66 | and shaders that appear, at least to my eye, to treat normal maps somewhat differently, or produce
67 | different results from them. The "twisting around" of the light source shown here is exactly what
68 | I'm trying to avoid (although there are additional problems in this image due to incorrect import
69 | settings in Blender).
70 |
73 |
74 | Next let's fix the import settings. Here I've told Blender to treat the incoming image as non-color,
75 | and interpret it as a tangent-space normal map, which it is.
76 |
79 |
80 | Well, that's improved, but I still see the light source moving around when the UV map orientation
81 | changes, so it's no good. It turns out that Substance Painter 2.4 has texture export options for two different
82 | kinds of normal maps, "OpenGL" and "DirectX" (their terms) in the texture export configuration
83 | panel. The "PBR MetalRough" preset in this version defaults to the "DirectX" version, which has
84 | the effect of flipping the V axis vectors (the green channel intensity) compared to "OpenGL" version.
85 |
86 | This is not what Blender or Three.JS expects, and so produces the bad result shown here.
87 |
90 |
91 | At last, the correct result was achieved by using Substance Painter's "OpenGL" export option
92 | paired with the Blender settings shown above. The same map also works in Three.js:
93 | View Demo.
94 |
95 | Notice that all of the tiles now appear very consistent when viewed directly face-on, with
96 | the light source coming from the same direction, regardless of the twisting happening in the
97 | texture coordinate space.
98 |
101 | I hope this test object proves useful, particularly to the development of glTF 2.0 and its own 102 | normal map implementations. The next step from here will be to construct a glTF 2.0 model that 103 | uses this map, and test its behavior in a variety of glTF loaders and engines. 104 |
105 |