簡體   English   中英

無法在Qt OpenGL中將紋理應用於頂點網格

[英]Can't apply texture to grid of vertices in Qt OpenGL

現在,我正在創建一個基於Heightmap的地形網格,類似於Lighthouse 3D Terrain教程 ,但我使用的是VBO和EBO。 一切都進行得很好,直到我嘗試對網格進行紋理化處理為止。 目前,我正在應用一種橫跨整個網格的紋理。 使用Window 7的示例水母圖片,我得到以下結果:

地形扭曲的地形

對於熟悉圖片的人,您可以看到它在整個地形網格中重復了幾次。 這使我相信我的UV坐標已損壞。 但是,如果我使用一個始終返回0的函數來確定每個網格頂點的高度,我將得出以下結論:

穩定的藍色網格

現在,我感到非常困惑,而且似乎找不到其他資源來幫助我。

我的代碼如下:

generate_terrain()函數:

QImage terrainImage;
terrainImage.load(imagePath.data());
int width = terrainImage.width();
int height = terrainImage.height();

float uStep = 1.0f / width;
float vStep = 1.0f / height;

grid = new std::vector<float>;
indices = new std::vector<unsigned short>;

for (int i = 0; i <= height-1; ++i) {
    for (int j = 0; j <= width-1; ++j) {
        QVector3D vertex1{j, heightFunction(terrainImage.pixel(j, i)), i};
        QVector3D vertex2{j, heightFunction(terrainImage.pixel(j, i+1)), i+1};
        QVector3D vertex3{j+1, heightFunction(terrainImage.pixel(j+1, i+1)), i+1};

        QVector3D edge1 = vertex2 - vertex1;
        QVector3D edge2 = vertex3 - vertex1;
        QVector3D normal = QVector3D::crossProduct(edge1, edge2);
        normal.normalize();

        grid->push_back(vertex1.x());
        grid->push_back(vertex1.y());
        grid->push_back(vertex1.z());

        grid->push_back(normal.x());
        grid->push_back(normal.y());
        grid->push_back(normal.z());

        grid->push_back(j * uStep);
        grid->push_back(i * vStep);
    }
}

for (int i = 0; i < height-1; ++i) {
    for (int j = 0; j < width-1; ++j) {
        indices->push_back(i * width + j);
        indices->push_back((i+1) * width + j);
        indices->push_back((i+1) * width + (j+1));

        indices->push_back((i+1) * width + (j+1));
        indices->push_back(i * width + (j+1));
        indices->push_back(i * width + j);
    }
}

vertices = grid->size()/8;
indexCount = indices->size();

紋理加載:

f->glGenTextures(1, &textureId);
f->glBindTexture(GL_TEXTURE_2D, textureId);

QImage texture;
texture.load(texturePath.data());
QImage glTexture = QGLWidget::convertToGLFormat(texture);

f->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, glTexture.width(), glTexture.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, glTexture.bits());
f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

畫畫:

f->glActiveTexture(GL_TEXTURE0);
f->glBindTexture(GL_TEXTURE_2D, textureId);
program->setUniformValue(textureUniform.data(), 0);

f->glBindBuffer(GL_ARRAY_BUFFER, vbo.bufferId());
f->glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8*sizeof(float), 0);
f->glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8*sizeof(float), (void *) (sizeof(float) * 3));
f->glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8*sizeof(float), (void *) (sizeof(float) * 6));

f->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo.bufferId());
f->glEnableVertexAttribArray(0);
f->glEnableVertexAttribArray(1);
f->glEnableVertexAttribArray(2);
f->glDrawElements(GL_TRIANGLES, indexCount, GL_UNSIGNED_SHORT, 0);
f->glDisableVertexAttribArray(2);
f->glDisableVertexAttribArray(1);
f->glDisableVertexAttribArray(0);

着色器:

頂點:

attribute vec3 vertex_modelspace;
attribute vec3 normal_in;
attribute vec2 uv_in;

uniform mat4 mvp;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
uniform vec3 lightPosition;

varying vec2 uv;
varying vec3 normal;
varying vec3 fragPos;

void main(void)
{
    gl_Position = projection * view * model * vec4(vertex_modelspace, 1);
    uv = uv_in;
    normal = normal_in;

    fragPos = vec3(model * vec4(vertex_modelspace, 1));
}

分段:

varying vec2 uv;
varying vec3 normal;
varying vec3 fragPos;

uniform sampler2D texture;
uniform vec3 lightPosition;

void main(void)
{
    vec3 lightColor = vec3(0.6, 0.6, 0.6);

    float ambientStrength = 0.2;
    vec3 ambient = ambientStrength * lightColor;

    vec3 norm = normalize(normal);
    vec3 lightDirection = normalize(lightPosition - fragPos);
    float diff = max(dot(norm, lightDirection), 0.0);
    vec3 diffuse = diff * lightColor;

    vec3 color = texture2D(texture, uv).rgb;

    vec3 result = (ambient + diffuse) * color;
    gl_FragColor = vec4(result, 1.0);
}

我完全被卡住了,所以歡迎提出任何建議:)

PS:我也在努力使我的照明看起來更好,因此也歡迎您提出任何建議。

您的代碼假定屬性位置的值,這些值用作glVertexAttribPointer()glEnableVertexAttribArray()的第一個參數。 例如這里:

f->glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8*sizeof(float), 0);
f->glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8*sizeof(float), (void *) (sizeof(float) * 3));
f->glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8*sizeof(float), (void *) (sizeof(float) * 6));

您假設位置的位置為0,法線的位置為1,紋理坐標的位置為2。

當前代碼中沒有任何保證。 該順序attribute的聲明在GLSL代碼沒有定義的位置分配。 例如,來自OpenGL 3.2規范:

鏈接程序時,GL將自動將任何沒有通過BindAttribLocation指定綁定的活動屬性綁定到頂點屬性。

請注意,這並未指定如何自動分配位置。 這意味着它取決於實現。

要解決此問題,有兩種方法:

  1. 鏈接着色器程序之前 ,可以為所有屬性調用glBindAttribLocation()
  2. 鏈接程序 ,可以通過調用glGetAttribLocation()查詢自動分配的位置。
  3. 在較新的OpenGL版本(GLSL 3.30和更高版本,它是與OpenGL 3.3匹配的版本)中,您還可以選擇使用layout(location=...)形式的限定符直接在GLSL代碼中指定位置。

這些選擇都沒有一個比其他選擇有任何主要優勢。 只需根據自己的喜好和軟件體系結構使用效果最好的軟件即可。

暫無
暫無

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

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