由于GPU驱动供应商通常不会费心在GLSL中实现noiseX,我正在寻找一个“图形随机化瑞士军刀”实用函数集,最好是在GPU着色器中优化使用。我更喜欢GLSL,但是任何语言的代码对我来说都可以,我可以把它翻译成GLSL。
具体来说,我希望:
a)伪随机函数- n维,均匀分布于[-1,1]或[0,1]之上,从m维种子(理想情况下是任何值,但我同意将种子限制在,比如说,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);
// ...
我对随机数生成理论不太感兴趣,所以我最渴望的是一个现成的解决方案,但我也很喜欢这样的回答:“这里有一个非常好的,高效的1D rand(),让我解释一下如何在它的基础上制作一个好的n维rand()……”.
请看下面的例子如何添加白噪声渲染纹理。
解决方案是使用两种纹理:原始白噪声和纯白噪声,就像这个:wiki白噪声
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);
一定要用这个:
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);
}
您可以在改进OpenGL ES 2.0的规范一行程序GLSL rand()中找到解释