162 篇文章 8 订阅
130 篇文章 4 订阅
86 篇文章 0 订阅

_ScreenLightPos屏幕上光线的位置，这个需要在c#脚本中计算并传出，稍后会讲解
_Density密度
_Decay衰减
_Exposure曝光，用来控制亮度，大家都知道，在相机中，曝光时间越长图像越亮

	v2f vert(v2in v)
{
v2f o;
o.pos = mul(UNITY_MATRIX_MVP, v.vertex);

half2 texCoord = v.texcoord;
half2 deltaTexCoord = texCoord - _ScreenLightPos.xy;
deltaTexCoord *= 1.0f / 8 * _Density;

texCoord -= deltaTexCoord;
o.uv0 = texCoord;
texCoord -= deltaTexCoord;
o.uv1 = texCoord;
texCoord -= deltaTexCoord;
o.uv2 = texCoord;
texCoord -= deltaTexCoord;
o.uv3 = texCoord;
texCoord -= deltaTexCoord;
o.uv4 = texCoord;
texCoord -= deltaTexCoord;
o.uv5 = texCoord;
texCoord -= deltaTexCoord;
o.uv6 = texCoord;
texCoord -= deltaTexCoord;
o.uv7 = texCoord;
return o;
}

v.texcoord为当前点的坐标

deltaTexCoord为当前点对光源点的反向向量，长度为两点间距离

_Density越大采样点间距越大

	struct v2f {
float4 pos : POSITION;
float2 uv0 : TEXCOORD0;
float2 uv1 : TEXCOORD1;
float2 uv2 : TEXCOORD2;
float2 uv3 : TEXCOORD3;
float2 uv4 : TEXCOORD4;
float2 uv5 : TEXCOORD5;
float2 uv6 : TEXCOORD6;
float2 uv7 : TEXCOORD7;
};

	struct v2in {
float4 vertex : POSITION;
float2 texcoord : TEXCOORD0;
};

    half4 frag(v2f i) : COLOR
{
half illuminationDecay = 1.0f;

half4 color = tex2D(_MainTex, i.uv0)*illuminationDecay;
illuminationDecay *= _Decay;
color += tex2D(_MainTex, i.uv1)*illuminationDecay;
illuminationDecay *= _Decay;
color += tex2D(_MainTex, i.uv2)*illuminationDecay;
illuminationDecay *= _Decay;
color += tex2D(_MainTex, i.uv3)*illuminationDecay;
illuminationDecay *= _Decay;
color += tex2D(_MainTex, i.uv4)*illuminationDecay;
illuminationDecay *= _Decay;
color += tex2D(_MainTex, i.uv5)*illuminationDecay;
illuminationDecay *= _Decay;
color += tex2D(_MainTex, i.uv6)*illuminationDecay;
illuminationDecay *= _Decay;
color += tex2D(_MainTex, i.uv7)*illuminationDecay;

color /= 8;

return half4(color.xyz * _Exposure, 1);

}

illuminationDecay光照衰减，_Decay是我们外部可控衰减

_Exposure增加亮度

Ray我们就制造好了，接下来我们需要把光线ray与原屏幕图像混合，这一步就比较简单了，只给出源代码，各位自己意会。

Shader "Custom/god ray 2 blend" {
Properties{
_MainTex("Base (RGB)", 2D) = "" {}
_GodRayTex ("God (RGB)", 2D) = ""{}
_Alpha("_Alpha", Float) = 0.5
}

// Shader code pasted into all further CGPROGRAM blocks
CGINCLUDE

#include "UnityCG.cginc"

struct v2in {
float4 vertex : POSITION;
float2 texcoord : TEXCOORD0;
};

struct v2f {
float4 pos : POSITION;
float2 uv : TEXCOORD0;
};

sampler2D _MainTex;

sampler2D _GodRayTex;

uniform float _Alpha;

v2f vert(v2in v)
{
v2f o;
o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
o.uv = v.texcoord;
return o;
}

half4 frag(v2f i) : COLOR
{
half4 color = tex2D(_MainTex, i.uv) + tex2D(_GodRayTex, i.uv)*_Alpha;
//half4 color = tex2D(_MainTex, i.uv);

return color;
}

ENDCG

Tags{ "Queue" = "Transparent" }

Pass{
ZWrite Off

BindChannels
{
Bind "Vertex", vertex
Bind "texcoord", texcoord0
Bind "texcoord1", texcoord1
}

Fog{ Mode off }
CGPROGRAM
#pragma fragmentoption ARB_precision_hint_fastest
#pragma vertex vert
#pragma fragment frag
ENDCG
}

}

Fallback off

} // shader

Camera类中有这么一个函数可以把世界坐标转换为屏幕坐标
Camera.WorldToScreenPoint(position)

Transforms position from world space into screen space.

Screenspace is defined in pixels. The bottom-left of the screen is (0,0); the right-top is (pixelWidth,pixelHeight). The z position is in world units from the camera.

if (lightScreenPos.z > 0 && lightScreenPos.x > 0 && lightScreenPos.x < camera.pixelWidth  && lightScreenPos.y >0 && lightScreenPos.y < camera.pixelHeight)

Graphics.Blit(sourceTexture, tempRtA, material);

Graphics.Blit(tempRtA, tempRtB, material);

Graphics.Blit(tempRtB, tempRtA, material);
Graphics.Blit(tempRtA, tempRtB, material);
Graphics.Blit(tempRtB, tempRtA, material);

materialBlend.SetTexture("_GodRayTex", tempRtA);
Graphics.Blit(sourceTexture, destTexture, materialBlend, 0);

using UnityEngine;
using System.Collections;
[ExecuteInEditMode]
public class godRay2 : MonoBehaviour
{
public Transform lightpos;
private Material curMaterial;
private Material curMateriaBlend;
public Vector4 ScreenLightPos = new Vector4(0, 0, 0, 0);
public float Density = 0.01f;
public float Decay = 0.5f;
public float Exposure = 0.5f;
public float Alpha = 1;
public RenderTexture tempRtA = null;
public RenderTexture tempRtB = null;

private Vector3 lightScreenPos;
#region Properties
Material material
{
get
{
if (curMaterial == null)
{
curMaterial.hideFlags = HideFlags.HideAndDontSave;
}
return curMaterial;
}
}
Material materialBlend
{
get
{
if (curMateriaBlend == null)
{
curMateriaBlend.hideFlags = HideFlags.HideAndDontSave;
}
return curMateriaBlend;
}
}
#endregion

void Start()
{
if (!SystemInfo.supportsImageEffects)
{
enabled = false;
return;
}

{
enabled = false;
}
}

void OnRenderImage(RenderTexture sourceTexture, RenderTexture destTexture)
{

{
lightScreenPos = Camera.main.WorldToScreenPoint(lightpos.position);

if (lightScreenPos.z > 0 && lightScreenPos.x > 0 && lightScreenPos.x < camera.pixelWidth  && lightScreenPos.y > 0 && lightScreenPos.y < camera.pixelHeight)
{
material.SetVector("ScreenLightPos", new Vector4(lightScreenPos.x / camera.pixelWidth, lightScreenPos.y / camera.pixelHeight, 0, 0));
//   material.SetVector("ScreenLightPos", ScreenLightPos);
material.SetFloat("Density", Density);
material.SetFloat("Decay", Decay);
material.SetFloat("Exposure", Exposure);
materialBlend.SetFloat("Alpha", Alpha);
CreateBuffers();
Graphics.Blit(sourceTexture, tempRtA, material);
Graphics.Blit(tempRtA, tempRtB, material);
Graphics.Blit(tempRtB, tempRtA, material);
Graphics.Blit(tempRtA, tempRtB, material);
Graphics.Blit(tempRtB, tempRtA, material);

materialBlend.SetTexture("_GodRayTex", tempRtA);
Graphics.Blit(sourceTexture, destTexture, materialBlend, 0);
//   Graphics.Blit(tempRtA, destTexture, material, 0);
}
else
{
Graphics.Blit(sourceTexture, destTexture);
}
}
else
{
Graphics.Blit(sourceTexture, destTexture);
}

}

void CreateBuffers()
{
if (!tempRtA)
{
tempRtA = new RenderTexture(Screen.width / 4, Screen.height / 4, 0);
tempRtA.hideFlags = HideFlags.DontSave;
}

if (!tempRtB)
{
tempRtB = new RenderTexture(Screen.width / 4, Screen.height / 4, 0);
tempRtB.hideFlags = HideFlags.DontSave;
}
}
void OnDisable()
{
if (curMaterial)
{
DestroyImmediate(curMaterial);
}
}
}



------ by  wolf96 http://blog.csdn.net/wolf96

• 5
点赞
• 10
收藏
觉得还不错? 一键收藏
• 打赏
• 0
评论
12-04 620
12-30 1万+

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

• 非常没帮助
• 没帮助
• 一般
• 有帮助
• 非常有帮助

wolf96

¥1 ¥2 ¥4 ¥6 ¥10 ¥20

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