Twitter
2021年03月27日 - Three.js・WebVR

GLSLでノイズ

GLSLでジュリア集合」に続き「フラグメントシェーダ ノイズ-wgld.org」を参考に、GLSLでノイズを試してみました。

GLSLでノイズ

フォトショップに雲模様フィルタがありますが、ノイズは雲や炎などを表現するさいに使用します。GLSLで自然な仕上がりのノイズ(パーリンノイズのような)を生成するには、線形補間して均衡化した複数の階層(オクターブ)のノイズを合成します。各階層のノイズをどの程度の割合で合成するかはパーシステンスと呼ばれる値を使用し、一般的には0.5を設定します。

● script.jsの読み込み

script.jsは「WebGLでシェーダ(GLSL)入門」と同じものを使用します。

<script src="js/script.js" type="module"></script>

● glsl.js

const vertexShader =`
	attribute vec3 position;

	void main(void){
		gl_Position = vec4(position,1.0);
	}
`;

const fragmentShader =`
	precision highp float;

	uniform float time;
	uniform vec2 mouse;
	uniform vec2 resolution;

	//合成するノイズの階層(オクターブ)数
	const int oct = 8;

	//ノイズを合成する割合(パーシステンス)
	const float per = 0.5;
	const float PI = 3.1415926;

	//ノイズを均衡化するための線形補間
	float interpolate(float a,float b,float x){
		float f = (1.0 - cos(x * PI)) * 0.5;
		return a * (1.0 - f) + b * f;
	}

	//乱数を生成
	float rnd(vec2 p){
		return fract(sin(dot(p,vec2(12.9898,78.233))) * 43758.5453);
	}

	//補間した乱数を生成
	float irnd(vec2 p){
		vec2 i = floor(p);
		vec2 f = fract(p);
		vec4 v = vec4(rnd(vec2(i.x,i.y)),
					  rnd(vec2(i.x + 1.0,i.y)),
					  rnd(vec2(i.x,i.y + 1.0)),
					  rnd(vec2(i.x + 1.0,i.y + 1.0)));
		return interpolate(interpolate(v.x,v.y,f.x),interpolate(v.z,v.w,f.x),f.y);
	}

	//ノイズを生成
	float noise(vec2 p){
		float t = 0.0;
		for(int i = 0; i < oct; i++){
			float freq = pow(2.0,float(i));
			float amp = pow(per,float(oct - i));
			t += irnd(vec2(p.x / freq, p.y / freq)) * amp;
		}
		return t;
	}

	//シームレスノイズを生成
	float snoise(vec2 p,vec2 q,vec2 r){
		return noise(vec2(p.x,p.y)) * q.x * q.y +
			   noise(vec2(p.x,p.y + r.y)) * q.x * (1.0 - q.y) +
			   noise(vec2(p.x + r.x,p.y)) * (1.0 - q.x) * q.y +
			   noise(vec2(p.x + r.x,p.y + r.y)) * (1.0 - q.x) * (1.0 - q.y);
	}

	void main(void){

		//シームレスノイズ
		const float map = 700.0;
		vec2 t = mod(gl_FragCoord.xy + vec2(time * 10.0),map);
		float n = snoise(t,t / map,vec2(map));

		gl_FragColor = vec4(vec3(n),1.0);
	}
`;

export { vertexShader, fragmentShader };

完成したデモになります。GLSLでノイズを試してみました。

  • このエントリーをはてなブックマークに追加

関連記事

前の記事へ

GLSLでジュリア集合

次の記事へ

GLSLでシンプレックスノイズ