UnityShader入门精要学习笔记(七):基础纹理之单张纹理

来源:互联网 发布:weka java api文档 编辑:程序博客网 时间:2024/05/29 17:16

一 .基础纹理应用

纹理的最初目的就是使用一张图片来控制模型的外观。使用纹理映射技术,我们可以吧一张图“黏”在模型表面,逐纹素(texel)(名字是为了和逐像素进行区分)地控制模型的颜色。

结合之前的光照模型的单张纹理应用:

// Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'// Upgrade NOTE: replaced '_World2Object' with 'unity_WorldToObject'Shader "Custom/Edu/SingleTexture" {    Properties     {        _MainTex("MainTex",2D)= "white"{}        _Diffuse("Diffuse",Color) = (1,1,1,1)        _Specular("Specular",Color) = (1,1,1,1)        _Gloss("Gloss",Range(8,256)) = 40        _Color("ColorTint",Color) = (1,1,1,1)    }    SubShader     {        Pass        {            Tags{"LightMode" = "ForwardBase"}            CGPROGRAM            #pragma vertex vert            #pragma fragment frag            #include "UnityCG.cginc"            #include "Lighting.cginc"            sampler2D _MainTex;            float4 _MainTex_ST;            fixed4 _Diffuse;            fixed4 _Specular;            fixed4 _Color;            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 v)            {                v2f o;                o.pos = mul(UNITY_MATRIX_MVP,v.vertex);                o.worldPos = mul(unity_ObjectToWorld,v.vertex);                o.worldNormal = mul(v.normal,(float3x3)unity_WorldToObject);                o.uv = TRANSFORM_TEX(v.texcoord,_MainTex);                return o;            }            fixed4 frag(v2f i):SV_Target            {                fixed3 worldNormal = normalize(i.worldNormal);                fixed3 worldLightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));                fixed3 albedo = tex2D(_MainTex,i.uv).rgb * _Color.rgb;                fixed3 diffuse = _LightColor0.rgb * albedo * _Diffuse.rgb * saturate(dot(worldNormal,worldLightDir));                fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.rgb * albedo;                fixed3 viewDir = normalize(UnityWorldSpaceViewDir(i.worldPos));                fixed3 halfDir = normalize(viewDir + worldLightDir);                fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(saturate(dot(worldNormal,halfDir)),_Gloss);                return fixed4( diffuse + ambient + specular , 1.0);            }            ENDCG        }    }    FallBack "Diffuse"}

TRASFORM_TEX实在UnityCG.cginc中定义的:

//Transform 2D UV by scale/bias property#define TRANSFORM_TEX(tex,name)(tex.xy * name##_ST.xy + name##_ST.zw)

它接受两个参数
第一个参数是顶点的纹理坐标
第二个参数是纹理的名称

看一下效果:

这里写图片描述

二.纹理采样区间设置

下面为了阐释纹理的属性,编写一个更为纯粹的纹理属性应用shader

Shader "Custom/Edu/SimpleTextureProperties" {    Properties {        _Color ("Color", Color) = (1,1,1,1)        _MainTex ("Albedo (RGB)", 2D) = "white" {}    }    SubShader     {        Pass        {            Tags{"LightMode" = "ForwardBase"}            CGPROGRAM            #pragma vertex vert            #pragma fragment frag            #include "UnityCG.cginc"            #include "Lighting.cginc"            sampler2D _MainTex;            float4 _MainTex_ST;            fixed4 _Color;            struct a2v            {                float4 vertex:POSITION;                float2 texcoord:TEXCOORD0;            };            struct v2f            {                float4 pos:SV_POSITION;                float2 uv:TEXCOORD0;            };            v2f vert(a2v v)            {                v2f o;                o.pos = mul(UNITY_MATRIX_MVP,v.vertex);                o.uv = TRANSFORM_TEX(v.texcoord,_MainTex);                return o;            }            fixed4 frag(v2f i):SV_Target            {                fixed3 color = tex2D(_MainTex,i.uv);                return fixed4(color,1.0);            }            ENDCG        }    }    FallBack "Diffuse"}

利用这个shader在场景中创建一个Quad。

这里写图片描述

此时我们对纹理使用的Wrap Mode的是Repeat——重复纹理采样。
这种模式下,如果纹理的坐标超过了1,那么整数部分将会被舍弃,而直接使用小数部分进行采用。
下面我们来看另外一种模式

这里写图片描述

当使用Clamp模式时,超过的部分将会截取到边界值,从而形成一个条形结构。

三.3种滤波模式

纹理导入面板中的下一个属性是FilterMode属性,它决定了当纹理由于变换而产生拉伸是将会使用哪种滤波模式。

Point模式使用了最近邻滤波,在放大或缩小时,它的采样像素数目通常只有一个,因此图像看起来有种像素风格的效果。

Bilinear滤波采用了线性滤波,对于每个目标像素,它会找4个邻近的像素,然后对他们进行线性插值混合后得到最终的像素,因此图像看起来像被模糊了。

Trilinear滤波几乎和Bilinear是一样的,知识Trilinear还会在多级渐远纹理(mipmapping)之间进行混合。

四.纹理的最大尺寸和纹理模式

这里写图片描述
【我只安装了安卓build的模块】
Unity允许我们为不同目标平选择不同的纹理尺寸和压缩格式。
如果导入的纹理超过了MaxTextureSize中的设置,那么Unity会把这个纹理所防伪这个最大分辨率。
导入的纹理的长宽大小应该是2的整数次幂。
如果使用了非2的整数次幂大小(Non Power of Two,NPOT)的纹理,那么这些纹理往往会占用更多的内存空间,而且GPU的读取该纹理的速度也会下降。甚至有一些平台不支持NPOY纹理。
对于一些不需要使用很高精度的纹理(例如漫反射颜色的纹理),我们应该尽量使用压缩格式!

阅读全文
0 0
原创粉丝点击