Skip to content

Instantly share code, notes, and snippets.

@miketucker
Created September 23, 2012 15:56
Show Gist options
  • Save miketucker/3772118 to your computer and use it in GitHub Desktop.
Save miketucker/3772118 to your computer and use it in GitHub Desktop.
turbulence library bugs
-------- GLSL error: ERROR: Uniform precision mismatch '_NoiseOffset'
ERROR: Uniform precision mismatch '_Frequency'
ERROR: Uniform precision mismatch '_AnimSpeed'
ERROR: Uniform precision mismatch '_Time'
ERROR: Uniform precision mismatch '_Amplitude'
Vertex Shader:
#define SHADER_API_GLES 1
#define tex2D texture2D
#line 32
uniform vec4 _Time;
uniform float _Frequency;
uniform float _Amplitude;
uniform vec3 _NoiseOffset;
uniform float _Contribution;
uniform float _Normalize;
uniform float _AnimSpeed;
//
// FAST32_hash
// A very fast hashing function. Requires 32bit support.
// http://briansharpe.wordpress.com/2011/11/15/a-fast-and-simple-32bit-floating-point-hash-function/
//
// The hash formula takes the form....
// hash = fmod( coord.x * coord.x * coord.y * coord.y, SOMELARGEFLOAT ) / SOMELARGEFLOAT
// We truncate and offset the domain to the most interesting part of the noise.
// SOMELARGEFLOAT should be in the range of 400.0->1000.0 and needs to be hand picked. Only some give good results.
// 3D Noise is achieved by offsetting the SOMELARGEFLOAT value by the Z coordinate
//
vec4 FAST32_hash_3D_Cell( vec3 gridcell ) // generates 4 different random numbers for the single given cell point
{
// gridcell is assumed to be an integer coordinate
// TODO: these constants need tweaked to find the best possible noise.
// probably requires some kind of brute force computational searching or something....
const vec2 OFFSET = vec2( 50.0, 161.0 );
const float DOMAIN = 69.0;
const vec4 SOMELARGEFLOATS = vec4( 635.298681, 682.357502, 668.926525, 588.255119 );
const vec4 ZINC = vec4( 48.500388, 65.294118, 63.934599, 63.279683 );
// truncate the domain
gridcell.xyz = gridcell - floor(gridcell * ( 1.0 / DOMAIN )) * DOMAIN;
gridcell.xy += OFFSET.xy;
gridcell.xy *= gridcell.xy;
return fract( ( gridcell.x * gridcell.y ) * ( 1.0 / ( SOMELARGEFLOATS + gridcell.zzzz * ZINC ) ) );
}
float Cellular3D(vec3 xyz)
{
int xi = int(floor(xyz.x));
int yi = int(floor(xyz.y));
int zi = int(floor(xyz.z));
float xf = xyz.x - float(xi);
float yf = xyz.y - float(yi);
float zf = xyz.z - float(zi);
float dist1 = 9999999.0;
float dist2 = 9999999.0;
float dist3 = 9999999.0;
float dist4 = 9999999.0;
vec3 cell;
for (int z = -1; z <= 1; z++) {
for (int y = -1; y <= 1; y++) {
for (int x = -1; x <= 1; x++) {
cell = FAST32_hash_3D_Cell(vec3(xi + x, yi + y, zi + z)).xyz;
cell.x += (float(x) - xf);
cell.y += (float(y) - yf);
cell.z += (float(z) - zf);
float dist = 0.0;
dist = dot(cell, cell) + cell.x*cell.y + cell.x*cell.z + cell.y*cell.z;
if (dist < dist1)
{
dist4 = dist3;
dist3 = dist2;
dist2 = dist1;
dist1 = dist;
}
else if (dist < dist2)
{
dist4 = dist3;
dist3 = dist2;
dist2 = dist;
}
else if (dist < dist3)
{
dist4 = dist3;
dist3 = dist;
}
else if (dist < dist4)
{
dist4 = dist;
}
}
}
}
return dist1 * dist2; // scale return value from 0.0->1.333333 to 0.0->1.0 (2/3)^2 * 3 == (12/9) == 1.333333
}
//
// 3D fractional Brownian Motion
//
float fBM(vec3 p, vec3 offset, float frequency, float amplitude)
{
float h = 0.0;
h = Cellular3D((p+offset) * frequency);
h += h*amplitude;
return h;
}
#define gl_ModelViewProjectionMatrix glstate_matrix_mvp
uniform mat4 glstate_matrix_mvp;
#define gl_Vertex _glesVertex
attribute vec4 _glesVertex;
#define gl_MultiTexCoord0 _glesMultiTexCoord0
attribute vec4 _glesMultiTexCoord0;
uniform float _Displace;
varying vec4 position;
varying vec2 texCoord;
void main()
{
position = gl_Vertex;
if(_Displace > 0.0)
{
position.y = fBM(vec3(position.xz, _Time*_AnimSpeed), _NoiseOffset, _Frequency, _Amplitude);
}
gl_Position = gl_ModelViewProjectionMatrix * position;
texCoord = gl_MultiTexCoord0.xy;
}
Fragment Shader:
precision mediump float;
#define SHADER_API_GLES 1
#define tex2D texture2D
#line 32
uniform vec4 _Time;
uniform float _Frequency;
uniform float _Amplitude;
uniform vec3 _NoiseOffset;
uniform float _Contribution;
uniform float _Normalize;
uniform float _AnimSpeed;
//
// FAST32_hash
// A very fast hashing function. Requires 32bit support.
// http://briansharpe.wordpress.com/2011/11/15/a-fast-and-simple-32bit-floating-point-hash-function/
//
// The hash formula takes the form....
// hash = fmod( coord.x * coord.x * coord.y * coord.y, SOMELARGEFLOAT ) / SOMELARGEFLOAT
// We truncate and offset the domain to the most interesting part of the noise.
// SOMELARGEFLOAT should be in the range of 400.0->1000.0 and needs to be hand picked. Only some give good results.
// 3D Noise is achieved by offsetting the SOMELARGEFLOAT value by the Z coordinate
//
vec4 FAST32_hash_3D_Cell( vec3 gridcell ) // generates 4 different random numbers for the single given cell point
{
// gridcell is assumed to be an integer coordinate
// TODO: these constants need tweaked to find the best possible noise.
// probably requires some kind of brute force computational searching or something....
const vec2 OFFSET = vec2( 50.0, 161.0 );
const float DOMAIN = 69.0;
const vec4 SOMELARGEFLOATS = vec4( 635.298681, 682.357502, 668.926525, 588.255119 );
const vec4 ZINC = vec4( 48.500388, 65.294118, 63.934599, 63.279683 );
// truncate the domain
gridcell.xyz = gridcell - floor(gridcell * ( 1.0 / DOMAIN )) * DOMAIN;
gridcell.xy += OFFSET.xy;
gridcell.xy *= gridcell.xy;
return fract( ( gridcell.x * gridcell.y ) * ( 1.0 / ( SOMELARGEFLOATS + gridcell.zzzz * ZINC ) ) );
}
float Cellular3D(vec3 xyz)
{
int xi = int(floor(xyz.x));
int yi = int(floor(xyz.y));
int zi = int(floor(xyz.z));
float xf = xyz.x - float(xi);
float yf = xyz.y - float(yi);
float zf = xyz.z - float(zi);
float dist1 = 9999999.0;
float dist2 = 9999999.0;
float dist3 = 9999999.0;
float dist4 = 9999999.0;
vec3 cell;
for (int z = -1; z <= 1; z++) {
for (int y = -1; y <= 1; y++) {
for (int x = -1; x <= 1; x++) {
cell = FAST32_hash_3D_Cell(vec3(xi + x, yi + y, zi + z)).xyz;
cell.x += (float(x) - xf);
cell.y += (float(y) - yf);
cell.z += (float(z) - zf);
float dist = 0.0;
dist = dot(cell, cell) + cell.x*cell.y + cell.x*cell.z + cell.y*cell.z;
if (dist < dist1)
{
dist4 = dist3;
dist3 = dist2;
dist2 = dist1;
dist1 = dist;
}
else if (dist < dist2)
{
dist4 = dist3;
dist3 = dist2;
dist2 = dist;
}
else if (dist < dist3)
{
dist4 = dist3;
dist3 = dist;
}
else if (dist < dist4)
{
dist4 = dist;
}
}
}
}
return dist1 * dist2; // scale return value from 0.0->1.333333 to 0.0->1.0 (2/3)^2 * 3 == (12/9) == 1.333333
}
//
// 3D fractional Brownian Motion
//
float fBM(vec3 p, vec3 offset, float frequency, float amplitude)
{
float h = 0.0;
h = Cellular3D((p+offset) * frequency);
h += h*amplitude;
return h;
}
uniform vec4 _LowColor;
uniform vec4 _HighColor;
uniform float _Texturing;
uniform sampler2D _LowTexture;
uniform vec4 _LowTexture_ST;
uniform sampler2D _HighTexture;
uniform vec4 _HighTexture_ST;
varying vec4 position;
varying vec2 texCoord;
void main()
{
float h = fBM(vec3(vec2(position.xz), _Time*_AnimSpeed), _NoiseOffset, _Frequency, _Amplitude);
if(_Normalize > 0.0)
{
// set range to (0, 1)
h = h*0.5 + 0.5;
}
// do the accumulation with the previous fixed-point height
h = h*_Contribution;
vec4 color;
if(_Texturing > 0.0)
{
color = mix(_LowColor * texture2D(_LowTexture, _LowTexture_ST.xy * texCoord + _LowTexture_ST.zw), _HighColor * texture2D(_HighTexture, _HighTexture_ST.xy * texCoord + _HighTexture_ST.zw), h);
}
else
{
color = mix(_LowColor, _HighColor, h);
}
gl_FragColor = vec4(color.r, color.g, color.b, h);
}
-------- GLSL error: ERROR: Uniform precision mismatch '_NoiseOffset'
ERROR: Uniform precision mismatch '_Frequency'
ERROR: Uniform precision mismatch '_AnimSpeed'
ERROR: Uniform precision mismatch '_Time'
ERROR: Uniform precision mismatch '_Amplitude'
Vertex Shader:
#define SHADER_API_GLES 1
#define tex2D texture2D
#line 32
uniform vec4 _Time;
uniform float _Frequency;
uniform float _Amplitude;
uniform vec3 _NoiseOffset;
uniform float _Contribution;
uniform float _Normalize;
uniform float _AnimSpeed;
//
// FAST32_hash
// A very fast hashing function. Requires 32bit support.
// http://briansharpe.wordpress.com/2011/11/15/a-fast-and-simple-32bit-floating-point-hash-function/
//
// The hash formula takes the form....
// hash = fmod( coord.x * coord.x * coord.y * coord.y, SOMELARGEFLOAT ) / SOMELARGEFLOAT
// We truncate and offset the domain to the most interesting part of the noise.
// SOMELARGEFLOAT should be in the range of 400.0->1000.0 and needs to be hand picked. Only some give good results.
// 3D Noise is achieved by offsetting the SOMELARGEFLOAT value by the Z coordinate
//
vec4 FAST32_hash_3D_Cell( vec3 gridcell ) // generates 4 different random numbers for the single given cell point
{
// gridcell is assumed to be an integer coordinate
// TODO: these constants need tweaked to find the best possible noise.
// probably requires some kind of brute force computational searching or something....
const vec2 OFFSET = vec2( 50.0, 161.0 );
const float DOMAIN = 69.0;
const vec4 SOMELARGEFLOATS = vec4( 635.298681, 682.357502, 668.926525, 588.255119 );
const vec4 ZINC = vec4( 48.500388, 65.294118, 63.934599, 63.279683 );
// truncate the domain
gridcell.xyz = gridcell - floor(gridcell * ( 1.0 / DOMAIN )) * DOMAIN;
gridcell.xy += OFFSET.xy;
gridcell.xy *= gridcell.xy;
return fract( ( gridcell.x * gridcell.y ) * ( 1.0 / ( SOMELARGEFLOATS + gridcell.zzzz * ZINC ) ) );
}
float Cellular3D(vec3 xyz)
{
int xi = int(floor(xyz.x));
int yi = int(floor(xyz.y));
int zi = int(floor(xyz.z));
float xf = xyz.x - float(xi);
float yf = xyz.y - float(yi);
float zf = xyz.z - float(zi);
float dist1 = 9999999.0;
float dist2 = 9999999.0;
float dist3 = 9999999.0;
float dist4 = 9999999.0;
vec3 cell;
for (int z = -1; z <= 1; z++) {
for (int y = -1; y <= 1; y++) {
for (int x = -1; x <= 1; x++) {
cell = FAST32_hash_3D_Cell(vec3(xi + x, yi + y, zi + z)).xyz;
cell.x += (float(x) - xf);
cell.y += (float(y) - yf);
cell.z += (float(z) - zf);
float dist = 0.0;
dist = max(abs(cell.x), max(abs(cell.y), abs(cell.z)));
dist *= dist;
if (dist < dist1)
{
dist4 = dist3;
dist3 = dist2;
dist2 = dist1;
dist1 = dist;
}
else if (dist < dist2)
{
dist4 = dist3;
dist3 = dist2;
dist2 = dist;
}
else if (dist < dist3)
{
dist4 = dist3;
dist3 = dist;
}
else if (dist < dist4)
{
dist4 = dist;
}
}
}
}
return dist4; // scale return value from 0.0->1.333333 to 0.0->1.0 (2/3)^2 * 3 == (12/9) == 1.333333
}
//
// 3D fractional Brownian Motion
//
float fBM(vec3 p, vec3 offset, float frequency, float amplitude)
{
float h = 0.0;
h = Cellular3D((p+offset) * frequency);
h += h*amplitude;
return h;
}
#define gl_ModelViewProjectionMatrix glstate_matrix_mvp
uniform mat4 glstate_matrix_mvp;
#define gl_Vertex _glesVertex
attribute vec4 _glesVertex;
#define gl_MultiTexCoord0 _glesMultiTexCoord0
attribute vec4 _glesMultiTexCoord0;
uniform float _Displace;
varying vec4 position;
varying vec2 texCoord;
void main()
{
position = gl_Vertex;
if(_Displace > 0.0)
{
position.y = fBM(vec3(position.xz, _Time*_AnimSpeed), _NoiseOffset, _Frequency, _Amplitude);
}
gl_Position = gl_ModelViewProjectionMatrix * position;
texCoord = gl_MultiTexCoord0.xy;
}
Fragment Shader:
precision mediump float;
#define SHADER_API_GLES 1
#define tex2D texture2D
#line 32
uniform vec4 _Time;
uniform float _Frequency;
uniform float _Amplitude;
uniform vec3 _NoiseOffset;
uniform float _Contribution;
uniform float _Normalize;
uniform float _AnimSpeed;
//
// FAST32_hash
// A very fast hashing function. Requires 32bit support.
// http://briansharpe.wordpress.com/2011/11/15/a-fast-and-simple-32bit-floating-point-hash-function/
//
// The hash formula takes the form....
// hash = fmod( coord.x * coord.x * coord.y * coord.y, SOMELARGEFLOAT ) / SOMELARGEFLOAT
// We truncate and offset the domain to the most interesting part of the noise.
// SOMELARGEFLOAT should be in the range of 400.0->1000.0 and needs to be hand picked. Only some give good results.
// 3D Noise is achieved by offsetting the SOMELARGEFLOAT value by the Z coordinate
//
vec4 FAST32_hash_3D_Cell( vec3 gridcell ) // generates 4 different random numbers for the single given cell point
{
// gridcell is assumed to be an integer coordinate
// TODO: these constants need tweaked to find the best possible noise.
// probably requires some kind of brute force computational searching or something....
const vec2 OFFSET = vec2( 50.0, 161.0 );
const float DOMAIN = 69.0;
const vec4 SOMELARGEFLOATS = vec4( 635.298681, 682.357502, 668.926525, 588.255119 );
const vec4 ZINC = vec4( 48.500388, 65.294118, 63.934599, 63.279683 );
// truncate the domain
gridcell.xyz = gridcell - floor(gridcell * ( 1.0 / DOMAIN )) * DOMAIN;
gridcell.xy += OFFSET.xy;
gridcell.xy *= gridcell.xy;
return fract( ( gridcell.x * gridcell.y ) * ( 1.0 / ( SOMELARGEFLOATS + gridcell.zzzz * ZINC ) ) );
}
float Cellular3D(vec3 xyz)
{
int xi = int(floor(xyz.x));
int yi = int(floor(xyz.y));
int zi = int(floor(xyz.z));
float xf = xyz.x - float(xi);
float yf = xyz.y - float(yi);
float zf = xyz.z - float(zi);
float dist1 = 9999999.0;
float dist2 = 9999999.0;
float dist3 = 9999999.0;
float dist4 = 9999999.0;
vec3 cell;
for (int z = -1; z <= 1; z++) {
for (int y = -1; y <= 1; y++) {
for (int x = -1; x <= 1; x++) {
cell = FAST32_hash_3D_Cell(vec3(xi + x, yi + y, zi + z)).xyz;
cell.x += (float(x) - xf);
cell.y += (float(y) - yf);
cell.z += (float(z) - zf);
float dist = 0.0;
dist = max(abs(cell.x), max(abs(cell.y), abs(cell.z)));
dist *= dist;
if (dist < dist1)
{
dist4 = dist3;
dist3 = dist2;
dist2 = dist1;
dist1 = dist;
}
else if (dist < dist2)
{
dist4 = dist3;
dist3 = dist2;
dist2 = dist;
}
else if (dist < dist3)
{
dist4 = dist3;
dist3 = dist;
}
else if (dist < dist4)
{
dist4 = dist;
}
}
}
}
return dist4; // scale return value from 0.0->1.333333 to 0.0->1.0 (2/3)^2 * 3 == (12/9) == 1.333333
}
//
// 3D fractional Brownian Motion
//
float fBM(vec3 p, vec3 offset, float frequency, float amplitude)
{
float h = 0.0;
h = Cellular3D((p+offset) * frequency);
h += h*amplitude;
return h;
}
uniform vec4 _LowColor;
uniform vec4 _HighColor;
uniform float _Texturing;
uniform sampler2D _LowTexture;
uniform vec4 _LowTexture_ST;
uniform sampler2D _HighTexture;
uniform vec4 _HighTexture_ST;
varying vec4 position;
varying vec2 texCoord;
void main()
{
float h = fBM(vec3(vec2(position.xz), _Time*_AnimSpeed), _NoiseOffset, _Frequency, _Amplitude);
if(_Normalize > 0.0)
{
// set range to (0, 1)
h = h*0.5 + 0.5;
}
// do the accumulation with the previous fixed-point height
h = h*_Contribution;
vec4 color;
if(_Texturing > 0.0)
{
color = mix(_LowColor * texture2D(_LowTexture, _LowTexture_ST.xy * texCoord + _LowTexture_ST.zw), _HighColor * texture2D(_HighTexture, _HighTexture_ST.xy * texCoord + _HighTexture_ST.zw), h);
}
else
{
color = mix(_LowColor, _HighColor, h);
}
gl_FragColor = vec4(color.r, color.g, color.b, h);
}
-------- GLSL error: ERROR: Uniform precision mismatch '_Powered'
Vertex Shader:
#define SHADER_API_GLES 1
#define tex2D texture2D
#line 37
precision mediump float;
const int OCTAVES = 12;
uniform vec4 _Time;
uniform float _Frequency;
uniform float _Amplitude;
uniform vec3 _NoiseOffset;
uniform float _Contribution;
uniform float _Normalize;
uniform float _AnimSpeed;
uniform float _Lacunarity;
uniform float _Persistence;
uniform int _Powered;
uniform float _BillowPower;
//
// FAST32_hash
// A very fast hashing function. Requires 32bit support.
// http://briansharpe.wordpress.com/2011/11/15/a-fast-and-simple-32bit-floating-point-hash-function/
//
// The hash formula takes the form....
// hash = mod( coord.x * coord.x * coord.y * coord.y, SOMELARGEFLOAT ) / SOMELARGEFLOAT
// We truncate and offset the domain to the most interesting part of the noise.
// SOMELARGEFLOAT should be in the range of 400.0->1000.0 and needs to be hand picked. Only some give good results.
// 3D Noise is achieved by offsetting the SOMELARGEFLOAT value by the Z coordinate
//
void FAST32_hash_3D( vec3 gridcell,
out vec4 lowz_hash_0,
out vec4 lowz_hash_1,
out vec4 lowz_hash_2,
out vec4 highz_hash_0,
out vec4 highz_hash_1,
out vec4 highz_hash_2 ) // generates 3 random numbers for each of the 8 cell corners
{
// gridcell is assumed to be an integer coordinate
// TODO: these constants need tweaked to find the best possible noise.
// probably requires some kind of brute force computational searching or something....
const vec2 OFFSET = vec2( 50.0, 161.0 );
const float DOMAIN = 69.0;
const vec3 SOMELARGEFLOATS = vec3( 635.298681, 682.357502, 668.926525 );
const vec3 ZINC = vec3( 48.500388, 65.294118, 63.934599 );
// truncate the domain
gridcell.xyz = gridcell.xyz - floor(gridcell.xyz * ( 1.0 / DOMAIN )) * DOMAIN;
vec3 gridcell_inc1 = step( gridcell, vec3( DOMAIN - 1.5 ) ) * ( gridcell + 1.0 );
// calculate the noise
vec4 P = vec4( gridcell.xy, gridcell_inc1.xy ) + OFFSET.xyxy;
P *= P;
P = P.xzxz * P.yyww;
vec3 lowz_mod = vec3( 1.0 / ( SOMELARGEFLOATS.xyz + gridcell.zzz * ZINC.xyz ) );
vec3 highz_mod = vec3( 1.0 / ( SOMELARGEFLOATS.xyz + gridcell_inc1.zzz * ZINC.xyz ) );
lowz_hash_0 = fract( P * lowz_mod.xxxx );
highz_hash_0 = fract( P * highz_mod.xxxx );
lowz_hash_1 = fract( P * lowz_mod.yyyy );
highz_hash_1 = fract( P * highz_mod.yyyy );
lowz_hash_2 = fract( P * lowz_mod.zzzz );
highz_hash_2 = fract( P * highz_mod.zzzz );
}
//
// Quintic Hermite Interpolation
// http://www.rose-hulman.edu/~finn/CCLI/Notes/day09.pdf
//
// NOTE: maximum value of a hermitequintic interpolation with zero acceleration at the endpoints would be...
// f(x=0.5) = MAXPOS + MAXVELOCITY * ( ( x - 6x^3 + 8x^4 - 3x^5 ) - ( -4x^3 + 7x^4 -3x^5 ) ) = MAXPOS + MAXVELOCITY * 0.3125
//
// variable naming conventions:
// val = value ( position )
// grad = gradient ( velocity )
// x = 0.0->1.0 ( time )
// i = interpolation = a value to be interpolated
// e = evaluation = a value to be used to calculate the interpolation
// 0 = start
// 1 = end
//
float QuinticHermite( float x, float ival0, float ival1, float egrad0, float egrad1 ) // quintic hermite with start/end acceleration of 0.0
{
const vec3 C0 = vec3( -15.0, 8.0, 7.0 );
const vec3 C1 = vec3( 6.0, -3.0, -3.0 );
const vec3 C2 = vec3( 10.0, -6.0, -4.0 );
vec3 h123 = ( ( ( C0 + C1 * x ) * x ) + C2 ) * ( x*x*x );
return ival0 + dot( vec3( (ival1 - ival0), egrad0, egrad1 ), h123.xyz + vec3( 0.0, x, 0.0 ) );
}
vec4 QuinticHermite( float x, vec4 ival0, vec4 ival1, vec4 egrad0, vec4 egrad1 ) // quintic hermite with start/end acceleration of 0.0
{
const vec3 C0 = vec3( -15.0, 8.0, 7.0 );
const vec3 C1 = vec3( 6.0, -3.0, -3.0 );
const vec3 C2 = vec3( 10.0, -6.0, -4.0 );
vec3 h123 = ( ( ( C0 + C1 * x ) * x ) + C2 ) * ( x*x*x );
return ival0 + (ival1 - ival0) * h123.xxxx + egrad0 * vec4( h123.y + x ) + egrad1 * h123.zzzz;
}
vec4 QuinticHermite( float x, vec2 igrad0, vec2 igrad1, vec2 egrad0, vec2 egrad1 ) // quintic hermite with start/end position and acceleration of 0.0
{
const vec3 C0 = vec3( -15.0, 8.0, 7.0 );
const vec3 C1 = vec3( 6.0, -3.0, -3.0 );
const vec3 C2 = vec3( 10.0, -6.0, -4.0 );
vec3 h123 = ( ( ( C0 + C1 * x ) * x ) + C2 ) * ( x*x*x );
return vec4( egrad1, igrad0 ) * vec4( h123.zz, 1.0, 1.0 ) + vec4( egrad0, h123.xx ) * vec4( vec2( h123.y + x ), (igrad1 - igrad0) ); // returns vec4( out_ival.xy, out_igrad.xy )
}
void QuinticHermite( float x,
vec4 ival0, vec4 ival1, // values are interpolated using the gradient arguments
vec4 igrad_x0, vec4 igrad_x1, // gradients are interpolated using eval gradients of 0.0
vec4 igrad_y0, vec4 igrad_y1,
vec4 egrad0, vec4 egrad1, // our evaluation gradients
out vec4 out_ival, out vec4 out_igrad_x, out vec4 out_igrad_y ) // quintic hermite with start/end acceleration of 0.0
{
const vec3 C0 = vec3( -15.0, 8.0, 7.0 );
const vec3 C1 = vec3( 6.0, -3.0, -3.0 );
const vec3 C2 = vec3( 10.0, -6.0, -4.0 );
vec3 h123 = ( ( ( C0 + C1 * x ) * x ) + C2 ) * ( x*x*x );
out_ival = ival0 + (ival1 - ival0) * h123.xxxx + egrad0 * vec4( h123.y + x ) + egrad1 * h123.zzzz;
out_igrad_x = igrad_x0 + (igrad_x1 - igrad_x0) * h123.xxxx; // NOTE: gradients of 0.0
out_igrad_y = igrad_y0 + (igrad_y1 - igrad_y0) * h123.xxxx; // NOTE: gradients of 0.0
}
void QuinticHermite( float x,
vec4 igrad_x0, vec4 igrad_x1, // gradients are interpolated using eval gradients of 0.0
vec4 igrad_y0, vec4 igrad_y1,
vec4 egrad0, vec4 egrad1, // our evaluation gradients
out vec4 out_ival, out vec4 out_igrad_x, out vec4 out_igrad_y ) // quintic hermite with start/end position and acceleration of 0.0
{
const vec3 C0 = vec3( -15.0, 8.0, 7.0 );
const vec3 C1 = vec3( 6.0, -3.0, -3.0 );
const vec3 C2 = vec3( 10.0, -6.0, -4.0 );
vec3 h123 = ( ( ( C0 + C1 * x ) * x ) + C2 ) * ( x*x*x );
out_ival = egrad0 * vec4( h123.y + x ) + egrad1 * h123.zzzz;
out_igrad_x = igrad_x0 + (igrad_x1 - igrad_x0) * h123.xxxx; // NOTE: gradients of 0.0
out_igrad_y = igrad_y0 + (igrad_y1 - igrad_y0) * h123.xxxx; // NOTE: gradients of 0.0
}
float QuinticHermiteDeriv( float x, float ival0, float ival1, float egrad0, float egrad1 ) // gives the derivative of quintic hermite with start/end acceleration of 0.0
{
const vec3 C0 = vec3( 30.0, -15.0, -15.0 );
const vec3 C1 = vec3( -60.0, 32.0, 28.0 );
const vec3 C2 = vec3( 30.0, -18.0, -12.0 );
vec3 h123 = ( ( ( C1 + C0 * x ) * x ) + C2 ) * ( x*x );
return dot( vec3( (ival1 - ival0), egrad0, egrad1 ), h123.xyz + vec3( 0.0, 1.0, 0.0 ) );
}
//
// Hermite3D
// Return value range of -1.0->1.0
// http://briansharpe.files.wordpress.com/2012/01/hermitesample.jpg
//
float Hermite3D( vec3 P )
{
// establish our grid cell and unit position
vec3 Pi = floor(P);
vec3 Pf = P - Pi;
// calculate the hash.
// ( various hashing methods listed in order of speed )
vec4 hash_gradx0, hash_grady0, hash_gradz0, hash_gradx1, hash_grady1, hash_gradz1;
FAST32_hash_3D( Pi, hash_gradx0, hash_grady0, hash_gradz0, hash_gradx1, hash_grady1, hash_gradz1 );
// scale the hash values
hash_gradx0 = ( hash_gradx0 - 0.49999);
hash_grady0 = ( hash_grady0 - 0.49999);
hash_gradz0 = ( hash_gradz0 - 0.49999);
hash_gradx1 = ( hash_gradx1 - 0.49999);
hash_grady1 = ( hash_grady1 - 0.49999);
hash_gradz1 = ( hash_gradz1 - 0.49999);
#if 1
// normalize gradients
vec4 norm0 = inversesqrt( hash_gradx0 * hash_gradx0 + hash_grady0 * hash_grady0 + hash_gradz0 * hash_gradz0 );
hash_gradx0 *= norm0;
hash_grady0 *= norm0;
hash_gradz0 *= norm0;
vec4 norm1 = inversesqrt( hash_gradx1 * hash_gradx1 + hash_grady1 * hash_grady1 + hash_gradz1 * hash_gradz1 );
hash_gradx1 *= norm1;
hash_grady1 *= norm1;
hash_gradz1 *= norm1;
const float FINAL_NORM_VAL = 1.8475208614068024464292760976063;
#else
// unnormalized gradients
const float FINAL_NORM_VAL = (1.0/0.46875); // = 1.0 / ( 0.5 * 0.3125 * 3.0 )
#endif
// evaluate the hermite
vec4 ival_results, igrad_results_x, igrad_results_y;
QuinticHermite( Pf.z, hash_gradx0, hash_gradx1, hash_grady0, hash_grady1, hash_gradz0, hash_gradz1, ival_results, igrad_results_x, igrad_results_y );
vec4 qh_results = QuinticHermite( Pf.y, vec4(ival_results.xy, igrad_results_x.xy), vec4(ival_results.zw, igrad_results_x.zw), vec4( igrad_results_y.xy, 0.0, 0.0 ), vec4( igrad_results_y.zw, 0.0, 0.0 ) );
return QuinticHermite( Pf.x, qh_results.x, qh_results.y, qh_results.z, qh_results.w ) * FINAL_NORM_VAL;
}
float billow(vec3 p, int powered, float billowPower)
{
// Powered Billow
if(powered > 0)
{
return pow(abs(4.0*Hermite3D(p)), billowPower);
}
else
{
return abs(4.0*Hermite3D(p));
}
}
//
// 3D fractional Brownian Motion
//
float fBM(vec3 p, vec3 offset, float frequency, float amplitude, float lacunarity, float persistence, int powered, float billowPower)
{
float sum = 0.0;
float bias = 0.0;
for (int i = 0; i < OCTAVES; i++)
{
float h = 0.5 * (1.0 + billow((p+offset)*frequency, powered, billowPower));
sum += h*amplitude;
bias -= amplitude;
frequency *= lacunarity;
amplitude *= persistence;
}
sum += 0.5 * bias;
return sum;
}
#define gl_ModelViewProjectionMatrix glstate_matrix_mvp
uniform mat4 glstate_matrix_mvp;
#define gl_Vertex _glesVertex
attribute vec4 _glesVertex;
#define gl_MultiTexCoord0 _glesMultiTexCoord0
attribute vec4 _glesMultiTexCoord0;
uniform float _Displace;
varying vec4 position;
varying vec2 texCoord;
void main()
{
position = gl_Vertex;
if(_Displace > 0.0)
{
position.y = fBM(vec3(position.xz, _Time*_AnimSpeed), _NoiseOffset, _Frequency, _Amplitude, _Lacunarity, _Persistence, _Powered, _BillowPower);
}
gl_Position = gl_ModelViewProjectionMatrix * position;
texCoord = gl_MultiTexCoord0.xy;
}
Fragment Shader:
precision mediump float;
#define SHADER_API_GLES 1
#define tex2D texture2D
#line 37
precision mediump float;
const int OCTAVES = 12;
uniform vec4 _Time;
uniform float _Frequency;
uniform float _Amplitude;
uniform vec3 _NoiseOffset;
uniform float _Contribution;
uniform float _Normalize;
uniform float _AnimSpeed;
uniform float _Lacunarity;
uniform float _Persistence;
uniform int _Powered;
uniform float _BillowPower;
//
// FAST32_hash
// A very fast hashing function. Requires 32bit support.
// http://briansharpe.wordpress.com/2011/11/15/a-fast-and-simple-32bit-floating-point-hash-function/
//
// The hash formula takes the form....
// hash = mod( coord.x * coord.x * coord.y * coord.y, SOMELARGEFLOAT ) / SOMELARGEFLOAT
// We truncate and offset the domain to the most interesting part of the noise.
// SOMELARGEFLOAT should be in the range of 400.0->1000.0 and needs to be hand picked. Only some give good results.
// 3D Noise is achieved by offsetting the SOMELARGEFLOAT value by the Z coordinate
//
void FAST32_hash_3D( vec3 gridcell,
out vec4 lowz_hash_0,
out vec4 lowz_hash_1,
out vec4 lowz_hash_2,
out vec4 highz_hash_0,
out vec4 highz_hash_1,
out vec4 highz_hash_2 ) // generates 3 random numbers for each of the 8 cell corners
{
// gridcell is assumed to be an integer coordinate
// TODO: these constants need tweaked to find the best possible noise.
// probably requires some kind of brute force computational searching or something....
const vec2 OFFSET = vec2( 50.0, 161.0 );
const float DOMAIN = 69.0;
const vec3 SOMELARGEFLOATS = vec3( 635.298681, 682.357502, 668.926525 );
const vec3 ZINC = vec3( 48.500388, 65.294118, 63.934599 );
// truncate the domain
gridcell.xyz = gridcell.xyz - floor(gridcell.xyz * ( 1.0 / DOMAIN )) * DOMAIN;
vec3 gridcell_inc1 = step( gridcell, vec3( DOMAIN - 1.5 ) ) * ( gridcell + 1.0 );
// calculate the noise
vec4 P = vec4( gridcell.xy, gridcell_inc1.xy ) + OFFSET.xyxy;
P *= P;
P = P.xzxz * P.yyww;
vec3 lowz_mod = vec3( 1.0 / ( SOMELARGEFLOATS.xyz + gridcell.zzz * ZINC.xyz ) );
vec3 highz_mod = vec3( 1.0 / ( SOMELARGEFLOATS.xyz + gridcell_inc1.zzz * ZINC.xyz ) );
lowz_hash_0 = fract( P * lowz_mod.xxxx );
highz_hash_0 = fract( P * highz_mod.xxxx );
lowz_hash_1 = fract( P * lowz_mod.yyyy );
highz_hash_1 = fract( P * highz_mod.yyyy );
lowz_hash_2 = fract( P * lowz_mod.zzzz );
highz_hash_2 = fract( P * highz_mod.zzzz );
}
//
// Quintic Hermite Interpolation
// http://www.rose-hulman.edu/~finn/CCLI/Notes/day09.pdf
//
// NOTE: maximum value of a hermitequintic interpolation with zero acceleration at the endpoints would be...
// f(x=0.5) = MAXPOS + MAXVELOCITY * ( ( x - 6x^3 + 8x^4 - 3x^5 ) - ( -4x^3 + 7x^4 -3x^5 ) ) = MAXPOS + MAXVELOCITY * 0.3125
//
// variable naming conventions:
// val = value ( position )
// grad = gradient ( velocity )
// x = 0.0->1.0 ( time )
// i = interpolation = a value to be interpolated
// e = evaluation = a value to be used to calculate the interpolation
// 0 = start
// 1 = end
//
float QuinticHermite( float x, float ival0, float ival1, float egrad0, float egrad1 ) // quintic hermite with start/end acceleration of 0.0
{
const vec3 C0 = vec3( -15.0, 8.0, 7.0 );
const vec3 C1 = vec3( 6.0, -3.0, -3.0 );
const vec3 C2 = vec3( 10.0, -6.0, -4.0 );
vec3 h123 = ( ( ( C0 + C1 * x ) * x ) + C2 ) * ( x*x*x );
return ival0 + dot( vec3( (ival1 - ival0), egrad0, egrad1 ), h123.xyz + vec3( 0.0, x, 0.0 ) );
}
vec4 QuinticHermite( float x, vec4 ival0, vec4 ival1, vec4 egrad0, vec4 egrad1 ) // quintic hermite with start/end acceleration of 0.0
{
const vec3 C0 = vec3( -15.0, 8.0, 7.0 );
const vec3 C1 = vec3( 6.0, -3.0, -3.0 );
const vec3 C2 = vec3( 10.0, -6.0, -4.0 );
vec3 h123 = ( ( ( C0 + C1 * x ) * x ) + C2 ) * ( x*x*x );
return ival0 + (ival1 - ival0) * h123.xxxx + egrad0 * vec4( h123.y + x ) + egrad1 * h123.zzzz;
}
vec4 QuinticHermite( float x, vec2 igrad0, vec2 igrad1, vec2 egrad0, vec2 egrad1 ) // quintic hermite with start/end position and acceleration of 0.0
{
const vec3 C0 = vec3( -15.0, 8.0, 7.0 );
const vec3 C1 = vec3( 6.0, -3.0, -3.0 );
const vec3 C2 = vec3( 10.0, -6.0, -4.0 );
vec3 h123 = ( ( ( C0 + C1 * x ) * x ) + C2 ) * ( x*x*x );
return vec4( egrad1, igrad0 ) * vec4( h123.zz, 1.0, 1.0 ) + vec4( egrad0, h123.xx ) * vec4( vec2( h123.y + x ), (igrad1 - igrad0) ); // returns vec4( out_ival.xy, out_igrad.xy )
}
void QuinticHermite( float x,
vec4 ival0, vec4 ival1, // values are interpolated using the gradient arguments
vec4 igrad_x0, vec4 igrad_x1, // gradients are interpolated using eval gradients of 0.0
vec4 igrad_y0, vec4 igrad_y1,
vec4 egrad0, vec4 egrad1, // our evaluation gradients
out vec4 out_ival, out vec4 out_igrad_x, out vec4 out_igrad_y ) // quintic hermite with start/end acceleration of 0.0
{
const vec3 C0 = vec3( -15.0, 8.0, 7.0 );
const vec3 C1 = vec3( 6.0, -3.0, -3.0 );
const vec3 C2 = vec3( 10.0, -6.0, -4.0 );
vec3 h123 = ( ( ( C0 + C1 * x ) * x ) + C2 ) * ( x*x*x );
out_ival = ival0 + (ival1 - ival0) * h123.xxxx + egrad0 * vec4( h123.y + x ) + egrad1 * h123.zzzz;
out_igrad_x = igrad_x0 + (igrad_x1 - igrad_x0) * h123.xxxx; // NOTE: gradients of 0.0
out_igrad_y = igrad_y0 + (igrad_y1 - igrad_y0) * h123.xxxx; // NOTE: gradients of 0.0
}
void QuinticHermite( float x,
vec4 igrad_x0, vec4 igrad_x1, // gradients are interpolated using eval gradients of 0.0
vec4 igrad_y0, vec4 igrad_y1,
vec4 egrad0, vec4 egrad1, // our evaluation gradients
out vec4 out_ival, out vec4 out_igrad_x, out vec4 out_igrad_y ) // quintic hermite with start/end position and acceleration of 0.0
{
const vec3 C0 = vec3( -15.0, 8.0, 7.0 );
const vec3 C1 = vec3( 6.0, -3.0, -3.0 );
const vec3 C2 = vec3( 10.0, -6.0, -4.0 );
vec3 h123 = ( ( ( C0 + C1 * x ) * x ) + C2 ) * ( x*x*x );
out_ival = egrad0 * vec4( h123.y + x ) + egrad1 * h123.zzzz;
out_igrad_x = igrad_x0 + (igrad_x1 - igrad_x0) * h123.xxxx; // NOTE: gradients of 0.0
out_igrad_y = igrad_y0 + (igrad_y1 - igrad_y0) * h123.xxxx; // NOTE: gradients of 0.0
}
float QuinticHermiteDeriv( float x, float ival0, float ival1, float egrad0, float egrad1 ) // gives the derivative of quintic hermite with start/end acceleration of 0.0
{
const vec3 C0 = vec3( 30.0, -15.0, -15.0 );
const vec3 C1 = vec3( -60.0, 32.0, 28.0 );
const vec3 C2 = vec3( 30.0, -18.0, -12.0 );
vec3 h123 = ( ( ( C1 + C0 * x ) * x ) + C2 ) * ( x*x );
return dot( vec3( (ival1 - ival0), egrad0, egrad1 ), h123.xyz + vec3( 0.0, 1.0, 0.0 ) );
}
//
// Hermite3D
// Return value range of -1.0->1.0
// http://briansharpe.files.wordpress.com/2012/01/hermitesample.jpg
//
float Hermite3D( vec3 P )
{
// establish our grid cell and unit position
vec3 Pi = floor(P);
vec3 Pf = P - Pi;
// calculate the hash.
// ( various hashing methods listed in order of speed )
vec4 hash_gradx0, hash_grady0, hash_gradz0, hash_gradx1, hash_grady1, hash_gradz1;
FAST32_hash_3D( Pi, hash_gradx0, hash_grady0, hash_gradz0, hash_gradx1, hash_grady1, hash_gradz1 );
// scale the hash values
hash_gradx0 = ( hash_gradx0 - 0.49999);
hash_grady0 = ( hash_grady0 - 0.49999);
hash_gradz0 = ( hash_gradz0 - 0.49999);
hash_gradx1 = ( hash_gradx1 - 0.49999);
hash_grady1 = ( hash_grady1 - 0.49999);
hash_gradz1 = ( hash_gradz1 - 0.49999);
#if 1
// normalize gradients
vec4 norm0 = inversesqrt( hash_gradx0 * hash_gradx0 + hash_grady0 * hash_grady0 + hash_gradz0 * hash_gradz0 );
hash_gradx0 *= norm0;
hash_grady0 *= norm0;
hash_gradz0 *= norm0;
vec4 norm1 = inversesqrt( hash_gradx1 * hash_gradx1 + hash_grady1 * hash_grady1 + hash_gradz1 * hash_gradz1 );
hash_gradx1 *= norm1;
hash_grady1 *= norm1;
hash_gradz1 *= norm1;
const float FINAL_NORM_VAL = 1.8475208614068024464292760976063;
#else
// unnormalized gradients
const float FINAL_NORM_VAL = (1.0/0.46875); // = 1.0 / ( 0.5 * 0.3125 * 3.0 )
#endif
// evaluate the hermite
vec4 ival_results, igrad_results_x, igrad_results_y;
QuinticHermite( Pf.z, hash_gradx0, hash_gradx1, hash_grady0, hash_grady1, hash_gradz0, hash_gradz1, ival_results, igrad_results_x, igrad_results_y );
vec4 qh_results = QuinticHermite( Pf.y, vec4(ival_results.xy, igrad_results_x.xy), vec4(ival_results.zw, igrad_results_x.zw), vec4( igrad_results_y.xy, 0.0, 0.0 ), vec4( igrad_results_y.zw, 0.0, 0.0 ) );
return QuinticHermite( Pf.x, qh_results.x, qh_results.y, qh_results.z, qh_results.w ) * FINAL_NORM_VAL;
}
float billow(vec3 p, int powered, float billowPower)
{
// Powered Billow
if(powered > 0)
{
return pow(abs(4.0*Hermite3D(p)), billowPower);
}
else
{
return abs(4.0*Hermite3D(p));
}
}
//
// 3D fractional Brownian Motion
//
float fBM(vec3 p, vec3 offset, float frequency, float amplitude, float lacunarity, float persistence, int powered, float billowPower)
{
float sum = 0.0;
float bias = 0.0;
for (int i = 0; i < OCTAVES; i++)
{
float h = 0.5 * (1.0 + billow((p+offset)*frequency, powered, billowPower));
sum += h*amplitude;
bias -= amplitude;
frequency *= lacunarity;
amplitude *= persistence;
}
sum += 0.5 * bias;
return sum;
}
uniform vec4 _LowColor;
uniform vec4 _HighColor;
uniform float _Texturing;
uniform sampler2D _LowTexture;
uniform vec4 _LowTexture_ST;
uniform sampler2D _HighTexture;
uniform vec4 _HighTexture_ST;
varying vec4 position;
varying vec2 texCoord;
void main()
{
float h = fBM(vec3(vec2(position.xz), _Time*_AnimSpeed), _NoiseOffset, _Frequency, _Amplitude, _Lacunarity, _Persistence, _Powered, _BillowPower);
if(_Normalize > 0.0)
{
// set range to (0, 1)
h = h*0.5 + 0.5;
}
// do the accumulation with the previous fixed-point height
h = h*_Contribution;
vec4 color;
if(_Texturing > 0.0)
{
color = mix(_LowColor * texture2D(_LowTexture, _LowTexture_ST.xy * texCoord + _LowTexture_ST.zw), _HighColor * texture2D(_HighTexture, _HighTexture_ST.xy * texCoord + _HighTexture_ST.zw), h);
}
else
{
color = mix(_LowColor, _HighColor, h);
}
gl_FragColor = vec4(color.r, color.g, color.b, h);
}
-------- GLSL error: ERROR: Uniform precision mismatch '_Powered'
Vertex Shader:
#define SHADER_API_GLES 1
#define tex2D texture2D
#line 37
precision mediump float;
const int OCTAVES = 12;
uniform vec4 _Time;
uniform float _Frequency;
uniform float _Amplitude;
uniform vec3 _NoiseOffset;
uniform float _Contribution;
uniform float _Normalize;
uniform float _AnimSpeed;
uniform float _Lacunarity;
uniform float _Persistence;
uniform int _Powered;
uniform float _RidgePower;
uniform float _RidgeOffset;
//
// FAST32_hash
// A very fast hashing function. Requires 32bit support.
// http://briansharpe.wordpress.com/2011/11/15/a-fast-and-simple-32bit-floating-point-hash-function/
//
// The hash formula takes the form....
// hash = mod( coord.x * coord.x * coord.y * coord.y, SOMELARGEFLOAT ) / SOMELARGEFLOAT
// We truncate and offset the domain to the most interesting part of the noise.
// SOMELARGEFLOAT should be in the range of 400.0->1000.0 and needs to be hand picked. Only some give good results.
// 3D Noise is achieved by offsetting the SOMELARGEFLOAT value by the Z coordinate
//
void FAST32_hash_3D( vec3 gridcell,
out vec4 lowz_hash_0,
out vec4 lowz_hash_1,
out vec4 lowz_hash_2,
out vec4 highz_hash_0,
out vec4 highz_hash_1,
out vec4 highz_hash_2 ) // generates 3 random numbers for each of the 8 cell corners
{
// gridcell is assumed to be an integer coordinate
// TODO: these constants need tweaked to find the best possible noise.
// probably requires some kind of brute force computational searching or something....
const vec2 OFFSET = vec2( 50.0, 161.0 );
const float DOMAIN = 69.0;
const vec3 SOMELARGEFLOATS = vec3( 635.298681, 682.357502, 668.926525 );
const vec3 ZINC = vec3( 48.500388, 65.294118, 63.934599 );
// truncate the domain
gridcell.xyz = gridcell.xyz - floor(gridcell.xyz * ( 1.0 / DOMAIN )) * DOMAIN;
vec3 gridcell_inc1 = step( gridcell, vec3( DOMAIN - 1.5 ) ) * ( gridcell + 1.0 );
// calculate the noise
vec4 P = vec4( gridcell.xy, gridcell_inc1.xy ) + OFFSET.xyxy;
P *= P;
P = P.xzxz * P.yyww;
vec3 lowz_mod = vec3( 1.0 / ( SOMELARGEFLOATS.xyz + gridcell.zzz * ZINC.xyz ) );
vec3 highz_mod = vec3( 1.0 / ( SOMELARGEFLOATS.xyz + gridcell_inc1.zzz * ZINC.xyz ) );
lowz_hash_0 = fract( P * lowz_mod.xxxx );
highz_hash_0 = fract( P * highz_mod.xxxx );
lowz_hash_1 = fract( P * lowz_mod.yyyy );
highz_hash_1 = fract( P * highz_mod.yyyy );
lowz_hash_2 = fract( P * lowz_mod.zzzz );
highz_hash_2 = fract( P * highz_mod.zzzz );
}
vec3 Interpolation_C2( vec3 x )
{
return x * x * x * (x * (x * 6.0 - 15.0) + 10.0);
}
//
// Perlin Noise 3D ( gradient noise )
// Return value range of -1.0->1.0
// http://briansharpe.files.wordpress.com/2011/11/perlinsample.jpg
//
float Perlin3D( vec3 P )
{
// establish our grid cell and unit position
vec3 Pi = floor(P);
vec3 Pf = P - Pi;
vec3 Pf_min1 = Pf - 1.0;
#if 1
//
// classic noise.
// requires 3 random values per point. with an efficent hash function will run faster than improved noise
//
// calculate the hash.
// ( various hashing methods listed in order of speed )
vec4 hashx0, hashy0, hashz0, hashx1, hashy1, hashz1;
FAST32_hash_3D( Pi, hashx0, hashy0, hashz0, hashx1, hashy1, hashz1 );
//SGPP_hash_3D( Pi, hashx0, hashy0, hashz0, hashx1, hashy1, hashz1 );
// calculate the gradients
vec4 grad_x0 = hashx0 - 0.49999;
vec4 grad_y0 = hashy0 - 0.49999;
vec4 grad_z0 = hashz0 - 0.49999;
vec4 grad_x1 = hashx1 - 0.49999;
vec4 grad_y1 = hashy1 - 0.49999;
vec4 grad_z1 = hashz1 - 0.49999;
vec4 grad_results_0 = inversesqrt( grad_x0 * grad_x0 + grad_y0 * grad_y0 + grad_z0 * grad_z0 ) * ( vec2( Pf.x, Pf_min1.x ).xyxy * grad_x0 + vec2( Pf.y, Pf_min1.y ).xxyy * grad_y0 + Pf.zzzz * grad_z0 );
vec4 grad_results_1 = inversesqrt( grad_x1 * grad_x1 + grad_y1 * grad_y1 + grad_z1 * grad_z1 ) * ( vec2( Pf.x, Pf_min1.x ).xyxy * grad_x1 + vec2( Pf.y, Pf_min1.y ).xxyy * grad_y1 + Pf_min1.zzzz * grad_z1 );
#if 1
// Classic Perlin Interpolation
vec3 blend = Interpolation_C2( Pf );
vec4 res0 = mix( grad_results_0, grad_results_1, blend.z );
vec2 res1 = mix( res0.xy, res0.zw, blend.y );
float final = mix( res1.x, res1.y, blend.x );
final *= 1.1547005383792515290182975610039; // (optionally) scale things to a strict -1.0->1.0 range *= 1.0/sqrt(0.75)
return final;
#else
// Classic Perlin Surflet
// http://briansharpe.wordpress.com/2012/03/09/modifications-to-classic-perlin-noise/
Pf *= Pf;
Pf_min1 *= Pf_min1;
vec4 vecs_len_sq = vec4( Pf.x, Pf_min1.x, Pf.x, Pf_min1.x ) + vec4( Pf.yy, Pf_min1.yy );
float final = dot( Falloff_Xsq_C2( min( vec4( 1.0 ), vecs_len_sq + Pf.zzzz ) ), grad_results_0 ) + dot( Falloff_Xsq_C2( min( vec4( 1.0 ), vecs_len_sq + Pf_min1.zzzz ) ), grad_results_1 );
final *= 2.3703703703703703703703703703704; // (optionally) scale things to a strict -1.0->1.0 range *= 1.0/cube(0.75)
return final;
#endif
#else
//
// improved noise.
// requires 1 random value per point. Will run faster than classic noise if a slow hashing function is used
//
// calculate the hash.
// ( various hashing methods listed in order of speed )
vec4 hash_lowz, hash_highz;
FAST32_hash_3D( Pi, hash_lowz, hash_highz );
//BBS_hash_3D( Pi, hash_lowz, hash_highz );
//SGPP_hash_3D( Pi, hash_lowz, hash_highz );
//
// 'improved' noise using 8 corner gradients. Faster than the 12 mid-edge point method.
// Ken mentions using diagonals like this can cause 'clumping', but we'll live with that.
// [1,1,1] [-1,1,1] [1,-1,1] [-1,-1,1]
// [1,1,-1] [-1,1,-1] [1,-1,-1] [-1,-1,-1]
//
hash_lowz -= 0.5;
vec4 grad_results_0_0 = vec2( Pf.x, Pf_min1.x ).xyxy * sign( hash_lowz );
hash_lowz = abs( hash_lowz ) - 0.25;
vec4 grad_results_0_1 = vec2( Pf.y, Pf_min1.y ).xxyy * sign( hash_lowz );
vec4 grad_results_0_2 = Pf.zzzz * sign( abs( hash_lowz ) - 0.125 );
vec4 grad_results_0 = grad_results_0_0 + grad_results_0_1 + grad_results_0_2;
hash_highz -= 0.5;
vec4 grad_results_1_0 = vec2( Pf.x, Pf_min1.x ).xyxy * sign( hash_highz );
hash_highz = abs( hash_highz ) - 0.25;
vec4 grad_results_1_1 = vec2( Pf.y, Pf_min1.y ).xxyy * sign( hash_highz );
vec4 grad_results_1_2 = Pf_min1.zzzz * sign( abs( hash_highz ) - 0.125 );
vec4 grad_results_1 = grad_results_1_0 + grad_results_1_1 + grad_results_1_2;
// blend the gradients and return
vec3 blend = Interpolation_C2( Pf );
vec4 res0 = mix( grad_results_0, grad_results_1, blend.z );
vec2 res1 = mix( res0.xy, res0.zw, blend.y );
return mix( res1.x, res1.y, blend.x ) * (2.0 / 3.0); // (optionally) mult by (2.0/3.0) to scale to a strict -1.0->1.0 range
#endif
}
float ridge(vec3 p, int powered, float ridgePower, float offset)
{
// Powered Ridge
if(powered > 0)
{
return pow(offset - abs(4.0*Perlin3D(p)), ridgePower);
}
else
{
return offset - abs(4.0*Perlin3D(p));
}
}
//
// 3D fractional Brownian Motion
//
float fBM(vec3 p, vec3 offset, float frequency, float amplitude, float lacunarity, float persistence, int powered, float ridgePower, float ridgeOffset)
{
float sum = 0.0;
float bias = 0.0;
for (int i = 0; i < OCTAVES; i++)
{
float h = 0.5 * (1.0 + ridge((p+offset*amplitude)*frequency, powered, ridgePower, ridgeOffset));
sum += h*amplitude;
bias -= amplitude;
frequency *= lacunarity;
amplitude *= persistence;
}
sum += 0.5 * bias;
return sum;
}
#define gl_ModelViewProjectionMatrix glstate_matrix_mvp
uniform mat4 glstate_matrix_mvp;
#define gl_Vertex _glesVertex
attribute vec4 _glesVertex;
#define gl_MultiTexCoord0 _glesMultiTexCoord0
attribute vec4 _glesMultiTexCoord0;
uniform float _Displace;
varying vec4 position;
varying vec2 texCoord;
void main()
{
position = gl_Vertex;
if(_Displace > 0.0)
{
position.y = fBM(vec3(position.xz, _Time*_AnimSpeed), _NoiseOffset, _Frequency, _Amplitude, _Lacunarity, _Persistence, _Powered, _RidgePower, _RidgeOffset);
}
gl_Position = gl_ModelViewProjectionMatrix * position;
texCoord = gl_MultiTexCoord0.xy;
}
Fragment Shader:
precision mediump float;
#define SHADER_API_GLES 1
#define tex2D texture2D
#line 37
precision mediump float;
const int OCTAVES = 12;
uniform vec4 _Time;
uniform float _Frequency;
uniform float _Amplitude;
uniform vec3 _NoiseOffset;
uniform float _Contribution;
uniform float _Normalize;
uniform float _AnimSpeed;
uniform float _Lacunarity;
uniform float _Persistence;
uniform int _Powered;
uniform float _RidgePower;
uniform float _RidgeOffset;
//
// FAST32_hash
// A very fast hashing function. Requires 32bit support.
// http://briansharpe.wordpress.com/2011/11/15/a-fast-and-simple-32bit-floating-point-hash-function/
//
// The hash formula takes the form....
// hash = mod( coord.x * coord.x * coord.y * coord.y, SOMELARGEFLOAT ) / SOMELARGEFLOAT
// We truncate and offset the domain to the most interesting part of the noise.
// SOMELARGEFLOAT should be in the range of 400.0->1000.0 and needs to be hand picked. Only some give good results.
// 3D Noise is achieved by offsetting the SOMELARGEFLOAT value by the Z coordinate
//
void FAST32_hash_3D( vec3 gridcell,
out vec4 lowz_hash_0,
out vec4 lowz_hash_1,
out vec4 lowz_hash_2,
out vec4 highz_hash_0,
out vec4 highz_hash_1,
out vec4 highz_hash_2 ) // generates 3 random numbers for each of the 8 cell corners
{
// gridcell is assumed to be an integer coordinate
// TODO: these constants need tweaked to find the best possible noise.
// probably requires some kind of brute force computational searching or something....
const vec2 OFFSET = vec2( 50.0, 161.0 );
const float DOMAIN = 69.0;
const vec3 SOMELARGEFLOATS = vec3( 635.298681, 682.357502, 668.926525 );
const vec3 ZINC = vec3( 48.500388, 65.294118, 63.934599 );
// truncate the domain
gridcell.xyz = gridcell.xyz - floor(gridcell.xyz * ( 1.0 / DOMAIN )) * DOMAIN;
vec3 gridcell_inc1 = step( gridcell, vec3( DOMAIN - 1.5 ) ) * ( gridcell + 1.0 );
// calculate the noise
vec4 P = vec4( gridcell.xy, gridcell_inc1.xy ) + OFFSET.xyxy;
P *= P;
P = P.xzxz * P.yyww;
vec3 lowz_mod = vec3( 1.0 / ( SOMELARGEFLOATS.xyz + gridcell.zzz * ZINC.xyz ) );
vec3 highz_mod = vec3( 1.0 / ( SOMELARGEFLOATS.xyz + gridcell_inc1.zzz * ZINC.xyz ) );
lowz_hash_0 = fract( P * lowz_mod.xxxx );
highz_hash_0 = fract( P * highz_mod.xxxx );
lowz_hash_1 = fract( P * lowz_mod.yyyy );
highz_hash_1 = fract( P * highz_mod.yyyy );
lowz_hash_2 = fract( P * lowz_mod.zzzz );
highz_hash_2 = fract( P * highz_mod.zzzz );
}
vec3 Interpolation_C2( vec3 x )
{
return x * x * x * (x * (x * 6.0 - 15.0) + 10.0);
}
//
// Perlin Noise 3D ( gradient noise )
// Return value range of -1.0->1.0
// http://briansharpe.files.wordpress.com/2011/11/perlinsample.jpg
//
float Perlin3D( vec3 P )
{
// establish our grid cell and unit position
vec3 Pi = floor(P);
vec3 Pf = P - Pi;
vec3 Pf_min1 = Pf - 1.0;
#if 1
//
// classic noise.
// requires 3 random values per point. with an efficent hash function will run faster than improved noise
//
// calculate the hash.
// ( various hashing methods listed in order of speed )
vec4 hashx0, hashy0, hashz0, hashx1, hashy1, hashz1;
FAST32_hash_3D( Pi, hashx0, hashy0, hashz0, hashx1, hashy1, hashz1 );
//SGPP_hash_3D( Pi, hashx0, hashy0, hashz0, hashx1, hashy1, hashz1 );
// calculate the gradients
vec4 grad_x0 = hashx0 - 0.49999;
vec4 grad_y0 = hashy0 - 0.49999;
vec4 grad_z0 = hashz0 - 0.49999;
vec4 grad_x1 = hashx1 - 0.49999;
vec4 grad_y1 = hashy1 - 0.49999;
vec4 grad_z1 = hashz1 - 0.49999;
vec4 grad_results_0 = inversesqrt( grad_x0 * grad_x0 + grad_y0 * grad_y0 + grad_z0 * grad_z0 ) * ( vec2( Pf.x, Pf_min1.x ).xyxy * grad_x0 + vec2( Pf.y, Pf_min1.y ).xxyy * grad_y0 + Pf.zzzz * grad_z0 );
vec4 grad_results_1 = inversesqrt( grad_x1 * grad_x1 + grad_y1 * grad_y1 + grad_z1 * grad_z1 ) * ( vec2( Pf.x, Pf_min1.x ).xyxy * grad_x1 + vec2( Pf.y, Pf_min1.y ).xxyy * grad_y1 + Pf_min1.zzzz * grad_z1 );
#if 1
// Classic Perlin Interpolation
vec3 blend = Interpolation_C2( Pf );
vec4 res0 = mix( grad_results_0, grad_results_1, blend.z );
vec2 res1 = mix( res0.xy, res0.zw, blend.y );
float final = mix( res1.x, res1.y, blend.x );
final *= 1.1547005383792515290182975610039; // (optionally) scale things to a strict -1.0->1.0 range *= 1.0/sqrt(0.75)
return final;
#else
// Classic Perlin Surflet
// http://briansharpe.wordpress.com/2012/03/09/modifications-to-classic-perlin-noise/
Pf *= Pf;
Pf_min1 *= Pf_min1;
vec4 vecs_len_sq = vec4( Pf.x, Pf_min1.x, Pf.x, Pf_min1.x ) + vec4( Pf.yy, Pf_min1.yy );
float final = dot( Falloff_Xsq_C2( min( vec4( 1.0 ), vecs_len_sq + Pf.zzzz ) ), grad_results_0 ) + dot( Falloff_Xsq_C2( min( vec4( 1.0 ), vecs_len_sq + Pf_min1.zzzz ) ), grad_results_1 );
final *= 2.3703703703703703703703703703704; // (optionally) scale things to a strict -1.0->1.0 range *= 1.0/cube(0.75)
return final;
#endif
#else
//
// improved noise.
// requires 1 random value per point. Will run faster than classic noise if a slow hashing function is used
//
// calculate the hash.
// ( various hashing methods listed in order of speed )
vec4 hash_lowz, hash_highz;
FAST32_hash_3D( Pi, hash_lowz, hash_highz );
//BBS_hash_3D( Pi, hash_lowz, hash_highz );
//SGPP_hash_3D( Pi, hash_lowz, hash_highz );
//
// 'improved' noise using 8 corner gradients. Faster than the 12 mid-edge point method.
// Ken mentions using diagonals like this can cause 'clumping', but we'll live with that.
// [1,1,1] [-1,1,1] [1,-1,1] [-1,-1,1]
// [1,1,-1] [-1,1,-1] [1,-1,-1] [-1,-1,-1]
//
hash_lowz -= 0.5;
vec4 grad_results_0_0 = vec2( Pf.x, Pf_min1.x ).xyxy * sign( hash_lowz );
hash_lowz = abs( hash_lowz ) - 0.25;
vec4 grad_results_0_1 = vec2( Pf.y, Pf_min1.y ).xxyy * sign( hash_lowz );
vec4 grad_results_0_2 = Pf.zzzz * sign( abs( hash_lowz ) - 0.125 );
vec4 grad_results_0 = grad_results_0_0 + grad_results_0_1 + grad_results_0_2;
hash_highz -= 0.5;
vec4 grad_results_1_0 = vec2( Pf.x, Pf_min1.x ).xyxy * sign( hash_highz );
hash_highz = abs( hash_highz ) - 0.25;
vec4 grad_results_1_1 = vec2( Pf.y, Pf_min1.y ).xxyy * sign( hash_highz );
vec4 grad_results_1_2 = Pf_min1.zzzz * sign( abs( hash_highz ) - 0.125 );
vec4 grad_results_1 = grad_results_1_0 + grad_results_1_1 + grad_results_1_2;
// blend the gradients and return
vec3 blend = Interpolation_C2( Pf );
vec4 res0 = mix( grad_results_0, grad_results_1, blend.z );
vec2 res1 = mix( res0.xy, res0.zw, blend.y );
return mix( res1.x, res1.y, blend.x ) * (2.0 / 3.0); // (optionally) mult by (2.0/3.0) to scale to a strict -1.0->1.0 range
#endif
}
float ridge(vec3 p, int powered, float ridgePower, float offset)
{
// Powered Ridge
if(powered > 0)
{
return pow(offset - abs(4.0*Perlin3D(p)), ridgePower);
}
else
{
return offset - abs(4.0*Perlin3D(p));
}
}
//
// 3D fractional Brownian Motion
//
float fBM(vec3 p, vec3 offset, float frequency, float amplitude, float lacunarity, float persistence, int powered, float ridgePower, float ridgeOffset)
{
float sum = 0.0;
float bias = 0.0;
for (int i = 0; i < OCTAVES; i++)
{
float h = 0.5 * (1.0 + ridge((p+offset*amplitude)*frequency, powered, ridgePower, ridgeOffset));
sum += h*amplitude;
bias -= amplitude;
frequency *= lacunarity;
amplitude *= persistence;
}
sum += 0.5 * bias;
return sum;
}
uniform vec4 _LowColor;
uniform vec4 _HighColor;
uniform float _Texturing;
uniform sampler2D _LowTexture;
uniform vec4 _LowTexture_ST;
uniform sampler2D _HighTexture;
uniform vec4 _HighTexture_ST;
varying vec4 position;
varying vec2 texCoord;
void main()
{
float h = fBM(vec3(vec2(position.xz), _Time*_AnimSpeed), _NoiseOffset, _Frequency, _Amplitude, _Lacunarity, _Persistence, _Powered, _RidgePower, _RidgeOffset);
if(_Normalize > 0.0)
{
// set range to (0, 1)
h = h*0.5 + 0.5;
}
// do the accumulation with the previous fixed-point height
h = h*_Contribution;
vec4 color;
if(_Texturing > 0.0)
{
color = mix(_LowColor * texture2D(_LowTexture, _LowTexture_ST.xy * texCoord + _LowTexture_ST.zw), _HighColor * texture2D(_HighTexture, _HighTexture_ST.xy * texCoord + _HighTexture_ST.zw), h);
}
else
{
color = mix(_LowColor, _HighColor, h);
}
gl_FragColor = vec4(color.r, color.g, color.b, h);
}
-------- GLSL error: ERROR: Uniform precision mismatch '_NoiseOffset'
ERROR: Uniform precision mismatch '_Frequency'
ERROR: Uniform precision mismatch '_AnimSpeed'
ERROR: Uniform precision mismatch '_Time'
ERROR: Uniform precision mismatch '_Amplitude'
Vertex Shader:
#define SHADER_API_GLES 1
#define tex2D texture2D
#line 32
uniform vec4 _Time;
uniform float _Frequency;
uniform float _Amplitude;
uniform vec3 _NoiseOffset;
uniform float _Contribution;
uniform float _Normalize;
uniform float _AnimSpeed;
//
// FAST32_hash
// A very fast hashing function. Requires 32bit support.
// http://briansharpe.wordpress.com/2011/11/15/a-fast-and-simple-32bit-floating-point-hash-function/
//
// The hash formula takes the form....
// hash = fmod( coord.x * coord.x * coord.y * coord.y, SOMELARGEFLOAT ) / SOMELARGEFLOAT
// We truncate and offset the domain to the most interesting part of the noise.
// SOMELARGEFLOAT should be in the range of 400.0->1000.0 and needs to be hand picked. Only some give good results.
// 3D Noise is achieved by offsetting the SOMELARGEFLOAT value by the Z coordinate
//
vec4 FAST32_hash_3D_Cell( vec3 gridcell ) // generates 4 different random numbers for the single given cell point
{
// gridcell is assumed to be an integer coordinate
// TODO: these constants need tweaked to find the best possible noise.
// probably requires some kind of brute force computational searching or something....
const vec2 OFFSET = vec2( 50.0, 161.0 );
const float DOMAIN = 69.0;
const vec4 SOMELARGEFLOATS = vec4( 635.298681, 682.357502, 668.926525, 588.255119 );
const vec4 ZINC = vec4( 48.500388, 65.294118, 63.934599, 63.279683 );
// truncate the domain
gridcell.xyz = gridcell - floor(gridcell * ( 1.0 / DOMAIN )) * DOMAIN;
gridcell.xy += OFFSET.xy;
gridcell.xy *= gridcell.xy;
return fract( ( gridcell.x * gridcell.y ) * ( 1.0 / ( SOMELARGEFLOATS + gridcell.zzzz * ZINC ) ) );
}
float Cellular3D(vec3 xyz)
{
int xi = int(floor(xyz.x));
int yi = int(floor(xyz.y));
int zi = int(floor(xyz.z));
float xf = xyz.x - float(xi);
float yf = xyz.y - float(yi);
float zf = xyz.z - float(zi);
float dist1 = 9999999.0;
float dist2 = 9999999.0;
float dist3 = 9999999.0;
float dist4 = 9999999.0;
vec3 cell;
for (int z = -1; z <= 1; z++) {
for (int y = -1; y <= 1; y++) {
for (int x = -1; x <= 1; x++) {
cell = FAST32_hash_3D_Cell(vec3(xi + x, yi + y, zi + z)).xyz;
cell.x += (float(x) - xf);
cell.y += (float(y) - yf);
cell.z += (float(z) - zf);
float dist = 0.0;
dist = max(abs(cell.x), max(abs(cell.y), abs(cell.z)));
dist *= dist;
if (dist < dist1)
{
dist4 = dist3;
dist3 = dist2;
dist2 = dist1;
dist1 = dist;
}
else if (dist < dist2)
{
dist4 = dist3;
dist3 = dist2;
dist2 = dist;
}
else if (dist < dist3)
{
dist4 = dist3;
dist3 = dist;
}
else if (dist < dist4)
{
dist4 = dist;
}
}
}
}
return dist3; // scale return value from 0.0->1.333333 to 0.0->1.0 (2/3)^2 * 3 == (12/9) == 1.333333
}
//
// 3D fractional Brownian Motion
//
float fBM(vec3 p, vec3 offset, float frequency, float amplitude)
{
float h = 0.0;
h = Cellular3D((p+offset) * frequency);
h += h*amplitude;
return h;
}
#define gl_ModelViewProjectionMatrix glstate_matrix_mvp
uniform mat4 glstate_matrix_mvp;
#define gl_Vertex _glesVertex
attribute vec4 _glesVertex;
#define gl_MultiTexCoord0 _glesMultiTexCoord0
attribute vec4 _glesMultiTexCoord0;
uniform float _Displace;
varying vec4 position;
varying vec2 texCoord;
void main()
{
position = gl_Vertex;
if(_Displace > 0.0)
{
position.y = fBM(vec3(position.xz, _Time*_AnimSpeed), _NoiseOffset, _Frequency, _Amplitude);
}
gl_Position = gl_ModelViewProjectionMatrix * position;
texCoord = gl_MultiTexCoord0.xy;
}
Fragment Shader:
precision mediump float;
#define SHADER_API_GLES 1
#define tex2D texture2D
#line 32
uniform vec4 _Time;
uniform float _Frequency;
uniform float _Amplitude;
uniform vec3 _NoiseOffset;
uniform float _Contribution;
uniform float _Normalize;
uniform float _AnimSpeed;
//
// FAST32_hash
// A very fast hashing function. Requires 32bit support.
// http://briansharpe.wordpress.com/2011/11/15/a-fast-and-simple-32bit-floating-point-hash-function/
//
// The hash formula takes the form....
// hash = fmod( coord.x * coord.x * coord.y * coord.y, SOMELARGEFLOAT ) / SOMELARGEFLOAT
// We truncate and offset the domain to the most interesting part of the noise.
// SOMELARGEFLOAT should be in the range of 400.0->1000.0 and needs to be hand picked. Only some give good results.
// 3D Noise is achieved by offsetting the SOMELARGEFLOAT value by the Z coordinate
//
vec4 FAST32_hash_3D_Cell( vec3 gridcell ) // generates 4 different random numbers for the single given cell point
{
// gridcell is assumed to be an integer coordinate
// TODO: these constants need tweaked to find the best possible noise.
// probably requires some kind of brute force computational searching or something....
const vec2 OFFSET = vec2( 50.0, 161.0 );
const float DOMAIN = 69.0;
const vec4 SOMELARGEFLOATS = vec4( 635.298681, 682.357502, 668.926525, 588.255119 );
const vec4 ZINC = vec4( 48.500388, 65.294118, 63.934599, 63.279683 );
// truncate the domain
gridcell.xyz = gridcell - floor(gridcell * ( 1.0 / DOMAIN )) * DOMAIN;
gridcell.xy += OFFSET.xy;
gridcell.xy *= gridcell.xy;
return fract( ( gridcell.x * gridcell.y ) * ( 1.0 / ( SOMELARGEFLOATS + gridcell.zzzz * ZINC ) ) );
}
float Cellular3D(vec3 xyz)
{
int xi = int(floor(xyz.x));
int yi = int(floor(xyz.y));
int zi = int(floor(xyz.z));
float xf = xyz.x - float(xi);
float yf = xyz.y - float(yi);
float zf = xyz.z - float(zi);
float dist1 = 9999999.0;
float dist2 = 9999999.0;
float dist3 = 9999999.0;
float dist4 = 9999999.0;
vec3 cell;
for (int z = -1; z <= 1; z++) {
for (int y = -1; y <= 1; y++) {
for (int x = -1; x <= 1; x++) {
cell = FAST32_hash_3D_Cell(vec3(xi + x, yi + y, zi + z)).xyz;
cell.x += (float(x) - xf);
cell.y += (float(y) - yf);
cell.z += (float(z) - zf);
float dist = 0.0;
dist = max(abs(cell.x), max(abs(cell.y), abs(cell.z)));
dist *= dist;
if (dist < dist1)
{
dist4 = dist3;
dist3 = dist2;
dist2 = dist1;
dist1 = dist;
}
else if (dist < dist2)
{
dist4 = dist3;
dist3 = dist2;
dist2 = dist;
}
else if (dist < dist3)
{
dist4 = dist3;
dist3 = dist;
}
else if (dist < dist4)
{
dist4 = dist;
}
}
}
}
return dist3; // scale return value from 0.0->1.333333 to 0.0->1.0 (2/3)^2 * 3 == (12/9) == 1.333333
}
//
// 3D fractional Brownian Motion
//
float fBM(vec3 p, vec3 offset, float frequency, float amplitude)
{
float h = 0.0;
h = Cellular3D((p+offset) * frequency);
h += h*amplitude;
return h;
}
uniform vec4 _LowColor;
uniform vec4 _HighColor;
uniform float _Texturing;
uniform sampler2D _LowTexture;
uniform vec4 _LowTexture_ST;
uniform sampler2D _HighTexture;
uniform vec4 _HighTexture_ST;
varying vec4 position;
varying vec2 texCoord;
void main()
{
float h = fBM(vec3(vec2(position.xz), _Time*_AnimSpeed), _NoiseOffset, _Frequency, _Amplitude);
if(_Normalize > 0.0)
{
// set range to (0, 1)
h = h*0.5 + 0.5;
}
// do the accumulation with the previous fixed-point height
h = h*_Contribution;
vec4 color;
if(_Texturing > 0.0)
{
color = mix(_LowColor * texture2D(_LowTexture, _LowTexture_ST.xy * texCoord + _LowTexture_ST.zw), _HighColor * texture2D(_HighTexture, _HighTexture_ST.xy * texCoord + _HighTexture_ST.zw), h);
}
else
{
color = mix(_LowColor, _HighColor, h);
}
gl_FragColor = vec4(color.r, color.g, color.b, h);
}
-------- GLSL error: ERROR: Uniform precision mismatch '_Powered'
Vertex Shader:
#define SHADER_API_GLES 1
#define tex2D texture2D
#line 36
precision mediump float;
const int OCTAVES = 12;
uniform vec4 _Time;
uniform float _Frequency;
uniform float _Amplitude;
uniform vec3 _NoiseOffset;
uniform float _Contribution;
uniform float _Normalize;
uniform float _AnimSpeed;
uniform float _Lacunarity;
uniform float _Persistence;
uniform int _Powered;
uniform float _BillowPower;
//
// FAST32_hash
// A very fast hashing function. Requires 32bit support.
// http://briansharpe.wordpress.com/2011/11/15/a-fast-and-simple-32bit-floating-point-hash-function/
//
// The hash formula takes the form....
// hash = mod( coord.x * coord.x * coord.y * coord.y, SOMELARGEFLOAT ) / SOMELARGEFLOAT
// We truncate and offset the domain to the most interesting part of the noise.
// SOMELARGEFLOAT should be in the range of 400.0->1000.0 and needs to be hand picked. Only some give good results.
// 3D Noise is achieved by offsetting the SOMELARGEFLOAT value by the Z coordinate
//
void FAST32_hash_3D(vec3 gridcell,
vec3 v1_mask, // user definable v1 and v2. ( 0's and 1's )
vec3 v2_mask,
out vec4 hash_0,
out vec4 hash_1,
out vec4 hash_2 ) // generates 3 random numbers for each of the 4 3D cell corners. cell corners: v0=0,0,0 v3=1,1,1 the other two are user definable
{
// gridcell is assumed to be an integer coordinate
// TODO: these constants need tweaked to find the best possible noise.
// probably requires some kind of brute force computational searching or something....
const vec2 OFFSET = vec2( 50.0, 161.0 );
const float DOMAIN = 69.0;
const vec3 SOMELARGEFLOATS = vec3( 635.298681, 682.357502, 668.926525 );
const vec3 ZINC = vec3( 48.500388, 65.294118, 63.934599 );
// truncate the domain
gridcell.xyz = gridcell.xyz - floor(gridcell.xyz * ( 1.0 / DOMAIN )) * DOMAIN;
vec3 gridcell_inc1 = step( gridcell, vec3( DOMAIN - 1.5 ) ) * ( gridcell + 1.0 );
// compute x*x*y*y for the 4 corners
vec4 P = vec4( gridcell.xy, gridcell_inc1.xy ) + OFFSET.xyxy;
P *= P;
vec4 V1xy_V2xy = mix( P.xyxy, P.zwzw, vec4( v1_mask.xy, v2_mask.xy ) ); // apply mask for v1 and v2
P = vec4( P.x, V1xy_V2xy.xz, P.z ) * vec4( P.y, V1xy_V2xy.yw, P.w );
// get the lowz and highz mods
vec3 lowz_mods = vec3( 1.0 / ( SOMELARGEFLOATS.xyz + gridcell.zzz * ZINC.xyz ) );
vec3 highz_mods = vec3( 1.0 / ( SOMELARGEFLOATS.xyz + gridcell_inc1.zzz * ZINC.xyz ) );
// apply mask for v1 and v2 mod values
v1_mask = ( v1_mask.z < 0.5 ) ? lowz_mods : highz_mods;
v2_mask = ( v2_mask.z < 0.5 ) ? lowz_mods : highz_mods;
// compute the final hash
hash_0 = fract( P * vec4( lowz_mods.x, v1_mask.x, v2_mask.x, highz_mods.x ) );
hash_1 = fract( P * vec4( lowz_mods.y, v1_mask.y, v2_mask.y, highz_mods.y ) );
hash_2 = fract( P * vec4( lowz_mods.z, v1_mask.z, v2_mask.z, highz_mods.z ) );
}
//
// Given an arbitrary 3D point this calculates the 4 vectors from the corners of the simplex pyramid to the point
// It also returns the integer grid index information for the corners
//
void Simplex3D_GetCornerVectors( vec3 P, // input point
out vec3 Pi, // integer grid index for the origin
out vec3 Pi_1, // offsets for the 2nd and 3rd corners. ( the 4th = Pi + 1.0 )
out vec3 Pi_2,
out vec4 v1234_x, // vectors from the 4 corners to the intput point
out vec4 v1234_y,
out vec4 v1234_z )
{
//
// Simplex math from Stefan Gustavson's and Ian McEwan's work at...
// http://github.com/ashima/webgl-noise
//
// simplex math constants
const float SKEWFACTOR = 1.0/3.0;
const float UNSKEWFACTOR = 1.0/6.0;
const float SIMPLEX_CORNER_POS = 0.5;
const float SIMPLEX_PYRAMID_HEIGHT = 0.70710678118654752440084436210485; // sqrt( 0.5 ) height of simplex pyramid.
P *= SIMPLEX_PYRAMID_HEIGHT; // scale space so we can have an approx feature size of 1.0 ( optional )
// Find the vectors to the corners of our simplex pyramid
Pi = floor( P + dot( P, vec3( SKEWFACTOR) ) );
vec3 x0 = P - Pi + dot(Pi, vec3( UNSKEWFACTOR ) );
vec3 g = step(x0.yzx, x0.xyz);
vec3 l = 1.0 - g;
Pi_1 = min( g.xyz, l.zxy );
Pi_2 = max( g.xyz, l.zxy );
vec3 x1 = x0 - Pi_1 + UNSKEWFACTOR;
vec3 x2 = x0 - Pi_2 + SKEWFACTOR;
vec3 x3 = x0 - SIMPLEX_CORNER_POS;
// pack them into a parallel-friendly arrangement
v1234_x = vec4( x0.x, x1.x, x2.x, x3.x );
v1234_y = vec4( x0.y, x1.y, x2.y, x3.y );
v1234_z = vec4( x0.z, x1.z, x2.z, x3.z );
}
//
// Calculate the weights for the 3D simplex surflet
//
vec4 Simplex3D_GetSurfletWeights( vec4 v1234_x,
vec4 v1234_y,
vec4 v1234_z )
{
// perlins original implementation uses the surlet falloff formula of (0.6-x*x)^4.
// This is buggy as it can cause discontinuities along simplex faces. (0.5-x*x)^3 solves this and gives an almost identical curve
// evaluate surflet. f(x)=(0.5-x*x)^3
vec4 surflet_weights = v1234_x * v1234_x + v1234_y * v1234_y + v1234_z * v1234_z;
surflet_weights = max(0.5 - surflet_weights, 0.0); // 0.5 here represents the closest distance (squared) of any simplex pyramid corner to any of its planes. ie, SIMPLEX_PYRAMID_HEIGHT^2
return surflet_weights*surflet_weights*surflet_weights;
}
//
// SimplexPerlin3D ( simplex gradient noise )
// Perlin noise over a simplex (tetrahedron) grid
// Return value range of -1.0->1.0
// http://briansharpe.files.wordpress.com/2012/01/simplexperlinsample.jpg
//
// Implementation originally based off Stefan Gustavson's and Ian McEwan's work at...
// http://github.com/ashima/webgl-noise
//
float SimplexPerlin3D(vec3 P)
{
// calculate the simplex vector and index math
vec3 Pi;
vec3 Pi_1;
vec3 Pi_2;
vec4 v1234_x;
vec4 v1234_y;
vec4 v1234_z;
Simplex3D_GetCornerVectors( P, Pi, Pi_1, Pi_2, v1234_x, v1234_y, v1234_z );
// generate the random vectors
// ( various hashing methods listed in order of speed )
vec4 hash_0;
vec4 hash_1;
vec4 hash_2;
FAST32_hash_3D( Pi, Pi_1, Pi_2, hash_0, hash_1, hash_2 );
//SGPP_hash_3D( Pi, Pi_1, Pi_2, hash_0, hash_1, hash_2 );
hash_0 -= 0.49999;
hash_1 -= 0.49999;
hash_2 -= 0.49999;
// evaluate gradients
vec4 grad_results = inversesqrt( hash_0 * hash_0 + hash_1 * hash_1 + hash_2 * hash_2 ) * ( hash_0 * v1234_x + hash_1 * v1234_y + hash_2 * v1234_z );
// Normalization factor to scale the final result to a strict 1.0->-1.0 range
// x = sqrt( 0.75 ) * 0.5
// NF = 1.0 / ( x * ( ( 0.5 ? x*x ) ^ 3 ) * 2.0 )
// http://briansharpe.wordpress.com/2012/01/13/simplex-noise/#comment-36
const float FINAL_NORMALIZATION = 37.837227241611314102871574478976;
// sum with the surflet and return
return dot( Simplex3D_GetSurfletWeights( v1234_x, v1234_y, v1234_z ), grad_results ) * FINAL_NORMALIZATION;
}
float billow(vec3 p, int powered, float billowPower)
{
// Powered Billow
if(powered > 0)
{
return pow(abs(4.0*SimplexPerlin3D(p)), billowPower);
}
else
{
return abs(4.0*SimplexPerlin3D(p));
}
}
//
// 3D fractional Brownian Motion
//
float fBM(vec3 p, vec3 offset, float frequency, float amplitude, float lacunarity, float persistence, int powered, float billowPower)
{
float sum = 0.0;
float bias = 0.0;
for (int i = 0; i < OCTAVES; i++)
{
float h = 0.5 * (1.0 + billow((p+offset)*frequency, powered, billowPower));
sum += h*amplitude;
bias -= amplitude;
frequency *= lacunarity;
amplitude *= persistence;
}
sum += 0.5 * bias;
return sum;
}
#define gl_ModelViewProjectionMatrix glstate_matrix_mvp
uniform mat4 glstate_matrix_mvp;
#define gl_Vertex _glesVertex
attribute vec4 _glesVertex;
#define gl_MultiTexCoord0 _glesMultiTexCoord0
attribute vec4 _glesMultiTexCoord0;
uniform float _Displace;
varying vec4 position;
varying vec2 texCoord;
void main()
{
position = gl_Vertex;
if(_Displace > 0.0)
{
position.y = fBM(vec3(position.xz, _Time*_AnimSpeed), _NoiseOffset, _Frequency, _Amplitude, _Lacunarity, _Persistence, _Powered, _BillowPower);
}
gl_Position = gl_ModelViewProjectionMatrix * position;
texCoord = gl_MultiTexCoord0.xy;
}
Fragment Shader:
precision mediump float;
#define SHADER_API_GLES 1
#define tex2D texture2D
#line 36
precision mediump float;
const int OCTAVES = 12;
uniform vec4 _Time;
uniform float _Frequency;
uniform float _Amplitude;
uniform vec3 _NoiseOffset;
uniform float _Contribution;
uniform float _Normalize;
uniform float _AnimSpeed;
uniform float _Lacunarity;
uniform float _Persistence;
uniform int _Powered;
uniform float _BillowPower;
//
// FAST32_hash
// A very fast hashing function. Requires 32bit support.
// http://briansharpe.wordpress.com/2011/11/15/a-fast-and-simple-32bit-floating-point-hash-function/
//
// The hash formula takes the form....
// hash = mod( coord.x * coord.x * coord.y * coord.y, SOMELARGEFLOAT ) / SOMELARGEFLOAT
// We truncate and offset the domain to the most interesting part of the noise.
// SOMELARGEFLOAT should be in the range of 400.0->1000.0 and needs to be hand picked. Only some give good results.
// 3D Noise is achieved by offsetting the SOMELARGEFLOAT value by the Z coordinate
//
void FAST32_hash_3D(vec3 gridcell,
vec3 v1_mask, // user definable v1 and v2. ( 0's and 1's )
vec3 v2_mask,
out vec4 hash_0,
out vec4 hash_1,
out vec4 hash_2 ) // generates 3 random numbers for each of the 4 3D cell corners. cell corners: v0=0,0,0 v3=1,1,1 the other two are user definable
{
// gridcell is assumed to be an integer coordinate
// TODO: these constants need tweaked to find the best possible noise.
// probably requires some kind of brute force computational searching or something....
const vec2 OFFSET = vec2( 50.0, 161.0 );
const float DOMAIN = 69.0;
const vec3 SOMELARGEFLOATS = vec3( 635.298681, 682.357502, 668.926525 );
const vec3 ZINC = vec3( 48.500388, 65.294118, 63.934599 );
// truncate the domain
gridcell.xyz = gridcell.xyz - floor(gridcell.xyz * ( 1.0 / DOMAIN )) * DOMAIN;
vec3 gridcell_inc1 = step( gridcell, vec3( DOMAIN - 1.5 ) ) * ( gridcell + 1.0 );
// compute x*x*y*y for the 4 corners
vec4 P = vec4( gridcell.xy, gridcell_inc1.xy ) + OFFSET.xyxy;
P *= P;
vec4 V1xy_V2xy = mix( P.xyxy, P.zwzw, vec4( v1_mask.xy, v2_mask.xy ) ); // apply mask for v1 and v2
P = vec4( P.x, V1xy_V2xy.xz, P.z ) * vec4( P.y, V1xy_V2xy.yw, P.w );
// get the lowz and highz mods
vec3 lowz_mods = vec3( 1.0 / ( SOMELARGEFLOATS.xyz + gridcell.zzz * ZINC.xyz ) );
vec3 highz_mods = vec3( 1.0 / ( SOMELARGEFLOATS.xyz + gridcell_inc1.zzz * ZINC.xyz ) );
// apply mask for v1 and v2 mod values
v1_mask = ( v1_mask.z < 0.5 ) ? lowz_mods : highz_mods;
v2_mask = ( v2_mask.z < 0.5 ) ? lowz_mods : highz_mods;
// compute the final hash
hash_0 = fract( P * vec4( lowz_mods.x, v1_mask.x, v2_mask.x, highz_mods.x ) );
hash_1 = fract( P * vec4( lowz_mods.y, v1_mask.y, v2_mask.y, highz_mods.y ) );
hash_2 = fract( P * vec4( lowz_mods.z, v1_mask.z, v2_mask.z, highz_mods.z ) );
}
//
// Given an arbitrary 3D point this calculates the 4 vectors from the corners of the simplex pyramid to the point
// It also returns the integer grid index information for the corners
//
void Simplex3D_GetCornerVectors( vec3 P, // input point
out vec3 Pi, // integer grid index for the origin
out vec3 Pi_1, // offsets for the 2nd and 3rd corners. ( the 4th = Pi + 1.0 )
out vec3 Pi_2,
out vec4 v1234_x, // vectors from the 4 corners to the intput point
out vec4 v1234_y,
out vec4 v1234_z )
{
//
// Simplex math from Stefan Gustavson's and Ian McEwan's work at...
// http://github.com/ashima/webgl-noise
//
// simplex math constants
const float SKEWFACTOR = 1.0/3.0;
const float UNSKEWFACTOR = 1.0/6.0;
const float SIMPLEX_CORNER_POS = 0.5;
const float SIMPLEX_PYRAMID_HEIGHT = 0.70710678118654752440084436210485; // sqrt( 0.5 ) height of simplex pyramid.
P *= SIMPLEX_PYRAMID_HEIGHT; // scale space so we can have an approx feature size of 1.0 ( optional )
// Find the vectors to the corners of our simplex pyramid
Pi = floor( P + dot( P, vec3( SKEWFACTOR) ) );
vec3 x0 = P - Pi + dot(Pi, vec3( UNSKEWFACTOR ) );
vec3 g = step(x0.yzx, x0.xyz);
vec3 l = 1.0 - g;
Pi_1 = min( g.xyz, l.zxy );
Pi_2 = max( g.xyz, l.zxy );
vec3 x1 = x0 - Pi_1 + UNSKEWFACTOR;
vec3 x2 = x0 - Pi_2 + SKEWFACTOR;
vec3 x3 = x0 - SIMPLEX_CORNER_POS;
// pack them into a parallel-friendly arrangement
v1234_x = vec4( x0.x, x1.x, x2.x, x3.x );
v1234_y = vec4( x0.y, x1.y, x2.y, x3.y );
v1234_z = vec4( x0.z, x1.z, x2.z, x3.z );
}
//
// Calculate the weights for the 3D simplex surflet
//
vec4 Simplex3D_GetSurfletWeights( vec4 v1234_x,
vec4 v1234_y,
vec4 v1234_z )
{
// perlins original implementation uses the surlet falloff formula of (0.6-x*x)^4.
// This is buggy as it can cause discontinuities along simplex faces. (0.5-x*x)^3 solves this and gives an almost identical curve
// evaluate surflet. f(x)=(0.5-x*x)^3
vec4 surflet_weights = v1234_x * v1234_x + v1234_y * v1234_y + v1234_z * v1234_z;
surflet_weights = max(0.5 - surflet_weights, 0.0); // 0.5 here represents the closest distance (squared) of any simplex pyramid corner to any of its planes. ie, SIMPLEX_PYRAMID_HEIGHT^2
return surflet_weights*surflet_weights*surflet_weights;
}
//
// SimplexPerlin3D ( simplex gradient noise )
// Perlin noise over a simplex (tetrahedron) grid
// Return value range of -1.0->1.0
// http://briansharpe.files.wordpress.com/2012/01/simplexperlinsample.jpg
//
// Implementation originally based off Stefan Gustavson's and Ian McEwan's work at...
// http://github.com/ashima/webgl-noise
//
float SimplexPerlin3D(vec3 P)
{
// calculate the simplex vector and index math
vec3 Pi;
vec3 Pi_1;
vec3 Pi_2;
vec4 v1234_x;
vec4 v1234_y;
vec4 v1234_z;
Simplex3D_GetCornerVectors( P, Pi, Pi_1, Pi_2, v1234_x, v1234_y, v1234_z );
// generate the random vectors
// ( various hashing methods listed in order of speed )
vec4 hash_0;
vec4 hash_1;
vec4 hash_2;
FAST32_hash_3D( Pi, Pi_1, Pi_2, hash_0, hash_1, hash_2 );
//SGPP_hash_3D( Pi, Pi_1, Pi_2, hash_0, hash_1, hash_2 );
hash_0 -= 0.49999;
hash_1 -= 0.49999;
hash_2 -= 0.49999;
// evaluate gradients
vec4 grad_results = inversesqrt( hash_0 * hash_0 + hash_1 * hash_1 + hash_2 * hash_2 ) * ( hash_0 * v1234_x + hash_1 * v1234_y + hash_2 * v1234_z );
// Normalization factor to scale the final result to a strict 1.0->-1.0 range
// x = sqrt( 0.75 ) * 0.5
// NF = 1.0 / ( x * ( ( 0.5 ? x*x ) ^ 3 ) * 2.0 )
// http://briansharpe.wordpress.com/2012/01/13/simplex-noise/#comment-36
const float FINAL_NORMALIZATION = 37.837227241611314102871574478976;
// sum with the surflet and return
return dot( Simplex3D_GetSurfletWeights( v1234_x, v1234_y, v1234_z ), grad_results ) * FINAL_NORMALIZATION;
}
float billow(vec3 p, int powered, float billowPower)
{
// Powered Billow
if(powered > 0)
{
return pow(abs(4.0*SimplexPerlin3D(p)), billowPower);
}
else
{
return abs(4.0*SimplexPerlin3D(p));
}
}
//
// 3D fractional Brownian Motion
//
float fBM(vec3 p, vec3 offset, float frequency, float amplitude, float lacunarity, float persistence, int powered, float billowPower)
{
float sum = 0.0;
float bias = 0.0;
for (int i = 0; i < OCTAVES; i++)
{
float h = 0.5 * (1.0 + billow((p+offset)*frequency, powered, billowPower));
sum += h*amplitude;
bias -= amplitude;
frequency *= lacunarity;
amplitude *= persistence;
}
sum += 0.5 * bias;
return sum;
}
uniform vec4 _LowColor;
uniform vec4 _HighColor;
uniform float _Texturing;
uniform sampler2D _LowTexture;
uniform vec4 _LowTexture_ST;
uniform sampler2D _HighTexture;
uniform vec4 _HighTexture_ST;
varying vec4 position;
varying vec2 texCoord;
void main()
{
float h = fBM(vec3(vec2(position.xz), _Time*_AnimSpeed), _NoiseOffset, _Frequency, _Amplitude, _Lacunarity, _Persistence, _Powered, _BillowPower);
if(_Normalize > 0.0)
{
// set range to (0, 1)
h = h*0.5 + 0.5;
}
// do the accumulation with the previous fixed-point height
h = h*_Contribution;
vec4 color;
if(_Texturing > 0.0)
{
color = mix(_LowColor * texture2D(_LowTexture, _LowTexture_ST.xy * texCoord + _LowTexture_ST.zw), _HighColor * texture2D(_HighTexture, _HighTexture_ST.xy * texCoord + _HighTexture_ST.zw), h);
}
else
{
color = mix(_LowColor, _HighColor, h);
}
gl_FragColor = vec4(color.r, color.g, color.b, h);
}
-------- GLSL error: ERROR: Uniform precision mismatch '_Octaves'
Vertex Shader:
#define SHADER_API_GLES 1
#define tex2D texture2D
#line 35
precision mediump float;
const int OCTAVES = 12;
uniform vec4 _Time;
uniform float _Frequency;
uniform float _Amplitude;
uniform vec3 _NoiseOffset;
uniform float _Contribution;
uniform float _Normalize;
uniform float _AnimSpeed;
uniform int _Octaves;
uniform float _Lacunarity;
uniform float _Persistence;
//
// FAST32_hash
// A very fast hashing function. Requires 32bit support.
// http://briansharpe.wordpress.com/2011/11/15/a-fast-and-simple-32bit-floating-point-hash-function/
//
// The hash formula takes the form....
// hash = mod( coord.x * coord.x * coord.y * coord.y, SOMELARGEFLOAT ) / SOMELARGEFLOAT
// We truncate and offset the domain to the most interesting part of the noise.
// SOMELARGEFLOAT should be in the range of 400.0->1000.0 and needs to be hand picked. Only some give good results.
// 3D Noise is achieved by offsetting the SOMELARGEFLOAT value by the Z coordinate
//
void FAST32_hash_3D( vec3 gridcell, out vec4 lowz_hash, out vec4 highz_hash ) // generates a random number for each of the 8 cell corners
{
// gridcell is assumed to be an integer coordinate
// TODO: these constants need tweaked to find the best possible noise.
// probably requires some kind of brute force computational searching or something....
const vec2 OFFSET = vec2( 50.0, 161.0 );
const float DOMAIN = 69.0;
const float SOMELARGEFLOAT = 635.298681;
const float ZINC = 48.500388;
// truncate the domain
gridcell.xyz = gridcell.xyz - floor(gridcell.xyz * ( 1.0 / DOMAIN )) * DOMAIN;
vec3 gridcell_inc1 = step( gridcell, vec3( DOMAIN - 1.5 ) ) * ( gridcell + 1.0 );
// calculate the noise
vec4 P = vec4( gridcell.xy, gridcell_inc1.xy ) + OFFSET.xyxy;
P *= P;
P = P.xzxz * P.yyww;
highz_hash.xy = vec2( 1.0 / ( SOMELARGEFLOAT + vec2( gridcell.z, gridcell_inc1.z ) * ZINC ) );
lowz_hash = fract( P * highz_hash.xxxx );
highz_hash = fract( P * highz_hash.yyyy );
}
vec3 Interpolation_C2( vec3 x )
{
return x * x * x * (x * (x * 6.0 - 15.0) + 10.0);
}
//
// Value Noise 3D
// Return value range of 0.0->1.0
// http://briansharpe.files.wordpress.com/2011/11/valuesample1.jpg
//
float Value3D( vec3 P )
{
// establish our grid cell and unit position
vec3 Pi = floor(P);
vec3 Pf = P - Pi;
// calculate the hash.
// ( various hashing methods listed in order of speed )
vec4 hash_lowz, hash_highz;
FAST32_hash_3D( Pi, hash_lowz, hash_highz );
//BBS_hash_3D( Pi, hash_lowz, hash_highz );
//SGPP_hash_3D( Pi, hash_lowz, hash_highz );
// blend the results and return
vec3 blend = Interpolation_C2( Pf );
vec4 res0 = mix( hash_lowz, hash_highz, blend.z );
vec2 res1 = mix( res0.xy, res0.zw, blend.y );
return mix( res1.x, res1.y, blend.x );
}
//
// 3D fractional Brownian Motion
//
float fBM(vec3 p, int octaves, vec3 offset, float frequency, float amplitude, float lacunarity, float persistence)
{
float sum = 0.0;
for (int i = 0; i < OCTAVES; i++)
{
float h = Value3D((p+offset) * frequency);
sum += h*amplitude;
frequency *= lacunarity;
amplitude *= persistence;
}
return sum;
}
#define gl_ModelViewProjectionMatrix glstate_matrix_mvp
uniform mat4 glstate_matrix_mvp;
#define gl_Vertex _glesVertex
attribute vec4 _glesVertex;
#define gl_MultiTexCoord0 _glesMultiTexCoord0
attribute vec4 _glesMultiTexCoord0;
uniform float _Displace;
varying vec4 position;
varying vec2 texCoord;
void main()
{
position = gl_Vertex;
if(_Displace > 0.0)
{
position.y = fBM(vec3(position.xz, _Time*_AnimSpeed), _Octaves, _NoiseOffset, _Frequency, _Amplitude, _Lacunarity, _Persistence);
}
gl_Position = gl_ModelViewProjectionMatrix * position;
texCoord = gl_MultiTexCoord0.xy;
}
Fragment Shader:
precision mediump float;
#define SHADER_API_GLES 1
#define tex2D texture2D
#line 35
precision mediump float;
const int OCTAVES = 12;
uniform vec4 _Time;
uniform float _Frequency;
uniform float _Amplitude;
uniform vec3 _NoiseOffset;
uniform float _Contribution;
uniform float _Normalize;
uniform float _AnimSpeed;
uniform int _Octaves;
uniform float _Lacunarity;
uniform float _Persistence;
//
// FAST32_hash
// A very fast hashing function. Requires 32bit support.
// http://briansharpe.wordpress.com/2011/11/15/a-fast-and-simple-32bit-floating-point-hash-function/
//
// The hash formula takes the form....
// hash = mod( coord.x * coord.x * coord.y * coord.y, SOMELARGEFLOAT ) / SOMELARGEFLOAT
// We truncate and offset the domain to the most interesting part of the noise.
// SOMELARGEFLOAT should be in the range of 400.0->1000.0 and needs to be hand picked. Only some give good results.
// 3D Noise is achieved by offsetting the SOMELARGEFLOAT value by the Z coordinate
//
void FAST32_hash_3D( vec3 gridcell, out vec4 lowz_hash, out vec4 highz_hash ) // generates a random number for each of the 8 cell corners
{
// gridcell is assumed to be an integer coordinate
// TODO: these constants need tweaked to find the best possible noise.
// probably requires some kind of brute force computational searching or something....
const vec2 OFFSET = vec2( 50.0, 161.0 );
const float DOMAIN = 69.0;
const float SOMELARGEFLOAT = 635.298681;
const float ZINC = 48.500388;
// truncate the domain
gridcell.xyz = gridcell.xyz - floor(gridcell.xyz * ( 1.0 / DOMAIN )) * DOMAIN;
vec3 gridcell_inc1 = step( gridcell, vec3( DOMAIN - 1.5 ) ) * ( gridcell + 1.0 );
// calculate the noise
vec4 P = vec4( gridcell.xy, gridcell_inc1.xy ) + OFFSET.xyxy;
P *= P;
P = P.xzxz * P.yyww;
highz_hash.xy = vec2( 1.0 / ( SOMELARGEFLOAT + vec2( gridcell.z, gridcell_inc1.z ) * ZINC ) );
lowz_hash = fract( P * highz_hash.xxxx );
highz_hash = fract( P * highz_hash.yyyy );
}
vec3 Interpolation_C2( vec3 x )
{
return x * x * x * (x * (x * 6.0 - 15.0) + 10.0);
}
//
// Value Noise 3D
// Return value range of 0.0->1.0
// http://briansharpe.files.wordpress.com/2011/11/valuesample1.jpg
//
float Value3D( vec3 P )
{
// establish our grid cell and unit position
vec3 Pi = floor(P);
vec3 Pf = P - Pi;
// calculate the hash.
// ( various hashing methods listed in order of speed )
vec4 hash_lowz, hash_highz;
FAST32_hash_3D( Pi, hash_lowz, hash_highz );
//BBS_hash_3D( Pi, hash_lowz, hash_highz );
//SGPP_hash_3D( Pi, hash_lowz, hash_highz );
// blend the results and return
vec3 blend = Interpolation_C2( Pf );
vec4 res0 = mix( hash_lowz, hash_highz, blend.z );
vec2 res1 = mix( res0.xy, res0.zw, blend.y );
return mix( res1.x, res1.y, blend.x );
}
//
// 3D fractional Brownian Motion
//
float fBM(vec3 p, int octaves, vec3 offset, float frequency, float amplitude, float lacunarity, float persistence)
{
float sum = 0.0;
for (int i = 0; i < OCTAVES; i++)
{
float h = Value3D((p+offset) * frequency);
sum += h*amplitude;
frequency *= lacunarity;
amplitude *= persistence;
}
return sum;
}
uniform vec4 _LowColor;
uniform vec4 _HighColor;
uniform float _Texturing;
uniform sampler2D _LowTexture;
uniform vec4 _LowTexture_ST;
uniform sampler2D _HighTexture;
uniform vec4 _HighTexture_ST;
varying vec4 position;
varying vec2 texCoord;
void main()
{
float h = fBM(vec3(vec2(position.xz), _Time*_AnimSpeed), _Octaves, _NoiseOffset, _Frequency, _Amplitude, _Lacunarity, _Persistence);
if(_Normalize > 0.0)
{
// set range to (0, 1)
h = h*0.5 + 0.5;
}
// do the accumulation with the previous fixed-point height
h = h*_Contribution;
vec4 color;
if(_Texturing > 0.0)
{
color = mix(_LowColor * texture2D(_LowTexture, _LowTexture_ST.xy * texCoord + _LowTexture_ST.zw), _HighColor * texture2D(_HighTexture, _HighTexture_ST.xy * texCoord + _HighTexture_ST.zw), h);
}
else
{
color = mix(_LowColor, _HighColor, h);
}
gl_FragColor = vec4(color.r, color.g, color.b, h);
}
-------- GLSL error: ERROR: Uniform precision mismatch '_Powered'
Vertex Shader:
#define SHADER_API_GLES 1
#define tex2D texture2D
#line 37
precision mediump float;
const int OCTAVES = 12;
uniform vec4 _Time;
uniform float _Frequency;
uniform float _Amplitude;
uniform vec3 _NoiseOffset;
uniform float _Contribution;
uniform float _Normalize;
uniform float _AnimSpeed;
uniform float _Lacunarity;
uniform float _Persistence;
uniform int _Powered;
uniform float _RidgePower;
uniform float _RidgeOffset;
//
// FAST32_hash
// A very fast hashing function. Requires 32bit support.
// http://briansharpe.wordpress.com/2011/11/15/a-fast-and-simple-32bit-floating-point-hash-function/
//
// The hash formula takes the form....
// hash = mod( coord.x * coord.x * coord.y * coord.y, SOMELARGEFLOAT ) / SOMELARGEFLOAT
// We truncate and offset the domain to the most interesting part of the noise.
// SOMELARGEFLOAT should be in the range of 400.0->1000.0 and needs to be hand picked. Only some give good results.
// 3D Noise is achieved by offsetting the SOMELARGEFLOAT value by the Z coordinate
//
void FAST32_hash_3D(vec3 gridcell,
vec3 v1_mask, // user definable v1 and v2. ( 0's and 1's )
vec3 v2_mask,
out vec4 hash_0,
out vec4 hash_1,
out vec4 hash_2 ) // generates 3 random numbers for each of the 4 3D cell corners. cell corners: v0=0,0,0 v3=1,1,1 the other two are user definable
{
// gridcell is assumed to be an integer coordinate
// TODO: these constants need tweaked to find the best possible noise.
// probably requires some kind of brute force computational searching or something....
const vec2 OFFSET = vec2( 50.0, 161.0 );
const float DOMAIN = 69.0;
const vec3 SOMELARGEFLOATS = vec3( 635.298681, 682.357502, 668.926525 );
const vec3 ZINC = vec3( 48.500388, 65.294118, 63.934599 );
// truncate the domain
gridcell.xyz = gridcell.xyz - floor(gridcell.xyz * ( 1.0 / DOMAIN )) * DOMAIN;
vec3 gridcell_inc1 = step( gridcell, vec3( DOMAIN - 1.5 ) ) * ( gridcell + 1.0 );
// compute x*x*y*y for the 4 corners
vec4 P = vec4( gridcell.xy, gridcell_inc1.xy ) + OFFSET.xyxy;
P *= P;
vec4 V1xy_V2xy = mix( P.xyxy, P.zwzw, vec4( v1_mask.xy, v2_mask.xy ) ); // apply mask for v1 and v2
P = vec4( P.x, V1xy_V2xy.xz, P.z ) * vec4( P.y, V1xy_V2xy.yw, P.w );
// get the lowz and highz mods
vec3 lowz_mods = vec3( 1.0 / ( SOMELARGEFLOATS.xyz + gridcell.zzz * ZINC.xyz ) );
vec3 highz_mods = vec3( 1.0 / ( SOMELARGEFLOATS.xyz + gridcell_inc1.zzz * ZINC.xyz ) );
// apply mask for v1 and v2 mod values
v1_mask = ( v1_mask.z < 0.5 ) ? lowz_mods : highz_mods;
v2_mask = ( v2_mask.z < 0.5 ) ? lowz_mods : highz_mods;
// compute the final hash
hash_0 = fract( P * vec4( lowz_mods.x, v1_mask.x, v2_mask.x, highz_mods.x ) );
hash_1 = fract( P * vec4( lowz_mods.y, v1_mask.y, v2_mask.y, highz_mods.y ) );
hash_2 = fract( P * vec4( lowz_mods.z, v1_mask.z, v2_mask.z, highz_mods.z ) );
}
//
// Given an arbitrary 3D point this calculates the 4 vectors from the corners of the simplex pyramid to the point
// It also returns the integer grid index information for the corners
//
void Simplex3D_GetCornerVectors( vec3 P, // input point
out vec3 Pi, // integer grid index for the origin
out vec3 Pi_1, // offsets for the 2nd and 3rd corners. ( the 4th = Pi + 1.0 )
out vec3 Pi_2,
out vec4 v1234_x, // vectors from the 4 corners to the intput point
out vec4 v1234_y,
out vec4 v1234_z )
{
//
// Simplex math from Stefan Gustavson's and Ian McEwan's work at...
// http://github.com/ashima/webgl-noise
//
// simplex math constants
const float SKEWFACTOR = 1.0/3.0;
const float UNSKEWFACTOR = 1.0/6.0;
const float SIMPLEX_CORNER_POS = 0.5;
const float SIMPLEX_PYRAMID_HEIGHT = 0.70710678118654752440084436210485; // sqrt( 0.5 ) height of simplex pyramid.
P *= SIMPLEX_PYRAMID_HEIGHT; // scale space so we can have an approx feature size of 1.0 ( optional )
// Find the vectors to the corners of our simplex pyramid
Pi = floor( P + dot( P, vec3( SKEWFACTOR) ) );
vec3 x0 = P - Pi + dot(Pi, vec3( UNSKEWFACTOR ) );
vec3 g = step(x0.yzx, x0.xyz);
vec3 l = 1.0 - g;
Pi_1 = min( g.xyz, l.zxy );
Pi_2 = max( g.xyz, l.zxy );
vec3 x1 = x0 - Pi_1 + UNSKEWFACTOR;
vec3 x2 = x0 - Pi_2 + SKEWFACTOR;
vec3 x3 = x0 - SIMPLEX_CORNER_POS;
// pack them into a parallel-friendly arrangement
v1234_x = vec4( x0.x, x1.x, x2.x, x3.x );
v1234_y = vec4( x0.y, x1.y, x2.y, x3.y );
v1234_z = vec4( x0.z, x1.z, x2.z, x3.z );
}
//
// Calculate the weights for the 3D simplex surflet
//
vec4 Simplex3D_GetSurfletWeights( vec4 v1234_x,
vec4 v1234_y,
vec4 v1234_z )
{
// perlins original implementation uses the surlet falloff formula of (0.6-x*x)^4.
// This is buggy as it can cause discontinuities along simplex faces. (0.5-x*x)^3 solves this and gives an almost identical curve
// evaluate surflet. f(x)=(0.5-x*x)^3
vec4 surflet_weights = v1234_x * v1234_x + v1234_y * v1234_y + v1234_z * v1234_z;
surflet_weights = max(0.5 - surflet_weights, 0.0); // 0.5 here represents the closest distance (squared) of any simplex pyramid corner to any of its planes. ie, SIMPLEX_PYRAMID_HEIGHT^2
return surflet_weights*surflet_weights*surflet_weights;
}
//
// SimplexPerlin3D ( simplex gradient noise )
// Perlin noise over a simplex (tetrahedron) grid
// Return value range of -1.0->1.0
// http://briansharpe.files.wordpress.com/2012/01/simplexperlinsample.jpg
//
// Implementation originally based off Stefan Gustavson's and Ian McEwan's work at...
// http://github.com/ashima/webgl-noise
//
float SimplexPerlin3D(vec3 P)
{
// calculate the simplex vector and index math
vec3 Pi;
vec3 Pi_1;
vec3 Pi_2;
vec4 v1234_x;
vec4 v1234_y;
vec4 v1234_z;
Simplex3D_GetCornerVectors( P, Pi, Pi_1, Pi_2, v1234_x, v1234_y, v1234_z );
// generate the random vectors
// ( various hashing methods listed in order of speed )
vec4 hash_0;
vec4 hash_1;
vec4 hash_2;
FAST32_hash_3D( Pi, Pi_1, Pi_2, hash_0, hash_1, hash_2 );
//SGPP_hash_3D( Pi, Pi_1, Pi_2, hash_0, hash_1, hash_2 );
hash_0 -= 0.49999;
hash_1 -= 0.49999;
hash_2 -= 0.49999;
// evaluate gradients
vec4 grad_results = inversesqrt( hash_0 * hash_0 + hash_1 * hash_1 + hash_2 * hash_2 ) * ( hash_0 * v1234_x + hash_1 * v1234_y + hash_2 * v1234_z );
// Normalization factor to scale the final result to a strict 1.0->-1.0 range
// x = sqrt( 0.75 ) * 0.5
// NF = 1.0 / ( x * ( ( 0.5 ? x*x ) ^ 3 ) * 2.0 )
// http://briansharpe.wordpress.com/2012/01/13/simplex-noise/#comment-36
const float FINAL_NORMALIZATION = 37.837227241611314102871574478976;
// sum with the surflet and return
return dot( Simplex3D_GetSurfletWeights( v1234_x, v1234_y, v1234_z ), grad_results ) * FINAL_NORMALIZATION;
}
float ridge(vec3 p, int powered, float ridgePower, float offset)
{
// Powered Ridge
if(powered > 0)
{
return pow(offset - abs(4.0*SimplexPerlin3D(p)), ridgePower);
}
else
{
return offset - abs(4.0*SimplexPerlin3D(p));
}
}
//
// 3D fractional Brownian Motion
//
float fBM(vec3 p, vec3 offset, float frequency, float amplitude, float lacunarity, float persistence, int powered, float ridgePower, float ridgeOffset)
{
float sum = 0.0;
float bias = 0.0;
for (int i = 0; i < OCTAVES; i++)
{
float h = 0.5 * (1.0 + ridge((p+offset)*frequency, powered, ridgePower, ridgeOffset));
sum += h*amplitude;
bias -= amplitude;
frequency *= lacunarity;
amplitude *= persistence;
}
sum += 0.5 * bias;
return sum;
}
#define gl_ModelViewProjectionMatrix glstate_matrix_mvp
uniform mat4 glstate_matrix_mvp;
#define gl_Vertex _glesVertex
attribute vec4 _glesVertex;
#define gl_MultiTexCoord0 _glesMultiTexCoord0
attribute vec4 _glesMultiTexCoord0;
uniform float _Displace;
varying vec4 position;
varying vec2 texCoord;
void main()
{
position = gl_Vertex;
if(_Displace > 0.0)
{
position.y = fBM(vec3(position.xz, _Time*_AnimSpeed), _NoiseOffset, _Frequency, _Amplitude, _Lacunarity, _Persistence, _Powered, _RidgePower, _RidgeOffset);
}
gl_Position = gl_ModelViewProjectionMatrix * position;
texCoord = gl_MultiTexCoord0.xy;
}
Fragment Shader:
precision mediump float;
#define SHADER_API_GLES 1
#define tex2D texture2D
#line 37
precision mediump float;
const int OCTAVES = 12;
uniform vec4 _Time;
uniform float _Frequency;
uniform float _Amplitude;
uniform vec3 _NoiseOffset;
uniform float _Contribution;
uniform float _Normalize;
uniform float _AnimSpeed;
uniform float _Lacunarity;
uniform float _Persistence;
uniform int _Powered;
uniform float _RidgePower;
uniform float _RidgeOffset;
//
// FAST32_hash
// A very fast hashing function. Requires 32bit support.
// http://briansharpe.wordpress.com/2011/11/15/a-fast-and-simple-32bit-floating-point-hash-function/
//
// The hash formula takes the form....
// hash = mod( coord.x * coord.x * coord.y * coord.y, SOMELARGEFLOAT ) / SOMELARGEFLOAT
// We truncate and offset the domain to the most interesting part of the noise.
// SOMELARGEFLOAT should be in the range of 400.0->1000.0 and needs to be hand picked. Only some give good results.
// 3D Noise is achieved by offsetting the SOMELARGEFLOAT value by the Z coordinate
//
void FAST32_hash_3D(vec3 gridcell,
vec3 v1_mask, // user definable v1 and v2. ( 0's and 1's )
vec3 v2_mask,
out vec4 hash_0,
out vec4 hash_1,
out vec4 hash_2 ) // generates 3 random numbers for each of the 4 3D cell corners. cell corners: v0=0,0,0 v3=1,1,1 the other two are user definable
{
// gridcell is assumed to be an integer coordinate
// TODO: these constants need tweaked to find the best possible noise.
// probably requires some kind of brute force computational searching or something....
const vec2 OFFSET = vec2( 50.0, 161.0 );
const float DOMAIN = 69.0;
const vec3 SOMELARGEFLOATS = vec3( 635.298681, 682.357502, 668.926525 );
const vec3 ZINC = vec3( 48.500388, 65.294118, 63.934599 );
// truncate the domain
gridcell.xyz = gridcell.xyz - floor(gridcell.xyz * ( 1.0 / DOMAIN )) * DOMAIN;
vec3 gridcell_inc1 = step( gridcell, vec3( DOMAIN - 1.5 ) ) * ( gridcell + 1.0 );
// compute x*x*y*y for the 4 corners
vec4 P = vec4( gridcell.xy, gridcell_inc1.xy ) + OFFSET.xyxy;
P *= P;
vec4 V1xy_V2xy = mix( P.xyxy, P.zwzw, vec4( v1_mask.xy, v2_mask.xy ) ); // apply mask for v1 and v2
P = vec4( P.x, V1xy_V2xy.xz, P.z ) * vec4( P.y, V1xy_V2xy.yw, P.w );
// get the lowz and highz mods
vec3 lowz_mods = vec3( 1.0 / ( SOMELARGEFLOATS.xyz + gridcell.zzz * ZINC.xyz ) );
vec3 highz_mods = vec3( 1.0 / ( SOMELARGEFLOATS.xyz + gridcell_inc1.zzz * ZINC.xyz ) );
// apply mask for v1 and v2 mod values
v1_mask = ( v1_mask.z < 0.5 ) ? lowz_mods : highz_mods;
v2_mask = ( v2_mask.z < 0.5 ) ? lowz_mods : highz_mods;
// compute the final hash
hash_0 = fract( P * vec4( lowz_mods.x, v1_mask.x, v2_mask.x, highz_mods.x ) );
hash_1 = fract( P * vec4( lowz_mods.y, v1_mask.y, v2_mask.y, highz_mods.y ) );
hash_2 = fract( P * vec4( lowz_mods.z, v1_mask.z, v2_mask.z, highz_mods.z ) );
}
//
// Given an arbitrary 3D point this calculates the 4 vectors from the corners of the simplex pyramid to the point
// It also returns the integer grid index information for the corners
//
void Simplex3D_GetCornerVectors( vec3 P, // input point
out vec3 Pi, // integer grid index for the origin
out vec3 Pi_1, // offsets for the 2nd and 3rd corners. ( the 4th = Pi + 1.0 )
out vec3 Pi_2,
out vec4 v1234_x, // vectors from the 4 corners to the intput point
out vec4 v1234_y,
out vec4 v1234_z )
{
//
// Simplex math from Stefan Gustavson's and Ian McEwan's work at...
// http://github.com/ashima/webgl-noise
//
// simplex math constants
const float SKEWFACTOR = 1.0/3.0;
const float UNSKEWFACTOR = 1.0/6.0;
const float SIMPLEX_CORNER_POS = 0.5;
const float SIMPLEX_PYRAMID_HEIGHT = 0.70710678118654752440084436210485; // sqrt( 0.5 ) height of simplex pyramid.
P *= SIMPLEX_PYRAMID_HEIGHT; // scale space so we can have an approx feature size of 1.0 ( optional )
// Find the vectors to the corners of our simplex pyramid
Pi = floor( P + dot( P, vec3( SKEWFACTOR) ) );
vec3 x0 = P - Pi + dot(Pi, vec3( UNSKEWFACTOR ) );
vec3 g = step(x0.yzx, x0.xyz);
vec3 l = 1.0 - g;
Pi_1 = min( g.xyz, l.zxy );
Pi_2 = max( g.xyz, l.zxy );
vec3 x1 = x0 - Pi_1 + UNSKEWFACTOR;
vec3 x2 = x0 - Pi_2 + SKEWFACTOR;
vec3 x3 = x0 - SIMPLEX_CORNER_POS;
// pack them into a parallel-friendly arrangement
v1234_x = vec4( x0.x, x1.x, x2.x, x3.x );
v1234_y = vec4( x0.y, x1.y, x2.y, x3.y );
v1234_z = vec4( x0.z, x1.z, x2.z, x3.z );
}
//
// Calculate the weights for the 3D simplex surflet
//
vec4 Simplex3D_GetSurfletWeights( vec4 v1234_x,
vec4 v1234_y,
vec4 v1234_z )
{
// perlins original implementation uses the surlet falloff formula of (0.6-x*x)^4.
// This is buggy as it can cause discontinuities along simplex faces. (0.5-x*x)^3 solves this and gives an almost identical curve
// evaluate surflet. f(x)=(0.5-x*x)^3
vec4 surflet_weights = v1234_x * v1234_x + v1234_y * v1234_y + v1234_z * v1234_z;
surflet_weights = max(0.5 - surflet_weights, 0.0); // 0.5 here represents the closest distance (squared) of any simplex pyramid corner to any of its planes. ie, SIMPLEX_PYRAMID_HEIGHT^2
return surflet_weights*surflet_weights*surflet_weights;
}
//
// SimplexPerlin3D ( simplex gradient noise )
// Perlin noise over a simplex (tetrahedron) grid
// Return value range of -1.0->1.0
// http://briansharpe.files.wordpress.com/2012/01/simplexperlinsample.jpg
//
// Implementation originally based off Stefan Gustavson's and Ian McEwan's work at...
// http://github.com/ashima/webgl-noise
//
float SimplexPerlin3D(vec3 P)
{
// calculate the simplex vector and index math
vec3 Pi;
vec3 Pi_1;
vec3 Pi_2;
vec4 v1234_x;
vec4 v1234_y;
vec4 v1234_z;
Simplex3D_GetCornerVectors( P, Pi, Pi_1, Pi_2, v1234_x, v1234_y, v1234_z );
// generate the random vectors
// ( various hashing methods listed in order of speed )
vec4 hash_0;
vec4 hash_1;
vec4 hash_2;
FAST32_hash_3D( Pi, Pi_1, Pi_2, hash_0, hash_1, hash_2 );
//SGPP_hash_3D( Pi, Pi_1, Pi_2, hash_0, hash_1, hash_2 );
hash_0 -= 0.49999;
hash_1 -= 0.49999;
hash_2 -= 0.49999;
// evaluate gradients
vec4 grad_results = inversesqrt( hash_0 * hash_0 + hash_1 * hash_1 + hash_2 * hash_2 ) * ( hash_0 * v1234_x + hash_1 * v1234_y + hash_2 * v1234_z );
// Normalization factor to scale the final result to a strict 1.0->-1.0 range
// x = sqrt( 0.75 ) * 0.5
// NF = 1.0 / ( x * ( ( 0.5 ? x*x ) ^ 3 ) * 2.0 )
// http://briansharpe.wordpress.com/2012/01/13/simplex-noise/#comment-36
const float FINAL_NORMALIZATION = 37.837227241611314102871574478976;
// sum with the surflet and return
return dot( Simplex3D_GetSurfletWeights( v1234_x, v1234_y, v1234_z ), grad_results ) * FINAL_NORMALIZATION;
}
float ridge(vec3 p, int powered, float ridgePower, float offset)
{
// Powered Ridge
if(powered > 0)
{
return pow(offset - abs(4.0*SimplexPerlin3D(p)), ridgePower);
}
else
{
return offset - abs(4.0*SimplexPerlin3D(p));
}
}
//
// 3D fractional Brownian Motion
//
float fBM(vec3 p, vec3 offset, float frequency, float amplitude, float lacunarity, float persistence, int powered, float ridgePower, float ridgeOffset)
{
float sum = 0.0;
float bias = 0.0;
for (int i = 0; i < OCTAVES; i++)
{
float h = 0.5 * (1.0 + ridge((p+offset)*frequency, powered, ridgePower, ridgeOffset));
sum += h*amplitude;
bias -= amplitude;
frequency *= lacunarity;
amplitude *= persistence;
}
sum += 0.5 * bias;
return sum;
}
uniform vec4 _LowColor;
uniform vec4 _HighColor;
uniform float _Texturing;
uniform sampler2D _LowTexture;
uniform vec4 _LowTexture_ST;
uniform sampler2D _HighTexture;
uniform vec4 _HighTexture_ST;
varying vec4 position;
varying vec2 texCoord;
void main()
{
float h = fBM(vec3(vec2(position.xz), _Time*_AnimSpeed), _NoiseOffset, _Frequency, _Amplitude, _Lacunarity, _Persistence, _Powered, _RidgePower, _RidgeOffset);
if(_Normalize > 0.0)
{
// set range to (0, 1)
h = h*0.5 + 0.5;
}
// do the accumulation with the previous fixed-point height
h = h*_Contribution;
vec4 color;
if(_Texturing > 0.0)
{
color = mix(_LowColor * texture2D(_LowTexture, _LowTexture_ST.xy * texCoord + _LowTexture_ST.zw), _HighColor * texture2D(_HighTexture, _HighTexture_ST.xy * texCoord + _HighTexture_ST.zw), h);
}
else
{
color = mix(_LowColor, _HighColor, h);
}
gl_FragColor = vec4(color.r, color.g, color.b, h);
}
-------- GLSL error: ERROR: Uniform precision mismatch '_Powered'
Vertex Shader:
#define SHADER_API_GLES 1
#define tex2D texture2D
#line 38
precision mediump float;
const int OCTAVES = 12;
uniform vec4 _Time;
uniform float _Frequency;
uniform float _Amplitude;
uniform vec3 _NoiseOffset;
uniform float _Contribution;
uniform float _Normalize;
uniform float _AnimSpeed;
uniform float _Lacunarity;
uniform float _Persistence;
uniform int _Powered;
uniform float _RidgePower;
uniform float _RidgeOffset;
//
// FAST32_hash
// A very fast hashing function. Requires 32bit support.
// http://briansharpe.wordpress.com/2011/11/15/a-fast-and-simple-32bit-floating-point-hash-function/
//
// The hash formula takes the form....
// hash = mod( coord.x * coord.x * coord.y * coord.y, SOMELARGEFLOAT ) / SOMELARGEFLOAT
// We truncate and offset the domain to the most interesting part of the noise.
// SOMELARGEFLOAT should be in the range of 400.0->1000.0 and needs to be hand picked. Only some give good results.
// 3D Noise is achieved by offsetting the SOMELARGEFLOAT value by the Z coordinate
//
void FAST32_hash_3D( vec3 gridcell,
out vec4 lowz_hash_0,
out vec4 lowz_hash_1,
out vec4 lowz_hash_2,
out vec4 highz_hash_0,
out vec4 highz_hash_1,
out vec4 highz_hash_2 ) // generates 3 random numbers for each of the 8 cell corners
{
// gridcell is assumed to be an integer coordinate
// TODO: these constants need tweaked to find the best possible noise.
// probably requires some kind of brute force computational searching or something....
const vec2 OFFSET = vec2( 50.0, 161.0 );
const float DOMAIN = 69.0;
const vec3 SOMELARGEFLOATS = vec3( 635.298681, 682.357502, 668.926525 );
const vec3 ZINC = vec3( 48.500388, 65.294118, 63.934599 );
// truncate the domain
gridcell.xyz = gridcell.xyz - floor(gridcell.xyz * ( 1.0 / DOMAIN )) * DOMAIN;
vec3 gridcell_inc1 = step( gridcell, vec3( DOMAIN - 1.5 ) ) * ( gridcell + 1.0 );
// calculate the noise
vec4 P = vec4( gridcell.xy, gridcell_inc1.xy ) + OFFSET.xyxy;
P *= P;
P = P.xzxz * P.yyww;
vec3 lowz_mod = vec3( 1.0 / ( SOMELARGEFLOATS.xyz + gridcell.zzz * ZINC.xyz ) );
vec3 highz_mod = vec3( 1.0 / ( SOMELARGEFLOATS.xyz + gridcell_inc1.zzz * ZINC.xyz ) );
lowz_hash_0 = fract( P * lowz_mod.xxxx );
highz_hash_0 = fract( P * highz_mod.xxxx );
lowz_hash_1 = fract( P * lowz_mod.yyyy );
highz_hash_1 = fract( P * highz_mod.yyyy );
lowz_hash_2 = fract( P * lowz_mod.zzzz );
highz_hash_2 = fract( P * highz_mod.zzzz );
}
//
// Quintic Hermite Interpolation
// http://www.rose-hulman.edu/~finn/CCLI/Notes/day09.pdf
//
// NOTE: maximum value of a hermitequintic interpolation with zero acceleration at the endpoints would be...
// f(x=0.5) = MAXPOS + MAXVELOCITY * ( ( x - 6x^3 + 8x^4 - 3x^5 ) - ( -4x^3 + 7x^4 -3x^5 ) ) = MAXPOS + MAXVELOCITY * 0.3125
//
// variable naming conventions:
// val = value ( position )
// grad = gradient ( velocity )
// x = 0.0->1.0 ( time )
// i = interpolation = a value to be interpolated
// e = evaluation = a value to be used to calculate the interpolation
// 0 = start
// 1 = end
//
float QuinticHermite( float x, float ival0, float ival1, float egrad0, float egrad1 ) // quintic hermite with start/end acceleration of 0.0
{
const vec3 C0 = vec3( -15.0, 8.0, 7.0 );
const vec3 C1 = vec3( 6.0, -3.0, -3.0 );
const vec3 C2 = vec3( 10.0, -6.0, -4.0 );
vec3 h123 = ( ( ( C0 + C1 * x ) * x ) + C2 ) * ( x*x*x );
return ival0 + dot( vec3( (ival1 - ival0), egrad0, egrad1 ), h123.xyz + vec3( 0.0, x, 0.0 ) );
}
vec4 QuinticHermite( float x, vec4 ival0, vec4 ival1, vec4 egrad0, vec4 egrad1 ) // quintic hermite with start/end acceleration of 0.0
{
const vec3 C0 = vec3( -15.0, 8.0, 7.0 );
const vec3 C1 = vec3( 6.0, -3.0, -3.0 );
const vec3 C2 = vec3( 10.0, -6.0, -4.0 );
vec3 h123 = ( ( ( C0 + C1 * x ) * x ) + C2 ) * ( x*x*x );
return ival0 + (ival1 - ival0) * h123.xxxx + egrad0 * vec4( h123.y + x ) + egrad1 * h123.zzzz;
}
vec4 QuinticHermite( float x, vec2 igrad0, vec2 igrad1, vec2 egrad0, vec2 egrad1 ) // quintic hermite with start/end position and acceleration of 0.0
{
const vec3 C0 = vec3( -15.0, 8.0, 7.0 );
const vec3 C1 = vec3( 6.0, -3.0, -3.0 );
const vec3 C2 = vec3( 10.0, -6.0, -4.0 );
vec3 h123 = ( ( ( C0 + C1 * x ) * x ) + C2 ) * ( x*x*x );
return vec4( egrad1, igrad0 ) * vec4( h123.zz, 1.0, 1.0 ) + vec4( egrad0, h123.xx ) * vec4( vec2( h123.y + x ), (igrad1 - igrad0) ); // returns vec4( out_ival.xy, out_igrad.xy )
}
void QuinticHermite( float x,
vec4 ival0, vec4 ival1, // values are interpolated using the gradient arguments
vec4 igrad_x0, vec4 igrad_x1, // gradients are interpolated using eval gradients of 0.0
vec4 igrad_y0, vec4 igrad_y1,
vec4 egrad0, vec4 egrad1, // our evaluation gradients
out vec4 out_ival, out vec4 out_igrad_x, out vec4 out_igrad_y ) // quintic hermite with start/end acceleration of 0.0
{
const vec3 C0 = vec3( -15.0, 8.0, 7.0 );
const vec3 C1 = vec3( 6.0, -3.0, -3.0 );
const vec3 C2 = vec3( 10.0, -6.0, -4.0 );
vec3 h123 = ( ( ( C0 + C1 * x ) * x ) + C2 ) * ( x*x*x );
out_ival = ival0 + (ival1 - ival0) * h123.xxxx + egrad0 * vec4( h123.y + x ) + egrad1 * h123.zzzz;
out_igrad_x = igrad_x0 + (igrad_x1 - igrad_x0) * h123.xxxx; // NOTE: gradients of 0.0
out_igrad_y = igrad_y0 + (igrad_y1 - igrad_y0) * h123.xxxx; // NOTE: gradients of 0.0
}
void QuinticHermite( float x,
vec4 igrad_x0, vec4 igrad_x1, // gradients are interpolated using eval gradients of 0.0
vec4 igrad_y0, vec4 igrad_y1,
vec4 egrad0, vec4 egrad1, // our evaluation gradients
out vec4 out_ival, out vec4 out_igrad_x, out vec4 out_igrad_y ) // quintic hermite with start/end position and acceleration of 0.0
{
const vec3 C0 = vec3( -15.0, 8.0, 7.0 );
const vec3 C1 = vec3( 6.0, -3.0, -3.0 );
const vec3 C2 = vec3( 10.0, -6.0, -4.0 );
vec3 h123 = ( ( ( C0 + C1 * x ) * x ) + C2 ) * ( x*x*x );
out_ival = egrad0 * vec4( h123.y + x ) + egrad1 * h123.zzzz;
out_igrad_x = igrad_x0 + (igrad_x1 - igrad_x0) * h123.xxxx; // NOTE: gradients of 0.0
out_igrad_y = igrad_y0 + (igrad_y1 - igrad_y0) * h123.xxxx; // NOTE: gradients of 0.0
}
float QuinticHermiteDeriv( float x, float ival0, float ival1, float egrad0, float egrad1 ) // gives the derivative of quintic hermite with start/end acceleration of 0.0
{
const vec3 C0 = vec3( 30.0, -15.0, -15.0 );
const vec3 C1 = vec3( -60.0, 32.0, 28.0 );
const vec3 C2 = vec3( 30.0, -18.0, -12.0 );
vec3 h123 = ( ( ( C1 + C0 * x ) * x ) + C2 ) * ( x*x );
return dot( vec3( (ival1 - ival0), egrad0, egrad1 ), h123.xyz + vec3( 0.0, 1.0, 0.0 ) );
}
//
// Hermite3D
// Return value range of -1.0->1.0
// http://briansharpe.files.wordpress.com/2012/01/hermitesample.jpg
//
float Hermite3D( vec3 P )
{
// establish our grid cell and unit position
vec3 Pi = floor(P);
vec3 Pf = P - Pi;
// calculate the hash.
// ( various hashing methods listed in order of speed )
vec4 hash_gradx0, hash_grady0, hash_gradz0, hash_gradx1, hash_grady1, hash_gradz1;
FAST32_hash_3D( Pi, hash_gradx0, hash_grady0, hash_gradz0, hash_gradx1, hash_grady1, hash_gradz1 );
// scale the hash values
hash_gradx0 = ( hash_gradx0 - 0.49999);
hash_grady0 = ( hash_grady0 - 0.49999);
hash_gradz0 = ( hash_gradz0 - 0.49999);
hash_gradx1 = ( hash_gradx1 - 0.49999);
hash_grady1 = ( hash_grady1 - 0.49999);
hash_gradz1 = ( hash_gradz1 - 0.49999);
#if 1
// normalize gradients
vec4 norm0 = inversesqrt( hash_gradx0 * hash_gradx0 + hash_grady0 * hash_grady0 + hash_gradz0 * hash_gradz0 );
hash_gradx0 *= norm0;
hash_grady0 *= norm0;
hash_gradz0 *= norm0;
vec4 norm1 = inversesqrt( hash_gradx1 * hash_gradx1 + hash_grady1 * hash_grady1 + hash_gradz1 * hash_gradz1 );
hash_gradx1 *= norm1;
hash_grady1 *= norm1;
hash_gradz1 *= norm1;
const float FINAL_NORM_VAL = 1.8475208614068024464292760976063;
#else
// unnormalized gradients
const float FINAL_NORM_VAL = (1.0/0.46875); // = 1.0 / ( 0.5 * 0.3125 * 3.0 )
#endif
// evaluate the hermite
vec4 ival_results, igrad_results_x, igrad_results_y;
QuinticHermite( Pf.z, hash_gradx0, hash_gradx1, hash_grady0, hash_grady1, hash_gradz0, hash_gradz1, ival_results, igrad_results_x, igrad_results_y );
vec4 qh_results = QuinticHermite( Pf.y, vec4(ival_results.xy, igrad_results_x.xy), vec4(ival_results.zw, igrad_results_x.zw), vec4( igrad_results_y.xy, 0.0, 0.0 ), vec4( igrad_results_y.zw, 0.0, 0.0 ) );
return QuinticHermite( Pf.x, qh_results.x, qh_results.y, qh_results.z, qh_results.w ) * FINAL_NORM_VAL;
}
float ridge(vec3 p, int powered, float ridgePower, float offset)
{
// Powered Ridge
if(powered > 0)
{
return pow(offset - abs(4.0*Hermite3D(p)), ridgePower);
}
else
{
return offset - abs(4.0*Hermite3D(p));
}
}
//
// 3D fractional Brownian Motion
//
float fBM(vec3 p, vec3 offset, float frequency, float amplitude, float lacunarity, float persistence, int powered, float ridgePower, float ridgeOffset)
{
float sum = 0.0;
float bias = 0.0;
for (int i = 0; i < OCTAVES; i++)
{
float h = 0.5 * (1.0 + ridge((p+offset)*frequency, powered, ridgePower, ridgeOffset));
sum += h*amplitude;
bias -= amplitude;
frequency *= lacunarity;
amplitude *= persistence;
}
sum += 0.5 * bias;
return sum;
}
#define gl_ModelViewProjectionMatrix glstate_matrix_mvp
uniform mat4 glstate_matrix_mvp;
#define gl_Vertex _glesVertex
attribute vec4 _glesVertex;
#define gl_MultiTexCoord0 _glesMultiTexCoord0
attribute vec4 _glesMultiTexCoord0;
uniform float _Displace;
varying vec4 position;
varying vec2 texCoord;
void main()
{
position = gl_Vertex;
if(_Displace > 0.0)
{
position.y = fBM(vec3(position.xz, _Time*_AnimSpeed), _NoiseOffset, _Frequency, _Amplitude, _Lacunarity, _Persistence, _Powered, _RidgePower, _RidgeOffset);
}
gl_Position = gl_ModelViewProjectionMatrix * position;
texCoord = gl_MultiTexCoord0.xy;
}
Fragment Shader:
precision mediump float;
#define SHADER_API_GLES 1
#define tex2D texture2D
#line 38
precision mediump float;
const int OCTAVES = 12;
uniform vec4 _Time;
uniform float _Frequency;
uniform float _Amplitude;
uniform vec3 _NoiseOffset;
uniform float _Contribution;
uniform float _Normalize;
uniform float _AnimSpeed;
uniform float _Lacunarity;
uniform float _Persistence;
uniform int _Powered;
uniform float _RidgePower;
uniform float _RidgeOffset;
//
// FAST32_hash
// A very fast hashing function. Requires 32bit support.
// http://briansharpe.wordpress.com/2011/11/15/a-fast-and-simple-32bit-floating-point-hash-function/
//
// The hash formula takes the form....
// hash = mod( coord.x * coord.x * coord.y * coord.y, SOMELARGEFLOAT ) / SOMELARGEFLOAT
// We truncate and offset the domain to the most interesting part of the noise.
// SOMELARGEFLOAT should be in the range of 400.0->1000.0 and needs to be hand picked. Only some give good results.
// 3D Noise is achieved by offsetting the SOMELARGEFLOAT value by the Z coordinate
//
void FAST32_hash_3D( vec3 gridcell,
out vec4 lowz_hash_0,
out vec4 lowz_hash_1,
out vec4 lowz_hash_2,
out vec4 highz_hash_0,
out vec4 highz_hash_1,
out vec4 highz_hash_2 ) // generates 3 random numbers for each of the 8 cell corners
{
// gridcell is assumed to be an integer coordinate
// TODO: these constants need tweaked to find the best possible noise.
// probably requires some kind of brute force computational searching or something....
const vec2 OFFSET = vec2( 50.0, 161.0 );
const float DOMAIN = 69.0;
const vec3 SOMELARGEFLOATS = vec3( 635.298681, 682.357502, 668.926525 );
const vec3 ZINC = vec3( 48.500388, 65.294118, 63.934599 );
// truncate the domain
gridcell.xyz = gridcell.xyz - floor(gridcell.xyz * ( 1.0 / DOMAIN )) * DOMAIN;
vec3 gridcell_inc1 = step( gridcell, vec3( DOMAIN - 1.5 ) ) * ( gridcell + 1.0 );
// calculate the noise
vec4 P = vec4( gridcell.xy, gridcell_inc1.xy ) + OFFSET.xyxy;
P *= P;
P = P.xzxz * P.yyww;
vec3 lowz_mod = vec3( 1.0 / ( SOMELARGEFLOATS.xyz + gridcell.zzz * ZINC.xyz ) );
vec3 highz_mod = vec3( 1.0 / ( SOMELARGEFLOATS.xyz + gridcell_inc1.zzz * ZINC.xyz ) );
lowz_hash_0 = fract( P * lowz_mod.xxxx );
highz_hash_0 = fract( P * highz_mod.xxxx );
lowz_hash_1 = fract( P * lowz_mod.yyyy );
highz_hash_1 = fract( P * highz_mod.yyyy );
lowz_hash_2 = fract( P * lowz_mod.zzzz );
highz_hash_2 = fract( P * highz_mod.zzzz );
}
//
// Quintic Hermite Interpolation
// http://www.rose-hulman.edu/~finn/CCLI/Notes/day09.pdf
//
// NOTE: maximum value of a hermitequintic interpolation with zero acceleration at the endpoints would be...
// f(x=0.5) = MAXPOS + MAXVELOCITY * ( ( x - 6x^3 + 8x^4 - 3x^5 ) - ( -4x^3 + 7x^4 -3x^5 ) ) = MAXPOS + MAXVELOCITY * 0.3125
//
// variable naming conventions:
// val = value ( position )
// grad = gradient ( velocity )
// x = 0.0->1.0 ( time )
// i = interpolation = a value to be interpolated
// e = evaluation = a value to be used to calculate the interpolation
// 0 = start
// 1 = end
//
float QuinticHermite( float x, float ival0, float ival1, float egrad0, float egrad1 ) // quintic hermite with start/end acceleration of 0.0
{
const vec3 C0 = vec3( -15.0, 8.0, 7.0 );
const vec3 C1 = vec3( 6.0, -3.0, -3.0 );
const vec3 C2 = vec3( 10.0, -6.0, -4.0 );
vec3 h123 = ( ( ( C0 + C1 * x ) * x ) + C2 ) * ( x*x*x );
return ival0 + dot( vec3( (ival1 - ival0), egrad0, egrad1 ), h123.xyz + vec3( 0.0, x, 0.0 ) );
}
vec4 QuinticHermite( float x, vec4 ival0, vec4 ival1, vec4 egrad0, vec4 egrad1 ) // quintic hermite with start/end acceleration of 0.0
{
const vec3 C0 = vec3( -15.0, 8.0, 7.0 );
const vec3 C1 = vec3( 6.0, -3.0, -3.0 );
const vec3 C2 = vec3( 10.0, -6.0, -4.0 );
vec3 h123 = ( ( ( C0 + C1 * x ) * x ) + C2 ) * ( x*x*x );
return ival0 + (ival1 - ival0) * h123.xxxx + egrad0 * vec4( h123.y + x ) + egrad1 * h123.zzzz;
}
vec4 QuinticHermite( float x, vec2 igrad0, vec2 igrad1, vec2 egrad0, vec2 egrad1 ) // quintic hermite with start/end position and acceleration of 0.0
{
const vec3 C0 = vec3( -15.0, 8.0, 7.0 );
const vec3 C1 = vec3( 6.0, -3.0, -3.0 );
const vec3 C2 = vec3( 10.0, -6.0, -4.0 );
vec3 h123 = ( ( ( C0 + C1 * x ) * x ) + C2 ) * ( x*x*x );
return vec4( egrad1, igrad0 ) * vec4( h123.zz, 1.0, 1.0 ) + vec4( egrad0, h123.xx ) * vec4( vec2( h123.y + x ), (igrad1 - igrad0) ); // returns vec4( out_ival.xy, out_igrad.xy )
}
void QuinticHermite( float x,
vec4 ival0, vec4 ival1, // values are interpolated using the gradient arguments
vec4 igrad_x0, vec4 igrad_x1, // gradients are interpolated using eval gradients of 0.0
vec4 igrad_y0, vec4 igrad_y1,
vec4 egrad0, vec4 egrad1, // our evaluation gradients
out vec4 out_ival, out vec4 out_igrad_x, out vec4 out_igrad_y ) // quintic hermite with start/end acceleration of 0.0
{
const vec3 C0 = vec3( -15.0, 8.0, 7.0 );
const vec3 C1 = vec3( 6.0, -3.0, -3.0 );
const vec3 C2 = vec3( 10.0, -6.0, -4.0 );
vec3 h123 = ( ( ( C0 + C1 * x ) * x ) + C2 ) * ( x*x*x );
out_ival = ival0 + (ival1 - ival0) * h123.xxxx + egrad0 * vec4( h123.y + x ) + egrad1 * h123.zzzz;
out_igrad_x = igrad_x0 + (igrad_x1 - igrad_x0) * h123.xxxx; // NOTE: gradients of 0.0
out_igrad_y = igrad_y0 + (igrad_y1 - igrad_y0) * h123.xxxx; // NOTE: gradients of 0.0
}
void QuinticHermite( float x,
vec4 igrad_x0, vec4 igrad_x1, // gradients are interpolated using eval gradients of 0.0
vec4 igrad_y0, vec4 igrad_y1,
vec4 egrad0, vec4 egrad1, // our evaluation gradients
out vec4 out_ival, out vec4 out_igrad_x, out vec4 out_igrad_y ) // quintic hermite with start/end position and acceleration of 0.0
{
const vec3 C0 = vec3( -15.0, 8.0, 7.0 );
const vec3 C1 = vec3( 6.0, -3.0, -3.0 );
const vec3 C2 = vec3( 10.0, -6.0, -4.0 );
vec3 h123 = ( ( ( C0 + C1 * x ) * x ) + C2 ) * ( x*x*x );
out_ival = egrad0 * vec4( h123.y + x ) + egrad1 * h123.zzzz;
out_igrad_x = igrad_x0 + (igrad_x1 - igrad_x0) * h123.xxxx; // NOTE: gradients of 0.0
out_igrad_y = igrad_y0 + (igrad_y1 - igrad_y0) * h123.xxxx; // NOTE: gradients of 0.0
}
float QuinticHermiteDeriv( float x, float ival0, float ival1, float egrad0, float egrad1 ) // gives the derivative of quintic hermite with start/end acceleration of 0.0
{
const vec3 C0 = vec3( 30.0, -15.0, -15.0 );
const vec3 C1 = vec3( -60.0, 32.0, 28.0 );
const vec3 C2 = vec3( 30.0, -18.0, -12.0 );
vec3 h123 = ( ( ( C1 + C0 * x ) * x ) + C2 ) * ( x*x );
return dot( vec3( (ival1 - ival0), egrad0, egrad1 ), h123.xyz + vec3( 0.0, 1.0, 0.0 ) );
}
//
// Hermite3D
// Return value range of -1.0->1.0
// http://briansharpe.files.wordpress.com/2012/01/hermitesample.jpg
//
float Hermite3D( vec3 P )
{
// establish our grid cell and unit position
vec3 Pi = floor(P);
vec3 Pf = P - Pi;
// calculate the hash.
// ( various hashing methods listed in order of speed )
vec4 hash_gradx0, hash_grady0, hash_gradz0, hash_gradx1, hash_grady1, hash_gradz1;
FAST32_hash_3D( Pi, hash_gradx0, hash_grady0, hash_gradz0, hash_gradx1, hash_grady1, hash_gradz1 );
// scale the hash values
hash_gradx0 = ( hash_gradx0 - 0.49999);
hash_grady0 = ( hash_grady0 - 0.49999);
hash_gradz0 = ( hash_gradz0 - 0.49999);
hash_gradx1 = ( hash_gradx1 - 0.49999);
hash_grady1 = ( hash_grady1 - 0.49999);
hash_gradz1 = ( hash_gradz1 - 0.49999);
#if 1
// normalize gradients
vec4 norm0 = inversesqrt( hash_gradx0 * hash_gradx0 + hash_grady0 * hash_grady0 + hash_gradz0 * hash_gradz0 );
hash_gradx0 *= norm0;
hash_grady0 *= norm0;
hash_gradz0 *= norm0;
vec4 norm1 = inversesqrt( hash_gradx1 * hash_gradx1 + hash_grady1 * hash_grady1 + hash_gradz1 * hash_gradz1 );
hash_gradx1 *= norm1;
hash_grady1 *= norm1;
hash_gradz1 *= norm1;
const float FINAL_NORM_VAL = 1.8475208614068024464292760976063;
#else
// unnormalized gradients
const float FINAL_NORM_VAL = (1.0/0.46875); // = 1.0 / ( 0.5 * 0.3125 * 3.0 )
#endif
// evaluate the hermite
vec4 ival_results, igrad_results_x, igrad_results_y;
QuinticHermite( Pf.z, hash_gradx0, hash_gradx1, hash_grady0, hash_grady1, hash_gradz0, hash_gradz1, ival_results, igrad_results_x, igrad_results_y );
vec4 qh_results = QuinticHermite( Pf.y, vec4(ival_results.xy, igrad_results_x.xy), vec4(ival_results.zw, igrad_results_x.zw), vec4( igrad_results_y.xy, 0.0, 0.0 ), vec4( igrad_results_y.zw, 0.0, 0.0 ) );
return QuinticHermite( Pf.x, qh_results.x, qh_results.y, qh_results.z, qh_results.w ) * FINAL_NORM_VAL;
}
float ridge(vec3 p, int powered, float ridgePower, float offset)
{
// Powered Ridge
if(powered > 0)
{
return pow(offset - abs(4.0*Hermite3D(p)), ridgePower);
}
else
{
return offset - abs(4.0*Hermite3D(p));
}
}
//
// 3D fractional Brownian Motion
//
float fBM(vec3 p, vec3 offset, float frequency, float amplitude, float lacunarity, float persistence, int powered, float ridgePower, float ridgeOffset)
{
float sum = 0.0;
float bias = 0.0;
for (int i = 0; i < OCTAVES; i++)
{
float h = 0.5 * (1.0 + ridge((p+offset)*frequency, powered, ridgePower, ridgeOffset));
sum += h*amplitude;
bias -= amplitude;
frequency *= lacunarity;
amplitude *= persistence;
}
sum += 0.5 * bias;
return sum;
}
uniform vec4 _LowColor;
uniform vec4 _HighColor;
uniform float _Texturing;
uniform sampler2D _LowTexture;
uniform vec4 _LowTexture_ST;
uniform sampler2D _HighTexture;
uniform vec4 _HighTexture_ST;
varying vec4 position;
varying vec2 texCoord;
void main()
{
float h = fBM(vec3(vec2(position.xz), _Time*_AnimSpeed), _NoiseOffset, _Frequency, _Amplitude, _Lacunarity, _Persistence, _Powered, _RidgePower, _RidgeOffset);
if(_Normalize > 0.0)
{
// set range to (0, 1)
h = h*0.5 + 0.5;
}
// do the accumulation with the previous fixed-point height
h = h*_Contribution;
vec4 color;
if(_Texturing > 0.0)
{
color = mix(_LowColor * texture2D(_LowTexture, _LowTexture_ST.xy * texCoord + _LowTexture_ST.zw), _HighColor * texture2D(_HighTexture, _HighTexture_ST.xy * texCoord + _HighTexture_ST.zw), h);
}
else
{
color = mix(_LowColor, _HighColor, h);
}
gl_FragColor = vec4(color.r, color.g, color.b, h);
}
-------- GLSL error: ERROR: Uniform precision mismatch '_Powered'
Vertex Shader:
#define SHADER_API_GLES 1
#define tex2D texture2D
#line 36
precision mediump float;
const int OCTAVES = 12;
uniform vec4 _Time;
uniform float _Frequency;
uniform float _Amplitude;
uniform vec3 _NoiseOffset;
uniform float _Contribution;
uniform float _Normalize;
uniform float _AnimSpeed;
uniform float _Lacunarity;
uniform float _Persistence;
uniform int _Powered;
uniform float _BillowPower;
//
// FAST32_hash
// A very fast hashing function. Requires 32bit support.
// http://briansharpe.wordpress.com/2011/11/15/a-fast-and-simple-32bit-floating-point-hash-function/
//
// The hash formula takes the form....
// hash = mod( coord.x * coord.x * coord.y * coord.y, SOMELARGEFLOAT ) / SOMELARGEFLOAT
// We truncate and offset the domain to the most interesting part of the noise.
// SOMELARGEFLOAT should be in the range of 400.0->1000.0 and needs to be hand picked. Only some give good results.
// 3D Noise is achieved by offsetting the SOMELARGEFLOAT value by the Z coordinate
//
void FAST32_hash_3D( vec3 gridcell,
out vec4 lowz_hash_0,
out vec4 lowz_hash_1,
out vec4 lowz_hash_2,
out vec4 highz_hash_0,
out vec4 highz_hash_1,
out vec4 highz_hash_2 ) // generates 3 random numbers for each of the 8 cell corners
{
// gridcell is assumed to be an integer coordinate
// TODO: these constants need tweaked to find the best possible noise.
// probably requires some kind of brute force computational searching or something....
const vec2 OFFSET = vec2( 50.0, 161.0 );
const float DOMAIN = 69.0;
const vec3 SOMELARGEFLOATS = vec3( 635.298681, 682.357502, 668.926525 );
const vec3 ZINC = vec3( 48.500388, 65.294118, 63.934599 );
// truncate the domain
gridcell.xyz = gridcell.xyz - floor(gridcell.xyz * ( 1.0 / DOMAIN )) * DOMAIN;
vec3 gridcell_inc1 = step( gridcell, vec3( DOMAIN - 1.5 ) ) * ( gridcell + 1.0 );
// calculate the noise
vec4 P = vec4( gridcell.xy, gridcell_inc1.xy ) + OFFSET.xyxy;
P *= P;
P = P.xzxz * P.yyww;
vec3 lowz_mod = vec3( 1.0 / ( SOMELARGEFLOATS.xyz + gridcell.zzz * ZINC.xyz ) );
vec3 highz_mod = vec3( 1.0 / ( SOMELARGEFLOATS.xyz + gridcell_inc1.zzz * ZINC.xyz ) );
lowz_hash_0 = fract( P * lowz_mod.xxxx );
highz_hash_0 = fract( P * highz_mod.xxxx );
lowz_hash_1 = fract( P * lowz_mod.yyyy );
highz_hash_1 = fract( P * highz_mod.yyyy );
lowz_hash_2 = fract( P * lowz_mod.zzzz );
highz_hash_2 = fract( P * highz_mod.zzzz );
}
vec3 Interpolation_C2( vec3 x )
{
return x * x * x * (x * (x * 6.0 - 15.0) + 10.0);
}
//
// Perlin Noise 3D ( gradient noise )
// Return value range of -1.0->1.0
// http://briansharpe.files.wordpress.com/2011/11/perlinsample.jpg
//
float Perlin3D( vec3 P )
{
// establish our grid cell and unit position
vec3 Pi = floor(P);
vec3 Pf = P - Pi;
vec3 Pf_min1 = Pf - 1.0;
#if 1
//
// classic noise.
// requires 3 random values per point. with an efficent hash function will run faster than improved noise
//
// calculate the hash.
// ( various hashing methods listed in order of speed )
vec4 hashx0, hashy0, hashz0, hashx1, hashy1, hashz1;
FAST32_hash_3D( Pi, hashx0, hashy0, hashz0, hashx1, hashy1, hashz1 );
//SGPP_hash_3D( Pi, hashx0, hashy0, hashz0, hashx1, hashy1, hashz1 );
// calculate the gradients
vec4 grad_x0 = hashx0 - 0.49999;
vec4 grad_y0 = hashy0 - 0.49999;
vec4 grad_z0 = hashz0 - 0.49999;
vec4 grad_x1 = hashx1 - 0.49999;
vec4 grad_y1 = hashy1 - 0.49999;
vec4 grad_z1 = hashz1 - 0.49999;
vec4 grad_results_0 = inversesqrt( grad_x0 * grad_x0 + grad_y0 * grad_y0 + grad_z0 * grad_z0 ) * ( vec2( Pf.x, Pf_min1.x ).xyxy * grad_x0 + vec2( Pf.y, Pf_min1.y ).xxyy * grad_y0 + Pf.zzzz * grad_z0 );
vec4 grad_results_1 = inversesqrt( grad_x1 * grad_x1 + grad_y1 * grad_y1 + grad_z1 * grad_z1 ) * ( vec2( Pf.x, Pf_min1.x ).xyxy * grad_x1 + vec2( Pf.y, Pf_min1.y ).xxyy * grad_y1 + Pf_min1.zzzz * grad_z1 );
#if 1
// Classic Perlin Interpolation
vec3 blend = Interpolation_C2( Pf );
vec4 res0 = mix( grad_results_0, grad_results_1, blend.z );
vec2 res1 = mix( res0.xy, res0.zw, blend.y );
float final = mix( res1.x, res1.y, blend.x );
final *= 1.1547005383792515290182975610039; // (optionally) scale things to a strict -1.0->1.0 range *= 1.0/sqrt(0.75)
return final;
#else
// Classic Perlin Surflet
// http://briansharpe.wordpress.com/2012/03/09/modifications-to-classic-perlin-noise/
Pf *= Pf;
Pf_min1 *= Pf_min1;
vec4 vecs_len_sq = vec4( Pf.x, Pf_min1.x, Pf.x, Pf_min1.x ) + vec4( Pf.yy, Pf_min1.yy );
float final = dot( Falloff_Xsq_C2( min( vec4( 1.0 ), vecs_len_sq + Pf.zzzz ) ), grad_results_0 ) + dot( Falloff_Xsq_C2( min( vec4( 1.0 ), vecs_len_sq + Pf_min1.zzzz ) ), grad_results_1 );
final *= 2.3703703703703703703703703703704; // (optionally) scale things to a strict -1.0->1.0 range *= 1.0/cube(0.75)
return final;
#endif
#else
//
// improved noise.
// requires 1 random value per point. Will run faster than classic noise if a slow hashing function is used
//
// calculate the hash.
// ( various hashing methods listed in order of speed )
vec4 hash_lowz, hash_highz;
FAST32_hash_3D( Pi, hash_lowz, hash_highz );
//BBS_hash_3D( Pi, hash_lowz, hash_highz );
//SGPP_hash_3D( Pi, hash_lowz, hash_highz );
//
// 'improved' noise using 8 corner gradients. Faster than the 12 mid-edge point method.
// Ken mentions using diagonals like this can cause 'clumping', but we'll live with that.
// [1,1,1] [-1,1,1] [1,-1,1] [-1,-1,1]
// [1,1,-1] [-1,1,-1] [1,-1,-1] [-1,-1,-1]
//
hash_lowz -= 0.5;
vec4 grad_results_0_0 = vec2( Pf.x, Pf_min1.x ).xyxy * sign( hash_lowz );
hash_lowz = abs( hash_lowz ) - 0.25;
vec4 grad_results_0_1 = vec2( Pf.y, Pf_min1.y ).xxyy * sign( hash_lowz );
vec4 grad_results_0_2 = Pf.zzzz * sign( abs( hash_lowz ) - 0.125 );
vec4 grad_results_0 = grad_results_0_0 + grad_results_0_1 + grad_results_0_2;
hash_highz -= 0.5;
vec4 grad_results_1_0 = vec2( Pf.x, Pf_min1.x ).xyxy * sign( hash_highz );
hash_highz = abs( hash_highz ) - 0.25;
vec4 grad_results_1_1 = vec2( Pf.y, Pf_min1.y ).xxyy * sign( hash_highz );
vec4 grad_results_1_2 = Pf_min1.zzzz * sign( abs( hash_highz ) - 0.125 );
vec4 grad_results_1 = grad_results_1_0 + grad_results_1_1 + grad_results_1_2;
// blend the gradients and return
vec3 blend = Interpolation_C2( Pf );
vec4 res0 = mix( grad_results_0, grad_results_1, blend.z );
vec2 res1 = mix( res0.xy, res0.zw, blend.y );
return mix( res1.x, res1.y, blend.x ) * (2.0 / 3.0); // (optionally) mult by (2.0/3.0) to scale to a strict -1.0->1.0 range
#endif
}
float billow(vec3 p, int powered, float billowPower)
{
// Powered Billow
if(powered > 0)
{
return pow(abs(4.0*Perlin3D(p)), billowPower);
}
else
{
return abs(4.0*Perlin3D(p));
}
}
//
// 3D fractional Brownian Motion
//
float fBM(vec3 p, vec3 offset, float frequency, float amplitude, float lacunarity, float persistence, int powered, float billowPower)
{
float sum = 0.0;
float bias = 0.0;
for (int i = 0; i < OCTAVES; i++)
{
float h = 0.5 * (1.0 + billow((p+offset)*frequency, powered, billowPower));
sum += h*amplitude;
bias -= amplitude;
frequency *= lacunarity;
amplitude *= persistence;
}
sum += 0.5 * bias;
return sum;
}
#define gl_ModelViewProjectionMatrix glstate_matrix_mvp
uniform mat4 glstate_matrix_mvp;
#define gl_Vertex _glesVertex
attribute vec4 _glesVertex;
#define gl_MultiTexCoord0 _glesMultiTexCoord0
attribute vec4 _glesMultiTexCoord0;
uniform float _Displace;
varying vec4 position;
varying vec2 texCoord;
void main()
{
position = gl_Vertex;
if(_Displace > 0.0)
{
position.y = fBM(vec3(position.xz, _Time*_AnimSpeed), _NoiseOffset, _Frequency, _Amplitude, _Lacunarity, _Persistence, _Powered, _BillowPower);
}
gl_Position = gl_ModelViewProjectionMatrix * position;
texCoord = gl_MultiTexCoord0.xy;
}
Fragment Shader:
precision mediump float;
#define SHADER_API_GLES 1
#define tex2D texture2D
#line 36
precision mediump float;
const int OCTAVES = 12;
uniform vec4 _Time;
uniform float _Frequency;
uniform float _Amplitude;
uniform vec3 _NoiseOffset;
uniform float _Contribution;
uniform float _Normalize;
uniform float _AnimSpeed;
uniform float _Lacunarity;
uniform float _Persistence;
uniform int _Powered;
uniform float _BillowPower;
//
// FAST32_hash
// A very fast hashing function. Requires 32bit support.
// http://briansharpe.wordpress.com/2011/11/15/a-fast-and-simple-32bit-floating-point-hash-function/
//
// The hash formula takes the form....
// hash = mod( coord.x * coord.x * coord.y * coord.y, SOMELARGEFLOAT ) / SOMELARGEFLOAT
// We truncate and offset the domain to the most interesting part of the noise.
// SOMELARGEFLOAT should be in the range of 400.0->1000.0 and needs to be hand picked. Only some give good results.
// 3D Noise is achieved by offsetting the SOMELARGEFLOAT value by the Z coordinate
//
void FAST32_hash_3D( vec3 gridcell,
out vec4 lowz_hash_0,
out vec4 lowz_hash_1,
out vec4 lowz_hash_2,
out vec4 highz_hash_0,
out vec4 highz_hash_1,
out vec4 highz_hash_2 ) // generates 3 random numbers for each of the 8 cell corners
{
// gridcell is assumed to be an integer coordinate
// TODO: these constants need tweaked to find the best possible noise.
// probably requires some kind of brute force computational searching or something....
const vec2 OFFSET = vec2( 50.0, 161.0 );
const float DOMAIN = 69.0;
const vec3 SOMELARGEFLOATS = vec3( 635.298681, 682.357502, 668.926525 );
const vec3 ZINC = vec3( 48.500388, 65.294118, 63.934599 );
// truncate the domain
gridcell.xyz = gridcell.xyz - floor(gridcell.xyz * ( 1.0 / DOMAIN )) * DOMAIN;
vec3 gridcell_inc1 = step( gridcell, vec3( DOMAIN - 1.5 ) ) * ( gridcell + 1.0 );
// calculate the noise
vec4 P = vec4( gridcell.xy, gridcell_inc1.xy ) + OFFSET.xyxy;
P *= P;
P = P.xzxz * P.yyww;
vec3 lowz_mod = vec3( 1.0 / ( SOMELARGEFLOATS.xyz + gridcell.zzz * ZINC.xyz ) );
vec3 highz_mod = vec3( 1.0 / ( SOMELARGEFLOATS.xyz + gridcell_inc1.zzz * ZINC.xyz ) );
lowz_hash_0 = fract( P * lowz_mod.xxxx );
highz_hash_0 = fract( P * highz_mod.xxxx );
lowz_hash_1 = fract( P * lowz_mod.yyyy );
highz_hash_1 = fract( P * highz_mod.yyyy );
lowz_hash_2 = fract( P * lowz_mod.zzzz );
highz_hash_2 = fract( P * highz_mod.zzzz );
}
vec3 Interpolation_C2( vec3 x )
{
return x * x * x * (x * (x * 6.0 - 15.0) + 10.0);
}
//
// Perlin Noise 3D ( gradient noise )
// Return value range of -1.0->1.0
// http://briansharpe.files.wordpress.com/2011/11/perlinsample.jpg
//
float Perlin3D( vec3 P )
{
// establish our grid cell and unit position
vec3 Pi = floor(P);
vec3 Pf = P - Pi;
vec3 Pf_min1 = Pf - 1.0;
#if 1
//
// classic noise.
// requires 3 random values per point. with an efficent hash function will run faster than improved noise
//
// calculate the hash.
// ( various hashing methods listed in order of speed )
vec4 hashx0, hashy0, hashz0, hashx1, hashy1, hashz1;
FAST32_hash_3D( Pi, hashx0, hashy0, hashz0, hashx1, hashy1, hashz1 );
//SGPP_hash_3D( Pi, hashx0, hashy0, hashz0, hashx1, hashy1, hashz1 );
// calculate the gradients
vec4 grad_x0 = hashx0 - 0.49999;
vec4 grad_y0 = hashy0 - 0.49999;
vec4 grad_z0 = hashz0 - 0.49999;
vec4 grad_x1 = hashx1 - 0.49999;
vec4 grad_y1 = hashy1 - 0.49999;
vec4 grad_z1 = hashz1 - 0.49999;
vec4 grad_results_0 = inversesqrt( grad_x0 * grad_x0 + grad_y0 * grad_y0 + grad_z0 * grad_z0 ) * ( vec2( Pf.x, Pf_min1.x ).xyxy * grad_x0 + vec2( Pf.y, Pf_min1.y ).xxyy * grad_y0 + Pf.zzzz * grad_z0 );
vec4 grad_results_1 = inversesqrt( grad_x1 * grad_x1 + grad_y1 * grad_y1 + grad_z1 * grad_z1 ) * ( vec2( Pf.x, Pf_min1.x ).xyxy * grad_x1 + vec2( Pf.y, Pf_min1.y ).xxyy * grad_y1 + Pf_min1.zzzz * grad_z1 );
#if 1
// Classic Perlin Interpolation
vec3 blend = Interpolation_C2( Pf );
vec4 res0 = mix( grad_results_0, grad_results_1, blend.z );
vec2 res1 = mix( res0.xy, res0.zw, blend.y );
float final = mix( res1.x, res1.y, blend.x );
final *= 1.1547005383792515290182975610039; // (optionally) scale things to a strict -1.0->1.0 range *= 1.0/sqrt(0.75)
return final;
#else
// Classic Perlin Surflet
// http://briansharpe.wordpress.com/2012/03/09/modifications-to-classic-perlin-noise/
Pf *= Pf;
Pf_min1 *= Pf_min1;
vec4 vecs_len_sq = vec4( Pf.x, Pf_min1.x, Pf.x, Pf_min1.x ) + vec4( Pf.yy, Pf_min1.yy );
float final = dot( Falloff_Xsq_C2( min( vec4( 1.0 ), vecs_len_sq + Pf.zzzz ) ), grad_results_0 ) + dot( Falloff_Xsq_C2( min( vec4( 1.0 ), vecs_len_sq + Pf_min1.zzzz ) ), grad_results_1 );
final *= 2.3703703703703703703703703703704; // (optionally) scale things to a strict -1.0->1.0 range *= 1.0/cube(0.75)
return final;
#endif
#else
//
// improved noise.
// requires 1 random value per point. Will run faster than classic noise if a slow hashing function is used
//
// calculate the hash.
// ( various hashing methods listed in order of speed )
vec4 hash_lowz, hash_highz;
FAST32_hash_3D( Pi, hash_lowz, hash_highz );
//BBS_hash_3D( Pi, hash_lowz, hash_highz );
//SGPP_hash_3D( Pi, hash_lowz, hash_highz );
//
// 'improved' noise using 8 corner gradients. Faster than the 12 mid-edge point method.
// Ken mentions using diagonals like this can cause 'clumping', but we'll live with that.
// [1,1,1] [-1,1,1] [1,-1,1] [-1,-1,1]
// [1,1,-1] [-1,1,-1] [1,-1,-1] [-1,-1,-1]
//
hash_lowz -= 0.5;
vec4 grad_results_0_0 = vec2( Pf.x, Pf_min1.x ).xyxy * sign( hash_lowz );
hash_lowz = abs( hash_lowz ) - 0.25;
vec4 grad_results_0_1 = vec2( Pf.y, Pf_min1.y ).xxyy * sign( hash_lowz );
vec4 grad_results_0_2 = Pf.zzzz * sign( abs( hash_lowz ) - 0.125 );
vec4 grad_results_0 = grad_results_0_0 + grad_results_0_1 + grad_results_0_2;
hash_highz -= 0.5;
vec4 grad_results_1_0 = vec2( Pf.x, Pf_min1.x ).xyxy * sign( hash_highz );
hash_highz = abs( hash_highz ) - 0.25;
vec4 grad_results_1_1 = vec2( Pf.y, Pf_min1.y ).xxyy * sign( hash_highz );
vec4 grad_results_1_2 = Pf_min1.zzzz * sign( abs( hash_highz ) - 0.125 );
vec4 grad_results_1 = grad_results_1_0 + grad_results_1_1 + grad_results_1_2;
// blend the gradients and return
vec3 blend = Interpolation_C2( Pf );
vec4 res0 = mix( grad_results_0, grad_results_1, blend.z );
vec2 res1 = mix( res0.xy, res0.zw, blend.y );
return mix( res1.x, res1.y, blend.x ) * (2.0 / 3.0); // (optionally) mult by (2.0/3.0) to scale to a strict -1.0->1.0 range
#endif
}
float billow(vec3 p, int powered, float billowPower)
{
// Powered Billow
if(powered > 0)
{
return pow(abs(4.0*Perlin3D(p)), billowPower);
}
else
{
return abs(4.0*Perlin3D(p));
}
}
//
// 3D fractional Brownian Motion
//
float fBM(vec3 p, vec3 offset, float frequency, float amplitude, float lacunarity, float persistence, int powered, float billowPower)
{
float sum = 0.0;
float bias = 0.0;
for (int i = 0; i < OCTAVES; i++)
{
float h = 0.5 * (1.0 + billow((p+offset)*frequency, powered, billowPower));
sum += h*amplitude;
bias -= amplitude;
frequency *= lacunarity;
amplitude *= persistence;
}
sum += 0.5 * bias;
return sum;
}
uniform vec4 _LowColor;
uniform vec4 _HighColor;
uniform float _Texturing;
uniform sampler2D _LowTexture;
uniform vec4 _LowTexture_ST;
uniform sampler2D _HighTexture;
uniform vec4 _HighTexture_ST;
varying vec4 position;
varying vec2 texCoord;
void main()
{
float h = fBM(vec3(vec2(position.xz), _Time*_AnimSpeed), _NoiseOffset, _Frequency, _Amplitude, _Lacunarity, _Persistence, _Powered, _BillowPower);
if(_Normalize > 0.0)
{
// set range to (0, 1)
h = h*0.5 + 0.5;
}
// do the accumulation with the previous fixed-point height
h = h*_Contribution;
vec4 color;
if(_Texturing > 0.0)
{
color = mix(_LowColor * texture2D(_LowTexture, _LowTexture_ST.xy * texCoord + _LowTexture_ST.zw), _HighColor * texture2D(_HighTexture, _HighTexture_ST.xy * texCoord + _HighTexture_ST.zw), h);
}
else
{
color = mix(_LowColor, _HighColor, h);
}
gl_FragColor = vec4(color.r, color.g, color.b, h);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment