利用shader生成随机数及简单噪声图

##

随机在shader中制作各种noise非常常见。下文中我将介绍如何利用shader生成随机数。

1维随机

1维随机是我们在shader中制作随机数的基础。我简单介绍下各个函数、参数的作用。

fract(x)->就是取x小数部分然后做个绝对值处理

sin(x)->不必多说

fract(sin(x)*a),a=1.0 如上图

fract(sin(x)*a),a=10.5 如上图

fract( sin(x + b) * a ),a=100,b=0.546 如上图

fract( sin(x + 0.546) * 143758.5964)->如上图

通常程序中我们把a、b看做随机数种子的一部分,当a越大时实际上fract( sin(x) * a)会表现的“更密集"(扩大了定义域),也就会更“随机”。实际上定义好种子数后,我们得到的是特定的随机。

float Random1DTo1D(float value,float a,float b){
	//make value more random by making it bigger
	float random = frac(sin(value+b)*a);
        return random;
}

2维/3维/4维 高维到低维随机

在程序中我们更常用的是4D/3D/2D->3D/2D/1D的随机,通常我们使用dot()来处理高维到1维的情况,并且在dot()前为了减少artifacts(超过float边界)我们一般会对传进来的value进行处理。

2D->1D:

float Random2DTo1D(float2 value,float a ,float2 b)
{			
	//avaoid artifacts
	float2 smallValue = sin(value);
	//get scalar value from 2d vector	
	float  random = dot(smallValue,b);
	random = frac(sin(random) * a);
	return random;
}

2D->2D:(其实就是对2D用不同的种子处理2次)

float2 Random2DTo2D(float2 value){
	return float2(
		Random2DTo1D(value,14375.5964, float2(15.637, 76.243)),
		Random2DTo1D(value,14684.6034,float2(45.366, 23.168))
	);
}

3D->1D

float Random3DTo1D(float3 value,float a,float3 b)
{			
	float3 smallValue = sin(value);
	float  random = dot(smallValue,b);
	random = frac(sin(random) * a);
	return random;
}

3D->2D

float2 Random3DTo2D(float3 value){
	return float2(
		Random3DTo1D(value,14375.5964, float3(15.637,76.243,37.168)),
		Random3DTo1D(value,14684.6034,float3(45.366, 23.168,65.918))
	);
}

3D->3D

float3 Random3DTo3D(float3 value){
	return float3(
		Random3DTo1D(value,14375.5964, float3(15.637,76.243,37.168)),
		Random3DTo1D(value,14684.6034,float3(45.366, 23.168,65.918)),
		Random3DTo1D(value,17635.1739,float3(62.654, 88.467,25.111))
	);
}

4D->1D

float Random4DTo1D(float4 value,float a ,float4 b)
{			
	float4 smallValue = sin(value);
	float  random = dot(smallValue,b);
	random = frac(sin(random) * a);
	return random;
}

4D->2D

float2 Random4DTo2D(float4 value)
{			
    return float2(		
        Random4DTo1D(value,14375.5964,float4(15.637,76.243,37.168,83.511)),
        Random4DTo1D(value,14684.6034,float4(45.366, 23.168,65.918,57.514))
	);
}

4D->3D

float3 Random4DTo3D(float4 value)
{			
    return float3(		
        Random4DTo1D(value,14375.5964,float4(15.637,76.243,37.168,83.511)),
        Random4DTo1D(value,14684.6034,float4(45.366, 23.168,65.918,57.514)),
        Random4DTo1D(value,14985.1739,float4(62.654, 88.467,25.111,61.875))
	);
}

4D->4D

float4 Random4DTo4D(float4 value)
{			
    return float4(		
        Random4DTo1D(value,14375.5964,float4(15.637,76.243,37.168,83.511)),
        Random4DTo1D(value,14684.6034,float4(45.366, 23.168,65.918,57.514)),
        Random4DTo1D(value,14985.1739,float4(62.654, 88.467,25.111,61.875)),
        Random4DTo1D(value,17635.1739,float4(44.383, 38.174,67.688,22.351))	
	);
}

1维/2维/3维/4维 低维到高维随机

方法和上面一样不再赘述。

整个文件 :

源文件链接

(因为是在URP里写的,所以风格保持了统一;另外在URP中我们可以用real来替换float,提高在移动端的性能)

#ifndef UNIVERSAL_RANDOM_INCLUDED
#define UNIVERSAL_RANDOM_INCLUDED

//1D
float Random1DTo1D(float value,float a,float b){
	//make value more random by making it bigger
	float random = frac(sin(value+b)*a);
        return random;
}

float2 Random1DTo2D(float value){
    return float2(
        Random1DTo1D(value,14375.5964,0.546),
        Random1DTo1D(value,18694.2233,0.153)
    );
}

float3 Random1DTo3D(float value){
    return float3(
        Random1DTo1D(value,14375.5964,0.546),
        Random1DTo1D(value,18694.2233,0.153),
        Random1DTo1D(value,19663.6565,0.327)
    );
}

float4 Random1DTo4D(float value){
    return float4(
        Random1DTo1D(value,14375.5964,0.546),
        Random1DTo1D(value,18694.2233,0.153),
        Random1DTo1D(value,19663.6565,0.327),
        Random1DTo1D(value,12748.4774,0.688)
    );
}
//2D
float Random2DTo1D(float2 value,float a ,float2 b)
{			
	//avaoid artifacts
	float2 smallValue = sin(value);
	//get scalar value from 2d vector	
	float  random = dot(smallValue,b);
	random = frac(sin(random) * a);
	return random;
}

float2 Random2DTo2D(float2 value){
	return float2(
		Random2DTo1D(value,14375.5964, float2(15.637, 76.243)),
		Random2DTo1D(value,14684.6034,float2(45.366, 23.168))
	);
}

float3 Random2DTo3D(float2 value){
    return float3(
        Random2DTo1D(value,14375.5964,float2(15.637, 76.243)),
        Random2DTo1D(value,18694.2233,float2(45.366, 23.168)),
        Random2DTo1D(value,19663.6565,float2(62.654, 88.467))
    );
}

float4 Random2DTo4D(float2 value){
    return float4(
        Random2DTo1D(value,14375.5964,float2(15.637, 76.243)),
        Random2DTo1D(value,18694.2233,float2(45.366, 23.168)),
        Random2DTo1D(value,19663.6565,float2(62.654, 88.467)),
        Random2DTo1D(value,17635.1739,float2(44.383, 38.174))
    );
}
//3D
float Random3DTo1D(float3 value,float a,float3 b)
{			
	float3 smallValue = sin(value);
	float  random = dot(smallValue,b);
	random = frac(sin(random) * a);
	return random;
}

float2 Random3DTo2D(float3 value){
	return float2(
		Random3DTo1D(value,14375.5964, float3(15.637,76.243,37.168)),
		Random3DTo1D(value,14684.6034,float3(45.366, 23.168,65.918))
	);
}

float3 Random3DTo3D(float3 value){
	return float3(
		Random3DTo1D(value,14375.5964, float3(15.637,76.243,37.168)),
		Random3DTo1D(value,14684.6034,float3(45.366, 23.168,65.918)),
		Random3DTo1D(value,17635.1739,float3(62.654, 88.467,25.111))
	);
}

float4 Random3DTo4D(float3 value){
	return float4(
		Random3DTo1D(value,14375.5964, float3(15.637,76.243,37.168)),
		Random3DTo1D(value,14684.6034,float3(45.366, 23.168,65.918)),
		Random3DTo1D(value,17635.1739,float3(62.654, 88.467,25.111)),
        Random3DTo1D(value,17635.1739,float3(44.383, 38.174,67.688))	
	);
}
//4D
float Random4DTo1D(float4 value,float a ,float4 b)
{			
	float4 smallValue = sin(value);
	float  random = dot(smallValue,b);
	random = frac(sin(random) * a);
	return random;
}

float2 Random4DTo2D(float4 value)
{			
    return float2(		
        Random4DTo1D(value,14375.5964,float4(15.637,76.243,37.168,83.511)),
        Random4DTo1D(value,14684.6034,float4(45.366, 23.168,65.918,57.514))
	);
}

float3 Random4DTo3D(float4 value)
{			
    return float3(		
        Random4DTo1D(value,14375.5964,float4(15.637,76.243,37.168,83.511)),
        Random4DTo1D(value,14684.6034,float4(45.366, 23.168,65.918,57.514)),
        Random4DTo1D(value,14985.1739,float4(62.654, 88.467,25.111,61.875))
	);
}

float4 Random4DTo4D(float4 value)
{			
    return float4(		
        Random4DTo1D(value,14375.5964,float4(15.637,76.243,37.168,83.511)),
        Random4DTo1D(value,14684.6034,float4(45.366, 23.168,65.918,57.514)),
        Random4DTo1D(value,14985.1739,float4(62.654, 88.467,25.111,61.875)),
        Random4DTo1D(value,17635.1739,float4(44.383, 38.174,67.688,22.351))	
	);
}

#endif

随机算法其实利用了hash的思想,所以国外又有把Random function称为Hash function的。

Shadertoy​www.shadertoy.com/results?query=hash

生成简单噪声图

很简单的shader:源文件链接

Shader "Noise"
{

    SubShader
    {

        Pass
        {
            HLSLPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"   
            #include "Random.hlsl"

            struct appdata
            {
                float4 vertex : POSITION;
            };

            struct v2f
            {
                float4 vertex : SV_POSITION;
            };


            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = TransformObjectToHClip(v.vertex.xyz);
                return o;
            }

            float4 frag (v2f i) : SV_Target
            {
                float3 value = i.vertex.xyz;
                float4 col = Random3DTo4D(value);
                return col;
            }
            ENDHLSL
        }
    }
}

利用噪声图制作卡牌背景

————————————————

原文:利用shader生成随机数及简单噪声图 - 知乎

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
利用Shader实现边框效果的方法如下: 1. 创建一个新的ShaderUnity中,可以通过在Project面板中右键点击创建一个新的Shader来创建一个新的Shader文件。 2. 编写Shader代码 在创建好的Shader文件中,可以使用Shader语言编写代码来实现边框效果。以下是一个简单的示例代码: ``` Shader "Custom/TextOutline" { Properties { _MainTex ("Texture", 2D) = "white" {} _OutlineColor ("Outline Color", Color) = (0,0,0,1) _OutlineWidth ("Outline Width", Range(0, 0.1)) = 0.005 } SubShader { Tags {"Queue"="Transparent" "RenderType"="Transparent"} 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 _OutlineColor; float _OutlineWidth; v2f vert (appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.uv = v.uv; return o; } fixed4 frag (v2f i) : SV_Target { float4 col = tex2D(_MainTex, i.uv); float4 outline = tex2D(_MainTex, i.uv + float2(-_OutlineWidth, 0)) + tex2D(_MainTex, i.uv + float2(_OutlineWidth, 0)) + tex2D(_MainTex, i.uv + float2(0, -_OutlineWidth)) + tex2D(_MainTex, i.uv + float2(0, _OutlineWidth)); outline.a = 1.0; return lerp(outline, col, col.a); } ENDCG } } FallBack "Diffuse" } ``` 3. 将Shader应用到Text组件上 在创建好的Shader文件中,可以通过将Shader应用到Text组件的Material上来实现边框效果。具体的方法是在Project面板中选择Text组件的Material,然后将Shader设置为刚刚创建的Shader即可。 需要注意的是,以上示例代码实现的边框效果比较简单,可以根据实际需求来调整代码中的参数和算法。同时,Shader的编写也需要一定的基础知识和经验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值