Parallax Mapping Sample
This program is ParallaxOcclusionMapping Sample from D3D samples. I touch this technology because I found some one use DXT5 format as normal maps. DXT5 means the texture still keep full range of alpha channel. As I deeper into the code, I found they use the alpha channel as the parallax mapping. This will will make the normal map effect and details on the flattened surface become more obvious. Low polygon mesh could show some high polygon effect with less vertex data triangles, and textures.
The Basics When a texture map representing an uneven surface is applied to a flattened polygon, the surface appears to get flattened. In Figure 1 you can see that when viewing the polygon along the depicted eye vector, you will see point A of the surface. However, if you were viewing the actual surface instead of a texture mapping polygon, you would see point B. If the texture coordinate corresponding to point A could be corrected, then you could view point B instead. By offsetting all the texture coordinates individually, high areas of the surface would shift toward the eye and lows areas of the surface would shift away from the eye(This original words is like this: high areas of the surface would shift always the eye and low areas of the surface would shift toward the eye. As you see from the Figure 1, A locates the high area, it’s corrected position is B, B is more closer than A. So I think high areas should shift toward the eye instead of shifting away from the eye). The process of parallax mapping requires that, for each pixel drawn, a texture coordinate, used to index one or more texture maps, be corrected by some displacement.
To compute an offset texture coordinate for a pixel, 3 components are required: a starting texture coordinates, a value of the surface height, and a tangent space vector pointing from the pixel to the eye point. An application programmer must supply a tangent, bi-normall, and normal at each vertex. These can be used to create a rotation matrix which will transform vectors from the global coordinate system to tangent space.
A standard height map or one channel (usually the alpha channel) in texture is used to represent the varying height of the surface. The height map correlates to the surface’s regular texture map and stores one height value per Texel. These values are in the range[0.0, 1.0]. You could use following function to remap other range to range [0, 1].
And you could use the following function to calculate the corrected texture coordinate.
Here are some implementation details in the shader:
To create the tangent world space:
float3 vNormalWS = mul( vInNormalOS, (float3x3) g_mWorld ); float3 vTangentWS = mul( vInTangentOS, (float3x3) g_mWorld ); float3 vBinormalWS = mul( vInBinormalOS, (float3x3) g_mWorld ); vNormalWS = normalize( vNormalWS ); vTangentWS = normalize( vTangentWS ); vBinormalWS = normalize( vBinormalWS ); // Compute position in world space: float4 vPositionWS = mul( inPositionOS, g_mWorld ); // Normalize the light and view vectors and transform it to the tangent space: float3x3 mWorldToTangent = float3x3( vTangentWS, vBinormalWS, vNormalWS );
To calculate the corrected coordinate:
// Propagate the view and the light vectors (in tangent space): Out.vLightTS = mul( vLightWS, mWorldToTangent ); // mul(vector, matrix) ?? Out.vViewTS = mul( mWorldToTangent, vViewWS ); // mul(matrix, vector) ?? // Compute initial parallax displacement direction: float2 vParallaxDirection = normalize( Out.vViewTS.xy ); // The length of this vector determines the furthest amount of displacement: float fLength = length( Out.vViewTS ); float fParallaxLength = sqrt( fLength * fLength – Out.vViewTS.z * Out.vViewTS.z ) / Out.vViewTS.z; // Compute the actual reverse parallax displacement vector: Out.vParallaxOffsetTS = vParallaxDirection * fParallaxLength;
Here, there are still several thing make me a bit confused. Why we need to use mul(matrix, vector) instead of mul(vector, matrix) when calculate the view direction in the tangent space? I tried to modify the code, replaced mul(matrix, vector) with mul(vector, matrix), but some artifact appear as the angle between camera view and polygon surface become very small. Another thing is the the Parallax occlusion mapping have some better effect than Parallax Mapping, but I did not check how it works.
At first, I wanted to ship this sample into my d3d framework. That means I will re-do the whole process again with my own code. But why should I keep ask a VisualStudio IDE under Ubuntu OS system when I could use VS under windows XP at all? If it works, we should use it, no matter whether it was created by ourselves or not. We know it and know how to apply it that is enough. The wheels should not be re-build again and again.
The full source code could be downloaded from here.
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了