Created
September 23, 2012 15:56
-
-
Save miketucker/3772118 to your computer and use it in GitHub Desktop.
turbulence library bugs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-------- 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