图形学基础-实时渲染管线-Shader-纹理映射-Mipmap&各向异性过滤

目录

实时渲染管线

介绍

可编程管线

Shader编程

GPU介绍

纹理映射

映射方法

差值处理

纹理尺寸适配

纹理尺寸偏小

纹理尺寸偏大

Mipmap局限和优化


实时渲染管线

介绍

图形渲染管线, 就是指,一个你自己设定的场景,由最开始的顶点,到最后的屏幕上的图像,这个到底经历了什么过程, 这个处理的过程就是渲染管线,指的是一系列的操作,类比流程

下图是一般显卡GPU处理图像的渲染管线, 就是将输入的点的坐标转化为屏幕的图像的过程

步骤:

  • 先处理输入的点,这些点有的三个一组是决定构成一个面的,使用变换投影到屏幕的像素平面上
  • 为了适应像素的格子性,将场景光栅化成一个一个的格子
  • 着色,计算每一个着色单位的颜色的值
  • 最后显示的时候,同步进行深度缓冲,最后显示每一个像素, 得到正确的图像

对应成一个流程图,每一步的意义:

1.变换,变换至屏幕范围

2.光栅化,产生像素

3.深度缓冲,判断每一个像素最近的物体是什么

4.着色

顶点着色就是在顶点处理的时候就计算出每一个顶点的着色了,最后只需要按照深度数组显示出来就行了

像素着色那就是和深度测试一起进行的,同步完成后显示在屏幕上

可编程管线

在现在的GPU里面,管线有的部分是可以自己编程的,比如顶点着色像素的着色我们是可以自己编辑的,自己定义怎么对着色对象进行着色,这个编程着色的过程,就是在做Shader

红色框的是可以自己Shader的

Shader编程

我们知道现代的GPU是可以允许人去编辑怎么对顶点或者像素进行着色,shader对应的语言是可以在硬件上直接执行的,我们在写shader 的时候,我们是制定每一个像素或者顶点是如何进行着色的,只需要写一个着色方案,就可以运用到所有的着色对象上去

  • 如果我写的shader是对顶点的着色,那这个shader程序叫做顶点着色器
  • 如果我写的shader是对像素或三角形的着色,那这个shader程序叫做片元着色器

下面是使用openGL的GLSL语言写的一个对于像素的简单漫反射着色器(片元着色器)

这个shader代码

GPU介绍

GPU有两种集成显卡和独立显卡

GPU其实可以叫高度并行化的处理器,比如cpu的处理器的核的数量,其实就是可以并行处理的数量,但是GPU的并行的数量相当巨大的,所以我们可以同时处理很多需要相同操作的程序,比如像素的着色

纹理映射

映射方法

对于一个物体,如果这个物体表面是有图像的,我们如何把纹理图像覆盖到物体的表面上去,这就需要我们的纹理映射 texture mapping

纹理映射 做法就是将这个物体展开成一个二维的平面,然后把贴图覆盖在这个平面上。其中注意我们的贴图要转化为0到1的范围的大小,这个大小下的贴图就叫uv贴图,然后,展开后的物体表面的三角形的每一个顶点就可以依靠uv坐标查询这个坐标下的uv贴图在这个位置的颜色,然后三角形中间的部分使用差值,可以计算出来中间部分的uv坐标,从而在uv贴图里面找到对应的颜色是什么,这样在后面着色的时候,着色点的系数kd就有了依据

差值处理

差值就是,解决三角形内部某些属性的过度问题,就是已知三个顶点的信息, 怎么得到中间单位区域的过度信息?       

我们使用一个叫重心坐标的东西:已知三角形的三个顶点,中间的每一个点(x , y )都可以使用三个量来对三个顶点进行加权求得:

其中为了保证点是在三角形里面,必定有:而且都大于0

那我们怎么求这三个数的值呢?答案是使用三角形的面积来求,其中的A B C都是图中的面积

所以,假如我们要求点(x , y)的 \alpha \beta \gamma 同时我们知道三角形的三个顶点坐标,就可以使用一下的公式计算\alpha \beta \gamma的值:

就这样,我们计算出了\alpha \beta \gamma的值,就知道了对于中间的点(x , y),他的属性对于三角形三个顶点的属性各占多少,权值多大。

对于三个顶点的属性VaVbVc(这个属性可以是坐标,颜色, 法线,纹理uv坐标),就可以按照这个权值得到中间点(x , y)的属性V是多少了

这样,暂时的我们就可以找到每一个三角形中间的每一个点的uv, 就知道了每一个点的kd系数,有就知道了颜色

纹理尺寸适配

但是还是有一些问题的,比如纹理尺寸大,但是屏幕分辨率小,以及纹理尺寸很小,但是屏幕分辨率很高的话,就这样单纯的每一个像素去投影到三角形上,然后直接显示这个点的uv的纹理颜色,会出现很多问题,其实大部分情况像素的是不与贴图相匹配的

纹理尺寸偏小

就是我的屏幕分辨率很足,但是贴图尺寸偏小,这时候,单纯的每一个像素采对应贴图位置的颜色,可能4个屏幕像素才占据一个贴图像素,出现格子(左图),这时候,我们就使用一个叫双线性差值的方法来“模糊”我们显示的图像

比如一下的情况,红点是屏幕像素对应到贴图像素上去的位置,背景的小格子是贴图像素,黑点是每一个贴图像素的中心位置,我们使用双线性差值来计算这个红点的材质颜色到底是什么

做法:取最近的周围四个贴图像素的uv颜色值u01 , u11 , u00 , u10,按照一个统一方向计算出一个 t 和 s (图中所示)

使用线性差值的方法结合u01 , u11 , u00 , u10的值,上下两排差值取得点 u0 u1的颜色(其实是按一个比例)

再竖着uv坐标的方向差值u1 和u0,得到红点的对应的颜色,这样,这个红点对应的屏幕的像素就可以使用这个红点得到的颜色填充了

双线性差值是处理了两趟差值,先横着的上下两排,最后竖着的一次:

其中lerp()函数表示的过程是:

纹理尺寸偏大

纹理稍微大一些的话,如果按照单一的屏幕像素投影哪一个点就显示uv那一个位置颜色,会出右边的问题:

原因很简单,就是屏幕像素在显示地平线附近的区域的时候,我们一个屏幕像素在三维中投影过去后覆盖的贴图的范围是非常大的,但是我们只单单的取了像素中心对应的一个点的颜色来代表整个大区域的颜色(像下图右边的区域),肯定会出问题

这时候我们就需要一个很厉害流弊的方法来解决这个问题,这个方法是一个预处理,就是可以让我们在渲染时直接查询出,这个大区域的平均颜色是什么这个方法就是Mipmap

Mipmap方法

这个方法是预处理,纹理给我的时候,我就做好的一件事,什么事?我们处理出一系列图片,这些图片是成半分辨率压缩的,一直到压缩到1*1

我们使用D来表示压缩的层数,就可以得到下图类似一个金字塔:

有了这个预处理了,在渲染的时候,我们使用这个预处理得到一个像素颜色呢?我们知道,对于每一个像素,我们都可以映射到纹理的一个区域上去,我们可以以这个像素中心为左下角,往右上跨一个像素取几个中心,将点映射到纹理上,右图的四个红点和几个黄点

然后我们在uv坐标下计算距离周围这些点距离的最大的一个,记作L,最后我们把下图中,右边这个边长为L的正方形区域内的平均色彩近似成左边的这个像素的颜色

那我们怎么得到右边这个L正方形区域的平均颜色呢?这就用到前面的mipmap的一组图片了        

我们的这个L决定像素的大小,假如这个L 是 2.5屏幕像素大,那么我们只需要先在第2层和第三层图片对应位置使用双线性差值,计算出颜色,最后,两张图再依据L的大小使用线性差值得出最后颜色

就这样我们的Mipmap的原理就讲完了,可以帮我们计算当一个像素映射的纹理范围很大的时候,这个像素的颜色到底取什么

Mipmap局限和优化

但是按照这个mipmap出来的图,远处太模糊了

原因是因为投影过去后,有的是长条形,但是你却按照最长的边来划定一个正方形,使用这个正方形区域的平均颜色,当然糊了

有一个方法是可以部分解决这个问题——各向异性过滤

它不仅仅只处理出按照半分辨率衰减的图片,它还整了沿着uv坐标轴方向上的压缩,得到下图图组:

这样当我们像素映射到纹理上去的区域是一个横着的或竖着的区域时,就可以在上图找最接近这个区域形状和像素大小的两个图片,使用线性差值计算平均值了,斜的没办法

这样,我们既可以使用mipmap,也可用各向异性过滤来根据我们给定的uv纹理,确定每一个像素对应的颜色,从而计算着色

环境光照

这个图片反射出来的画面周围没有,所以这个是怎么来的呢?这就是环境贴图

环境光照中的光线是无限远,  没有深度意义,所以我们使用一个球来存储环境贴图,这个球上的贴图是自己发出光线的

凹凸贴图

 纹理不仅仅只可以影响颜色,其实还是可以影响着色的,可以让物体表面 看上去有高度差,这一类的贴图叫做凹凸贴图或者法线贴图

原理:凹凸贴图或者法线贴图在贴图上可以储存新的法线或者新的高度信息,这样在着色的时候使用的就不是物体原来的法线,而是使用法线贴图和凹凸贴图新的法线了,这样着色出来的样子就会出现类似凹凸的样子

其实这种(一维)法线贴图存储的是每一个点的切线,这样在着色的时候,使用这个切线计算出来的法线就行,二维的贴图存储的是每一个点的偏导数的值,这样就可以计算出两个偏导数构成的平面的法线来着色

  其实还有一种叫位移贴图,这种要求你的物体有很多三角形,细分需要足够,不然实现不了凹凸的感觉

以上介绍了一些贴图的作用


  • 22
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值