首先Unity自带有一个柏林噪声的API, Mathf.PerlinNoise(x,y) 但用起来不灵活,还是在即生成图片比较合适
c#代码
using UnityEngine;
using UnityEngine.UI;
using System;
using System.IO;
public class PerlinNoiseTest : MonoBehaviour
{
public Material noiseMaterial;
public Texture texture;
public RenderTexture renderTexture;
public RawImage rawImage;
public Vector2 tilling;
[Range(0,2)]
public float randomVal=1;
void Update()
{
if(Input.GetKeyDown(KeyCode.Space))
{
EncodeToPNG();
}
}
public void EncodeToPNG()
{
//noiseMaterial.SetTextureScale("_MainTex", tilling);
noiseMaterial.SetFloat("_RandomVal", randomVal);
noiseMaterial.SetVector("_Scale", new Vector4(tilling.x, tilling.y, 0, 0));
RenderTexture.ReleaseTemporary(renderTexture);
renderTexture = RenderTexture.GetTemporary(1000, 1000, 0);
Graphics.Blit(null, renderTexture, noiseMaterial, 0);
rawImage.texture = renderTexture;
RenderTexture.active = renderTexture;
var _w = renderTexture.width;
var _h = renderTexture.height;
var _texture = new Texture2D(_w, _h);
_texture.ReadPixels(new Rect(0, 0, _w, _h), 0, 0);
var _data = _texture.EncodeToPNG();
File.WriteAllBytes(Directory.GetCurrentDirectory()+"\\Assets\\"+ "perlinNoise.PNG", _data);
}
}
shader代码
这里碰到一个问题,正常的——MainTex的缩放偏移是声明_MainTex_ST配合TRANSFORM_TEX宏来实现。但是在Graphic.bilt()中材质被调用时_MainText_ST不起作用,而作为材质直接赋给物体又是起作用的,不明白为什么,只能声明个_Scale作为替代
Shader "Custom/PerlinNoise"
{
Properties
{
_MainTex ("Albedo (RGB)", 2D) = "white" {}
_Scale("_Scale",vector) = (1,1,0,0)
_RandomVal("RandomVal",Range(0,2)) = 1
}
SubShader
{
pass{
CGPROGRAM
#include"UnityCG.cginc"
#pragma vertex vert
#pragma fragment frag
sampler2D _MainTex;
float2 _Scale;
float _RandomVal;
float2 randomVec(float2 uv)
{
float vec = dot(uv, float2(127.1, 311.7));
return -1.0 + 2.0 * frac(sin(vec) * 1234.1234567*_RandomVal);
}
float perlinNoise(float2 uv)
{
float2 pi = floor(uv);
float2 pf = uv - pi;
float2 w = pf * pf * (3.0 - 2.0 * pf);
float2 lerp1 = lerp(
dot(randomVec(pi + float2(0.0, 0.0)), pf - float2(0.0, 0.0)),
dot(randomVec(pi + float2(1.0, 0.0)), pf - float2(1.0, 0.0)), w.x);
float2 lerp2 = lerp(
dot(randomVec(pi + float2(0.0, 1.0)), pf - float2(0.0, 1.0)),
dot(randomVec(pi + float2(1.0, 1.0)), pf - float2(1.0, 1.0)), w.x);
return lerp(lerp1, lerp2, w.y);
}
struct v2f
{
float4 pos:SV_POSITION;
float2 uv:TEXCOORD0;
};
v2f vert(appdata_img v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
// TRANSFORM_TEX在graphic.bilt里不起作用,或者说_MianTex_ST不起作用
o.uv =float2( v.texcoord.x*_Scale.x,v.texcoord.y*_Scale.y);
return o;
}
fixed4 frag(v2f i):SV_TARGET0
{
float res = perlinNoise(i.uv);
return fixed4(res,res,res,1);
}
ENDCG
}
}
}