首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在OpenGL中不复制内存的情况下旋转立体贴图?

如何在OpenGL中不复制内存的情况下旋转立体贴图?
EN

Stack Overflow用户
提问于 2018-12-27 02:01:47
回答 1查看 696关注 0票数 1

问题的最新情况:

在前面的问题描述中,我犯了几个严重的错误,使问题很难理解和解决。现在,我将分享我的最新代码,工作。

我先前关于每张脸的方向的描述是错误的。正确的方向如下:

右面顺时针旋转90度,顶部顺时针旋转180度。

因此,当为由两个三角形( 3 -7-8和8-4-3)组成的右面设置纹理坐标时,我们需要逆时针旋转90度,所以3将使用7's坐标,7 -> 8,8 -> 4,4 -> 3。当为由两个三角形(1-4-8和8-6-1)组成的顶部建立纹理坐标时,我们需要逆时针旋转,所以1将使用8's坐标,4 -> 6,8 -> 1,6 -> 4。

起作用的代码:

代码语言:javascript
复制
    bool setupCoordinates() {
    this->vertexCount = 36;
    float skyboxVertices[] = {
        // positions          

        // back
        -1.0f,  1.0f, -1.0f,
        -1.0f, -1.0f, -1.0f,
        1.0f, -1.0f, -1.0f,
        1.0f, -1.0f, -1.0f,
        1.0f,  1.0f, -1.0f,
        -1.0f,  1.0f, -1.0f,

        // Left
        -1.0f, -1.0f,  1.0f,
        -1.0f, -1.0f, -1.0f,
        -1.0f,  1.0f, -1.0f,
        -1.0f,  1.0f, -1.0f,
        -1.0f,  1.0f,  1.0f,
        -1.0f, -1.0f,  1.0f,
        // Right
        1.0f, -1.0f, -1.0f,
        1.0f, -1.0f,  1.0f,
        1.0f,  1.0f,  1.0f,
        1.0f,  1.0f,  1.0f,
        1.0f,  1.0f, -1.0f,
        1.0f, -1.0f, -1.0f,
        // Front
        -1.0f, -1.0f,  1.0f,
        -1.0f,  1.0f,  1.0f,
        1.0f,  1.0f,  1.0f,
        1.0f,  1.0f,  1.0f,
        1.0f, -1.0f,  1.0f,
        -1.0f, -1.0f,  1.0f,
        // Top
        -1.0f,  1.0f, -1.0f,
        1.0f,  1.0f, -1.0f,
        1.0f,  1.0f,  1.0f,
        1.0f,  1.0f,  1.0f,
        -1.0f,  1.0f,  1.0f,
        -1.0f,  1.0f, -1.0f,
        // Bottom
        -1.0f, -1.0f, -1.0f,
        -1.0f, -1.0f,  1.0f,
        1.0f, -1.0f, -1.0f,
        1.0f, -1.0f, -1.0f,
        -1.0f, -1.0f,  1.0f,
        1.0f, -1.0f,  1.0f
    };

    float skyboxTextures[] = {
        // positions          
        // Back same as skyboxVertices
        -1.0f,  1.0f, -1.0f,
        -1.0f, -1.0f, -1.0f,
        1.0f, -1.0f, -1.0f,
        1.0f, -1.0f, -1.0f,
        1.0f,  1.0f, -1.0f,
        -1.0f,  1.0f, -1.0f,

        // Left same as skyboxVertices
        -1.0f, -1.0f,  1.0f,
        -1.0f, -1.0f, -1.0f,
        -1.0f,  1.0f, -1.0f,
        -1.0f,  1.0f, -1.0f,
        -1.0f,  1.0f,  1.0f,
        -1.0f, -1.0f,  1.0f,

        // Right rotate in 90 ccw
        1.0f, -1.0f,  1.0f,
        1.0f,  1.0f,  1.0f,
        1.0f,  1.0f, -1.0f,
        1.0f,  1.0f, -1.0f,
        1.0f, -1.0f, -1.0f,
        1.0f, -1.0f,  1.0f,

        // Front same as skyboxVertices
        -1.0f, -1.0f,  1.0f,
        -1.0f,  1.0f,  1.0f,
        1.0f,  1.0f,  1.0f,
        1.0f,  1.0f,  1.0f,
        1.0f, -1.0f,  1.0f,
        -1.0f, -1.0f,  1.0f,

        // Top rotate in 180 ccw
        1.0f,  1.0f,  1.0f,
        -1.0f,  1.0f,  1.0f,
        -1.0f,  1.0f,  -1.0f,
        -1.0f,  1.0f,  -1.0f,
        1.0f,  1.0f, -1.0f,
        1.0f,  1.0f,  1.0f,

        // Bottom same as skyboxVertices
        -1.0f, -1.0f, -1.0f,
        -1.0f, -1.0f,  1.0f,
        1.0f, -1.0f, -1.0f,
        1.0f, -1.0f, -1.0f,
        -1.0f, -1.0f,  1.0f,
        1.0f, -1.0f,  1.0f
    };

    glGenVertexArrays(1, &sceneVAO);
    glBindVertexArray(sceneVAO);

    glGenBuffers(1, &sceneVertexBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, sceneVertexBuffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(skyboxVertices), &skyboxVertices, GL_STATIC_DRAW);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);

    glGenBuffers(1, &sceneUVBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, sceneUVBuffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(skyboxTextures), &skyboxTextures, GL_STATIC_DRAW);
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void *)0);

    glBindVertexArray(0);
    return true;
}

void drawFrame() {
    glBindTexture(GL_TEXTURE_CUBE_MAP, sceneTextureID);
    glPixelStorei(GL_UNPACK_ROW_LENGTH, videoFrameWidth);

    int width = videoFrameWidth / 3;
    int height = width;

    // back
    glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
    glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
    glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGB, width, width, 0, GL_RGB, GL_UNSIGNED_BYTE, textureData);

    // left
    glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
    glPixelStorei(GL_UNPACK_SKIP_PIXELS, width);
    glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGB, width, width, 0, GL_RGB, GL_UNSIGNED_BYTE, textureData);

    // front
    glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
    glPixelStorei(GL_UNPACK_SKIP_PIXELS, width * 2);
    glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGB, width, width, 0, GL_RGB, GL_UNSIGNED_BYTE, textureData);

    // bottom
    glPixelStorei(GL_UNPACK_SKIP_ROWS, width);
    glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
    glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGB, width, width, 0, GL_RGB, GL_UNSIGNED_BYTE, textureData);

    // right
    glPixelStorei(GL_UNPACK_SKIP_ROWS, width);
    glPixelStorei(GL_UNPACK_SKIP_PIXELS, width);
    glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGB,width,width,0,GL_RGB,GL_UNSIGNED_BYTE, textureData);

    // top
    glPixelStorei(GL_UNPACK_SKIP_ROWS, width);
    glPixelStorei(GL_UNPACK_SKIP_PIXELS, width * 2);
    glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGB, width, width, 0, GL_RGB, GL_UNSIGNED_BYTE, textureData);

}

我有一个360视频是cubemap3x2格式,我想渲染它在OpenGL中使用立方体纹理。然而,立方体的背面和顶部都是向不同方向旋转的。背面顺时针旋转90度,顶部顺时针旋转180度。现在我可以通过内存复制正确地呈现cubemap,但是我想知道是否有办法通过使用OpenGL的内置功能来避免这种情况呢?

我需要渲染的框架:

顶点着色器:

代码语言:javascript
复制
#version 410 core
uniform mat4 matrix;
out vec3 TexCoords;
layout(location = 0) in vec4 position;
layout(location = 1) in vec3 textureIn;
void main() {
   TexCoords = textureIn;
   gl_Position = matrix * position;
}

碎片着色器:

代码语言:javascript
复制
#version 410 core
varying vec3 TexCoords;
uniform samplerCube mytexture;
void main() {
   gl_FragColor = texture(mytexture, TexCoords);
}

用于呈现的代码:

代码语言:javascript
复制
void Player::SetupScene() {
this->m_sceneVertexCount = 36;
float skyboxVertices[] = {
    // positions          

    // Back
    -1.0f,  1.0f, -1.0f,
    -1.0f, -1.0f, -1.0f,
    1.0f, -1.0f, -1.0f,
    1.0f, -1.0f, -1.0f,
    1.0f,  1.0f, -1.0f,
    -1.0f,  1.0f, -1.0f,

    // Left
    -1.0f, -1.0f,  1.0f,
    -1.0f, -1.0f, -1.0f,
    -1.0f,  1.0f, -1.0f,
    -1.0f,  1.0f, -1.0f,
    -1.0f,  1.0f,  1.0f,
    -1.0f, -1.0f,  1.0f,

    // Right
    1.0f, -1.0f, -1.0f,
    1.0f, -1.0f,  1.0f,
    1.0f,  1.0f,  1.0f,
    1.0f,  1.0f,  1.0f,
    1.0f,  1.0f, -1.0f,
    1.0f, -1.0f, -1.0f,

    // Front
    -1.0f, -1.0f,  1.0f,
    -1.0f,  1.0f,  1.0f,
    1.0f,  1.0f,  1.0f,
    1.0f,  1.0f,  1.0f,
    1.0f, -1.0f,  1.0f,
    -1.0f, -1.0f,  1.0f,

    // Top
    -1.0f,  1.0f, -1.0f,
    1.0f,  1.0f, -1.0f,
    1.0f,  1.0f,  1.0f,
    1.0f,  1.0f,  1.0f,
    -1.0f,  1.0f,  1.0f,
    -1.0f,  1.0f, -1.0f,

    // Bottom
    -1.0f, -1.0f, -1.0f,
    -1.0f, -1.0f,  1.0f,
    1.0f, -1.0f, -1.0f,
    1.0f, -1.0f, -1.0f,
    -1.0f, -1.0f,  1.0f,
    1.0f, -1.0f,  1.0f
};

float skyboxTextures[] = {
    // positions          

    // Back
    -1.0f,  1.0f, -1.0f,
    -1.0f, -1.0f, -1.0f,
    1.0f, -1.0f, -1.0f,
    1.0f, -1.0f, -1.0f,
    1.0f,  1.0f, -1.0f,
    -1.0f,  1.0f, -1.0f,

    // Left
    -1.0f, -1.0f,  1.0f,
    -1.0f, -1.0f, -1.0f,
    -1.0f,  1.0f, -1.0f,
    -1.0f,  1.0f, -1.0f,
    -1.0f,  1.0f,  1.0f,
    -1.0f, -1.0f,  1.0f,

    // Right
    1.0f, -1.0f, -1.0f,
    1.0f, -1.0f,  1.0f,
    1.0f,  1.0f,  1.0f,
    1.0f,  1.0f,  1.0f,
    1.0f,  1.0f, -1.0f,
    1.0f, -1.0f, -1.0f,

    // Front
    -1.0f, -1.0f,  1.0f,
    -1.0f,  1.0f,  1.0f,
    1.0f,  1.0f,  1.0f,
    1.0f,  1.0f,  1.0f,
    1.0f, -1.0f,  1.0f,
    -1.0f, -1.0f,  1.0f,

    // Top
    -1.0f,  1.0f, -1.0f,
    1.0f,  1.0f, -1.0f,
    1.0f,  1.0f,  1.0f,
    1.0f,  1.0f,  1.0f,
    -1.0f,  1.0f,  1.0f,
    -1.0f,  1.0f, -1.0f,

    // Bottom
    -1.0f, -1.0f, -1.0f,
    -1.0f, -1.0f,  1.0f,
    1.0f, -1.0f, -1.0f,
    1.0f, -1.0f, -1.0f,
    -1.0f, -1.0f,  1.0f,
    1.0f, -1.0f,  1.0f
};

glGenVertexArrays(1, &m_SceneVAO);
glBindVertexArray(m_SceneVAO);

glGenBuffers(1, &m_sceneVertBuffer);
glBindBuffer(GL_ARRAY_BUFFER, m_sceneVertBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(skyboxVertices), &skyboxVertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void *)0);

glGenBuffers(1, &m_sceneTexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, m_sceneTexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(skyboxTextures), &skyboxTextures, GL_STATIC_DRAW);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void *)0);
glBindVertexArray(0);
}

void Player::SetupTexture(unsigned char *textureData) {


     int width = frameWidth / 3;


    glPixelStorei(GL_UNPACK_ROW_LENGTH, frameWidth);

    glBindTexture(GL_TEXTURE_CUBE_MAP, m_sceneTextureID);

    // Render left face
    glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
    glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
    glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGB, width, width, 0, GL_RGB, GL_UNSIGNED_BYTE, textureData);

    // Render front face
    glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
    glPixelStorei(GL_UNPACK_SKIP_PIXELS, width);
    glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGB, width, width, 0, GL_RGB, GL_UNSIGNED_BYTE, textureData);


    // Render right face 
    glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
    glPixelStorei(GL_UNPACK_SKIP_PIXELS, width * 2);
    glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGB, width, width, 0, GL_RGB, GL_UNSIGNED_BYTE, textureData);

    // Render bottom face
    glPixelStorei(GL_UNPACK_SKIP_ROWS, width);
    glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
    glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGB, width, width, 0, GL_RGB, GL_UNSIGNED_BYTE, textureData);

    // Rotate the back face 90 degrees counter clockwise 
    uint8_t *start = textureData + rowLength * height * 3 + width * 3;

    for (int j = 0; j < height; j++) {
        for (int i = 0; i < width; i++) {
            m_pRightFaceBuffer[((width - 1 - i) * width + j) * 3 + 0] = *(start + i * 3 + 0);
            m_pRightFaceBuffer[((width - 1 - i) * width + j) * 3 + 1] = *(start + i * 3 + 1);
            m_pRightFaceBuffer[((width - 1 - i) * width + j) * 3 + 2] = *(start + i * 3 + 2);
        }
        start += rowLength * 3;
    }

    glPixelStorei(GL_UNPACK_ROW_LENGTH, width);
    glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
    glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
    glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGB, width, width, 0, GL_RGB, GL_UNSIGNED_BYTE, m_pRightFaceBuffer);

    // Rotate the bottom face 180 degrees counter clockwise
    start = textureData + rowLength * height * 3 + width * 2 * 3;
    for (int j = 0; j < height; j++) {
        for (int i = 0; i < width; i++) {
            m_pUpFaceBuffer[((height - 1 - j)*width + (width - i)) * 3 + 0] = *(start + (i) * 3);
            m_pUpFaceBuffer[((height - 1 - j)*width + (width - i)) * 3 + 1] = *(start + (i) * 3 + 1);
            m_pUpFaceBuffer[((height - 1 - j)*width + (width - i)) * 3 + 2] = *(start + (i) * 3 + 2);
        }
        start += rowLength * 3;
    }

    glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
    glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
    glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGB, width, width, 0, GL_RGB, GL_UNSIGNED_BYTE, m_pUpFaceBuffer);

}

用于构建cubemap的坐标:

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-12-27 09:43:01

您可以通过glTexImage2D直接指定cubemap的两侧:

代码语言:javascript
复制
glPixelStorei(GL_UNPACK_ROW_LENGTH, frameWidth);

// Render left face
[...]

// Render front face
[...]

// Render right face 
[...]

// Render bottom face
[...]

// Render back face
glPixelStorei(GL_UNPACK_SKIP_ROWS, width);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, width);
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGB, width, width, 0, GL_RGB, GL_UNSIGNED_BYTE, textureData);

// Render top face
glPixelStorei(GL_UNPACK_SKIP_ROWS, width);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, width*2);
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGB, width, width, 0, GL_RGB, GL_UNSIGNED_BYTE, textureData);

但是你必须改变右边和顶部的纹理坐标。请注意,您混淆了多维数据集映射边到多维数据集边的映射,但不管怎样,它是工作的:

代码语言:javascript
复制
float skyboxTextures[] = {
    // positions          

    // Back
    // [...]

    // Left
    // [...]

    // Right
    1.0f, -1.0f,  1.0f,
    1.0f,  1.0f,  1.0f,
    1.0f,  1.0f, -1.0f,
    1.0f,  1.0f, -1.0f,
    1.0f, -1.0f, -1.0f,
    1.0f, -1.0f,  1.0f,

    // Front
    // [...]

    // Top
     1.0f,  1.0f,  1.0f,
    -1.0f,  1.0f,  1.0f,
    -1.0f,  1.0f, -1.0f,
    -1.0f,  1.0f, -1.0f,
     1.0f,  1.0f, -1.0f,
     1.0f,  1.0f,  1.0f,

    // Bottom
    // [...]
};

见结果:

由于边的映射似乎搞砸了,我宁愿像这样加载边:

代码语言:javascript
复制
glPixelStorei(GL_UNPACK_ROW_LENGTH, frameWidth);

// Render back face
glPixelStorei(GL_UNPACK_SKIP_ROWS, width);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, width);
glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGB, width, width, 0, GL_RGB, GL_UNSIGNED_BYTE, textureData);

// Render left face
glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGB, width, width, 0, GL_RGB, GL_UNSIGNED_BYTE, textureData);

// Render right face 
glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, width * 2);
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGB, width, width, 0, GL_RGB, GL_UNSIGNED_BYTE, textureData);

// Render front face
glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, width);
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGB, width, width, 0, GL_RGB, GL_UNSIGNED_BYTE, textureData);

// Render top face
glPixelStorei(GL_UNPACK_SKIP_ROWS, width);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, width*2);
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGB, width, width, 0, GL_RGB, GL_UNSIGNED_BYTE, textureData);

// Render bottom face
glPixelStorei(GL_UNPACK_SKIP_ROWS, width);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGB, width, width, 0, GL_RGB, GL_UNSIGNED_BYTE, textureData);

并使用以下纹理坐标:

代码语言:javascript
复制
float skyboxTextures[] = {
    // positions          

    // Back
    -1.0f, -1.0f, -1.0f,
     1.0f, -1.0f, -1.0f,
     1.0f,  1.0f, -1.0f,
     1.0f,  1.0f, -1.0f,
    -1.0f,  1.0f, -1.0f,
    -1.0f, -1.0f, -1.0f,

    // Left
    -1.0f, -1.0f,  1.0f,
    -1.0f, -1.0f, -1.0f,
    -1.0f,  1.0f, -1.0f,
    -1.0f,  1.0f, -1.0f,
    -1.0f,  1.0f,  1.0f,
    -1.0f, -1.0f,  1.0f,

    // Right
    1.0f, -1.0f, -1.0f,
    1.0f, -1.0f,  1.0f,
    1.0f,  1.0f,  1.0f,
    1.0f,  1.0f,  1.0f,
    1.0f,  1.0f, -1.0f,
    1.0f, -1.0f, -1.0f,

    // Front
    -1.0f, -1.0f,  1.0f,
    -1.0f,  1.0f,  1.0f,
     1.0f,  1.0f,  1.0f,
     1.0f,  1.0f,  1.0f,
     1.0f, -1.0f,  1.0f,
    -1.0f, -1.0f,  1.0f,

    // Top
    -1.0f,  1.0f,  1.0f,
    -1.0f,  1.0f, -1.0f,
     1.0f,  1.0f, -1.0f,
     1.0f,  1.0f, -1.0f,
     1.0f,  1.0f,  1.0f,
    -1.0f,  1.0f,  1.0f,

    // Bottom
     1.0f, -1.0f, -1.0f,
    -1.0f, -1.0f, -1.0f,
     1.0f, -1.0f,  1.0f,
     1.0f, -1.0f,  1.0f,
    -1.0f, -1.0f, -1.0f,
    -1.0f, -1.0f,  1.0f
};

但是请注意,y和z轴仍然是交换的。我想这是因为你场景中的世界空间向上向量是(0,1,0)。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53938973

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档