视差贴图(Parallax Mapping)与陡峭视差贴图(Steep Palallax Mapping)

视差贴图(Parallax Mapping)

Demo下载

视差贴图目前已经被广泛运用了,只需要增加一种模型表面的深度纹理信息之后,就能近似的模拟模型的凹凸,在不需要灯光,不需要环境反射的情况下,可以比较真实的模拟真实世界.

先来看一下视差贴图与其他贴图的区别

可以看出 Parallax Mapped 和Steep Parallax Mapped 实现的效果要好很多.

下面的图片更好的表现了视差贴图的好处

原理:

根据用户的观察角度来将纹理坐标偏移,就是把模型表面较高的位置来遮挡位置较低的位置.当用户观察角度改变的时候,让一些像素的纹理坐标偏移来遮挡一些像素,从而使观察者感觉到凹凸起伏.纹理的偏移需要一个描述模型的凹凸纹理和观察位置同时决定的.

这是一张原理的图片,在这里观察者的眼睛在V处,实际观察的物体的H(T1)点,也就是说物体的真实位置是在H(T1)处,但是眼睛观测的视线会落在To处.

要想得到真实的场景,我们需要把To处的光线偏移到H(T1)处,这样子就看起来就会比较真实.

如何来计算像素点To到H(T1)的偏移呢,需要观察者位置和当前像素点的位置才能计算出来.下面我们来看一下是如何实现计算的.

就是OffsetUV 和ViewDir.x 和ViewDir.y 我们是已经知道的.

通常用简化的公式

OffsetUV = OffsetUV + float2(-ViewDir.x,ViewDir,y)*v2Scale;

其中OffsetUV 表示最终得到的颜色纹理偏移,ViewDir 表示纹理观察向量(经归一处理过),v2Scale 表示与高度和模型有关的缩放因子,,这个缩放因子与表面起伏的大小和整个的大小的比相关.

在shader里面分为两部分写:

一部分是将每个顶点上的观察方向变化带模型空间,整个部分在Vertex里面计算实现;

另一部分是完成像素偏移的计算,此部分在PixelShader中完成.

PixelShader

//PixelShader
float4 RenderScenePS( VS_OUTPUT In ) :COLOR0
  {
    // 计算视差贴图的偏移
    float3 ViewDir = normalize( In.vLookAt );
    float2 OffsetUV = In.TextureUV ;
    float3 h = tex2D( MeshHeightSampler ,In.TextureUV ).y ;
    OffsetUV += float2( -ViewDir.x , ViewDir.y ) * ( h * 0.04 - 0.02 );
    float4 texColor = tex2D( MeshTextureSampler ,OffsetUV );
    //
    return texColor  ;

  }

OffsetUV += float2( -ViewDir.x , ViewDir.y ) * ( h * 0.04 - 0.02 );

其中这行代码就是表示视差贴图的公式;

在VertexShader里面要实现Tangent Space(我的另一篇博客有提到)坐标,

VS_OUTPUT RenderSceneVS( VS_INPUT In )
  {

    VS_OUTPUT Out = ( VS_OUTPUT )0;
   //正常流程变化模型的顶点
    float4x4 matWorldView = mul( g_matWorld ,g_matView );
    float4x4 matWorldViewProject = mul( matWorldView ,g_matProject );
    Out.Position = mul( In.Position , matWorldViewProject );
    Out.TextureUV = In.TextureUV;
    //----------------- 在此计算一个变换矩阵 ---------------------
    // 将世界坐标变换到切线空间系的变换矩阵
    float3x3 matWorldToModel = float3x3 (
      mul( In.Tanget ,                   g_matWorld ).xyz ,
      mul( cross( In.Tanget,In.Normal ), g_matWorld ).xyz ,
      mul( In.Normal ,                   g_matWorld ).xyz );

    //
    float4 Position = mul( In.Position ,g_matWorld );
    // 每个顶点上的指向观察者的方向
    Out.vLookAt = mul ( matWorldToModel ,normalize( Position - g_vEyePosition ));
    return Out;
  }

陡峭视差贴图Steep Parallax Mapped

我们接着看一下Steep Parallax Mapping,这种视图看起来会更加逼真,显示效果会好点,当然计算的方法也不一样.

下面是Steep Parallax Mapping的公式:

ti = s + (Ex , Ey) i / (n Ez)      
   
 0 ≤ i < n

陡峭视差映射,不像简单的视差映射近似,并不只是简单粗暴的对纹理坐标进行偏移而不检查合理性和关联性,会检查结果是否接近于正确值。这种方法的核心思想是把表面的深度切分成等距的若干层。然后从最顶端的一层开始采样高度图,每一次会沿着V的方向偏移纹理坐标。如果点已经低于了表面(当前的层的深度大于采样出的深度),停止检查并且使用最后一次采样的纹理坐标作为结果。

原理:

陡峭视差映射的工作方式在下面的图片上举例。深度被分割成8个层,每层的高度值是0.125。每层的纹理坐标偏移是V.xy/V.z
* scale/numLayers。从顶层黄色方块的位置开始检查,下面是手动计算步骤:

1.层的深度为0,高度图深度H(T0)大约为0.75。采样到的深度大于层的深度,所以开始下一次迭代。

2.沿着V方向偏移纹理坐标,选定下一层。层深度为0.125,高度图深度H(T1)大约为0.625。采样到的深度大于层的深度,所以开始下一次迭代。

3.沿着V方向偏移纹理坐标,选定下一层。层深度为0.25,高度图深度H(T2)大约为0.4。采样到的深度大于层的深度,所以开始下一次迭代。

4.沿着V方向偏移纹理坐标,选定下一层。层深度为0.375,高度图深度H(T3)大约为0.2。采样到的深度小于层的深度,所以向量V上的当前点在表面之下。我们找到了纹理坐标Tp=T3是实际交点的近似点。

下面是Steep Parallax Mapped的算法.

vec2 steepPallaxMapping(in vec3 v, in vec2 t)
{
	// determine number of layers from angle between V and N
	const float minLayers = 5;
	const float maxLayers = 15;
	float numLayers = mix(maxLayers, minLayers, abs(dot(vec3(0, 0, 1), v)));

	// height of each layer
	float layerHeight = 1.0 / numLayers;
	// depth of current layer
	float currentLayerHeight = 0;
	// shift of texture coordinates for each iteration
	vec2 dtex = gHeightScale * v.xy / v.z / numLayers;

 	// current texture coordinates
	vec2 currentTextureCoords = t;

	// get first depth from heightmap
 	float heightFromTexture = texture(NormTexSampler, currentTextureCoords).a;

	// while point is above surface
	while(heightFromTexture > currentLayerHeight)
	{
		// to the next layer
		currentLayerHeight += layerHeight;
		// shift texture coordinates along vector V
		currentTextureCoords -= dtex;
		// get new depth from heightmap
		heightFromTexture = texture(NormTexSampler, currentTextureCoords).a;
   }

   return currentTextureCoords;
}

Demo 下载

时间: 2024-10-25 12:08:24

视差贴图(Parallax Mapping)与陡峭视差贴图(Steep Palallax Mapping)的相关文章

心智图/思维导图(Mind Map/Mind Mapping),思维导图介绍

心智图(Mind Map),又称脑图.心智地图.脑力激荡图.思维导图.灵感触发图.概念地图.树状图.树枝图或思维地图,是一种图像式思维的工具以及一种利用图像式思考辅助工具来表达思维的工具. 心智图是使用一个中央关键词或想法引起形象化的构造和分类的想法; 它用一个中央关键词或想法以辐射线形连接所有的代表字词.想法.任务或其它关联项目的图解方式.它可以利用不同的方式去表现人们的想法,如引题式,可见形象化式,建构系统式和分类式.它是普遍地用作在研究.组织.解决问题和政策制定中. 心智图是一张集中了所有

java 数据结构 图中使用的一些常用算法 图的存储结构 邻接矩阵:图的邻接矩阵存储方式是用两个数组来标示图。一个一位数组存储图顶点的信息,一个二维数组(称为邻接矩阵)存储图中边或者弧的信息。 设图G有n个顶点,则邻接矩阵是一个n*n的方阵,定义为: 实例如下,左图是一个无向图。右图是邻接矩阵表示:

以下内容主要来自大话数据结构之中,部分内容参考互联网中其他前辈的博客. 图的定义 图是由顶点的有穷非空集合和顶点之间边的集合组成,通过表示为G(V,E),其中,G标示一个图,V是图G中顶点的集合,E是图G中边的集合. 无边图:若顶点Vi到Vj之间的边没有方向,则称这条边为无项边(Edge),用序偶对(Vi,Vj)标示. 对于下图无向图G1来说,G1=(V1, {E1}),其中顶点集合V1={A,B,C,D}:边集合E1={(A,B),(B,C),(C,D),(D,A),(A,C)}: 有向图:若

各种图(流程图,思维导图,UML,拓扑图,ER图)简介

来源于:http://www.cnblogs.com/jiqing9006/p/3344221.html 流程图 1.定义:流程图是对过程.算法.流程的一种图像表示,在技术设计.交流及商业简报等领域有广泛的应用. 2.案例 3.计算机语言只是一种工具.光学习语言的规则还不够,最重要的是学会针对各种类型的问题,拟定出有效的解决方法和步骤即算法.有了正确而有效的算法,可以利用任何一种计算机高级语言编写程序,使计算机进行工作.因此,设计算法是程序设计的核心. 对同一个问题,可以有不同的解题方法和步骤.

图的着色问题 带时间区间的图着色问题

安排会面问题,有几个研究组,不同的学生各自有自己感兴趣的若干个组想去看,每个组讨论时间为t,求总的最小的时间. 1.枚举颜色的可能 o((n-1)^n) 2.进行k着色,从1开始,看可能与否,不行把k加1然后再判断 3. 韦尔奇.鲍威尔法对图G进行着色 a)将图G中的结点按度数的递减次序排列 b)用第一种颜色对第一点着色,按排列次序,对前面的着色点不邻接的每一点用上同样的颜色 c)用第二种颜色对尚未着色的点重复(b),第三种继续. 4.有个叫 路线着色问题 还没看懂 5.有时间区间的图着色问题

【转】各种图(流程图,思维导图,UML,拓扑图,ER图)简介

原文地址:各种图(流程图,思维导图,UML,拓扑图,ER图)简介 流程图 1.定义:流程图是对过程.算法.流程的一种图像表示,在技术设计.交流及商业简报等领域有广泛的应用. 2.案例 3.计算机语言只是一种工具.光学习语言的规则还不够,最重要的是学会针对各种类型的问题,拟定出有效的解决方法和步骤即算法.有了正确而有效的算法,可以利用任何一种计算机高级语言编写程序,使计算机进行工作.因此,设计算法是程序设计的核心. 对同一个问题,可以有不同的解题方法和步骤.例如,求1+2+3+…+100,可以先进

Android图表库MPAndroidChart(八)——饼状图的扩展:折线饼状图

Android图表库MPAndroidChart(八)--饼状图的扩展:折线饼状图 我们接着上文,饼状图的扩展,增加折现的说明,来看下我们要实现的效果 因为之前对MPAndroidChart的熟悉,所有我们就可以直接来实现了 一.基本实现 首先,就是我们的来看下他的定义布局 <com.github.mikephil.charting.charts.PieChart android:id="@+id/mPieChart" android:layout_width="mat

最常用的UML图包括:用例图、类图、序列图、状态图、活动图、组件图和部署图

(转) 用例图 用例图描述了系统提供的一个功能单元.用例图的主要目的是帮助开发团队以一种可视化的方式理解系统的功能需求,包括基于基本流程的"角色" (actors,也就是与系统交互的其他实体)关系,以及系统内用例之间的关系.用例图一般表示出用例的组织关系--要么是整个系统的全部用例,要么是完 成具有功能(例如,所有安全管理相关的用例)的一组用例.要在用例图上显示某个用例,可绘制一个椭圆,然后将用例的名称放在椭圆的中心或椭圆下面的中间位 置.要在用例图上绘制一个角色(表示一个系统用户),

Python统计分析可视化库seaborn(相关性图,变量分布图,箱线图等等)

Visualization of seaborn  seaborn[1]是一个建立在matplot之上,可用于制作丰富和非常具有吸引力统计图形的Python库.Seaborn库旨在将可视化作为探索和理解数据的核心部分,有助于帮人们更近距离了解所研究的数据集.无论是在kaggle官网各项算法比赛中,还是互联网公司的实际业务数据挖掘场景中,都有它的身影.    在本次介绍的这个项目中,我们将利用seaborn库对数据集进行分析,分别展示不同类型的统计图形. 首先,我们将导入可视化所需的所有必要包,我

(转)【D3D11游戏编程】学习笔记二十三:Cube Mapping进阶之动态环境图

(注:[D3D11游戏编程]学习笔记系列由CSDN作者BonChoix所写,转载请注明出处:http://blog.csdn.net/BonChoix,谢谢~) 在前面两篇介绍Cube Mapping的文章中,我们所使用到的Cube Map都是事先制作好的,这样的一个好处就是运行时效率很高,适合于大多数情形.但如果对于即时动态变化的场景来说,依靠静态图来实现反射效果就不再适用了.因为在不同时刻,一个物体周围的场景是不断变化的,想要把这些变化在物表的反射中体现出来,就需要一张动态的环境图. 1.C