質問

GPU ドライバー ベンダーは通常、わざわざ実装しないため、 noiseX GLSLで、私は 「グラフィックスランダム化スイスアーミーナイフ」 ユーティリティ関数セット。GPU シェーダ内で使用するために最適化されることが望ましい。私は GLSL の方が好きですが、どの言語でコーディングしても問題ありません。自分で GLSL に翻訳しても問題ありません。

具体的には、次のことを期待します。

a) 擬似乱数関数 - M 次元シードから計算された、[-1,1] または [0,1] にわたる N 次元の一様分布 (理想的には任意の値ですが、シードをたとえば 0 に制限しても問題ありません)。均一な結果分布の場合は .1)。何かのようなもの:

float random  (T seed);
vec2  random2 (T seed);
vec3  random3 (T seed);
vec4  random4 (T seed);
// T being either float, vec2, vec3, vec4 - ideally.

b) 継続的なノイズ パーリン ノイズのようなものです。これも N 次元、+- 均一分布で、値のセットが制限されており、見栄えが良くなります (パーリン レベルのような外観を設定するオプションも便利です)。次のような署名が期待されます。

float noise  (T coord, TT seed);
vec2  noise2 (T coord, TT seed);
// ...

私は乱数生成理論にはあまり興味がないので、最も熱心に検討したいと思っています。 既製のソリューション, 、しかし、次のような答えも歓迎します 「これは非常に優れた効率的な 1 次元の rand() です。そして、その上に優れた N 次元の rand() を作成する方法を説明しましょう...」 .

役に立ちましたか?

解決

は非常に単純な擬似ランダムに見えるもののため、私はインターネットのどこかに見つけたこのonelinerを使用します:

float rand(vec2 co){
    return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453);
}

また、通常の方法でこれをアップロードし、シェーダ内の値をサンプリングし、その後、あなたが好きなPRNG使用してノイズテクスチャを生成することができます。私はあなたが好きな場合は、後のコードサンプルを掘ることができます。

また、パーリンノイズとシンプレックスのGLSLの実装のためにこのファイルをチェックしてください、ステファン・グスタフソンによります。

他のヒント

  ・グスタフソンの実装では、1Dテクスチャ

を使用しています

はありません、それは、ない2005年以来、それは、人々は古いバージョンのダウンロードを主張することだけだはありません。リンク上でのバージョンは、あなたは、2Dテクスチャます。

用途のみ8ビットを供給しました

イアン・マキューアンのAshimaと自分で新しいバージョンは、テクスチャを使用していますが、テクスチャ帯域幅のたくさんの一般的なデスクトップ・プラットフォーム上の約半分の速度で動作しません。テクスチャは、多くの場合、重要なボトルネックになっているので、モバイルプラットフォームでは、テクスチャのバージョンが速いかもしれません。

私たちの積極的な維持ソースリポジトリは、次のとおりです。

https://github.com/ashima/webgl-noise

は雑音のテクスチャのとテクスチャ使用バージョンの両方のコレクションは(のみ2Dテクスチャを使用して)ここで:

http://www.itn.liu.se/~stegu /simplexnoise/GLSL-noise-vs-noise.zipする

あなたが任意の特定の質問がある場合は、直接私にメールして自由に感じる(私のメールアドレスはclassicnoise*.glsl源で見つけることができます。)

あなたが単純な整数ハッシュ関数を使用して、フロートの仮数部に結果を挿入することができることを私に起こります。 IIRC GLSLスペック保証、32ビットの符号なし整数とIEEE binary32フロート表現、それは完全に移植する必要がありますので。

私はちょうど今、この試しを与えました。その結果は非常に優れている:それはまさに私が試したすべての入力、全く目に見えるパターンでスタティックように見えます。これとは対照的に人気の罪/ FRACTスニペットはかなり同じ入力与えられた私のGPU上で斜線を発音しています。

1つの欠点は、GLSLのV3.30を必要とすることです。それは十分に速いようだが、私は経験的にその性能を定量化していません。 AMDのシェーダAnalyzerはHD5870にVEC2バージョンのためのクロックあたり13.33ピクセルを主張します。罪/ FRACTスニペット用のクロックあたり16個のピクセルとは対照的。それは確かにあるので、少し遅くなります。

ここに私の実装です。私はそれが簡単に独自の関数を導き出すために作るためのアイデアの様々な順列でそれを残しています。

/*
    static.frag
    by Spatial
    05 July 2013
*/

#version 330 core

uniform float time;
out vec4 fragment;



// A single iteration of Bob Jenkins' One-At-A-Time hashing algorithm.
uint hash( uint x ) {
    x += ( x << 10u );
    x ^= ( x >>  6u );
    x += ( x <<  3u );
    x ^= ( x >> 11u );
    x += ( x << 15u );
    return x;
}



// Compound versions of the hashing algorithm I whipped together.
uint hash( uvec2 v ) { return hash( v.x ^ hash(v.y)                         ); }
uint hash( uvec3 v ) { return hash( v.x ^ hash(v.y) ^ hash(v.z)             ); }
uint hash( uvec4 v ) { return hash( v.x ^ hash(v.y) ^ hash(v.z) ^ hash(v.w) ); }



// Construct a float with half-open range [0:1] using low 23 bits.
// All zeroes yields 0.0, all ones yields the next smallest representable value below 1.0.
float floatConstruct( uint m ) {
    const uint ieeeMantissa = 0x007FFFFFu; // binary32 mantissa bitmask
    const uint ieeeOne      = 0x3F800000u; // 1.0 in IEEE binary32

    m &= ieeeMantissa;                     // Keep only mantissa bits (fractional part)
    m |= ieeeOne;                          // Add fractional part to 1.0

    float  f = uintBitsToFloat( m );       // Range [1:2]
    return f - 1.0;                        // Range [0:1]
}



// Pseudo-random value in half-open range [0:1].
float random( float x ) { return floatConstruct(hash(floatBitsToUint(x))); }
float random( vec2  v ) { return floatConstruct(hash(floatBitsToUint(v))); }
float random( vec3  v ) { return floatConstruct(hash(floatBitsToUint(v))); }
float random( vec4  v ) { return floatConstruct(hash(floatBitsToUint(v))); }





void main()
{
    vec3  inputs = vec3( gl_FragCoord.xy, time ); // Spatial and temporal inputs
    float rand   = random( inputs );              // Random per-pixel value
    vec3  luma   = vec3( rand );                  // Expand to RGB

    fragment = vec4( luma, 1.0 );
}
<時間>

スクリーンショットます:

static.fragでランダム(vec3)の出力

私は、画像編集プログラムでスクリーンショットを視察しました。そこに256色であり、平均値は、分布が均一であると予想される範囲をカバーする意味、127である。

金騒音

// Gold Noise ©2015 dcerisano@standard3d.com 
//  - based on the Golden Ratio, PI and Square Root of Two
//  - superior distribution
//  - fastest noise generator function
//  - works with all chipsets (including low precision)

float PHI = 1.61803398874989484820459 * 00000.1; // Golden Ratio   
float PI  = 3.14159265358979323846264 * 00000.1; // PI
float SQ2 = 1.41421356237309504880169 * 10000.0; // Square Root of Two

float gold_noise(in vec2 coordinate, in float seed){
    return fract(tan(distance(coordinate*(seed+PHI), vec2(PHI, PI)))*SQ2);
}

参照金騒音ブラウザでスグ!

enter image description here

この機能向上をランダムに分配する機能@appas'答えとして9,2017:

enter image description here

に@appas機能もに不備が種子供給(紫外線をカットすることはない種-同一フレーム毎に、動作しないの低い精度チップセット.金騒音が生み出すさまざまな低精度のデフォルト(います。

素晴らしい実装も説明されています ここ McEwan と @StefanGustavson による、パーリン ノイズのように見えますが、「セットアップは必要ありません。つまり、テクスチャや均一な配列ではありません。それをシェーダーのソース コードに追加し、必要な場所で呼び出すだけです。」

これは、@dep がリンクした Gustavson の以前の実装が 1D テクスチャを使用していることを考えると特に便利です。 GLSL ES ではサポートされていません (WebGL のシェーダー言語)。

だけはalledgedlyそれは最速1で、GPUのための3Dノイズのこのバージョンを見つけます:

#ifndef __noise_hlsl_
#define __noise_hlsl_

// hash based 3d value noise
// function taken from https://www.shadertoy.com/view/XslGRr
// Created by inigo quilez - iq/2013
// License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.

// ported from GLSL to HLSL

float hash( float n )
{
    return frac(sin(n)*43758.5453);
}

float noise( float3 x )
{
    // The noise function returns a value in the range -1.0f -> 1.0f

    float3 p = floor(x);
    float3 f = frac(x);

    f       = f*f*(3.0-2.0*f);
    float n = p.x + p.y*57.0 + 113.0*p.z;

    return lerp(lerp(lerp( hash(n+0.0), hash(n+1.0),f.x),
                   lerp( hash(n+57.0), hash(n+58.0),f.x),f.y),
               lerp(lerp( hash(n+113.0), hash(n+114.0),f.x),
                   lerp( hash(n+170.0), hash(n+171.0),f.x),f.y),f.z);
}

#endif

ストレートギ版1d Perlin、基本的にランダムlfoジグザグ.

half  rn(float xx){         
    half x0=floor(xx);
    half x1=x0+1;
    half v0 = frac(sin (x0*.014686)*31718.927+x0);
    half v1 = frac(sin (x1*.014686)*31718.927+x1);          

    return (v0*(1-frac(xx))+v1*(frac(xx)))*2-1*sin(xx);
}

また1-2-3-4次元perlinノイズshadertoyオーナー inigo quilez perlinチュートリアルサイトの算定、完全に高速実装およびコードします。

ハッシュ: 今日でwebGL2.0は整数GLSL(ワット)でご利用いただけますので、そこにあります。 - >(醜いフロートハッシュよりも同様のコストで)品質ポータブルハッシュのために、私たちは今、「深刻な」ハッシング技術を使用することができます。 IQは https://www.shadertoy.com/view/XlXcW4 の中でいくつかの実装(そしてより)

例えば:ます。

  const uint k = 1103515245U;  // GLIB C
//const uint k = 134775813U;   // Delphi and Turbo Pascal
//const uint k = 20170906U;    // Today's date (use three days ago's dateif you want a prime)
//const uint k = 1664525U;     // Numerical Recipes

vec3 hash( uvec3 x )
{
    x = ((x>>8U)^x.yzx)*k;
    x = ((x>>8U)^x.yzx)*k;
    x = ((x>>8U)^x.yzx)*k;

    return vec3(x)*(1.0/float(0xffffffffU));
}

Doが、これを使用します:

highp float rand(vec2 co)
{
    highp float a = 12.9898;
    highp float b = 78.233;
    highp float c = 43758.5453;
    highp float dt= dot(co.xy ,vec2(a,b));
    highp float sn= mod(dt,3.14);
    return fract(sin(sn) * c);
}

これを使用しないでください。

float rand(vec2 co){
    return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453);
}
あなたは<のhref = "http://byteblacksmith.com/improvements-to-the-canonical-one-liner-glsl-rand-for-opengl-es-2-0/" RELで説明を見つけることができます= "nofollowをnoreferrer">のOpenGL ES 2.0 の

の正規一ライナーGLSLのランドの改善()

レンダリングされたテクスチャにホワイト ノイズを追加する方法の例を以下に示します。解決策は、2 つのテクスチャを使用することです。次のようなオリジナルの純粋なホワイト ノイズ: ウィキのホワイトノイズ

private static final String VERTEX_SHADER =
    "uniform mat4 uMVPMatrix;\n" +
    "uniform mat4 uMVMatrix;\n" +
    "uniform mat4 uSTMatrix;\n" +
    "attribute vec4 aPosition;\n" +
    "attribute vec4 aTextureCoord;\n" +
    "varying vec2 vTextureCoord;\n" +
    "varying vec4 vInCamPosition;\n" +
    "void main() {\n" +
    "    vTextureCoord = (uSTMatrix * aTextureCoord).xy;\n" +
    "    gl_Position = uMVPMatrix * aPosition;\n" +
    "}\n";

private static final String FRAGMENT_SHADER =
        "precision mediump float;\n" +
        "uniform sampler2D sTextureUnit;\n" +
        "uniform sampler2D sNoiseTextureUnit;\n" +
        "uniform float uNoseFactor;\n" +
        "varying vec2 vTextureCoord;\n" +
        "varying vec4 vInCamPosition;\n" +
        "void main() {\n" +
                "    gl_FragColor = texture2D(sTextureUnit, vTextureCoord);\n" +
                "    vec4 vRandChosenColor = texture2D(sNoiseTextureUnit, fract(vTextureCoord + uNoseFactor));\n" +
                "    gl_FragColor.r += (0.05 * vRandChosenColor.r);\n" +
                "    gl_FragColor.g += (0.05 * vRandChosenColor.g);\n" +
                "    gl_FragColor.b += (0.05 * vRandChosenColor.b);\n" +
        "}\n";

共有フラグメントには、メイン アプリケーションによるレンダリングごとに更新されるパラメーター uNoiseFactor が含まれています。

float noiseValue = (float)(mRand.nextInt() % 1000)/1000;
int noiseFactorUniformHandle = GLES20.glGetUniformLocation( mProgram, "sNoiseTextureUnit");
GLES20.glUniform1f(noiseFactorUniformHandle, noiseFactor);

私はGLSLにケン・パーリンのJava実装の1つを翻訳し、ShaderToy上のカップルのプロジェクトでそれを使用しています。

以下は、私がやったGLSLの解釈です:

int b(int N, int B) { return N>>B & 1; }
int T[] = int[](0x15,0x38,0x32,0x2c,0x0d,0x13,0x07,0x2a);
int A[] = int[](0,0,0);

int b(int i, int j, int k, int B) { return T[b(i,B)<<2 | b(j,B)<<1 | b(k,B)]; }

int shuffle(int i, int j, int k) {
    return b(i,j,k,0) + b(j,k,i,1) + b(k,i,j,2) + b(i,j,k,3) +
        b(j,k,i,4) + b(k,i,j,5) + b(i,j,k,6) + b(j,k,i,7) ;
}

float K(int a, vec3 uvw, vec3 ijk)
{
    float s = float(A[0]+A[1]+A[2])/6.0;
    float x = uvw.x - float(A[0]) + s,
        y = uvw.y - float(A[1]) + s,
        z = uvw.z - float(A[2]) + s,
        t = 0.6 - x * x - y * y - z * z;
    int h = shuffle(int(ijk.x) + A[0], int(ijk.y) + A[1], int(ijk.z) + A[2]);
    A[a]++;
    if (t < 0.0)
        return 0.0;
    int b5 = h>>5 & 1, b4 = h>>4 & 1, b3 = h>>3 & 1, b2= h>>2 & 1, b = h & 3;
    float p = b==1?x:b==2?y:z, q = b==1?y:b==2?z:x, r = b==1?z:b==2?x:y;
    p = (b5==b3 ? -p : p); q = (b5==b4 ? -q : q); r = (b5!=(b4^b3) ? -r : r);
    t *= t;
    return 8.0 * t * t * (p + (b==0 ? q+r : b2==0 ? q : r));
}

float noise(float x, float y, float z)
{
    float s = (x + y + z) / 3.0;  
    vec3 ijk = vec3(int(floor(x+s)), int(floor(y+s)), int(floor(z+s)));
    s = float(ijk.x + ijk.y + ijk.z) / 6.0;
    vec3 uvw = vec3(x - float(ijk.x) + s, y - float(ijk.y) + s, z - float(ijk.z) + s);
    A[0] = A[1] = A[2] = 0;
    int hi = uvw.x >= uvw.z ? uvw.x >= uvw.y ? 0 : 1 : uvw.y >= uvw.z ? 1 : 2;
    int lo = uvw.x <  uvw.z ? uvw.x <  uvw.y ? 0 : 1 : uvw.y <  uvw.z ? 1 : 2;
    return K(hi, uvw, ijk) + K(3 - hi - lo, uvw, ijk) + K(lo, uvw, ijk) + K(0, uvw, ijk);
}

私はこのソースでケン・パーリンの騒音ハードウェアの第2章から付録Bからそれを翻訳します:

https://www.csee.umbc.edu/~olano /s2002c36/ch02.pdfする

ここに掲載ノイズ関数を使用してシェーダー玩具に私がやった公共日陰があります:

https://www.shadertoy.com/view/3slXzMする

私は私の研究中にノイズの主題にあるいくつかの他の良いソースが含まれます:

https://thebookofshaders.com/11/する

https://mzucker.github.io/html/perlin -noise-数学-faq.htmlよくする

https://rmarcus.info/blog/2018/03 /04/perlin-noise.htmlする

http://flafla2.github.io/2014/08/09 /perlinnoise.htmlする

https://mrl.nyu.edu/~perlin/noise/する

https://rmarcus.info/blog/assets/perlin/perlin_paper.pdf

https://developer.nvidia.com/gpugems/GPUGems/gpugems_ch05.html

それはノイズの大きなインタラクティブな説明を提供するだけでなくとして

は、私は非常にシェーダの本をお勧めしますが、他のシェーダの概念だけでなく、。

EDITます:

はGLSLで利用可能なハードウェアアクセラレーション機能の一部を使用して変換されたコードを最適化することができるかもしれません。私はこれをやってしまう場合は、この記事を更新します。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top