OpenGL 编程指南(第八版)学习笔记——8 程序式纹理

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wlk1229/article/details/81837980

OpenGL 编程指南学习资料以及我整理的代码下载地址https://pan.baidu.com/s/1bqrcspD

文中提到的代码为下载文件中的“OpenGL编程指南 VS2015代码.zip”文件,代码也可以到github上下载:https://github.com/Kylewlk/OpenGL-Programming-Guide-8th-Edition-Code

8 程序式纹理

3D物理模型

因为这章会使用3D物理模型,所以先讲解一下书中代码使用的3D物理模型。书中的3D物理模型格式有两种,扩展名都是.vbm,一种的人动物模型,另一种是几何体模型,如下图,图片上面对应的是代码中的工程名字。

所有的模型文件都存放在media文件夹中

 

虽然扩展名都是.vbm但是模型内部数据结构不一致,所以两种模型加载的时候使用的代码也是不一样。第一中人物使用的模型加载代码是放在工程目录下面的vbm.h和vbm.cpp,第二种几何模型使用的代码是lib/vbm.cpp和include/vmb.h。

 

两种模型包含的数据不一样,人物模型包含的数据有:顶点位置,法向量,纹理坐标;几何模型包含的数据有:顶点位置,法向量,切线向量,纹理坐标。关于第二种模型,书中代码的加载函数bool LoadFromVBM(const char * filename, int vertexIndex, int normalIndex, int texCoord0Index)最后一个参数texCoord0Index实际上是切线向量的顶点属性,纹理坐标的顶点属性固定是3,这一个bug我没改,懒。其他关与3D物理模型的问题可以参考代码。

扫描二维码关注公众号,回复: 2910052 查看本文章

 

规则的花纹

条纹

对应的代码工程8.1.1-01Stripe,运行结果:

程序使用到的一些函数可以在Opengl 4.x Reference查看其功能,程序中也涉及到反走样的问题,反走样原理可以查看第四章里面的图元反走样

 

程序的实现主要在片元着色器里面,以下是片元着色器的代码:

float scaledT = fract(fsTexCoord*Scale);//放大纹理坐标然后取小数部分。

float frac1 = clamp(scaledT/Fuzz, 0.0, 1.0);//除了fuzz区域,其他都时1.

float frac2 = clamp((scaledT-Width)/Fuzz, 0.0, 1.0);//除了fuzz+width区域,其他都是1

代码中fsTexCoord是一个float数据,在圆环上的分布如下图

Scale是整个圆环的条带数目,fsTexCoord与之相乘后取小数部分,这相当于确定片源在哪个条带。对于frac1frac2其在一个条带内值的分布如下图

其他请参考程序8.1.1-01Stripe

 

 

砖块

代码工程8.1.1-02BrickColor-Square

运行结果:

 

以下两张图片右边图片绘制的黑线分割开了每个砖块单元

实际上有两种砖块分别是: ,整个砖块纹理都是由这两种砖块组成,具体实现可以查看代码,代码有详细注释。

 

玩具球

这里我实现了一个相对简单一点的例子,在球上面绘制一个三角形,对应代码工程8.1.2TriangleBall。

运行结果:

 

这里用到了一个数学知识,线性规划。在绘制球的时候会通过线性规划计算片源是否在三角形内,如果在三角形内则绘制红色。下图是z=0平面时线性规划坐标。

 

程序中会用到3个平面也就是P1,P2,P3。3维中一个平面的数学表达式aX+bY+cZ+d=0。我们用vec4的四个分量代表a,b,c,d。这样一个vec4就是一个平面。

 

晶格

这一块没有书中8.1.3的具体模型,实现了一个相对简单的例子8.1.3Lattice

运行结果:

 

凹凸纹理

显示器是一个2D的平面,当显示一个3D物理模型时,为了使得物体有立体感,需要模拟光照,让物体表面各个点的亮度根据光照设置明亮。凹凸纹理利用这一点人为的增加法线的干扰,这使得同一表面一些位置明亮不一致,从而看上去有凹凸感。

 

为了更好的控制凹凸的纹理,设计凹凸纹理时,会在一个平行于z=0的平面上设计。当显示时,显示的模型的三角形平面并不会与z=0平面平行,所以需要做一个转换,将平面的切线当作x轴,法线向量当作z轴,让后在转换后的坐标里面计算凹凸纹理。转换的原理和视图矩阵一样,可以参考第五章视图矩阵的推导。因为只需要与z=0平面平行,所以不需要有位移,只需要转换,因此只需要mat3*3的矩阵。

 

以下是在一个平面里面显示6*6个凸起来的圆点,代码工程8.2-01Bump。

 

凹凸纹理的限制

凹凸纹理一般只用于显示细小突起的花纹,因为凹凸纹理实际只是对法线进行的干扰,物体表面实际还是平的。当从90侧面看过去时,物体依然是平的,无法看出凹凸感。如下图(代码工程:8.2-02Bump-tours), 使用了凹凸纹物体左右两边并没有凸起。

程序式纹理反走样

关于走样和反走样像素显示上的原理,可以参考第4章图元反走样

 

dFdxdFdy函数

这两个函数求的值是所求变量随视口(屏幕)x或y处的导数。当绘制三角形时,三角形内部颜色由三个点的颜色是采用线性插值的方式计算的,具体计算方法可以参考第四章光栅与插值。例如当视口宽度为W,高H,三角形内一个点的插值函数为R1 = k1*x1 + k2*y1 + b,片元着色器中dfdx(R1) = k1*(2/W),dfdy(R1) = k2*(2/H)。之所以要乘以2是因为x,y取值都是[-1,1]范围之间。具体测试两个函数的工程为8.3.4-02Test_dFdx_dFdy。

fwidth函数fwidth(p) = abs(dFdx(p)) + abs(dFdy(p))

 

条纹球体

利用dfdx和dfdy我们可以知道绘制图元时变量单个图元(像素)的跨度,这样我们就可以更好的控制反走样需要的宽度,可以对smoothstep设置合适的参数进行反走样。如下例子,对应代码(8.3.4-01StripesBall):

 

关与以上例子,书中给的球形几何3D模型纹理的s方向在球星处不连续,如下图,利用作为灰度进行绘制的球极点,明显可以看到锯齿纹:

由于这个原因当我们设置的条纹黑白交接处刚好在锯齿纹附件时,我们无法进行反走样。

 

反走样砖块

代码工程8.3.4-03BrickConvolution

 

反走样棋盘

当两个像素之间颜色变化过快时,直接使用一个平均颜色替代,代码工程8.3.5-01Checkerboard

运行后,缩小窗口,最终会变成一个平均颜色

 

噪声

提到噪声第一反应是嘈杂无序的声音,这里噪声指的是随机数,通过噪声我们可以模拟一些无序的运动火源、波浪,可以模拟一些无序的花纹云朵、裂痕等等。噪声的随机数与我们平时通过C语言生成的随机数有些不一样。首先噪声是连续的,C语言生成的随机数是离散。第二个不同是噪声生成随机数时需要一个参数,当参数相同时噪声函数返回的随机数也必须相同。当是一维噪声时,连续则可以通过数学表达式表示为f(x) ≈ f(x+dx),如果绘制成图像会是一条无序的波,如下图,代码为8.4-01Noise1:

 

关与噪声的更多讲解可以参考这篇文章:http://www.cnblogs.com/Memo/archive/2008/09/08/1286963.html

 

多云的天空,代码工程:8.4.4-01NoiseCloudy

 

太阳表面,代码工程:8.4.5-01Turbulence。

 

火焰,代码工程:8.4.5-02SimpleFire

猜你喜欢

转载自blog.csdn.net/wlk1229/article/details/81837980
今日推荐