使用Raylib渲染Perlin噪声失败,仅显示黑屏求助
C++ Raylib渲染Perlin噪声黑屏问题解决
核心问题:透明度值溢出导致像素不可见
Raylib的Color结构体中,alpha通道是8位无符号整数,取值范围为0-255。你代码中写的(char)256会因为char的溢出特性(8位最大值为255)被截断为0,导致所有像素完全透明,所以窗口显示黑屏。
将alpha值改为255即可解决这个基础问题:
Color col{c, c, c, 255};
额外优化与潜在问题修复
除了透明度问题,你的Perlin噪声实现还有两个潜在问题,可能导致噪声效果异常:
- 数组索引越界风险
p数组长度为256,当xInd或yInd为255时,xInd +1或yInd +1会变成256,超出数组范围引发未定义行为。需要对索引取模256:
// 修正梯度向量的索引计算,避免越界 int hash00 = p[(p[xi] + yi) & 255]; int hash10 = p[(p[xi + 1 & 255] + yi) & 255]; int hash01 = p[(p[xi] + yi + 1 & 255) & 255]; int hash11 = p[(p[xi + 1 & 255] + yi + 1 & 255) & 255];
- Perlin噪声插值顺序错误
原代码的双线性插值顺序不符合标准实现,会导致噪声纹理扭曲。正确的逻辑是先对x方向插值,再对y方向插值:
// 修正双线性插值顺序 float x1 = lerp(dot00, dot10, u); // 底部两个点的x方向插值 float x2 = lerp(dot01, dot11, u); // 顶部两个点的x方向插值 return lerp(x1, x2, v); // 上下结果的y方向插值
修正后的完整代码
#include <math.h> #include <iostream> #include <vector> #include "raylib.h" using namespace std; int p[] = {151, 160, 137, 91, 90, 15, 131, 13, 201, 95, 96, 53, 194, 233, 7, 225, 140, 36, 103, 30, 69, 142, 8, 99, 37, 240, 21, 10, 23, 190, 6, 148, 247, 120, 234, 75, 0, 26, 197, 62, 94, 252, 219, 203, 117, 35, 11, 32, 57, 177, 33, 88, 237, 149, 56, 87, 174, 20, 125, 136, 171, 168, 68, 175, 74, 165, 71, 134, 139, 48, 27, 166, 77, 146, 158, 231, 83, 111, 229, 122, 60, 211, 133, 230, 220, 105, 92, 41, 55, 46, 245, 40, 244, 102, 143, 54, 65, 25, 63, 161, 1, 216, 80, 73, 209, 76, 132, 187, 208, 89, 18, 169, 200, 196, 135, 130, 116, 188, 159, 86, 164, 100, 109, 198, 173, 186, 3, 64, 52, 217, 226, 250, 124, 123, 5, 202, 38, 147, 118, 126, 255, 82, 85, 212, 207, 206, 59, 227, 47, 16, 58, 17, 182, 189, 28, 42, 223, 183, 170, 213, 119, 248, 152, 2, 44, 154, 163, 70, 221, 153, 101, 155, 167, 43, 172, 9, 129, 22, 39, 253, 19, 98, 108, 110, 79, 113, 224, 232, 178, 185, 112, 104, 218, 246, 97, 228, 251, 34, 242, 193, 238, 210, 144, 12, 191, 179, 162, 241, 81, 51, 145, 235, 249, 14, 239, 107, 49, 192, 214, 31, 181, 199, 106, 157, 184, 84, 204, 176, 115, 121, 50, 45, 127, 4, 150, 254, 138, 236, 205, 93, 222, 114, 67, 29, 24, 72, 243, 141, 128, 195, 78, 66, 215, 61, 156, 180}; float fade(float t) { return t * t * t * (6 * t * t - 15 * t + 10); } float lerp(float a0, float a1, float t) { return a0 + t * (a1 - a0); } float dotp(Vector2 a, Vector2 b) { return a.x * b.x + a.y * b.y; } Vector2 grad(int a) { int l = a % 4; Vector2 v; if (l == 0) { v = {1.0, 1.0}; } else if (l == 1) { v = {-1.0, 1.0}; } else if (l == 2) { v = {-1.0, -1.0}; } else { v = {1.0, -1.0}; } return v; } float perlinNoise(float x, float y) { int xi = (int)floor(x) & 255; int yi = (int)floor(y) & 255; float xf = x - floor(x); float yf = y - floor(y); // 方向向量:从四个网格点到(x,y)的偏移 Vector2 d00 = {xf, yf}; Vector2 d10 = {xf - 1.0f, yf}; Vector2 d01 = {xf, yf - 1.0f}; Vector2 d11 = {xf - 1.0f, yf - 1.0f}; // 网格点的哈希值,避免越界 int hash00 = p[(p[xi] + yi) & 255]; int hash10 = p[(p[xi + 1 & 255] + yi) & 255]; int hash01 = p[(p[xi] + yi + 1 & 255) & 255]; int hash11 = p[(p[xi + 1 & 255] + yi + 1 & 255) & 255]; // 点积计算 float dot00 = dotp(grad(hash00), d00); float dot10 = dotp(grad(hash10), d10); float dot01 = dotp(grad(hash01), d01); float dot11 = dotp(grad(hash11), d11); // fade曲线 float u = fade(xf); float v = fade(yf); // 双线性插值 float x1 = lerp(dot00, dot10, u); float x2 = lerp(dot01, dot11, u); return lerp(x1, x2, v); } int main(void) { const int screenWidth = 512; const int screenHeight = 512; cout << perlinNoise(1.5, 1.5) << '\n'; InitWindow(screenWidth, screenHeight, "perlins go brrrrrrrrrrrrr"); SetTargetFPS(60); while (!WindowShouldClose()) { BeginDrawing(); ClearBackground(BLACK); for (int y = 0; y < screenHeight; y++) { for (int x = 0; x < screenWidth; x++) { float n = perlinNoise(x * 0.01f, y * 0.01f); // 将噪声值归一化到0-1 n = (n + 1.0f) / 2.0f; int c = (int)round(n * 255.0f); Color col{c, c, c, 255}; DrawPixel(x, y, col); } } EndDrawing(); } CloseWindow(); return 0; }
内容的提问来源于stack exchange,提问作者NikoMolecule
相关产品推荐
相关产品推荐

