Unity Shader 表面着色器边缘光(Rim Lighting)二

这一节我们要实现下面的效果


(图一)



(图二)


首先针对图一我们创建一个材质,并把颜色改成红色的,然后我们就得到了一个很普通的红色小球。


我们只需要在鼠标进入的时候把材质的Shader换成带边缘光的Shader就行了。

我们新建一个c#文件取名为ShowSelected.cs.然后把这个脚本文件赋值给小球。

我们来看一下ShowSelected.cs中的代码,几乎每一句都有注释:

using UnityEngine;
using System.Collections;

public class ShowSelected : MonoBehaviour {
	
	public Shader selectedShader;
	public Color outterColor;

	
	private Color myColor ;
	private Shader myShader;
	private bool Selected = false;
	
	// Use this for initialization
	void Start () {
		//保存原来的颜色值和shader,以便鼠标移出时恢复
		myColor = GetComponent<Renderer>().material.color;
		myShader = GetComponent<Renderer>().material.shader;
		//鼠标移入时要使用的shader
		selectedShader = Shader.Find("Custom/Rim Lighting2");
		if(!selectedShader)
		{
			enabled = false;
			return;
		}
	}
	//鼠标进入
	 void OnMouseEnter() {
		//替换Shader
		GetComponent<Renderer>().material.shader = selectedShader;
		//设置边缘光颜色值
		GetComponent<Renderer>().material.SetColor("_RimColor",outterColor);
		//设置纹理颜色值
		GetComponent<Renderer>().material.SetColor("_MainColor",myColor);
    }
	//鼠标移出
	void OnMouseExit(){
		//恢复颜色值
		GetComponent<Renderer>().material.color = myColor;
		//恢复shader
		GetComponent<Renderer>().material.shader = myShader;
	}
}


我们来看一下带边缘光的Shader的代码:

Shader "Custom/Rim Lighting2" {
		 //属性域
		Properties {
			//纹理颜色
			 _MainColor ("Main Color", Color) = (1,1,1,1)
			  //主纹理属性
			  _MainTex ("Texture", 2D) = "white" {}
			  //法线贴图纹理属性
			  _BumpMap ("Bumpmap", 2D) = "bump" {}
			  //边缘光颜色值
			  _RimColor ("Rim Color", Color) = (1,1,1,1)
			  //边缘光强度值
			  _RimPower ("Rim Power", Range(0.5,8.0)) = 3.0
	    }
		SubShader {
			  //标明渲染类型是不透明的物体
			  Tags { "RenderType" = "Opaque" }
			  //标明CG程序的开始
			  CGPROGRAM
			  //声明表面着色器函数
			  #pragma surface surf Lambert
			  //定义着色器函数输入的参数Input
			  struct Input {
			  	  //主纹理坐标值
			      float2 uv_MainTex;
			      //法线贴图坐标值
			      float2 uv_BumpMap;
			      //视图方向
			      float3 viewDir;
			  };
			  //声明对属性的引用
			  float4 _MainColor;
			  sampler2D _MainTex;
			  sampler2D _BumpMap;
			  float4 _RimColor;
			  float _RimPower;
			  //表面着色器函数
			  void surf (Input IN, inout SurfaceOutput o) {
			  	  fixed4 tex = tex2D(_MainTex, IN.uv_MainTex);
			  	  
			  	  //赋值颜色信息
				  o.Albedo = tex.rgb * _MainColor.rgb;
			      //赋值法线信息
			      o.Normal = UnpackNormal (tex2D (_BumpMap, IN.uv_BumpMap));
			      half rim = 1.0 - saturate(dot (normalize(IN.viewDir), o.Normal));
			      //赋值自发光颜色信息
			      o.Emission = _RimColor.rgb * pow (rim, _RimPower);
			  }
			  //标明CG程序的结束
			  ENDCG
		} 
	    Fallback "Diffuse"
}

这样就可以实现图一中的效果了


我们来看看图二的效果是怎么实现的

同样我们新建一个C#文件,取名为ShowSelectedBump.cs,我们来看一下这个CS文件中的代码,同样每一句都有注释

using UnityEngine;
using System.Collections;

public class ShowSelectedBump : MonoBehaviour {

	public Shader selectedShader;
	public Color outterColor;

	
	private Color myColor ;
	private Shader myShader;
	private SkinnedMeshRenderer sRenderer;
	private bool Selected = false;

	// Use this for initialization
	void Start () {
		sRenderer = GetComponentInChildren<SkinnedMeshRenderer>();
		//保存原来的颜色值和shader,以便鼠标移出时恢复
		myColor = sRenderer.material.color;
		myShader = sRenderer.material.shader;
		//鼠标移入时要使用的shader
		selectedShader = Shader.Find("Custom/RimLightSpecBump");
		if(!selectedShader)
		{
			enabled = false;
			return;
		}
	}

	//鼠标进入
	void OnMouseEnter() {
		//替换Shader
		sRenderer.material.shader = selectedShader;
		//设置边缘光颜色值
		sRenderer.material.SetColor("_RimColor",outterColor);
		//设置纹理颜色值
		sRenderer.material.SetColor("_MainColor",myColor);
    }
	//鼠标移出
	void OnMouseExit(){
		//恢复颜色值
		sRenderer.material.color = myColor;
		//恢复shader
		sRenderer.material.shader = myShader;
	}
	
}
我们看到处理动画模型的ShowSelectedBump.cs和ShowSelected.cs唯一不同的是这一句代码

sRenderer = GetComponentInChildren<SkinnedMeshRenderer>();

只是获取模型的渲染组件不同而已,我们的shader文件用的是同一个。

这样就可以很方便的实现图二的效果了。








  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 好的,下面是一个简单的用Unity Shader实现边缘效果的例子。 首先,我们需要一个称为"RenderTexture"的工具来在屏幕上渲染场景。这个RenderTexture将会成为我们在Shader计算边缘的基础。 在这个Shader,我们需要做以下几个步骤: 1. 将场景渲染到RenderTexture。 2. 对RenderTexture进行处理,找到场景边缘,并将边缘标记为白色。 3. 对处理后的RenderTexture进行模糊处理,以产生发效果。 4. 将模糊后的RenderTexture和原始场景图像混合在一起,产生最终的边缘效果。 下面是一个简单的Shader代码示例: ``` Shader "Custom/EdgeGlow" { Properties { _MainTex ("Texture", 2D) = "white" {} _EdgeColor ("Edge Color", Color) = (1,1,1,1) _EdgeWidth ("Edge Width", Range(0, 0.1)) = 0.01 _BlurRadius ("Blur Radius", Range(0, 10)) = 2 } SubShader { Tags { "RenderType"="Opaque" } Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; }; struct v2f { float2 uv : TEXCOORD0; float4 vertex : SV_POSITION; }; sampler2D _MainTex; float4 _MainTex_ST; float4 _EdgeColor; float _EdgeWidth; float _BlurRadius; v2f vert (appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.uv = TRANSFORM_TEX(v.uv, _MainTex); return o; } fixed4 frag (v2f i) : SV_Target { // Step 1: Render scene to a RenderTexture float4 scene = tex2D(_MainTex, i.uv); // Step 2: Find edges and mark them white float4 edge = (4 * scene.rgba - tex2D(_MainTex, i.uv + float2(0, 1) * _MainTex_ST.y).rgba - tex2D(_MainTex, i.uv - float2(0, 1) * _MainTex_ST.y).rgba - tex2D(_MainTex, i.uv + float2(1, 0) * _MainTex_ST.x).rgba - tex2D(_MainTex, i.uv - float2(1, 0) * _MainTex_ST.x).rgba); edge = max(edge, 0); edge = step(_EdgeWidth, edge.r); // Step 3: Apply Gaussian blur to edges for (int i = -_BlurRadius; i <= _BlurRadius; i++) { for (int j = -_BlurRadius; j <= _BlurRadius; j++) { float2 offset = float2(i, j) * ### 回答2: 使用Unity Shader编写边缘效果可以通过以下几个步骤来实现: 1. 为对象创建一个新的材质,并在着色器选项选择"Custom/Edge Glow"。 2. 编写一个新的边缘Shader,并将其与上一步骤创建的材质相关联。 3. 在着色器添加顶点和片段着色器函数。 4. 顶点着色器,使用传入的模型视图矩阵和投影矩阵将顶点位置转换为屏幕空间坐标。 5. 片段着色器,将屏幕空间坐标作为输入。 6. 在片段着色器,使用采样函数获取当前像素的颜色。 7. 使用一个for循环,遍历像素的邻居,比较颜色差异,如果颜色差异超过一个阈值,则表示该像素位于边缘。 8. 将边缘像素的颜色设置为发颜色,将非边缘像素的颜色设置为原始颜色。 9. 在Unity将该材质应用到需要应用该边缘效果的对象上。 以上是一种实现边缘效果的例子,可以根据具体需求适应更多的应用场景和效果。编写Shader需要一定的Shader编程经验,建议在学习和实践的过程参考Unity官方文档和其他相关资源。 ### 回答3: 要使用Unity Shader编写一段边缘效果,我们可以参考一种基本的方法。首先,我们需要两个Pass来实现效果:一个Pass用于将发部分高亮,另一个Pass使用轮廓检测算法将边缘区域描绘出来。 首先,在顶点着色器,我们需要将顶点位置从模型空间转换为剪辑空间,通过将顶点坐标乘以Unity内置变量`UNITY_MATRIX_MVP`实现。然后,我们可以将变换后的位置传递给片段着色器。 在片段着色器,我们需要进行两个Pass。在第一个Pass,通过计算法线和视线的角度余弦值,将发部分高亮。我们可以使用照信息和噪声函数来模拟高亮效果。最后,我们将高亮部分的颜色与原始颜色进行混合。 在第个Pass,我们使用轮廓检测算法来描绘边缘。我们可以通过计算像素的法线差异来确定边缘区域。如果法线差异大于阈值,则将像素颜色设置为边缘颜色,否则保持原始颜色。 边缘效果的实现需要额外的几何信息,例如模型的法线信息。因此,在Unity将需要在材质导入法线贴图,并在Shader进行采样。 总结起来,要使用Unity Shader编写一段边缘效果,我们需要进行两个Pass:一个用于高亮发部分,另一个用于描绘边缘部分。通过计算角度余弦和法线差异,我们可以实现边缘效果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值