Shader7-基础纹理

1.纹理映射(texture mapping)

将纹理空间中的纹理元素映射到屏幕空间中的像素的过程。(表象就是把图像映射到模型三角形表面)

ex:左边是两个三角面,右边是一个贴图,把一张图片映射到2个三角形上。 


在纹理映射过程中,我们使用纹理坐标的方式(或称u、v坐标),把纹理进行划分。UV(纹理映射坐标)它定义了图片上每个点的位置的信息,将图像上每一个点精确对应到模型表面。无论模型贴图大小如何,UV纹理一般都被归一化到[0,1]。

UV坐标算法 ex: 模型贴图1024 * 1024,贴图某个点的UV坐标 = (x/1024,y/1024)  例如(512,512)  UV坐标= (0.5,0.5)。

DirectX坐标系下纹理映射

对于一个三角形,我们要为每一个顶点指定uv坐标,如上图的2个三角形,我们按照图上标的纹理坐标指定uv坐标,则左边的2个三角形则会被完整的映射成右边的纹理形状。

2.纹理采样有关的概念:

  • Magnification 纹理放大

纹理大小为256*256,但我们的两个三角形组成的quad却是512*512,则一个纹理单元(纹素)要对应quad上的四个像素,一个纹理单元对应多个光栅化后的像素的情况通常称作Magnification。

纹理上一个点对应网格面片的四个点

 在magnification情况下如何进行纹理映射呢?通常是用双线性插值的方式,比如下面左边的图中红色的pixel,没有对应的纹理texel,则它的颜色值用它的上下左右的pixel颜色插值得到,当然我们也可以选择最接近的纹理单元颜色做为其颜色,

具体要视Filter Mode纹理滤波中设置的MAG值。

  • Minification 纹理缩小

和Magnification相反,三角面小,纹理大。例如128 * 128的面片大小,纹理大小 256 * 256。

这时可以选择最接近的纹理单元,也可以把上下左右纹理单元进行双线性插值,再和pixel映射起来。

具体要视Filter Mode纹理滤波中设置的MAG值。

  • Mipmap 多级渐远纹理技术

选择创建mipmp层,系统就自动创建一系列采样的图像,每个图像都是前面一个图像的1/4(如下图所示)。

 比如纹理原始大小是256*256,我们的三角形是178*178,那么这时会做三线性插值,四边形先和128*128纹理执行magnificaiton插值得到一个结果,再和256*256纹理做minification插值得到一个结果,最后再对这2个结果进行线性插值,得到的颜色为最终的pixel颜色。

  • Wrap Mode纹理的寻址模式: 

1.Repeat方式:

对于不在[0,1]之间的纹理坐标,采用缠绕的方式来对应纹理单元,比如下面图所示,这样的方式特别适合用小纹理来贴一个大的平面,比如在地面铺瓷砖,在地面上铺草地等等。这也要求我们设计纹理图片时,把左右、上下的边缘部分,最好能无缝的连接起来。纹理坐标[3.5,2.7] 整数部分被抛弃,变成采样[0.5,0.7]的纹理。

2.Border方式:

    把不在[0,1]范围的纹理坐标设置为一些指定的颜色,比如下图,指定为红色

 

3.Clamp方式

     把不在[0,1]范围的纹理坐标指定为离其最近的纹理单元颜色。纹理坐标大于1,截取到1。纹理坐标小于0。截取到0。

采样纹理坐标[-0.5,1.3]处的纹理,变成采样[0,0.3]。

4.Mirror方式:

     就是把不在[0,1]范围的纹理坐标按镜像的方式指定纹理单元,如下图所示:


Unity中纹理属性:

1.TextureType 纹理类型,让Shader得到正确的纹理,并在某些情况下对该纹理进行优化。

2.Wrap Mode,纹理的寻址方式。见上边所述

3.Filter Mode,纹理由于变换产生拉伸时,图片采用哪种滤波方式。

  • Point - 只采样一个像素点  (马赛克风格)
  • Bilinear - 采样4个邻近像素,然后线性插值得到最终像素 (感觉图片模糊了)
  • Trilinear - 跟Bilinear差不多,只是如果采用了Mippap,会在多级渐远纹理之间进行混合。如上所述。

三种方式,得到的图片效果依次提升。但是效率依次下降。

4.Format,决定了Unity使用哪种格式存储该纹理。效率越好,内存占用越大。

如下图。图片下边可看到纹理格式和内存占用

 

Shader纹理采样显示

Shader "Chan/Chapter7_SingleTexture" {
    Properties
    {
        _Color("Color Tint",Color) = (1,1,1,1)
        _MainTex("Mai Tex",2D) = "white"{}
        _Specular("Specular",Color) = (1,1,1,1)
        _Gloss("Gloss",Range(8,256)) = 20
    }

    SubShader
    {
        Pass
        {
            //LightMode定义该Pass在Unity光照流水线中的角色。
            Tags{"LightMode" = "ForwardBase"}

            CGPROGRAM

            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"
            #include "Lighting.cginc"

            fixed4 _Color;
            sampler2D _MainTex;
            //纹理名_ST 获取纹理的缩放和平移 ST scale和translation
            //纹理名_ST.xy = 缩放值    纹理名_ST.zw = 偏移
            float4 _MainTex_ST;
            fixed4 _Specular;
            float _Gloss;

            struct a2v
            {
                float4 vertex:POSITION;
                float3 normal:NORMAL;
                float4 texcoord:TEXCOORD0;
            };

            struct v2f
            {
                float4 pos:SV_POSITION;
                float3 worldNormal:TEXCOORD0;
                float3 worldPos:TEXCOORD1;
                float2 uv:TEXCOORD2;
            };

            v2f vert(a2v i)
            {
                v2f o;
                o.pos = UnityObjectToClipPos(i.vertex); 
                o.worldNormal = UnityObjectToWorldNormal(i.normal);
                o.worldPos = mul(unity_ObjectToWorld,i.vertex).xyz;
                //得到顶点纹理坐标
                o.uv = i.texcoord.xy * _MainTex_ST.xy + _MainTex_ST.zw;
                return o;
            }

&nbs
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值