前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Shader实例:高级纹理应用

Shader实例:高级纹理应用

作者头像
bering
发布2019-12-03 14:51:07
4900
发布2019-12-03 14:51:07
举报
文章被收录于专栏:游戏开发之旅游戏开发之旅

Shader实例:高级纹理应用

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

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

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

第三种方法:

这种方法比较灵活,就是利用Camera的RenderToCubeMap方法动态创建了,脚本要放在Editor文件夹下,因为是在编辑环境下执行:

代码语言:javascript
复制
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));

直接看代码:

代码语言:javascript
复制
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函数) //再利用反射方向对立方体纹理采样即可

代码语言:javascript
复制
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)折射:

代码语言:javascript
复制
代码语言:javascript
复制
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
		}
	}
}
代码语言:javascript
复制
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2017/11/24 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档