Added 4D classic noise, declutter, speedups, removed dep of noiseStdLib.glsl, benchmark changed to test all six versions of noise.

master
stegu 2011-04-03 17:30:50 +02:00
parent 7e87323fda
commit c2e657b438
15 changed files with 272 additions and 310 deletions

View File

@ -1,4 +1,5 @@
Copyright (C) 2011 by Ashima Arts
Copyright (C) 2011 by Ashima Arts (Simplex noise)
Copyright (C) 2011 by Stefan Gustavson (Classic noise)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@ -17,4 +18,3 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

16
README
View File

@ -1,14 +1,12 @@
This work follows Stefan Gustavson's paper "Simplex noise demystified"
http://staffwww.itn.liu.se/~stegu/simplexnoise/simplexnoise.pdf
http://www.itn.liu.se/~stegu/simplexnoise/simplexnoise.pdf
without using uniform arrays or texture engines.
A single vec4 uniform 'pParam' is used to set the length and a and
c constants respectively of the permutation polynomial to use. The
last element of the vec4 is the number of gradients to select from
on the vertices. An example vec4 is ( 19*19, 2*19, 1, 7 )
Refer to http://en.wikipedia.org/wiki/Permutation_polynomial for
more information on permutation polynomials.
The resulting noise functions are fast and self contained,
and their performance scales well with massive parallelism.
Simplex noise functions are (C) Ashima Arts
Classic noise functions are (C) Stefan Gustavson
Source code for the noise functions is released under the
conditions of the MIT license. See the file LICENSE for details.

View File

@ -1,5 +1,6 @@
SHADERS=GLSL-ashimanoise.vert GLSL-ashimanoise2D.frag \
GLSL-ashimanoise3D.frag GLSL-ashimanoise4D.frag
SHADERS=noisebench.vert simplexnoise2D.frag simplexnoise3D.frag\
simplexnoise4D.frag classicnoise2D.frag classicnoise3D.frag\
classicnoise4D.frag constant.frag
COMDIR=../common
VPATH=$(COMDIR)
EXECNAME=noisebench
@ -19,4 +20,3 @@ clean:
run:
./$(EXECNAME)
cat $(OUTPUTFILE)

View File

@ -3,8 +3,9 @@ OUTPUTFILE=ashimanoise.log
COMDIR=../common
OBJS=noisebench.o
SHADERS=GLSL-ashimanoise.vert GLSL-ashimanoise2D.frag \
GLSL-ashimanoise3D.frag GLSL-ashimanoise4D.frag
SHADERS=noisebench.vert simplexnoise2D.frag simplexnoise3D.frag\
simplexnoise4D.frag classicnoise2D.frag classicnoise3D.frag\
classicnoise4D.frag constant.frag
VPATH=$(COMDIR)
CFLAGS=-I. -I/usr/X11/include
@ -27,6 +28,5 @@ clean:
- rm $(EXECNAME) links_done $(OBJS) $(SHADERS) $(OUTPUTFILE)
run:
open -W -a $(EXECNAME)
open -W ./$(EXECNAME).app
cat $(OUTPUTFILE)

View File

@ -3,7 +3,8 @@ MINGW32 = C:/Dev-Cpp
#MINGW32 = C:/mingw
CC = gcc.exe
SRC = noisebench.c
SHADERS = GLSL-ashimanoise.vert GLSL-ashimanoise2D.frag GLSL-ashimanoise3D.frag GLSL-ashimanoise4D.frag
SHADERS = noisebench.vert constant.frag simplexnoise2D.frag simplexnoise3D.frag\
simplexnoise4D.frag classicnoise2D.frag classicnoise3D.frag classicnoise4D.frag
OBJ = noisebench.o
LINKOBJ = noisebench.o
LIBS = -L$(MINGW32)/lib -mwindows -lglfw -lopengl32 -lglu32 -mconsole -g3
@ -17,17 +18,29 @@ all: $(EXECNAME)
clean:
del $(OBJ) $(EXECNAME) $(SHADERS) $(OUTPUTFILE) $(SRC)
GLSL-ashimanoise.vert:
copy ..\common\GLSL-ashimanoise.vert .
noisebench.vert:
copy ..\common\noisebench.vert .
GLSL-ashimanoise2D.frag:
copy ..\common\GLSL-ashimanoise2D.frag .
constant.frag:
copy ..\common\constant.frag .
GLSL-ashimanoise3D.frag:
copy ..\common\GLSL-ashimanoise3D.frag .
simplexnoise2D.frag:
copy ..\common\simplexnoise2D.frag .
GLSL-ashimanoise4D.frag:
copy ..\common\GLSL-ashimanoise4D.frag .
simplexnoise3D.frag:
copy ..\common\simplexnoise3D.frag .
simplexnoise4D.frag:
copy ..\common\simplexnoise4D.frag .
classicnoise2D.frag:
copy ..\common\classicnoise2D.frag .
classicnoise3D.frag:
copy ..\common\classicnoise3D.frag .
classicnoise4D.frag:
copy ..\common\classicnoise4D.frag .
$(SRC):
copy ..\common\$(SRC) .

View File

@ -1,18 +0,0 @@
#version 120
uniform float time;
/*
* Both 2D and 3D texture coordinates are defined, for testing purposes.
*/
varying vec2 v_texCoord2D;
varying vec3 v_texCoord3D;
varying vec4 v_texCoord4D;
void main( void )
{
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
v_texCoord2D = gl_MultiTexCoord0.xy * 16.0 + vec2(0.0, time);
v_texCoord3D = vec3(gl_MultiTexCoord0.xy * 16.0, time);
v_texCoord4D = vec4(gl_MultiTexCoord0.xy * 16.0, 0.0, time);
}

View File

@ -1,25 +1,40 @@
OPTIONS=-DNORMALISE_GRADIENTS -DCOLLAPSE_SORTNET
OPTIONS=
SRCDIR=../../src
COMMON=commonShader.frag $(SRCDIR)/noiseStdLib.glsl
SHADERS=GLSL-ashimanoise2D.frag GLSL-ashimanoise3D.frag \
GLSL-ashimanoise4D.frag
COMMON=commonShader.frag
SHADERS=simplexnoise2D.frag simplexnoise3D.frag simplexnoise4D.frag \
classicnoise2D.frag classicnoise3D.frag classicnoise4D.frag
all: $(SHADERS)
clean:
- rm $(SHADERS)
GLSL-ashimanoise2D.frag: $(SRCDIR)/noise2D.glsl $(COMMON)
simplexnoise2D.frag: $(SRCDIR)/noise2D.glsl $(COMMON)
cpp -P -I$(SRCDIR) -DSHADER=\"noise2D.glsl\" \
-DVTYPE=vec2 -DVNAME=v_texCoord2D\
-DVTYPE=vec2 -DVNAME=v_texCoord2D -DNOISEFUN=snoise\
$(OPTIONS) -DVERSION='#version 120' commonShader.frag $@
GLSL-ashimanoise3D.frag: $(SRCDIR)/noise3D.glsl $(COMMON)
simplexnoise3D.frag: $(SRCDIR)/noise3D.glsl $(COMMON)
cpp -P -I$(SRCDIR) -DSHADER=\"noise3D.glsl\" \
-DVTYPE=vec3 -DVNAME=v_texCoord3D\
-DVTYPE=vec3 -DVNAME=v_texCoord3D -DNOISEFUN=snoise\
$(OPTIONS) -DVERSION='#version 120' commonShader.frag $@
GLSL-ashimanoise4D.frag: $(SRCDIR)/noise4D.glsl $(COMMON)
simplexnoise4D.frag: $(SRCDIR)/noise4D.glsl $(COMMON)
cpp -P -I$(SRCDIR) -DSHADER=\"noise4D.glsl\" \
-DVTYPE=vec4 -DVNAME=v_texCoord4D\
-DVTYPE=vec4 -DVNAME=v_texCoord4D -DNOISEFUN=snoise\
$(OPTIONS) -DVERSION='#version 120' commonShader.frag $@
classicnoise2D.frag: $(SRCDIR)/classicnoise2D.glsl $(COMMON)
cpp -P -I$(SRCDIR) -DSHADER=\"classicnoise2D.glsl\" \
-DVTYPE=vec2 -DVNAME=v_texCoord2D -DNOISEFUN=cnoise\
$(OPTIONS) -DVERSION='#version 120' commonShader.frag $@
classicnoise3D.frag: $(SRCDIR)/classicnoise3D.glsl $(COMMON)
cpp -P -I$(SRCDIR) -DSHADER=\"classicnoise3D.glsl\" \
-DVTYPE=vec3 -DVNAME=v_texCoord3D -DNOISEFUN=cnoise\
$(OPTIONS) -DVERSION='#version 120' commonShader.frag $@
classicnoise4D.frag: $(SRCDIR)/classicnoise4D.glsl $(COMMON)
cpp -P -I$(SRCDIR) -DSHADER=\"classicnoise4D.glsl\" \
-DVTYPE=vec4 -DVNAME=v_texCoord4D -DNOISEFUN=cnoise\
$(OPTIONS) -DVERSION='#version 120' commonShader.frag $@

View File

@ -1,22 +1,16 @@
VERSION
// uniform vec4 pParam;
// Example constant with a 289-element permutation
const vec4 pParam = vec4( 17.0*17.0, 34.0, 1.0, 7.0);
#include "noiseStdLib.glsl"
#include SHADER
uniform float time; // Used for texture animation
varying VTYPE VNAME ;
//
// main()
//
void main( void )
{
float n = simplexNoise(VNAME);
float n = NOISEFUN(VNAME);
gl_FragColor = vec4(0.5 + 0.5 * vec3(n, n, n), 1.0);
}

View File

@ -1,22 +1,26 @@
/*
* Testbed for GLSL procedural noise functions.
* Benchmark for GLSL procedural noise functions.
*
* Shaders are loaded from two external files:
* "GLSL-ashimanoise.vert" and "GLSL-ashimanoise.frag".
* The program itself draws a spinning sphere
* with a noise-generated fragment color.
* Shaders are loaded from external files, named in
* the macro definitions VERTSHADERFILE and FRAGSHADERFILE*.
* The main program draws a flat plane covering the
* viewport, activates each of six fragment shaders in turn
* and reports the fragment shading performance in Msamples/s
* for each.
*
* This program uses GLFW for convenience, to handle the OS-specific
* window management stuff. Some Windows-specific stuff for extension
* loading is still here, but that code is short-circuited on other
* platforms - this file compiles unedited on Windows, Linux and MacOS X.
* platforms - this file compiles unedited on Windows, Linux and MacOS X,
* provided you have the relevant libraries and header files installed
* and set up your compilation to include the GLFW and OpenGL libraries.
*
* Author: Stefan Gustavson (stegu@itn.liu.se) 2004, 2005, 2010, 2011
* This code is in the public domain.
*/
// Identify the exact version of noise being benchmarked
#define NOISEVERSION "2011-03-25"
#define NOISEVERSION "2011-04-03"
#include <stdio.h>
#include <stdlib.h>
@ -33,21 +37,25 @@
#ifdef __APPLE__
// MacOS application bundles have the executable inside a directory structure
#define VERTEXSHADERFILE2D "../../../GLSL-ashimanoise.vert"
#define FRAGMENTSHADERFILE2D "../../../GLSL-ashimanoise2D.frag"
#define VERTEXSHADERFILE3D "../../../GLSL-ashimanoise.vert"
#define FRAGMENTSHADERFILE3D "../../../GLSL-ashimanoise3D.frag"
#define VERTEXSHADERFILE4D "../../../GLSL-ashimanoise.vert"
#define FRAGMENTSHADERFILE4D "../../../GLSL-ashimanoise4D.frag"
#define VERTSHADERFILE "../../../noisebench.vert"
#define FRAGSHADERFILE_S2D "../../../simplexnoise2D.frag"
#define FRAGSHADERFILE_S3D "../../../simplexnoise3D.frag"
#define FRAGSHADERFILE_S4D "../../../simplexnoise4D.frag"
#define FRAGSHADERFILE_C2D "../../../classicnoise2D.frag"
#define FRAGSHADERFILE_C3D "../../../classicnoise3D.frag"
#define FRAGSHADERFILE_C4D "../../../classicnoise4D.frag"
#define FRAGSHADERFILE_CONST "../../../constant.frag"
#define LOGFILENAME "../../../ashimanoise.log"
#else
// Windows, Linux and other Unix systems expose executables as naked files
#define VERTEXSHADERFILE2D "GLSL-ashimanoise.vert"
#define FRAGMENTSHADERFILE2D "GLSL-ashimanoise2D.frag"
#define VERTEXSHADERFILE3D "GLSL-ashimanoise.vert"
#define FRAGMENTSHADERFILE3D "GLSL-ashimanoise3D.frag"
#define VERTEXSHADERFILE4D "GLSL-ashimanoise.vert"
#define FRAGMENTSHADERFILE4D "GLSL-ashimanoise4D.frag"
#define VERTSHADERFILE "noisebench.vert"
#define FRAGSHADERFILE_S2D "simplexnoise2D.frag"
#define FRAGSHADERFILE_S3D "simplexnoise3D.frag"
#define FRAGSHADERFILE_S4D "simplexnoise4D.frag"
#define FRAGSHADERFILE_C2D "classicnoise2D.frag"
#define FRAGSHADERFILE_C3D "classicnoise3D.frag"
#define FRAGSHADERFILE_C4D "classicnoise4D.frag"
#define FRAGSHADERFILE_CONST "constant.frag"
#define LOGFILENAME "ashimanoise.log"
#endif
@ -350,7 +358,7 @@ int main(int argc, char *argv[]) {
GLuint displayList;
GLuint programObject;
double performance = 0.0;
int ndims = 2; // Currently running version of noise: 2D, 3D or 4D
int activeshader = 0; // Currently active version of noise shader
FILE *logfile;
GLFWvidmode vidmode;
@ -382,14 +390,11 @@ int main(int argc, char *argv[]) {
logfile = fopen(LOGFILENAME, "w");
fprintf(logfile, "GL vendor: %s\n", glGetString(GL_VENDOR));
fprintf(logfile, "GL renderer: %s\n", glGetString(GL_RENDERER));
fprintf(logfile, "GL version: %s\n", glGetString(GL_VERSION));
fprintf(logfile, "Desktop size: %d x %d pixels\n", vidmode.Width, vidmode.Height);
// Create the shader object from two external GLSL source files
createShader(&programObject, VERTEXSHADERFILE2D, FRAGMENTSHADERFILE2D);
fprintf(logfile, "\n2D simplex noise, version %s, ", NOISEVERSION);
fprintf(logfile, "GL vendor: %s\n", glGetString(GL_VENDOR));
fprintf(logfile, "GL renderer: %s\n", glGetString(GL_RENDERER));
fprintf(logfile, "GL version: %s\n", glGetString(GL_VERSION));
fprintf(logfile, "Desktop size: %d x %d pixels\n", vidmode.Width, vidmode.Height);
fprintf(logfile, "Noise version: %s\n\n", NOISEVERSION);
// Disable Z buffering for this simple 2D shader benchmark
glDisable(GL_DEPTH_TEST); // Use the Z buffer
@ -402,6 +407,59 @@ int main(int argc, char *argv[]) {
// Main loop
while(running)
{
double benchmarktime = 3.0; // Total time to run each shader
// Switch between the different versions of noise
if(activeshader == 0) {
createShader(&programObject, VERTSHADERFILE, FRAGSHADERFILE_CONST);
activeshader++;
fprintf(logfile, "Constant shading, ");
}
if((activeshader == 1) && (glfwGetTime() > benchmarktime * activeshader)) {
fprintf(logfile, "%.1f Msamples/s\n", performance);
createShader(&programObject, VERTSHADERFILE, FRAGSHADERFILE_S2D);
activeshader++;
fprintf(logfile, "2D simplex noise, ");
}
if((activeshader == 2) && (glfwGetTime() > benchmarktime * activeshader)) {
fprintf(logfile, "%.1f Msamples/s\n", performance);
createShader(&programObject, VERTSHADERFILE, FRAGSHADERFILE_S3D);
activeshader++;
fprintf(logfile, "3D simplex noise, ");
}
if((activeshader == 3) && (glfwGetTime() > benchmarktime * activeshader)) {
fprintf(logfile, "%.1f Msamples/s\n", performance);
createShader(&programObject, VERTSHADERFILE, FRAGSHADERFILE_S4D);
activeshader++;
fprintf(logfile, "4D simplex noise, ");
}
if((activeshader == 4) && (glfwGetTime() > benchmarktime * activeshader)) {
fprintf(logfile, "%.1f Msamples/s\n", performance);
createShader(&programObject, VERTSHADERFILE, FRAGSHADERFILE_C2D);
activeshader++;
fprintf(logfile, "2D classic noise, ");
}
if((activeshader == 5) && (glfwGetTime() > benchmarktime * activeshader)) {
fprintf(logfile, "%.1f Msamples/s\n", performance);
createShader(&programObject, VERTSHADERFILE, FRAGSHADERFILE_C3D);
activeshader++;
fprintf(logfile, "3D classic noise, ");
}
if((activeshader == 6) && (glfwGetTime() > benchmarktime * activeshader)) {
fprintf(logfile, "%.1f Msamples/s\n", performance);
createShader(&programObject, VERTSHADERFILE, FRAGSHADERFILE_C4D);
activeshader++;
fprintf(logfile, "4D classic noise, ");
}
if((activeshader == 7) && (glfwGetTime() > benchmarktime * activeshader)) {
fprintf(logfile, "%.1f Msamples/s\n", performance);
running = GL_FALSE;
}
// Exit prematurely if the ESC key is pressed or the window is closed.
if(glfwGetKey(GLFW_KEY_ESC) || !glfwGetWindowParam(GLFW_OPENED)) {
running = GL_FALSE;
}
// Calculate and update the frames per second (FPS) display
performance = computeFPS();
@ -416,29 +474,6 @@ int main(int argc, char *argv[]) {
// Swap buffers, i.e. display the image and prepare for next frame.
glfwSwapBuffers();
// Switch between 2D, 3D and 4D versions of noise
if((glfwGetTime() > 5.0) && (ndims == 2)) {
fprintf(logfile, "%.1f Msamples/s\n", performance);
createShader(&programObject, VERTEXSHADERFILE3D, FRAGMENTSHADERFILE3D);
fprintf(logfile, "3D simplex noise, version %s, ", NOISEVERSION);
ndims = 3;
}
if((glfwGetTime() > 10.0) && (ndims == 3)) {
fprintf(logfile, "%.1f Msamples/s\n", performance);
createShader(&programObject, VERTEXSHADERFILE4D, FRAGMENTSHADERFILE4D);
fprintf(logfile, "4D simplex noise, version %s, ", NOISEVERSION);
ndims = 4;
}
if((glfwGetTime() > 15.0) && (ndims == 4)) {
fprintf(logfile, "%.1f Msamples/s\n", performance);
running = GL_FALSE;
}
// Exit prematurely if the ESC key is pressed or the window is closed.
if(glfwGetKey(GLFW_KEY_ESC) || !glfwGetWindowParam(GLFW_OPENED)) {
running = GL_FALSE;
}
}
// Close the OpenGL window and terminate GLFW.

View File

@ -2,7 +2,7 @@
// GLSL textureless classic 3D noise "cnoise",
// with an RSL-style periodic variant "pnoise".
// Author: Stefan Gustavson (stefan.gustavson@liu.se)
// Version: 2011-04-01
// Version: 2011-04-03
//
// Many thanks to Ian McEwan of Ashima Arts for the
// ideas for permutation and gradient selection.
@ -30,11 +30,8 @@
// THE SOFTWARE.
//
#version 120
vec4 permute(vec4 x)
{
x = mod(x, 289.0);
return floor(mod(((x*34.0)+1.0)*x, 289.0));
}
@ -50,18 +47,17 @@ vec2 fade(vec2 t) {
// Classic Perlin noise
float cnoise(vec2 P)
{
vec2 Pi = floor(P); // Integer part for indexing
vec2 Pf = fract(P); // Fractional part for interpolation
vec4 ox = vec4(0.0, 1.0, 0.0, 1.0);
vec4 oy = vec4(0.0, 0.0, 1.0, 1.0);
vec4 ix = vec4(Pi.x) + ox;
vec4 iy = vec4(Pi.y) + oy;
vec4 fx = vec4(Pf.x) - ox;
vec4 fy = vec4(Pf.y) - oy;
vec4 Pi = floor(P.xyxy) + vec4(0.0, 0.0, 1.0, 1.0);
vec4 Pf = fract(P.xyxy) - vec4(0.0, 0.0, 1.0, 1.0);
Pi = mod(Pi, 289.0); // To avoid truncation effects in permutation
vec4 ix = Pi.xzxz;
vec4 iy = Pi.yyww;
vec4 fx = Pf.xzxz;
vec4 fy = Pf.yyww;
vec4 i = permute(permute(ix) + iy);
vec4 gx = 2.0 * fract(i / 43.0) - 1.0 ;
vec4 gx = 2.0 * fract(i / 41.0) - 1.0 ;
vec4 gy = abs(gx) - 0.5 ;
vec4 tx = floor(gx + 0.5);
gx = gx - tx;
@ -82,7 +78,7 @@ float cnoise(vec2 P)
float n01 = dot(g01, vec2(fx.z, fy.z));
float n11 = dot(g11, vec2(fx.w, fy.w));
vec2 fade_xy = fade(Pf);
vec2 fade_xy = fade(Pf.xy);
vec2 n_x = mix(vec2(n00, n01), vec2(n10, n11), fade_xy.x);
float n_xy = mix(n_x.x, n_x.y, fade_xy.y);
return 2.3 * n_xy;
@ -91,18 +87,18 @@ float cnoise(vec2 P)
// Classic Perlin noise, periodic variant
float pnoise(vec2 P, vec2 rep)
{
vec2 Pi = floor(P); // Integer part for indexing
vec2 Pf = fract(P); // Fractional part for interpolation
vec4 ox = vec4(0.0, 1.0, 0.0, 1.0);
vec4 oy = vec4(0.0, 0.0, 1.0, 1.0);
vec4 ix = mod(vec4(Pi.x) + ox, rep.x); // Index modulo period. The only
vec4 iy = mod(vec4(Pi.y) + oy, rep.y); // difference from cnoise().
vec4 fx = vec4(Pf.x) - ox;
vec4 fy = vec4(Pf.y) - oy;
vec4 Pi = floor(P.xyxy) + vec4(0.0, 0.0, 1.0, 1.0);
vec4 Pf = fract(P.xyxy) - vec4(0.0, 0.0, 1.0, 1.0);
Pi = mod(Pi, rep.xyxy); // To create noise with explicit period
Pi = mod(Pi, 289.0); // To avoid truncation effects in permutation
vec4 ix = Pi.xzxz;
vec4 iy = Pi.yyww;
vec4 fx = Pf.xzxz;
vec4 fy = Pf.yyww;
vec4 i = permute(permute(ix) + iy);
vec4 gx = 2.0 * fract(i / 43.0) - 1.0 ;
vec4 gx = 2.0 * fract(i / 41.0) - 1.0 ;
vec4 gy = abs(gx) - 0.5 ;
vec4 tx = floor(gx + 0.5);
gx = gx - tx;
@ -123,7 +119,7 @@ float pnoise(vec2 P, vec2 rep)
float n01 = dot(g01, vec2(fx.z, fy.z));
float n11 = dot(g11, vec2(fx.w, fy.w));
vec2 fade_xy = fade(Pf);
vec2 fade_xy = fade(Pf.xy);
vec2 n_x = mix(vec2(n00, n01), vec2(n10, n11), fade_xy.x);
float n_xy = mix(n_x.x, n_x.y, fade_xy.y);
return 2.3 * n_xy;

View File

@ -2,7 +2,7 @@
// GLSL textureless classic 3D noise "cnoise",
// with an RSL-style periodic variant "pnoise".
// Author: Stefan Gustavson (stefan.gustavson@liu.se)
// Version: 2011-04-01
// Version: 2011-04-03
//
// Many thanks to Ian McEwan of Ashima Arts for the
// ideas for permutation and gradient selection.
@ -30,8 +30,6 @@
// THE SOFTWARE.
//
#version 120
vec4 permute(vec4 x)
{
x = mod(x, 289.0);
@ -119,8 +117,8 @@ float cnoise(vec3 P)
float pnoise(vec3 P, vec3 rep)
{
vec3 Pi0 = mod(floor(P), rep); // Integer part, modulo period
vec3 Pf0 = fract(P); // Fractional part for interpolation
vec3 Pi1 = mod(Pi0 + vec3(1.0), rep); // Integer part + 1, mod period
vec3 Pf0 = fract(P); // Fractional part for interpolation
vec3 Pf1 = Pf0 - vec3(1.0); // Fractional part - 1.0
vec4 ix = vec4(Pi0.x, Pi1.x, Pi0.x, Pi1.x);
vec4 iy = vec4(Pi0.yy, Pi1.yy);

View File

@ -1,25 +1,33 @@
//
// Description : Array and textureless GLSL 2D/3D/4D simplex
// noise functions.
// Description : Array and textureless GLSL 2D simplex noise function.
// Author : Ian McEwan, Ashima Arts.
// Maintainer : ijm
// Lastmod : 20110327
// Lastmod : 20110403 (stegu)
// License : Copyright (C) 2011 Ashima Arts. All rights reserved.
// Distributed under the MIT License. See LICENSE file.
//
float simplexNoise(vec2 v)
vec3 permute(vec3 x)
{
return floor(mod(((x*34.0)+1.0)*x, 289.0));
}
vec3 taylorInvSqrt(vec3 r)
{
return 1.79284291400159 - 0.85373472095314 * r;
}
float snoise(vec2 v)
{
const vec2 C = vec2(0.211324865405187134, // (3.0-sqrt(3.0))/6.0;
0.366025403784438597); // 0.5*(sqrt(3.0)-1.0);
const vec3 D = vec3( 0.0, 0.5, 2.0) * 3.14159265358979312;
// First corner
vec2 i = floor(v + dot(v, C.yy) );
vec2 x0 = v - i + dot(i, C.xx);
// Other corners
vec2 i1;
i1.x = float( (x0.x>x0.y) );
i1.x = step( x0.y, x0.x ); // 1.0 if x0.x > x0.y, else 0.0
i1.y = 1.0 - i1.x;
// x0 = x0 - 0.0 + 0.0 * C.xx ;
@ -30,46 +38,26 @@ float simplexNoise(vec2 v)
xC.xy -= i1;
// Permutations
i = mod(i, pParam.x);
vec3 p = permute( permute(
i.y + vec3(0.0, i1.y, 1.0 ), pParam.xyz)
+ i.x + vec3(0.0, i1.x, 1.0 ), pParam.xyz);
i = mod(i, 289.0); // Avoid truncation effects in permutation
vec3 p = permute( permute( i.y + vec3(0.0, i1.y, 1.0 ))
+ i.x + vec3(0.0, i1.x, 1.0 ));
vec3 m = max(0.5 - vec3(dot(x0,x0), dot(xC.xy,xC.xy), dot(xC.zw,xC.zw)), 0.0);
m = m*m ;
m = m*m ;
#ifndef USE_CIRCLE
// ( N points uniformly over a line, mapped onto a diamond.)
vec3 x = 2.0 * fract(p / pParam.w) - 1.0 ;
vec3 x = 2.0 * fract(p / 41.0) - 1.0 ;
vec3 h = abs(x) - 0.5 ;
vec3 ox = floor(x+0.5);
vec3 ox = floor(x + 0.5);
vec3 a0 = x - ox;
# ifdef NORMALISE_GRADIENTS
// Normalise gradients implicitly by scaling m
m *= taylorInvSqrt( a0*a0 + h*h );
# endif
//vec2 p0 = vec2(a0.x,h.x);
//vec2 p1 = vec2(a0.y,h.y);
//vec2 p2 = vec2(a0.z,h.z);
//vec3 g = vec3( dot(p0, x0), dot(p1, xC.xy), dot(p2, xC.zw) );
// Compute final noise value at P
vec3 g;
// a0 *= m;
// h *= m;
g.x = a0.x * x0.x + h.x * x0.y;
g.yz = a0.yz * xC.xz + h.yz * xC.yw;
#else
// N points around a unit circle.
vec3 phi = D.z * mod(p,pParam.w) /pParam.w ;
vec4 a0 = sin(phi.xxyy+D.xyxy);
vec2 a1 = sin(phi.zz +D.xy);
// mix
vec3 g = vec3( dot(a0.xy, x0), dot(a0.zw, xC.xy), dot(a1.xy, xC.zw) );
#endif
return 130.0 * dot(m, g);
}
}

View File

@ -3,14 +3,24 @@
// noise functions.
// Author : Ian McEwan, Ashima Arts.
// Maintainer : ijm
// Lastmod : 20110327
// Lastmod : 20110403 (stegu)
// License : Copyright (C) 2011 Ashima Arts. All rights reserved.
// Distributed under the MIT License. See LICENSE file.
//
float simplexNoise(vec3 v)
vec4 permute(vec4 x)
{
return floor(mod(((x*34.0)+1.0)*x, 289.0));
}
vec4 taylorInvSqrt(vec4 r)
{
return 1.79284291400159 - 0.85373472095314 * r;
}
float snoise(vec3 v)
{
const vec2 C = vec2(1.0/6.0, 1.0/3.0 ) ;
const vec2 C = vec2(1.0/6.0, 1.0/3.0) ;
const vec4 D = vec4(0.0, 0.5, 1.0, 2.0);
// First corner
@ -18,56 +28,32 @@ float simplexNoise(vec3 v)
vec3 x0 = v - i + dot(i, C.xxx) ;
// Other corners
#ifdef COLLAPSE_SORTNET
vec3 g = vec3( greaterThan( x0.xyz, x0.yzx) );
// vec3 l = vec3( lessThanEqual( x0.xyz, x0.yzx) );
vec3 g = step(x0.yzx, x0.xyz);
vec3 l = 1.0 - g;
vec3 i1 = min( g.xyz, l.zxy );
vec3 i2 = max( g.xyz, l.zxy );
#else
// Keeping this clean - let the compiler optimize.
// Force existence of strict total ordering in sort.
vec3 q0 = floor(x0 * 1024.0) + vec3( 0.0, 1.0/4.0, 2.0/4.0);
vec3 q1;
q1.x = max(q0.x, q0.y);
q1.y = min(q0.x, q0.y);
q1.z = q0.z;
vec3 q2;
q2.x = max(q1.x,q1.z);
q2.z = min(q1.x,q1.z);
q2.y = q1.y;
vec3 q3;
q3.y = max(q2.y, q2.z);
q3.z = min(q2.y, q2.z);
q3.x = q2.x;
vec3 i1 = vec3(lessThanEqual(q3.xxx, q0));
vec3 i2 = vec3(lessThanEqual(q3.yyy, q0));
#endif
// x0 = x0 - 0. + 0.0 * C
// x0 = x0 - 0. + 0.0 * C
vec3 x1 = x0 - i1 + 1.0 * C.xxx;
vec3 x2 = x0 - i2 + 2.0 * C.xxx;
vec3 x3 = x0 - 1. + 3.0 * C.xxx;
// Permutations
i = mod(i, pParam.x );
i = mod(i, 289.0 );
vec4 p = permute( permute( permute(
i.z + vec4(0.0, i1.z, i2.z, 1.0 ), pParam.xyz)
+ i.y + vec4(0.0, i1.y, i2.y, 1.0 ), pParam.xyz)
+ i.x + vec4(0.0, i1.x, i2.x, 1.0 ), pParam.xyz);
i.z + vec4(0.0, i1.z, i2.z, 1.0 ))
+ i.y + vec4(0.0, i1.y, i2.y, 1.0 ))
+ i.x + vec4(0.0, i1.x, i2.x, 1.0 ));
// Gradients
// ( N*N points uniformly over a square, mapped onto a octohedron.)
float n_ = 1.0/pParam.w ;
vec3 ns = n_ * D.wyz - D.xzx ;
float n_ = 1.0/7.0; // N=7
vec3 ns = n_ * D.wyz - D.xzx;
vec4 j = p - pParam.w*pParam.w*floor(p * ns.z *ns.z); // mod(p,N*N)
vec4 j = p - 49.0 * floor(p * ns.z *ns.z); // mod(p,N*N)
vec4 x_ = floor(j * ns.z) ;
vec4 y_ = floor(j - pParam.w * x_ ) ; // mod(j,N)
vec4 x_ = floor(j * ns.z);
vec4 y_ = floor(j - 7.0 * x_ ); // mod(j,N)
vec4 x = x_ *ns.x + ns.yyyy;
vec4 y = y_ *ns.x + ns.yyyy;
@ -76,11 +62,11 @@ float simplexNoise(vec3 v)
vec4 b0 = vec4( x.xy, y.xy );
vec4 b1 = vec4( x.zw, y.zw );
//vec4 s0 = vec4(lessThan(b0,D.xxxx)) *2.0 -1.0;
//vec4 s1 = vec4(lessThan(b1,D.xxxx)) *2.0 -1.0;
vec4 s0 = floor(b0) *2.0 +1.0;
vec4 s1 = floor(b1) *2.0 +1.0;
vec4 sh = -vec4(lessThan(h, D.xxxx));
//vec4 s0 = vec4(lessThan(b0,0.0))*2.0 - 1.0;
//vec4 s1 = vec4(lessThan(b1,0.0))*2.0 - 1.0;
vec4 s0 = floor(b0)*2.0 + 1.0;
vec4 s1 = floor(b1)*2.0 + 1.0;
vec4 sh = -step(h, vec4(0.0));
vec4 a0 = b0.xzyw + s0.xzyw*sh.xxyy ;
vec4 a1 = b1.xzyw + s1.xzyw*sh.zzww ;
@ -90,15 +76,15 @@ float simplexNoise(vec3 v)
vec3 p2 = vec3(a1.xy,h.z);
vec3 p3 = vec3(a1.zw,h.w);
#ifdef NORMALISE_GRADIENTS
p0 *= taylorInvSqrt(dot(p0,p0));
p1 *= taylorInvSqrt(dot(p1,p1));
p2 *= taylorInvSqrt(dot(p2,p2));
p3 *= taylorInvSqrt(dot(p3,p3));
#endif
//Normalise gradients
vec4 norm = taylorInvSqrt(vec4(dot(p0,p0), dot(p1,p1), dot(p2, p2), dot(p3,p3)));
p0 *= norm.x;
p1 *= norm.y;
p2 *= norm.z;
p3 *= norm.w;
// Mix
vec4 m = max(0.6 - vec4(dot(x0,x0), dot(x1,x1), dot(x2,x2), dot(x3,x3)), 0.);
// Mix final noise value
vec4 m = max(0.6 - vec4(dot(x0,x0), dot(x1,x1), dot(x2,x2), dot(x3,x3)), 0.0);
m = m * m;
return 42.0 * dot( m*m, vec4( dot(p0,x0), dot(p1,x1),
dot(p2,x2), dot(p3,x3) ) );

View File

@ -3,17 +3,37 @@
// noise functions.
// Author : Ian McEwan, Ashima Arts.
// Maintainer : ijm
// Lastmod : 20110327
// Lastmod : 20110403 (stegu)
// License : Copyright (C) 2011 Ashima Arts. All rights reserved.
// Distributed under the MIT License. See LICENSE file.
//
vec4 permute(vec4 x)
{
return floor(mod(((x*34.0)+1.0)*x, 289.0));
}
float permute(float x)
{
return floor(mod(((x*34.0)+1.0)*x, 289.0));
}
vec4 taylorInvSqrt(vec4 r)
{
return 1.79284291400159 - 0.85373472095314 * r;
}
float taylorInvSqrt(float r)
{
return 1.79284291400159 - 0.85373472095314 * r;
}
vec4 grad4(float j, vec4 ip)
{
const vec4 ones = vec4(1.0, 1.0, 1.0, -1.0);
vec4 p,s;
p.xyz = floor( fract (vec3(j) * ip.xyz) *pParam.w) * ip.z - 1.0;
p.xyz = floor( fract (vec3(j) * ip.xyz) * 7.0) * ip.z - 1.0;
p.w = 1.5 - dot(abs(p.xyz), ones.xyz);
s = vec4(lessThan(p, vec4(0.0)));
p.xyz = p.xyz + (s.xyz*2.0 - 1.0) * s.www;
@ -21,7 +41,7 @@ vec4 grad4(float j, vec4 ip)
return p;
}
float simplexNoise(vec4 v)
float snoise(vec4 v)
{
const vec2 C = vec2( 0.138196601125010504, // (5 - sqrt(5))/20 G4
0.309016994374947451); // (sqrt(5) - 1)/4 F4
@ -31,8 +51,7 @@ float simplexNoise(vec4 v)
// Other corners
#ifdef COLLAPSE_SORTNET
// Rank sorting originally contributed by Bill Licea-Kane, AMD (formerly ATI)
// Rank sorting originally contributed by Bill Licea-Kane, AMD (formerly ATI)
vec4 i0;
vec3 isX = step( x0.yzw, x0.xxx );
@ -52,26 +71,6 @@ float simplexNoise(vec4 v)
vec4 i3 = clamp( i0, 0.0, 1.0 );
vec4 i2 = clamp( i0-1.0, 0.0, 1.0 );
vec4 i1 = clamp( i0-2.0, 0.0, 1.0 );
#else
// Force existence of strict total ordering in sort.
vec4 q0 = floor(x0 * 1024.0) + vec4( 0.0, 1.0/4.0, 2.0/4.0 , 3.0/4.0);
vec4 q1;
q1.xy = max(q0.xy, q0.zw); // x:z y:w
q1.zw = min(q0.xy, q0.zw);
vec4 q2;
q2.xz = max(q1.xz, q1.yw); // x:y z:w
q2.yw = min(q1.xz, q1.yw);
vec4 q3;
q3.y = max(q2.y, q2.z); // y:z
q3.z = min(q2.y, q2.z);
q3.xw = q2.xw;
vec4 i1 = vec4(lessThanEqual(q3.xxxx, q0));
vec4 i2 = vec4(lessThanEqual(q3.yyyy, q0));
vec4 i3 = vec4(lessThanEqual(q3.zzzz, q0));
#endif
// x0 = x0 - 0.0 + 0.0 * C
vec4 x1 = x0 - i1 + 1.0 * C.xxxx;
@ -80,27 +79,18 @@ float simplexNoise(vec4 v)
vec4 x4 = x0 - 1.0 + 4.0 * C.xxxx;
// Permutations
i = mod(i, pParam.x);
float j0 = permute( permute( permute( permute (
i.w, pParam.xyz) + i.z, pParam.xyz)
+ i.y, pParam.xyz) + i.x, pParam.xyz);
i = mod(i, 289.0);
float j0 = permute( permute( permute( permute(i.w) + i.z) + i.y) + i.x);
vec4 j1 = permute( permute( permute( permute (
i.w + vec4(i1.w, i2.w, i3.w, 1.0 ), pParam.xyz)
+ i.z + vec4(i1.z, i2.z, i3.z, 1.0 ), pParam.xyz)
+ i.y + vec4(i1.y, i2.y, i3.y, 1.0 ), pParam.xyz)
+ i.x + vec4(i1.x, i2.x, i3.x, 1.0 ), pParam.xyz);
i.w + vec4(i1.w, i2.w, i3.w, 1.0 ))
+ i.z + vec4(i1.z, i2.z, i3.z, 1.0 ))
+ i.y + vec4(i1.y, i2.y, i3.y, 1.0 ))
+ i.x + vec4(i1.x, i2.x, i3.x, 1.0 ));
// Gradients
// ( 7*7*6 points uniformly over a cube, mapped onto a 4-octahedron.)
// The permutation ring is 17*17, and that should be close
// to an even multiple of the number of points to avoid
// directional preferences for the noise field.
// 7*7*6 = 294, which is close to 17*17 = 289.
// 7*7*6 = 294, which is close to the ring size 17*17 = 289.
vec4 ip = vec4(1.0/294.0, 1.0/49.0, 1.0/7.0, 0.0) ;
// vec4 ip = vec4(pParam.w) ;
// ip.xy *= pParam.w ;
// ip.x *= pParam.w ;
// ip = vec4(1.0, 1.0, 1.0, 2.0) / ip ;
vec4 ip = vec4(1.0/294.0, 1.0/49.0, 1.0/7.0, 0.0) ;
vec4 p0 = grad4(j0, ip);
vec4 p1 = grad4(j1.x, ip);
@ -108,13 +98,13 @@ float simplexNoise(vec4 v)
vec4 p3 = grad4(j1.z, ip);
vec4 p4 = grad4(j1.w, ip);
#ifdef NORMALISE_GRADIENTS
p0 *= taylorInvSqrt(dot(p0,p0));
p1 *= taylorInvSqrt(dot(p1,p1));
p2 *= taylorInvSqrt(dot(p2,p2));
p3 *= taylorInvSqrt(dot(p3,p3));
// Normalise gradients
vec4 norm = taylorInvSqrt(vec4(dot(p0,p0), dot(p1,p1), dot(p2, p2), dot(p3,p3)));
p0 *= norm.x;
p1 *= norm.y;
p2 *= norm.z;
p3 *= norm.w;
p4 *= taylorInvSqrt(dot(p4,p4));
#endif
// Mix contributions from the five corners
vec3 m0 = max(0.6 - vec3(dot(x0,x0), dot(x1,x1), dot(x2,x2)), 0.0);

View File

@ -1,33 +0,0 @@
//
// Description : Array and textureless GLSL 2D/3D/4D simplex
// noise functions. Library function.
// Author : Ian McEwan, Ashima Arts.
// Maintainer : ijm
// Lastmod : 20110227
// License : Copyright (C) 2011 Ashima Arts. All rights reserved.
// Distributed under the MIT License. See LICENSE file.
//
#ifdef FASTMOD
# define PERMMOD(X,Y) (X)
#else
# define PERMMOD(X,Y) mod((X),(Y))
#endif
#define PERMFUN(X) X permute(X x, vec3 p) { \
return floor( mod( (PERMMOD(x * p.y, p.x) + p.z)*x, p.x)); }
PERMFUN(float)
PERMFUN(vec2)
PERMFUN(vec3)
PERMFUN(vec4)
#define TAYLOR_L07(X) X taylorInvSqrt(X r) { \
return ( 1.195228609334394 + 0.7*0.85373472095314 - 0.85373472095314 * r ); }
TAYLOR_L07(float)
TAYLOR_L07(vec2)
TAYLOR_L07(vec3)
TAYLOR_L07(vec4)