簡體   English   中英

OpenGL 高度圖渲染器不會產生平滑的地形

[英]OpenGL heightmap renderer not producing smooth terrain

我正在使用嵌套網格和高度圖使用 C++ 和 OpenGL 編寫地形渲染器,並且在處理看起來塊狀/梯狀的更高細節(更近)網格時遇到了麻煩。

最初我認為問題出在我使用的 8 位高度圖上,但 16 位高度圖產生相同的結果(我使用 l3dt、World Machine 和 Photoshop 生成不同的地圖)。

我的代碼需要從引擎管道中抽象出來,以便使用頂點着色器中的變換反饋將高度圖應用於網格:

void main()
{
    float texOffset = 1.0 / mapWidthTexels, mapOffset = scale / mapWidthWorld; //Size of a texel in [0, 1] coordinates and size of a quad in world space
    vec2 texCoord = (vertPos.xz * scale + offset) / mapWidthWorld + 0.5; //Texture coordinate to sample heightmap at. vertPos is the input vertex, scale is pow(2, i) where i is the nested grid number, offset is eye position
    position = vertPos * scale;

    if(vertPos.y == 0.0) //Y coordinate of the input vertex is used as a flag to tell if the vertex is bordering between nested grids
        position.y = texture(heightmap, texCoord).r; //If it's not, just sample the heightmap
    else
    {
        //Otherwise get the two adjacent heights and average them
        vec2 side = vec2(0.0);
        if(abs(vertPos.x) < abs(vertPos.z))
            side.x = mapOffset;
        else
            side.y = mapOffset;
        float a = texture(heightmap, texCoord + side).r, b = texture(heightmap, texCoord - side).r;
        position.y = (a + b) * 0.5;
    }

    float mapF = mapWidthWorld * 0.5;
    position.xz = clamp(position.xz + offset, -mapF, mapF) - offset; //Vertices outside of the heightmap are clamped, creating degenrate triangles
    position.y *= heightMultiplier; //Y component so far is in the [0, 1] range, now multiply it to create the desired height

    //Calculate normal
    float leftHeight = texture(heightmap, texCoord + vec2(-texOffset, 0.0)).r * heightMultiplier, rightHeight = texture(heightmap, texCoord + vec2(texOffset, 0.0)).r * heightMultiplier;
    float downHeight = texture(heightmap, texCoord + vec2(0.0, -texOffset)).r * heightMultiplier, upHeight = texture(heightmap, texCoord + vec2(0.0, texOffset)).r * heightMultiplier;
    normal = normalize(vec3(leftHeight - rightHeight, 2.0, upHeight - downHeight));

    tex = vertTex; //Pass through texture coordinates
}

RAW 16 位高度圖按如下方式加載:

std::ifstream file(_path, std::ios::ate | std::ios::binary);
int size = file.tellg();
file.seekg(0, std::ios::beg);
m_heightmapWidth = sqrt(size / 2); //Assume 16-bit greyscale
unsigned short *data = new unsigned short[size / 2];
file.read(reinterpret_cast<char*>(data), size);

if (m_flip16bit) //Dirty endianness fix
{
    for (int i = 0; i < size / 2; i++)
        data[i] = (data[i] << 8) | ((data[i] >> 8) & 0xFF);
}

glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, m_heightmapWidth, m_heightmapWidth, 0, GL_RED, GL_UNSIGNED_SHORT, data);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
delete[] data;

其他格式與 stb_image 類似。

生成的地形如下所示: https : //imgur.com/a/d8tDPGO

正如您所看到的,幾乎不知道坡度的區域具有這種梯田狀外觀。 我究竟做錯了什么?

RAW 16 位高度圖按如下方式加載:

 [...] glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, m_heightmapWidth, m_heightmapWidth, 0, GL_RED, GL_UNSIGNED_SHORT, data); ^^^^^^

不。 internalFormat參數控制紋理存儲在 GPU 上的格式, GL_RED在任何現實場景中都只是 8 位。 您很可能希望GL_R16用於標准化的 16Bit 無符號整數格式。

原來 l3dt 的紋理是問題所在,原本應該在水下的部分變成了梯田。 此外,如果在使用l3dt高度范圍不匹配heightMulptiplier在着色器偽像可以從出現的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM