mirror of
https://github.com/overte-org/overte.git
synced 2025-08-06 08:29:33 +02:00
Merge pull request #3111 from noirsoft/master
Implementing improved perlin noise
This commit is contained in:
commit
257dc56168
2 changed files with 136 additions and 10 deletions
|
@ -11,18 +11,114 @@
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
//
|
//
|
||||||
|
|
||||||
// the texture containing our permutations and normals
|
// implementation based on Ken Perlin's Improved Noise reference implementation (orig. in Java) at
|
||||||
uniform sampler2D permutationNormalTexture;
|
// http://mrl.nyu.edu/~perlin/noise/
|
||||||
|
|
||||||
|
uniform sampler2D permutationTexture;
|
||||||
|
|
||||||
// the noise frequency
|
// the noise frequency
|
||||||
const float frequency = 65536.0; // looks better with current TREE_SCALE, was 1024 when TREE_SCALE was either 512 or 128
|
const float frequency = 256.0;
|
||||||
|
//const float frequency = 65536.0; // looks better with current TREE_SCALE, was 1024 when TREE_SCALE was either 512 or 128
|
||||||
|
|
||||||
// the noise amplitude
|
// the noise amplitude
|
||||||
const float amplitude = 0.1;
|
const float amplitude = 0.5;
|
||||||
|
|
||||||
// the position in model space
|
// the position in model space
|
||||||
varying vec3 position;
|
varying vec3 position;
|
||||||
|
|
||||||
|
// gradient based on gradients from cube edge centers rather than random from texture lookup
|
||||||
|
float randomEdgeGrad(int hash, vec3 position){
|
||||||
|
int h = int(mod(hash, 16));
|
||||||
|
float u = h < 8 ? position.x : position.y;
|
||||||
|
float v = h < 4 ? position.y : h == 12 || h == 14 ? position.x : position.z;
|
||||||
|
bool even = mod(hash, 2) == 0;
|
||||||
|
bool four = mod(hash, 4) == 0;
|
||||||
|
return (even ? u : -u) + (four ? v : -v);
|
||||||
|
}
|
||||||
|
|
||||||
|
// still have the option to lookup based on texture
|
||||||
|
float randomTextureGrad(int hash, vec3 position){
|
||||||
|
float u = float(hash) / 256.0;
|
||||||
|
vec3 g = -1 + 2 * texture2D(permutationTexture, vec2(u, 0.75)).rgb;
|
||||||
|
return dot(position, g);
|
||||||
|
}
|
||||||
|
|
||||||
|
float improvedGrad(int hash, vec3 position){
|
||||||
|
// Untested whether texture lookup is faster than math, uncomment one line or the other to try out
|
||||||
|
// cube edge gradients versus random spherical gradients sent in texture.
|
||||||
|
|
||||||
|
// return randomTextureGrad(hash, position);
|
||||||
|
return randomEdgeGrad(hash, position);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5th order fade function to remove 2nd order discontinuties
|
||||||
|
vec3 fade3(vec3 t){
|
||||||
|
return t * t * t * (t * (t * 6 - 15) + 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
int permutation(int index){
|
||||||
|
float u = float(index) / 256.0;
|
||||||
|
float t = texture2D(permutationTexture, vec2(u, 0.25)).r;
|
||||||
|
return int(t * 256);
|
||||||
|
}
|
||||||
|
|
||||||
|
float improvedNoise(vec3 position){
|
||||||
|
int X = int(mod(floor(position.x), 256));
|
||||||
|
int Y = int(mod(floor(position.y), 256));
|
||||||
|
int Z = int(mod(floor(position.z), 256));
|
||||||
|
|
||||||
|
vec3 fracs = fract(position);
|
||||||
|
|
||||||
|
vec3 fades = fade3(fracs);
|
||||||
|
|
||||||
|
int A = permutation(X + 0) + Y;
|
||||||
|
int AA = permutation(A + 0) + Z;
|
||||||
|
int AB = permutation(A + 1) + Z;
|
||||||
|
int B = permutation(X + 1) + Y;
|
||||||
|
int BA = permutation(B + 0) + Z;
|
||||||
|
int BB = permutation(B + 1) + Z;
|
||||||
|
|
||||||
|
float gradAA0 = improvedGrad(permutation(AA + 0), vec3(fracs.x , fracs.y , fracs.z ));
|
||||||
|
float gradBA0 = improvedGrad(permutation(BA + 0), vec3(fracs.x - 1, fracs.y , fracs.z ));
|
||||||
|
float gradAB0 = improvedGrad(permutation(AB + 0), vec3(fracs.x , fracs.y - 1, fracs.z ));
|
||||||
|
float gradBB0 = improvedGrad(permutation(BB + 0), vec3(fracs.x - 1, fracs.y - 1, fracs.z ));
|
||||||
|
float gradAA1 = improvedGrad(permutation(AA + 1), vec3(fracs.x , fracs.y , fracs.z - 1));
|
||||||
|
float gradBA1 = improvedGrad(permutation(BA + 1), vec3(fracs.x - 1, fracs.y , fracs.z - 1));
|
||||||
|
float gradAB1 = improvedGrad(permutation(AB + 1), vec3(fracs.x , fracs.y - 1, fracs.z - 1));
|
||||||
|
float gradBB1 = improvedGrad(permutation(BB + 1), vec3(fracs.x - 1, fracs.y - 1, fracs.z - 1));
|
||||||
|
|
||||||
|
return mix(mix(mix(gradAA0, gradBA0, fades.x), mix(gradAB0, gradBB0, fades.x), fades.y), mix(mix(gradAA1, gradBA1, fades.x), mix(gradAB1, gradBB1, fades.x), fades.y), fades.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
float turbulence(vec3 position, float power){
|
||||||
|
return (1.0f / power) * improvedNoise(power * position);
|
||||||
|
}
|
||||||
|
|
||||||
|
float turb(vec3 position){
|
||||||
|
return turbulence(position, 1)
|
||||||
|
+ turbulence(position, 2),
|
||||||
|
+ turbulence(position, 4)
|
||||||
|
+ turbulence(position, 8)
|
||||||
|
+ turbulence(position, 16)
|
||||||
|
+ turbulence(position, 32)
|
||||||
|
+ turbulence(position, 64)
|
||||||
|
+ turbulence(position, 128)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void main(void) {
|
||||||
|
|
||||||
|
// get noise in range 0 .. 1
|
||||||
|
float noise = clamp(0.5f + amplitude * turb(position * frequency), 0, 1);
|
||||||
|
|
||||||
|
// apply vertex lighting
|
||||||
|
vec3 color = gl_Color.rgb * vec3(noise, noise, noise);
|
||||||
|
gl_FragColor = vec4(color, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* old implementation
|
||||||
// returns the gradient at a single corner of our sampling cube
|
// returns the gradient at a single corner of our sampling cube
|
||||||
vec3 grad(vec3 location) {
|
vec3 grad(vec3 location) {
|
||||||
float p1 = texture2D(permutationNormalTexture, vec2(location.x / 256.0, 0.25)).r;
|
float p1 = texture2D(permutationNormalTexture, vec2(location.x / 256.0, 0.25)).r;
|
||||||
|
@ -60,7 +156,4 @@ float perlin(vec3 location) {
|
||||||
mix(mix(ffcv, cfcv, params.x), mix(fccv, cccv, params.x), params.y),
|
mix(mix(ffcv, cfcv, params.x), mix(fccv, cccv, params.x), params.y),
|
||||||
params.z);
|
params.z);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
void main(void) {
|
|
||||||
gl_FragColor = vec4(gl_Color.rgb * (1.0 + amplitude*(perlin(position * frequency) - 1.0)), 1.0);
|
|
||||||
}
|
|
|
@ -85,6 +85,33 @@ void TextureCache::setFrameBufferSize(QSize frameBufferSize) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// use fixed table of permutations. Could also make ordered list programmatically
|
||||||
|
// and then shuffle algorithm. For testing, this ensures consistent behavior in each run.
|
||||||
|
// this list taken from Ken Perlin's Improved Noise reference implementation (orig. in Java) at
|
||||||
|
// http://mrl.nyu.edu/~perlin/noise/
|
||||||
|
|
||||||
|
const int permutation[256] =
|
||||||
|
{
|
||||||
|
151, 160, 137, 91, 90, 15, 131, 13, 201, 95, 96, 53, 194, 233, 7, 225,
|
||||||
|
140, 36, 103, 30, 69, 142, 8, 99, 37, 240, 21, 10, 23, 190, 6, 148,
|
||||||
|
247, 120, 234, 75, 0, 26, 197, 62, 94, 252, 219, 203, 117, 35, 11, 32,
|
||||||
|
57, 177, 33, 88, 237, 149, 56, 87, 174, 20, 125, 136, 171, 168, 68, 175,
|
||||||
|
74, 165, 71, 134, 139, 48, 27, 166, 77, 146, 158, 231, 83, 111, 229, 122,
|
||||||
|
60, 211, 133, 230, 220, 105, 92, 41, 55, 46, 245, 40, 244, 102, 143, 54,
|
||||||
|
65, 25, 63, 161, 1, 216, 80, 73, 209, 76, 132, 187, 208, 89, 18, 169,
|
||||||
|
200, 196, 135, 130, 116, 188, 159, 86, 164, 100, 109, 198, 173, 186, 3, 64,
|
||||||
|
52, 217, 226, 250, 124, 123, 5, 202, 38, 147, 118, 126, 255, 82, 85, 212,
|
||||||
|
207, 206, 59, 227, 47, 16, 58, 17, 182, 189, 28, 42, 223, 183, 170, 213,
|
||||||
|
119, 248, 152, 2, 44, 154, 163, 70, 221, 153, 101, 155, 167, 43, 172, 9,
|
||||||
|
129, 22, 39, 253, 19, 98, 108, 110, 79, 113, 224, 232, 178, 185, 112, 104,
|
||||||
|
218, 246, 97, 228, 251, 34, 242, 193, 238, 210, 144, 12, 191, 179, 162, 241,
|
||||||
|
81, 51, 145, 235, 249, 14, 239, 107, 49, 192, 214, 31, 181, 199, 106, 157,
|
||||||
|
184, 84, 204, 176, 115, 121, 50, 45, 127, 4, 150, 254, 138, 236, 205, 93,
|
||||||
|
222, 114, 67, 29, 24, 72, 243, 141, 128, 195, 78, 66, 215, 61, 156, 180
|
||||||
|
};
|
||||||
|
|
||||||
|
#define USE_CHRIS_NOISE 1
|
||||||
|
|
||||||
GLuint TextureCache::getPermutationNormalTextureID() {
|
GLuint TextureCache::getPermutationNormalTextureID() {
|
||||||
if (_permutationNormalTextureID == 0) {
|
if (_permutationNormalTextureID == 0) {
|
||||||
glGenTextures(1, &_permutationNormalTextureID);
|
glGenTextures(1, &_permutationNormalTextureID);
|
||||||
|
@ -92,10 +119,17 @@ GLuint TextureCache::getPermutationNormalTextureID() {
|
||||||
|
|
||||||
// the first line consists of random permutation offsets
|
// the first line consists of random permutation offsets
|
||||||
unsigned char data[256 * 2 * 3];
|
unsigned char data[256 * 2 * 3];
|
||||||
|
#if (USE_CHRIS_NOISE==1)
|
||||||
|
for (int i = 0; i < 256; i++) {
|
||||||
|
data[3*i+0] = permutation[i];
|
||||||
|
data[3*i+1] = permutation[i];
|
||||||
|
data[3*i+2] = permutation[i];
|
||||||
|
#else
|
||||||
for (int i = 0; i < 256 * 3; i++) {
|
for (int i = 0; i < 256 * 3; i++) {
|
||||||
data[i] = rand() % 256;
|
data[i] = rand() % 256;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
// the next, random unit normals
|
|
||||||
for (int i = 256 * 3; i < 256 * 3 * 2; i += 3) {
|
for (int i = 256 * 3; i < 256 * 3 * 2; i += 3) {
|
||||||
glm::vec3 randvec = glm::sphericalRand(1.0f);
|
glm::vec3 randvec = glm::sphericalRand(1.0f);
|
||||||
data[i] = ((randvec.x + 1.0f) / 2.0f) * 255.0f;
|
data[i] = ((randvec.x + 1.0f) / 2.0f) * 255.0f;
|
||||||
|
@ -105,7 +139,6 @@ GLuint TextureCache::getPermutationNormalTextureID() {
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 256, 2, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 256, 2, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
}
|
}
|
||||||
return _permutationNormalTextureID;
|
return _permutationNormalTextureID;
|
||||||
|
|
Loading…
Reference in a new issue