Unity Shader入门精要 第七章

  1. 1. 基础纹理的介绍
  2. 2. 7.1 单张纹理
  3. 3. 7.2 凹凸映射
  4. 4. 渐变纹理
  5. 5. 遮罩纹理

 

基础纹理的介绍

  • 纹理的最初目的:使用一张图片来控制模型的外观
  • 使用纹理映射技术,我们可以把一张图贴在模型的表面,逐像素地控制模型的颜色
  • 通常在美术人员建模的过程中,会在建模软件中利用纹理展开技术把纹理映射坐标存储在每个顶点上面,纹理映射坐标定义了该顶点在纹理中对应的2D坐标。通常这些坐标用一个二维变量:UV来表示,其中U是横向坐标,V是纵向坐标,因此纹理映射坐标也被称为UV坐标
  • 尽管纹理的大小可以是多种多样的(256x256 1024x1024),但顶点UV坐标的范围通常会被归一化到0-1之间
  • 纹理采样时使用的纹理坐标不一定是0-1范围内的
  • 在OpenGL原点位于左下角,DirectX原点位于左上角,Unity符合OpenGL的传统

7.1 单张纹理

  • 其中_MainTex_ST不是随意起的,而是主纹理”_MainTex” + “ST” 其中”ST”是缩放和平移的缩写,可以得到模型的缩放和平移值,通过.xy存储缩放值,.zw存储偏移值

  • 在a2v里订阅了TEXCOORD0的语义,来声明一个新的变量TEXCOORD,Unity会将该模型的第一组纹理坐标存储到该变量中

  • 在v2f结构体中添加了用于存储纹理坐标的变量”uv”,以便在片元着色器中来使用该坐标进行纹理采样

  • 核心代码在片元着色器,在顶点着色器中只做一些简单的转换

  • // 声明一个v2f变量
    // 将模型空间顶点位置转换成裁剪空间
    // 模型顶点的法向量转换成世界空间下的法向量
    // 顶点空间下的顶点坐标转化成世界空间下的顶点坐标
    // 纹理坐标的变量uv:获取纹理坐标v.texcoord.xy,先缩放再偏移
    // 内置的宏,功能一样 参数:顶点纹理坐标,纹理名

  • 核心的渲染代码,逐像素渲染

  • // 先计算世界空间下的法线方向 和 光照方向
    // 用cg的函数tex2D进行纹理采样 参数:被采样的纹理、纹理坐标
    // 计算环境光部分 ambient
    // 计算漫反射 diffuse
    // 计算高光反射 speoular

7.2 凹凸映射

  • 目的:使用一张纹理来修改模型表面的法线,以便为模型提供更多的细节。这种方法不会真的改变模型顶点位置,只是让模型看起来好像是凹凸不平的,在模型的轮廓处可以看出破绽

  • 第一种方法:使用一张高度纹理来模拟表面的位移,得到一个修改后的法线值,这种方法也被称为高度映射

  • 另一种方法:使用一张法线纹理,来直接存储表面法线,这种方法也被称为法线映射

  • 第一张方法中,使用一张高度图进行凹凸映射,高度图中存储强度值,用于表示模型表面局部的海拔高度,颜色越浅表明该位置的表面越向外凸起,颜色越深表明该位置的表面越向里凹。
    · 这种方法的好处是很直观,问题在于计算得更加复杂,在实时计算时不能直接得到表面法线,而是需要由像素的灰度值计算得到,因此也会消耗更多性能。
    · 高度图通常会和法线映射一起使用,用于给出表面凹凸的额外信息,也就是我们通常会使用法线映射来修改光照:nor = 2pi - 1 (需要模型空间一致)
    · 根据变换空间的不同,分为两种:


    多了Bump
    · Bump是Unity内置的法线纹理,当我们没有提供任何的法线纹理时,Bump就对应模型自带的法线信息,而BumpScale则是用来控制凹凸的程度,当它为0时代表该法线纹理不会对光照产生任何的影响


    · 多了tangent语义,它告诉Unity把顶点的切线方向填充到这里,和法线方向的normal不同,tangent是float4类型而非float3,因为我们需要使用tangent.w的分量来决定切线空间中的第三个坐标轴,负切线的方向
    · v2f需要在顶点着色器中计算切线空间下的光照和视角方向,因此添加了lightDir和viewDir存储变化后的光照和视角方向

    · // uv的xy分量来保存纹理坐标,zw保存高度纹理坐标,减少了插值寄存器的使用,这样我们只计算和存储一个纹理坐标就可以了
    // 法线、切线坐标变换
    // 计算负切线时使用w。因为与切线和法线都垂直的方向有两个,w决定了用哪个方向

    · TANGENT_SPACE_ROTATION;加在o.lightDir=……上
    // 借助变换矩阵计算得到模型空间下的光照和视角方向,再借助该矩阵变换到切线空间中的光照和视角方向

    · 在片元着色器中得到切线空间下的法线方向和视角方向
    · 再借助tex2D对BumpMap采样
    · 在法线纹理中存储的是 把法线经过映射后得到的像素值

    · // 做反映射
    // 控制凹凸得到实际的xy分量
    // 由于法线是单位矢量,所以z分离可以用xy得到,因为x^2+y^2+z^2=1
    // 贴图部分 得到纹素值 albedo、ambient
    // 之后得到漫反射、高光反射

  • 第二种方法:在世界空间下计算,需要在片元着色器中把法线方向从切线空间变换到世界空间下

    · 要使v2f中包含从切线空间到世界空间的变换矩阵,在一个插值寄存器最多只能储存float4大小的变量,对于矩阵这样的变量可以按行拆成多个变量进行存储


    从高度图中生成法线纹理 白高灰低
    · Bumpiness控制凹凸程度
    · Filtering哪种方式计算凹凸程度

渐变纹理


遮罩纹理