It has been a long time since my last post. Life was not that good here in Hong Kong, but I was still working on my engine in spare time. This post will show some of the stuff I have been working on in the past few months.
Shading
On graphics side, the engine is now switched to use physically based shaders with GGX model for specular and Oren-Nayar model for diffuse shading. The GGX model is implemented according to this paper from Unreal Engine 4[1]. While the Oren-Nayar model is implemented according to this paper from tri-Ace[2].
Meshes shaded with physically based shaders with different roughness |
A mesh shaded without normal map under indirect lighting:
From left to right: final result, lighting only, normal, roughness, albedo
|
Also, a radiosity[3] baking tool was written to calculate the indirect diffuse lighting for static mesh by rendering cube-maps at every light map texel position. The cube maps are then projected into Spherical Harmonics(SH) during the radiosity iteration. And the results are stored in SH luma + average chroma along the vertex normal hemi-sphere (but the chroma format doesn't play well with the texture compression, so may need to find another storage representation in the future...).
|
|
|
The indirect specular lighting is baked by capturing reflection probe and pre-filtered with GGX model according to the Unreal Engine 4 paper[1]. Currently only the closest reflection probe is used without parallax correction.
|
|
The indirect diffuse lighting for dynamic mesh is baked into the Irradiance Volumes[4], storing in SH coefficients. The SH coefficients are modified according to roughness described in the tri-Ace paper[2] (This is also done for the SH luma store in the light map for static mesh).
|
|
Shadow
The shadow system is updated to use with a mix of baked and real-time shadow. The light map baker described above calculate a shadow term for the main directional light at each light map texel and stored using signed distance field representation[5][6] (Also, an additional binary shadow term is calculated for each Irradiance Volume sample position for dynamic objects).
|
|
|
Potential Visibility Set
A potential visibility set (PVS) baker is written to calculate which meshes are visible to the visibility cells for culling the scene during runtime. A brute force approach is used for baking by taking some sample positions on a given mesh (e.g. vertex position + light map texel position) and then rendering the scene to check whether the visibility cells are visible.
Particles
A basic particle system is implemented which can receive static lighting and receive static shadow. The particle are shaded on CPU using the Irradiance Volumes described above and can be calculated either per vertex, per particle or per emitter.
|
|
Cross platform support
The engine runtime supports 3 different platforms: Windows, Mac, iOS(Editors are Windows only). On Windows, the engine mainly runs with D3D11. An extra OpenGL wrapper was written for Windows to ease the porting to iOS and Mac because it is easier to debug OpenGL with tools like Nsight.
The engine runs on Windows, Mac, iOS platforms |
To write cross platform shaders, shaders are written in my own shading language which is similar to HLSL. Those shaders are then parsed by a shader parser generated by Flex and Bison[9] to obtain a syntax tree to output the actual HLSL and GLSL source code.
Final words
Hope you enjoy the above screen shots and wish I can find some time to describe them in details in future posts.
There are some other tasks implemented in the past few months, such as various editors, audio coding as well as asset hot-reload |
[1] Real Shading in Unreal Engine 4 http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_notes_v2.pdf
[2] Beyond a Simple Physically Based Blinn-Phong Model in Real-time http://research.tri-ace.com/Data/s2012_beyond_CourseNotes.pdf
[3] Radiosity http://en.wikipedia.org/wiki/Radiosity_(computer_graphics)
[4] Irradiance Volumes for Games http://developer.amd.com/wordpress/media/2012/10/Tatarchuk_Irradiance_Volumes.pdf
[5] Improved Alpha-Tested Magnification for Vector Textures and Special Effects http://www.valvesoftware.com/publications/2007/SIGGRAPH2007_AlphaTestedMagnification.pdf
[6] Distance Field Shadows http://udn.epicgames.com/Three/DistanceFieldShadows.html
[7] Exponential Shadow Maps http://research.edm.uhasselt.be/tmertens/papers/gi_08_esm.pdf
[8] Fourier Opacity Mapping http://sebastien.hillaire.free.fr/index.php?option=com_content&view=article&id=61&Itemid=72
[9] Flex and Bison http://aquamentus.com/flex_bison.html
Did you use some software for filtering cubemaps with GGX model or just coded it yourself ?
回覆刪除I code it by myself according to the "Real Shading in Unreal Engine 4" paper. First, rendering a cube map of scene at the target cube map position(without any tone-mapping), then for each face of the cube map, pre-filter it with a shader for different roughness described by the paper. Repeat the above steps for other cube map faces. After that the pre-filtered cube map is ready for use.
刪除Excellent works!!
回覆刪除Is it possible that you can talk about the specific details of the capture probe, I don't quite understand what it is like to capture what is similar to the "light probe". Is it direct lighting that captures the surrounding environment?
回覆刪除The captured reflection probe is a cube map captured at the probe location, capturing the direct lighting of surrounding environment. Then it will be pre-filtered and stored in mip-map chain for specular lighting.
回覆刪除And the "light probe" is the used for diffuse lighting, storing the SH projected indirect lighting.