Unity Shader学习:RayMarching2D云和海洋
根据 JiepengTan的教程魔改了下,代码中有些可以合并的地方没有处理,其中一些数学的运算和光照原理还是比较有难度的,等以后再深入研究。
采样的噪声图:
c#部分:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[ExecuteInEditMode]
public class RayMarchingCamera : MonoBehaviour {
private Matrix4x4 frustumCorners = Matrix4x4.identity;
public Material material;
public Camera myCamera;
public Transform cameraTransform;
// Use this for initialization
private void Start()
{
myCamera.depthTextureMode = DepthTextureMode.Depth;
}
private void OnRenderImage(RenderTexture source, RenderTexture destination)
{
//field of view
float fov = myCamera.fieldOfView;
//近裁面距离
float near = myCamera.nearClipPlane;
//横纵比
float aspect = myCamera.aspect;
//近裁面一半的高度
float halfHeight = near * Mathf.Tan(fov * 0.5f * Mathf.Deg2Rad);
//向上和向右的向量
Vector3 toRight = myCamera.transform.right * halfHeight * aspect;
Vector3 toTop = myCamera.transform.up * halfHeight;
//分别得到相机到近裁面四个角的向量
//depth/dist=near/|topLeft|
//dist=depth*(|TL|/near)
//scale=|TL|/near
Vector3 topLeft = cameraTransform.forward * near + toTop - toRight;
float scale = topLeft.magnitude / near;
topLeft.Normalize();
topLeft *= scale;
Vector3 topRight = cameraTransform.forward * near + toTop + toRight;
topRight.Normalize();
topRight *= scale;
Vector3 bottomLeft = cameraTransform.forward * near - toTop - toRight;
bottomLeft.Normalize();
bottomLeft *= scale;
Vector3 bottomRight = cameraTransform.forward * near - toTop + toRight;
bottomRight.Normalize();
bottomRight *= scale;
//给矩阵赋值
frustumCorners.SetRow(0, bottomLeft);
frustumCorners.SetRow(1, bottomRight);
frustumCorners.SetRow(2, topRight);
frustumCorners.SetRow(3, topLeft);
//将向量传给定点着色器,将屏幕画面传个shader
material.SetMatrix("_FrustumCornorsRay", frustumCorners);
material.SetTexture("_MainTex", source);
Graphics.Blit(source, destination,material,0);
}
}
shader部分:
Shader "Unlit/SeaCloudTest"
{
Properties{
_MainTex("Texture", 2D) = "white" {
}
//噪声贴图
_NoiseTex("NoiseTex",2D)="white"{
}
//海浪幅度
_SeaWaveHeight("SeaWaveHeight",float)=5.0
_SeaBaseColor("SeaBaseColor",Color)=(1,1,1,1)
_SeaWaterColor("SeaWaterColor",Color)=(1,1,1,1)
//海平面高度
_SeaLevel("SeaLevel",float)=0.0
}
SubShader{
Tags{
"RenderType" = "Opaque" }
LOD 100
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;
//由定点着色器输出插值得到射线,包含了像素到摄像机的方向和距离信息
float4 interpolatedRay:TEXCOORD1;
};
sampler2D _MainTex;
float4 _MainTex_ST;
//深度图
sampler2D _CameraDepthTexture;
//传入近裁面四个点的向量
float4x4 _FrustumCornorsRay;
sampler2D _NoiseTex;
float _SeaWaveHeight;
float4 _SeaBaseColor;
float4 _SeaWaterColor;
float _SeaLevel;
#define lightDir (normalize(float3(5.,3.0,-1.0)))
v2f vert(appdata v) {
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv