Generate noise heightmap

This commit is contained in:
Tobias Berger 2021-11-18 14:54:22 +01:00
parent 382b0e4bb0
commit fc1806e1b2

View file

@ -1,62 +1,78 @@
/*******************************************************************************************
*
* raylib [models] example - Heightmap loading and drawing
*
* This example has been created using raylib 1.8 (www.raylib.com)
* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
*
* Copyright (c) 2015 Ramon Santamaria (@raysan5)
*
********************************************************************************************/
#include "raylib.h"
#define FNL_IMPL
#include "FastNoiseLite.h"
#define INITIAL_SCREEN_WIDTH 900
#define INITIAL_SCREEN_HEIGHT 900
#define SCREEN_SCALE 8
#define CAMERA_SPEED (SCREEN_SCALE * 3.0f)
/* Controls
UP/DOWN - Change octaves (Min 1)
LEFT/RIGHT - Change period (Min 1)
SPACE - Change noise type
R - Reset
WASD - Move camera
*/
#define HEIGHT_MAP_SIZE 128
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
int noisePeriod = 4;
#if defined(__DEBUG)
SetTraceLogLevel(LOG_ALL);
#else
SetTraceLogLevel(LOG_NONE);
#endif
SetConfigFlags(FLAG_WINDOW_RESIZABLE);
InitWindow(INITIAL_SCREEN_WIDTH, INITIAL_SCREEN_HEIGHT, "raylib [core] example - basic window");
const int screenWidth = 800;
const int screenHeight = 450;
fnl_state fnlState = fnlCreateState();
fnlState.seed = 0;
fnlState.frequency = 1.0f / (float)noisePeriod;
fnlState.fractal_type = FNL_FRACTAL_FBM;
fnlState.octaves = 1;
fnlState.noise_type = 0;
fnlState.noise_type = FNL_NOISE_CELLULAR;
fnlState.fractal_type = FNL_FRACTAL_PINGPONG;
fnlState.octaves = 3;
fnlState.frequency = 1.0f / 50.0f;
int virtualScreenWidth = GetScreenWidth() / SCREEN_SCALE;
int virtualScreenHeight = GetScreenHeight() / SCREEN_SCALE;
InitWindow(screenWidth, screenHeight, "raylib [models] example - heightmap loading and drawing");
RenderTexture2D *target = (RenderTexture2D *)MemAlloc(sizeof(RenderTexture2D));
// Define our custom camera to look into our 3d world
Camera camera = {{18.0f, 18.0f, 18.0f}, {0.0f, 0.0f, 0.0f}, {0.0f, 1.0f, 0.0f}, 45.0f, 0};
*target = LoadRenderTexture(virtualScreenWidth, virtualScreenHeight);
Color pixels[HEIGHT_MAP_SIZE * HEIGHT_MAP_SIZE] = {0};
Vector2 offset = {0.0f, 0.0f};
for (int x = 0; x < HEIGHT_MAP_SIZE; x++)
{
for (int y = 0; y < HEIGHT_MAP_SIZE; y++)
{
float raw_noise = fnlGetNoise2D(&fnlState, (float)x, (float)y);
float noise = ((raw_noise + 1.0f) / 2.0f) * 255.0f;
unsigned char intensity = (unsigned char)noise;
pixels[x + y * HEIGHT_MAP_SIZE] = (Color){
intensity,
intensity,
intensity,
255,
};
}
}
Rectangle sourceRec = {0.0f,
0.0f,
(float)target->texture.width,
-(float)target->texture.height};
Rectangle destRec = {0.0f,
0.0f,
GetScreenWidth(),
GetScreenHeight()};
Image image = {
.data = pixels,
.width = HEIGHT_MAP_SIZE,
.height = HEIGHT_MAP_SIZE,
.format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8,
.mipmaps = 1,
}; // Load heightmap image (RAM)
Texture2D texture = LoadTextureFromImage(image); // Convert image to texture (VRAM)
Mesh mesh = GenMeshHeightmap(image, (Vector3){16, 8, 16}); // Generate heightmap mesh (RAM and VRAM)
Model model = LoadModelFromMesh(mesh); // Load model from generated mesh
model.materials[0].maps[MATERIAL_MAP_DIFFUSE].texture = texture; // Set map diffuse texture
Vector3 mapPosition = {-8.0f, 0.0f, -8.0f}; // Define model position
UnloadImage(image); // Unload heightmap image from RAM, already uploaded to VRAM
SetCameraMode(camera, CAMERA_ORBITAL); // Set an orbital camera mode
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
//--------------------------------------------------------------------------------------
// Main game loop
@ -64,129 +80,37 @@ int main(void)
{
// Update
//----------------------------------------------------------------------------------
if (IsKeyPressed(KEY_SPACE))
{
fnlState.noise_type++;
fnlState.noise_type %= (FNL_NOISE_VALUE + 1);
TraceLog(LOG_INFO, TextFormat("Noisetype: %i", fnlState.noise_type));
}
if (IsWindowResized())
{
TraceLog(LOG_DEBUG, "Resized.");
virtualScreenWidth = GetScreenWidth() / SCREEN_SCALE;
virtualScreenHeight = GetScreenHeight() / SCREEN_SCALE;
UnloadRenderTexture(*target);
*target = LoadRenderTexture(virtualScreenWidth, virtualScreenHeight);
sourceRec = (Rectangle){0.0f,
0.0f,
(float)target->texture.width,
-(float)target->texture.height};
destRec = (Rectangle){0.0f,
0.0f,
GetScreenWidth(),
GetScreenHeight()};
}
if (IsKeyPressed(KEY_UP))
{
fnlState.octaves++;
}
if (IsKeyPressed(KEY_DOWN))
{
fnlState.octaves--;
}
if (IsKeyPressed(KEY_UP) || IsKeyPressed(KEY_DOWN))
{
fnlState.octaves = fnlState.octaves <= 0 ? 1 : fnlState.octaves;
TraceLog(LOG_INFO, TextFormat("Octaves: %i", fnlState.octaves));
}
if (IsKeyPressed(KEY_LEFT))
{
noisePeriod--;
}
if (IsKeyPressed(KEY_RIGHT))
{
noisePeriod++;
}
if (IsKeyPressed(KEY_LEFT) || IsKeyPressed(KEY_RIGHT))
{
noisePeriod = noisePeriod <= 0 ? 1 : noisePeriod;
fnlState.frequency = 1.0f / (float)noisePeriod;
TraceLog(LOG_INFO, TextFormat("Noise period: %i", noisePeriod));
}
if (IsKeyPressed(KEY_R))
{
noisePeriod = 4;
fnlState.frequency = 1.0f / (float)noisePeriod;
fnlState.octaves = 1;
}
if (IsKeyDown(KEY_W))
{
offset.y -= GetFrameTime() * CAMERA_SPEED;
}
if (IsKeyDown(KEY_S))
{
offset.y += GetFrameTime() * CAMERA_SPEED;
}
if (IsKeyDown(KEY_A))
{
offset.x -= GetFrameTime() * CAMERA_SPEED;
}
if (IsKeyDown(KEY_D))
{
offset.x += GetFrameTime() * CAMERA_SPEED;
}
UpdateCamera(&camera); // Update camera
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginTextureMode(*target);
ClearBackground(RAYWHITE);
for (int x = 0; x < virtualScreenWidth; x++)
{
for (int y = 0; y < virtualScreenHeight; y++)
{
float raw_noise = fnlGetNoise2D(&fnlState, (float)x + floorf(offset.x), (float)y + floorf(offset.y));
float noise = (raw_noise + 1.0f) / 2.0f * 255.0f;
const unsigned char r = noise >= 170 ? 255 : (unsigned char)(noise * 1.5f);
const unsigned char g = 255;
const unsigned char b = 255;
DrawPixel(x, y, (Color){r, g, b, 255});
}
}
EndTextureMode();
BeginDrawing();
{
ClearBackground(RAYWHITE);
DrawTexturePro(target->texture, sourceRec, destRec, (Vector2){0.0f, 0.0f}, 0.0f, WHITE);
char const *drawText = TextFormat("Press [SPACEBAR] to cycle through different noise algorithms, arrow keys to control variables\n%i FPS\nNoise Period (Frequency): %i (%f)\nNoise Octaves: %i", GetFPS(), noisePeriod, fnlState.frequency, fnlState.octaves);
DrawRectangle(0, 0, MeasureText(drawText, 20), (int)(20 * 5.5), WHITE);
DrawText(drawText, 0, 0, 20, BLACK);
}
BeginMode3D(camera);
DrawModel(model, mapPosition, 1.0f, RED);
DrawGrid(20, 1.0f);
EndMode3D();
DrawTexture(texture, screenWidth - texture.width - 20, 20, WHITE);
DrawRectangleLines(screenWidth - texture.width - 20, 20, texture.width, texture.height, GREEN);
DrawFPS(10, 10);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
MemFree(target);
UnloadTexture(texture); // Unload texture
UnloadModel(model); // Unload model
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------