UnityShader应用——外发光实现

学习了一下实现物体外发光的Shader。分成两个Pass进行,第一个Pass渲染物体正面,剔除背面;第二个Pass渲染背面(剔除正面),通过扩展法线方向顶点,在进行颜色计算。
在这里插入图片描述

实现外发光的Pass
	//pass2 生成模型外部的光晕
		Pass
		{
			Name "OutLight"
			Tags {"LightMode" = "Always"}
			Cull Front     //不正面剔除会出错
			Blend SrcAlpha One

			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			#include "UnityCG.cginc"

			uniform float _Size;
			uniform float4 _AtmoColor;
			uniform float _OutLightPow;
			uniform float _OutLightStrength;

			struct v2f
			{	
				float3 normal : TEXCOORD0;
				float3 worldPos : TEXCOORD1;
				float4 vertex : SV_POSITION;
			};

			v2f vert(appdata_base v) 
			{
				v2f o;
				v.vertex.xyz += v.normal * _Size;    //进行法线方向的扩展
				o.vertex = UnityObjectToClipPos(v.vertex);
				o.normal = v.normal;
				o.worldPos = mul(unity_ObjectToWorld, v.vertex);
				return o;
			}

			fixed4 frag(v2f i) : COLOR
			{
				i.normal = normalize(i.normal);
				//视角观察方向
				float3 viewDir = normalize(i.worldPos - _WorldSpaceCameraPos.xyz);
				
				float4 color = _AtmoColor;

				color.a = pow(saturate(dot(viewDir, i.normal)), _OutLightPow);
				color.a *=  _OutLightStrength * dot(viewDir, i.normal);
				return color;
			}
			ENDCG
		}
将渲染队列设置为透明

在这里插入图片描述
如果不设置透明队列会出现下图这样的情况:
在这里插入图片描述

将Pass写进之前的内发光Shader中进行合成

内外发光合成效果是这样:
在这里插入图片描述

最后附上合成的Shader代码
Shader "Unlit/OutAndRimLight"
{
	Properties{
		_SpecularGlass("SpecularGlassStrength", Range(0,64)) = 32
		_ObjColor("ObjColor", color) = (1,1,1,1)
		_RimColor("RimColor", color) = (1,1,1,1)
		_RimStrength("RimStrength", Range(0.0001,3.0)) = 0.1

		_AtmoColor("Atmosphere Color", Color) = (0, 0.4, 1.0, 1)
		_Size("Size", Float) = 0.1
		_OutLightPow("LightPow", Float) = 5
		_OutLightStrength("Strength", Float) = 15
	}
		SubShader
	{


		Pass  //pass1 实现rim和贴图颜色
	{
		Tags{ "RenderType" = "Opaque" }

		CGPROGRAM
		#pragma vertex vert
		#pragma fragment frag
		
		#include "UnityCG.cginc"
		#include "Lighting.cginc"

		struct appdata
	{
		float4 vertex : POSITION;
		float3 normal : NORMAL;
	};

	struct v2f
	{
		float3 worldNormal:NORMAL;
		float4 vertex : SV_POSITION;
		float3 worldPos : TEXCOORD1;
	};

	v2f vert(appdata_base v)
	{
		v2f o;
		o.vertex = UnityObjectToClipPos(v.vertex);
		o.worldNormal = mul(v.normal, (float3x3)unity_WorldToObject);
		o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
		return o;
	}

	float _SpecularGlass;
	fixed4 _ObjColor;

	fixed4 _RimColor;
	float _RimStrength;

	fixed4 frag(v2f i) : SV_Target
	{
		fixed3 worldNormal = normalize(i.worldNormal);

	fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz);

	fixed3 diffuse = max(0.0, dot(worldNormal, worldLightDir));

	fixed3 diffuseColor = diffuse  * _LightColor0.xyz;

	//计算reflect方向
	fixed3 reflectDir = normalize(reflect(-worldLightDir, worldNormal));
	//计算视角方向
	fixed3 viewDir = normalize(_WorldSpaceCameraPos.xyz - i.worldPos);
	//specular分量
	fixed3 specular = pow(max(0.0, dot(reflectDir, viewDir)), _SpecularGlass);

	fixed3 specularColor = specular * _LightColor0.xyz;

	//环境光
	fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * _ObjColor;

	//RimLight
	fixed3 worldViewDir = normalize(viewDir);

	float rim = 1 - max(0, dot(worldViewDir, worldNormal));

	fixed3 rimColor = _RimColor * pow(rim, 1 / _RimStrength);


	return fixed4(diffuseColor + specularColor + ambient + rimColor, 0);
	}

		ENDCG
	}
	
	Pass  //pass2 实现OutLight
	{
		Name "AtmosphereBase"
		Tags{ "LightMode" = "Always" }
		
		Cull Front
		Blend SrcAlpha One

		CGPROGRAM
		#pragma vertex vert
		#pragma fragment frag
		#include "UnityCG.cginc"

		uniform float _Size;
		uniform float4 _AtmoColor;
		uniform float _OutLightPow;
		uniform float _OutLightStrength;

		struct v2f
		{
			float3 normal : TEXCOORD0;
			float3 worldPos : TEXCOORD1;
			float4 vertex : SV_POSITION;
		};

		v2f vert(appdata_base v)
		{
			v2f o;
			v.vertex.xyz += v.normal * _Size;
			o.vertex = UnityObjectToClipPos(v.vertex);
			o.normal = v.normal;
			o.worldPos = mul(unity_ObjectToWorld, v.vertex);
			return o;
		}
	
		fixed4 frag(v2f i) : COLOR
		{
			i.normal = normalize(i.normal);
			//视角观察方向
			float3 viewDir = normalize(i.worldPos - _WorldSpaceCameraPos.xyz);

			float4 color = _AtmoColor;

			color.a = pow(saturate(dot(viewDir, i.normal)), _OutLightPow);
			color.a *= _OutLightStrength*dot(viewDir, i.normal);
			return color;
		}
		ENDCG
	}
}
}

参考:
https://blog.csdn.net/v_xchen_v/article/details/78262919

  • 5
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
### 回答1: Unity Shader是一种专门用于制作游戏的图形渲染程序。在大多数游戏中,我们都希望让模型展现出崭新的效果。有时候,如果希望模型边缘看起来发光,则需要使用Shader来进行处理。其中,模型边缘自发光需要的是特别的处理技巧。 在Unity Shader中实现模型边缘自发光的方法有很多,但最常见的方式就是通过控制深度、法线和颜色等参数来增加颜色和光亮度。首先,我们需要分析模型边缘的特性,找到边缘的物理体积和光照条件,然后再运用一定的OpenGL技巧给予模型侧面以足够的颜色和光亮度。 另,还有一种方式可以实现模型的边缘自发光。那就是将模型的整体颜色设置为辉光色,然后通过代码控制其背面渐变,来实现边缘的自发光效果。这种方式主要是采用jungle Shader技术来实现模型纹理和物理光源之间的交互效果,运用较为广泛。 总之,实现Unity Shader模型边缘自发光就需要理解模型的特性,进行合适的参数设置和处理技巧,才能得到理想的效果。不同的游戏场景和模型也会有不同的处理方式,需要开发者结合实际情况进行具体分析和调整。 ### 回答2: Unity Shader中的模型边缘自发光,可以通过使用描边Shader实现。描边Shader是通过计算法线与表面之间的夹角来确定边缘,并将其与指定颜色进行混合,从而产生模型边缘的自发光效果。实现该效果的方法有多种,一种常用的做法是在一个关于深度等级的RenderTexture上绘制描边效果,然后将其与原始场景渲染结果叠加在一起。此,还可以使用几何着色器(Geometry Shader)来实现描边效果,但需要支持OpenGL 4.0以上版本的显卡才能正常运行。 描边Shader的效果取决于边缘权重的计算方法和颜色混合技术。使用不同的模型接口和最小距离阈值,可以调整边沿的宽度和数量。同时,利用颜色叠加,可以给边缘添加动态效果,比如透明度和闪烁等。在制作游戏时,可以通过组合描边Shader与材质、纹理、照明等属性,增强游戏画面的视觉效果,从而提高游戏的品质和受欢迎程度。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值