From a0ac8ee2c4ce14a23deedeccf9911977e119749d Mon Sep 17 00:00:00 2001 From: Wilhem Barbier Date: Wed, 28 Jun 2017 15:29:56 +0200 Subject: [PATCH] Add more image generation functions: radial gradient and perlin noise --- examples/textures/gen | Bin 0 -> 13112 bytes examples/textures/textures_image_generation.c | 12 +- src/external/stb_perlin.h | 316 ++++++++++++++++++ src/raylib.h | 2 + src/textures.c | 55 +++ 5 files changed, 381 insertions(+), 4 deletions(-) create mode 100755 examples/textures/gen create mode 100644 src/external/stb_perlin.h diff --git a/examples/textures/gen b/examples/textures/gen new file mode 100755 index 0000000000000000000000000000000000000000..a0f5bf619c28430f3e5fcfb966ce406e83437381 GIT binary patch literal 13112 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 literal 0 HcmV?d00001 diff --git a/examples/textures/textures_image_generation.c b/examples/textures/textures_image_generation.c index 9db64ef76..7525e8a28 100644 --- a/examples/textures/textures_image_generation.c +++ b/examples/textures/textures_image_generation.c @@ -11,7 +11,7 @@ #include "raylib.h" -#define TEXTURES_NUM 5 // for now we have 5 generation algorithms +#define TEXTURES_NUM 7 // for now we have 7 generation algorithms int main() { @@ -22,16 +22,20 @@ int main() Image verticalGradient = GenImageGradientV(screenWidth, screenHeight, RED, BLUE); Image horizontalGradient = GenImageGradientH(screenWidth, screenHeight, RED, BLUE); + Image radialGradient = GenImageRadialGradient(screenWidth, screenHeight, WHITE, BLACK); Image checked = GenImageChecked(screenWidth, screenHeight, 32, 32, RED, BLUE); Image whiteNoise = GenImageWhiteNoise(screenWidth, screenHeight, 0.5f); + Image perlinNoise = GenImagePerlinNoise(screenWidth, screenHeight, 8.f); Image cellular = GenImageCellular(screenWidth, screenHeight, 32); Texture2D textures[TEXTURES_NUM]; textures[0] = LoadTextureFromImage(verticalGradient); textures[1] = LoadTextureFromImage(horizontalGradient); - textures[2] = LoadTextureFromImage(checked); - textures[3] = LoadTextureFromImage(whiteNoise); - textures[4] = LoadTextureFromImage(cellular); + textures[2] = LoadTextureFromImage(radialGradient); + textures[3] = LoadTextureFromImage(checked); + textures[4] = LoadTextureFromImage(whiteNoise); + textures[5] = LoadTextureFromImage(perlinNoise); + textures[6] = LoadTextureFromImage(cellular); int currentTexture = 0; diff --git a/src/external/stb_perlin.h b/src/external/stb_perlin.h new file mode 100644 index 000000000..5d7622209 --- /dev/null +++ b/src/external/stb_perlin.h @@ -0,0 +1,316 @@ +// stb_perlin.h - v0.3 - perlin noise +// public domain single-file C implementation by Sean Barrett +// +// LICENSE +// +// See end of file. +// +// +// to create the implementation, +// #define STB_PERLIN_IMPLEMENTATION +// in *one* C/CPP file that includes this file. +// +// +// Documentation: +// +// float stb_perlin_noise3( float x, +// float y, +// float z, +// int x_wrap=0, +// int y_wrap=0, +// int z_wrap=0) +// +// This function computes a random value at the coordinate (x,y,z). +// Adjacent random values are continuous but the noise fluctuates +// its randomness with period 1, i.e. takes on wholly unrelated values +// at integer points. Specifically, this implements Ken Perlin's +// revised noise function from 2002. +// +// The "wrap" parameters can be used to create wraparound noise that +// wraps at powers of two. The numbers MUST be powers of two. Specify +// 0 to mean "don't care". (The noise always wraps every 256 due +// details of the implementation, even if you ask for larger or no +// wrapping.) +// +// Fractal Noise: +// +// Three common fractal noise functions are included, which produce +// a wide variety of nice effects depending on the parameters +// provided. Note that each function will call stb_perlin_noise3 +// 'octaves' times, so this parameter will affect runtime. +// +// float stb_perlin_ridge_noise3(float x, float y, float z, +// float lacunarity, float gain, float offset, int octaves, +// int x_wrap, int y_wrap, int z_wrap); +// +// float stb_perlin_fbm_noise3(float x, float y, float z, +// float lacunarity, float gain, int octaves, +// int x_wrap, int y_wrap, int z_wrap); +// +// float stb_perlin_turbulence_noise3(float x, float y, float z, +// float lacunarity, float gain,int octaves, +// int x_wrap, int y_wrap, int z_wrap); +// +// Typical values to start playing with: +// octaves = 6 -- number of "octaves" of noise3() to sum +// lacunarity = ~ 2.0 -- spacing between successive octaves (use exactly 2.0 for wrapping output) +// gain = 0.5 -- relative weighting applied to each successive octave +// offset = 1.0? -- used to invert the ridges, may need to be larger, not sure +// +// +// Contributors: +// Jack Mott - additional noise functions +// + + +#ifdef __cplusplus +extern "C" { +#endif +extern float stb_perlin_noise3(float x, float y, float z, int x_wrap, int y_wrap, int z_wrap); +extern float stb_perlin_ridge_noise3(float x, float y, float z,float lacunarity, float gain, float offset, int octaves,int x_wrap, int y_wrap, int z_wrap); +extern float stb_perlin_fbm_noise3(float x, float y, float z,float lacunarity, float gain, int octaves,int x_wrap, int y_wrap, int z_wrap); +extern float stb_perlin_turbulence_noise3(float x, float y, float z, float lacunarity, float gain, int octaves,int x_wrap, int y_wrap, int z_wrap); +#ifdef __cplusplus +} +#endif + +#ifdef STB_PERLIN_IMPLEMENTATION + +// not same permutation table as Perlin's reference to avoid copyright issues; +// Perlin's table can be found at http://mrl.nyu.edu/~perlin/noise/ +// @OPTIMIZE: should this be unsigned char instead of int for cache? +static unsigned char stb__perlin_randtab[512] = +{ + 23, 125, 161, 52, 103, 117, 70, 37, 247, 101, 203, 169, 124, 126, 44, 123, + 152, 238, 145, 45, 171, 114, 253, 10, 192, 136, 4, 157, 249, 30, 35, 72, + 175, 63, 77, 90, 181, 16, 96, 111, 133, 104, 75, 162, 93, 56, 66, 240, + 8, 50, 84, 229, 49, 210, 173, 239, 141, 1, 87, 18, 2, 198, 143, 57, + 225, 160, 58, 217, 168, 206, 245, 204, 199, 6, 73, 60, 20, 230, 211, 233, + 94, 200, 88, 9, 74, 155, 33, 15, 219, 130, 226, 202, 83, 236, 42, 172, + 165, 218, 55, 222, 46, 107, 98, 154, 109, 67, 196, 178, 127, 158, 13, 243, + 65, 79, 166, 248, 25, 224, 115, 80, 68, 51, 184, 128, 232, 208, 151, 122, + 26, 212, 105, 43, 179, 213, 235, 148, 146, 89, 14, 195, 28, 78, 112, 76, + 250, 47, 24, 251, 140, 108, 186, 190, 228, 170, 183, 139, 39, 188, 244, 246, + 132, 48, 119, 144, 180, 138, 134, 193, 82, 182, 120, 121, 86, 220, 209, 3, + 91, 241, 149, 85, 205, 150, 113, 216, 31, 100, 41, 164, 177, 214, 153, 231, + 38, 71, 185, 174, 97, 201, 29, 95, 7, 92, 54, 254, 191, 118, 34, 221, + 131, 11, 163, 99, 234, 81, 227, 147, 156, 176, 17, 142, 69, 12, 110, 62, + 27, 255, 0, 194, 59, 116, 242, 252, 19, 21, 187, 53, 207, 129, 64, 135, + 61, 40, 167, 237, 102, 223, 106, 159, 197, 189, 215, 137, 36, 32, 22, 5, + + // and a second copy so we don't need an extra mask or static initializer + 23, 125, 161, 52, 103, 117, 70, 37, 247, 101, 203, 169, 124, 126, 44, 123, + 152, 238, 145, 45, 171, 114, 253, 10, 192, 136, 4, 157, 249, 30, 35, 72, + 175, 63, 77, 90, 181, 16, 96, 111, 133, 104, 75, 162, 93, 56, 66, 240, + 8, 50, 84, 229, 49, 210, 173, 239, 141, 1, 87, 18, 2, 198, 143, 57, + 225, 160, 58, 217, 168, 206, 245, 204, 199, 6, 73, 60, 20, 230, 211, 233, + 94, 200, 88, 9, 74, 155, 33, 15, 219, 130, 226, 202, 83, 236, 42, 172, + 165, 218, 55, 222, 46, 107, 98, 154, 109, 67, 196, 178, 127, 158, 13, 243, + 65, 79, 166, 248, 25, 224, 115, 80, 68, 51, 184, 128, 232, 208, 151, 122, + 26, 212, 105, 43, 179, 213, 235, 148, 146, 89, 14, 195, 28, 78, 112, 76, + 250, 47, 24, 251, 140, 108, 186, 190, 228, 170, 183, 139, 39, 188, 244, 246, + 132, 48, 119, 144, 180, 138, 134, 193, 82, 182, 120, 121, 86, 220, 209, 3, + 91, 241, 149, 85, 205, 150, 113, 216, 31, 100, 41, 164, 177, 214, 153, 231, + 38, 71, 185, 174, 97, 201, 29, 95, 7, 92, 54, 254, 191, 118, 34, 221, + 131, 11, 163, 99, 234, 81, 227, 147, 156, 176, 17, 142, 69, 12, 110, 62, + 27, 255, 0, 194, 59, 116, 242, 252, 19, 21, 187, 53, 207, 129, 64, 135, + 61, 40, 167, 237, 102, 223, 106, 159, 197, 189, 215, 137, 36, 32, 22, 5, +}; + +static float stb__perlin_lerp(float a, float b, float t) +{ + return a + (b-a) * t; +} + +static int stb__perlin_fastfloor(float a) +{ + int ai = (int) a; + return (a < ai) ? ai-1 : ai; +} + +// different grad function from Perlin's, but easy to modify to match reference +static float stb__perlin_grad(int hash, float x, float y, float z) +{ + static float basis[12][4] = + { + { 1, 1, 0 }, + { -1, 1, 0 }, + { 1,-1, 0 }, + { -1,-1, 0 }, + { 1, 0, 1 }, + { -1, 0, 1 }, + { 1, 0,-1 }, + { -1, 0,-1 }, + { 0, 1, 1 }, + { 0,-1, 1 }, + { 0, 1,-1 }, + { 0,-1,-1 }, + }; + + // perlin's gradient has 12 cases so some get used 1/16th of the time + // and some 2/16ths. We reduce bias by changing those fractions + // to 5/64ths and 6/64ths, and the same 4 cases get the extra weight. + static unsigned char indices[64] = + { + 0,1,2,3,4,5,6,7,8,9,10,11, + 0,9,1,11, + 0,1,2,3,4,5,6,7,8,9,10,11, + 0,1,2,3,4,5,6,7,8,9,10,11, + 0,1,2,3,4,5,6,7,8,9,10,11, + 0,1,2,3,4,5,6,7,8,9,10,11, + }; + + // if you use reference permutation table, change 63 below to 15 to match reference + // (this is why the ordering of the table above is funky) + float *grad = basis[indices[hash & 63]]; + return grad[0]*x + grad[1]*y + grad[2]*z; +} + +float stb_perlin_noise3(float x, float y, float z, int x_wrap, int y_wrap, int z_wrap) +{ + float u,v,w; + float n000,n001,n010,n011,n100,n101,n110,n111; + float n00,n01,n10,n11; + float n0,n1; + + unsigned int x_mask = (x_wrap-1) & 255; + unsigned int y_mask = (y_wrap-1) & 255; + unsigned int z_mask = (z_wrap-1) & 255; + int px = stb__perlin_fastfloor(x); + int py = stb__perlin_fastfloor(y); + int pz = stb__perlin_fastfloor(z); + int x0 = px & x_mask, x1 = (px+1) & x_mask; + int y0 = py & y_mask, y1 = (py+1) & y_mask; + int z0 = pz & z_mask, z1 = (pz+1) & z_mask; + int r0,r1, r00,r01,r10,r11; + + #define stb__perlin_ease(a) (((a*6-15)*a + 10) * a * a * a) + + x -= px; u = stb__perlin_ease(x); + y -= py; v = stb__perlin_ease(y); + z -= pz; w = stb__perlin_ease(z); + + r0 = stb__perlin_randtab[x0]; + r1 = stb__perlin_randtab[x1]; + + r00 = stb__perlin_randtab[r0+y0]; + r01 = stb__perlin_randtab[r0+y1]; + r10 = stb__perlin_randtab[r1+y0]; + r11 = stb__perlin_randtab[r1+y1]; + + n000 = stb__perlin_grad(stb__perlin_randtab[r00+z0], x , y , z ); + n001 = stb__perlin_grad(stb__perlin_randtab[r00+z1], x , y , z-1 ); + n010 = stb__perlin_grad(stb__perlin_randtab[r01+z0], x , y-1, z ); + n011 = stb__perlin_grad(stb__perlin_randtab[r01+z1], x , y-1, z-1 ); + n100 = stb__perlin_grad(stb__perlin_randtab[r10+z0], x-1, y , z ); + n101 = stb__perlin_grad(stb__perlin_randtab[r10+z1], x-1, y , z-1 ); + n110 = stb__perlin_grad(stb__perlin_randtab[r11+z0], x-1, y-1, z ); + n111 = stb__perlin_grad(stb__perlin_randtab[r11+z1], x-1, y-1, z-1 ); + + n00 = stb__perlin_lerp(n000,n001,w); + n01 = stb__perlin_lerp(n010,n011,w); + n10 = stb__perlin_lerp(n100,n101,w); + n11 = stb__perlin_lerp(n110,n111,w); + + n0 = stb__perlin_lerp(n00,n01,v); + n1 = stb__perlin_lerp(n10,n11,v); + + return stb__perlin_lerp(n0,n1,u); +} + +float stb_perlin_ridge_noise3(float x, float y, float z,float lacunarity, float gain, float offset, int octaves,int x_wrap, int y_wrap, int z_wrap) +{ + int i; + float frequency = 1.0f; + float prev = 1.0f; + float amplitude = 0.5f; + float sum = 0.0f; + + for (i = 0; i < octaves; i++) { + float r = (float)(stb_perlin_noise3(x*frequency,y*frequency,z*frequency,x_wrap,y_wrap,z_wrap)); + r = r<0 ? -r : r; // fabs() + r = offset - r; + r = r*r; + sum += r*amplitude*prev; + prev = r; + frequency *= lacunarity; + amplitude *= gain; + } + return sum; +} + +float stb_perlin_fbm_noise3(float x, float y, float z,float lacunarity, float gain, int octaves,int x_wrap, int y_wrap, int z_wrap) +{ + int i; + float frequency = 1.0f; + float amplitude = 1.0f; + float sum = 0.0f; + + for (i = 0; i < octaves; i++) { + sum += stb_perlin_noise3(x*frequency,y*frequency,z*frequency,x_wrap,y_wrap,z_wrap)*amplitude; + frequency *= lacunarity; + amplitude *= gain; + } + return sum; +} + +float stb_perlin_turbulence_noise3(float x, float y, float z, float lacunarity, float gain, int octaves,int x_wrap, int y_wrap, int z_wrap) +{ + int i; + float frequency = 1.0f; + float amplitude = 1.0f; + float sum = 0.0f; + + for (i = 0; i < octaves; i++) { + float r = stb_perlin_noise3(x*frequency,y*frequency,z*frequency,x_wrap,y_wrap,z_wrap)*amplitude; + r = r<0 ? -r : r; // fabs() + sum += r; + frequency *= lacunarity; + amplitude *= gain; + } + return sum; +} + +#endif // STB_PERLIN_IMPLEMENTATION + +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +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. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to +this software under copyright law. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS 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. +------------------------------------------------------------------------------ +*/ diff --git a/src/raylib.h b/src/raylib.h index 29cc57289..828c2fe90 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -876,8 +876,10 @@ RLAPI void ImageColorBrightness(Image *image, int brightness); // Image generation functions RLAPI Image GenImageGradientV(int width, int height, Color top, Color bottom); // Generate image: vertical gradient RLAPI Image GenImageGradientH(int width, int height, Color left, Color right); // Generate image: horizontal gradient +RLAPI Image GenImageRadialGradient(int width, int height, Color inner, Color outer); // Generate image: radial gradient RLAPI Image GenImageChecked(int width, int height, int checksX, int checksY, Color col1, Color col2); // Generate image: checked RLAPI Image GenImageWhiteNoise(int width, int height, float factor); // Generate image: white noise +RLAPI Image GenImagePerlinNoise(int width, int height, float scale); // Generate image: perlin noise RLAPI Image GenImageCellular(int width, int height, int tileSize); // Generate image: cellular algorithm. Bigger tileSize means bigger cells // Texture2D configuration functions diff --git a/src/textures.c b/src/textures.c index 99392516b..be089a937 100644 --- a/src/textures.c +++ b/src/textures.c @@ -68,6 +68,9 @@ #include "utils.h" // Required for: fopen() Android mapping +#define STB_PERLIN_IMPLEMENTATION +#include "external/stb_perlin.h"// Required for: stb_perlin_fbm_noise3 + // Support only desired texture formats on stb_image #if !defined(SUPPORT_FILEFORMAT_BMP) #define STBI_NO_BMP @@ -1477,6 +1480,34 @@ Image GenImageGradientH(int width, int height, Color left, Color right) return image; } +// Generate image: radial gradient +Image GenImageRadialGradient(int width, int height, Color inner, Color outer) +{ + Color *pixels = (Color*)malloc(width * height * sizeof(Color)); + float radius = (width < height) ? (float)width / 2.f : (float)height / 2.f; + + float center_x = (float)width / 2.f; + float center_y = (float)height / 2.f; + for (int y = 0; y < height; y++) + { + for (int x = 0; x < width; x++) + { + float dist = hypotf((float)x - center_x, (float)y - center_y); + float factor = dist / radius; + factor = fmin(factor, 1.f); // dist can be bigger than radius so we have to check + pixels[y*width + x].r = (int)((float)outer.r * factor + (float)inner.r * (1.f - factor)); + pixels[y*width + x].g = (int)((float)outer.g * factor + (float)inner.g * (1.f - factor)); + pixels[y*width + x].b = (int)((float)outer.b * factor + (float)inner.b * (1.f - factor)); + pixels[y*width + x].a = (int)((float)outer.a * factor + (float)inner.a * (1.f - factor)); + } + } + + Image image = LoadImageEx(pixels, width, height); + free(pixels); + + return image; +} + // Generate image: checked Image GenImageChecked(int width, int height, int checksX, int checksY, Color col1, Color col2) { @@ -1514,6 +1545,30 @@ Image GenImageWhiteNoise(int width, int height, float factor) return image; } +// Generate image: perlin noise +Image GenImagePerlinNoise(int width, int height, float scale) +{ + Color *pixels = (Color*)malloc(width * height * sizeof(Color)); + + for (int y = 0; y < height; y++) + { + for (int x = 0; x < width; x++) + { + float nx = (float)x * scale / (float)width; + float ny = (float)y * scale / (float)height; + // we need to translate the data from [-1; 1] to [0; 1] + float p = (stb_perlin_fbm_noise3(nx, ny, 1.f, 2.f, 0.5f, 6, 0, 0, 0) + 1.f) / 2.f; + int intensity = (int)(p * 255.f); + pixels[y*width + x] = (Color){intensity, intensity, intensity, 255}; + } + } + + Image image = LoadImageEx(pixels, width, height); + free(pixels); + + return image; +} + // Generate image: cellular algorithm. Bigger tileSize means bigger cells Image GenImageCellular(int width, int height, int tileSize) {