Shader实例:高级纹理应用

发表于2018-04-14
评论0 636浏览
使用Shader处理纹理是件简单的事情,不过本篇要和大家介绍的是Shader高级纹理应用。

首先说下CubeMap的几种制作方式:

第一种方法:就是提供一张具有特殊布局的纹理(如:立方体展开贴图交叉布局,全景布局等)用的时候把Texture Type设置成Cubemap(优点:这种方法可以对纹理数据进行压缩,而且可以支持边缘修正,光滑反射和HDR等功能);

第二种方法:先创建一个CubeMap,然后赋予6张贴图;

第三种方法:这种方法比较灵活,就是利用Camera的RenderToCubeMap方法动态创建了,脚本要放在Editor文件夹下,因为是在编辑环境下执行:
using System.Collections;  
using System.Collections.Generic;  
using UnityEngine;  
using UnityEditor;  
public class SourceCubeMap : MonoBehaviour {  
    public Cubemap cubeMap;  
    public Transform RenderPos;  
   [MenuItem("Component/ExecuteRender")]  
    static void ExecuteRender() {  
            GameObject go = new GameObject("SourceCubeMap");  
            go.AddComponent<Camera>();  
            go.transform.position = GameObject.Find("Cube (2)").gameObject.transform.position;//获取具有反射效果对象的位置  
            go.GetComponent<Camera>().RenderToCubemap(Resources.Load("CubeMap") as Cubemap); //渲染立方体纹理  
            DestroyImmediate(go);  
    }  
}  

(1)菲涅尔反射:
运用公式:Schlick菲涅尔近似等式:F(v,n)=F0+(1-F0)pow(1-cos(v.n));
直接看代码:
Shader "MyShader/FresnelReflection"  
{  
    Properties  
    {  
        _MainColor("MainColor",color) = (1,1,1,1)  
        _FresnelScale("FresnelScale(反射系数)",Range(0,1))=0.5  
        _CubeMap("CubeMap",Cube) = "_Skybox"{}  
    }  
        SubShader  
    {  
        Tags { "RenderType" = "Opaque" }  
        Pass  
        {  
            CGPROGRAM  
            #pragma vertex vert  
            #pragma fragment frag  
            #include "UnityCG.cginc"  
#include "AutoLight.cginc"  
#include "Lighting.cginc"  
            fixed4 _MainColor;  
            float _FresnelScale;  
           samplerCUBE _CubeMap;  
            struct a2v  
            {  
                float4 vertex : POSITION;  
                float4 normal:NORMAL;  
            };  
            struct v2f  
            {  
                float4 vertex : SV_POSITION;  
                float4 worldPos:TEXCOORD1;  
                float3 worldNormal:TEXCOORD2;  
                float3 worldViewDir:TEXCOORD3;  
                float3 worldRefle : TEXCOORD4;  
            };  
            v2f vert (a2v v)  
            {  
                v2f o;  
                o.vertex = UnityObjectToClipPos(v.vertex);  
                o.worldPos = mul(unity_ObjectToWorld,v.vertex);  
                o.worldNormal = UnityObjectToWorldNormal(v.normal);  
                o.worldViewDir = UnityWorldSpaceViewDir(o.worldPos);  
                o.worldRefle = reflect(-o.worldViewDir,o.worldNormal);  
                TRANSFER_SHADOW(o); //顶点着色器中使用此内置宏  
                                    //计算阴影纹理坐标后传递给片元着色器;  
                return o;  
            }  
            fixed4 frag (v2f i) : SV_Target  
            {  
                fixed3 worldNor = normalize(i.worldNormal);  
               fixed3 worldLightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));  
               fixed3 worldViewDir = normalize(i.worldViewDir);  
               fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;  
               UNITY_LIGHT_ATTENUATION(atten,i,i.worldPos);    //内置宏,计算阴影和光照衰减;  
               fixed3 reflection = texCUBE(_CubeMap,i.worldRefle).rgb;  
               fixed fresnel = _FresnelScale + (1 - _FresnelScale)*pow(1 - dot(worldViewDir, worldNor), 5);  
               //Schlick菲涅尔近似等式:F(v,n)=F0+(1-F0)pow(1-cos(v.n));  
               //F0是反射系数,用于控制菲涅尔反射的强度,V是视角方向,n是表面法线;  
               fixed3 diffuse = _LightColor0.rgb*_MainColor.rgb*max(0, dot(worldLightDir, worldNor));  
               fixed3 color = ambient + lerp(diffuse, reflection, saturate(fresnel))*atten;  
               return fixed4(color,1);  
            }  
            ENDCG  
        }  
    }  
}  

(2)普通反射:
//反射原理:通过入射光线得方向和表面法线方向计算反射方向(reflect函数)
//再利用反射方向对立方体纹理采样即可
Shader "MyShader/ReflectionShader"  
{  
    Properties  
    {  
        _Color("MainColor",color) = (1,1,1,1)  
        _ReflectColor("ReflectColor",color) = (1,1,1,1)//反射颜色  
        _ReflectAmount("Reflect Amount",Range(0,1)) = 0.5 //反射程度  
        _CubeMap("Reflect Map",Cube) = "_Skybox"{}  
    }  
    SubShader  
    {  
        Tags { "RenderType"="Opaque" }  
        Pass  
        {  
            CGPROGRAM  
            #pragma vertex vert  
            #pragma fragment frag  
            #include "UnityCG.cginc"  
#include "AutoLight.cginc"  
#include "Lighting.cginc"  
            struct a2v  
            {  
                float4 vertex : POSITION;  
                float4 normal:NORMAL;  
            };  
            struct v2f  
            {  
                float4 vertex : SV_POSITION;  
                float4 worldPos:TEXCOORD0;  
                float3 worldNormal:TEXCOORD1;  
                float3 reflectDir:TEXCOORD2;  
                float3 viewDir:TEXCOORD3;  
                float3 lightDir:TEXCOORD4;  
            };  
            fixed4 _Color;  
            fixed4 _ReflectColor;  
            float _ReflectAmount;  
            samplerCUBE _CubeMap;  
            v2f vert (a2v v)  
            {  
                v2f o;  
                o.vertex = UnityObjectToClipPos(v.vertex);  
                o.worldPos = mul(unity_ObjectToWorld, v.vertex);  
                o.worldNormal = UnityObjectToWorldNormal(v.normal);  
                o.lightDir = normalize(UnityWorldSpaceLightDir(o.worldPos));  
                o.viewDir = UnityWorldSpaceViewDir(o.worldPos);  
                o.reflectDir = reflect(-o.viewDir, o.worldNormal);  
                TRANSFER_SHADOW(o);  
                return o;  
            }  
            fixed4 frag (v2f i) : SV_Target  
            {  
                fixed3 worldNor = normalize(i.worldNormal);  
                fixed3 viewDir = normalize(i.viewDir);  
                fixed3 lightDir = normalize(i.lightDir);  
                fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;  
                fixed3 diffuse = _Color.rgb*_LightColor0.rgb*max(0, dot(worldNor, lightDir));  
                fixed3 reflection = texCUBE(_CubeMap, i.reflectDir).rgb*_ReflectColor.rgb;  
                UNITY_LIGHT_ATTENUATION(atten,i,i.worldPos);  
                fixed3 color = ambient + lerp(diffuse, reflection, _ReflectAmount)*atten;  
                return fixed4(color,1);  
            }  
            ENDCG  
        }  
    }  
}  

(3)折射:
Shader "MyShader/RefractShader"  
{  
    Properties  
    {  
        _Color("MainColor",color) = (1,1,1,1)  
        _RefractColor("RefractColor",color) = (1,1,1,1)  
        _RefractAmount("RefractAmount",Range(0,1)) = 0.5  
        _RefractRatio("Refract Ratio",Range(0.1,1)) = 0.5  
        _CubeMap("Refract CubeMap",Cube) = "_Skybox"{}  
    }  
    SubShader  
    {  
        Tags { "RenderType"="Opaque" }  
        Pass  
        {  
            CGPROGRAM  
            #pragma vertex vert  
            #pragma fragment frag  
            #include "UnityCG.cginc"  
#include "AutoLight.cginc"  
#include "Lighting.cginc"  
            struct a2v  
            {  
                float4 vertex : POSITION;  
                float4 normal:NORMAL;  
            };  
            struct v2f  
            {  
                float4 vertex : SV_POSITION;  
                float4 worldPos:TEXCOORD0;  
                float3 worldNormal:TEXCOORD1;  
                float3 worldViewDir:TEXCOORD2;  
                float3 worldRefr:TEXCOORD3;  
            };  
            fixed4 _Color;  
            fixed4 _RefractColor;  
            float _RefractAmount;  
            float _RefractRatio;  
            samplerCUBE _CubeMap;  
            v2f vert (a2v v)  
            {  
                v2f o;  
                o.vertex = UnityObjectToClipPos(v.vertex);  
                o.worldPos = mul(unity_ObjectToWorld, v.vertex);  
                o.worldNormal = UnityObjectToWorldNormal(v.normal);  
                o.worldViewDir = UnityWorldSpaceViewDir(o.worldPos);  
                o.worldRefr = refract(-normalize(o.worldViewDir),normalize(o.worldNormal), _RefractRatio);  
                TRANSFER_SHADOW(o);  
                return o;  
            }  
            fixed4 frag (v2f i) : SV_Target  
            {  
                fixed3 worldNor = normalize(i.worldNormal);  
                fixed3 lightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));;  
                fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;  
                fixed3 diffuse = _LightColor0.rgb*_Color.rgb*max(0, dot(worldNor, lightDir));  
                UNITY_LIGHT_ATTENUATION(atten,i,i.worldPos);  
                fixed3 refract = texCUBE(_CubeMap, i.worldRefr).rgb*_RefractColor.rgb;  
                fixed3 color = ambient + lerp(diffuse,refract, _RefractAmount)*atten;  
                return fixed4(color,1);  
            }  
            ENDCG  
        }  
    }  
}  
来自:https://blog.csdn.net/linuxheik/article/details/46128405



如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引