OpenGL GLM绕Z轴旋转二维图形

cigdeys3  于 2022-09-26  发布在  其他
关注(0)|答案(1)|浏览(151)

这类似于this question,但我有一个2D三角形,我试图只绕z轴旋转,所以我认为我不需要做任何负旋转。我特意选择了一个以屏幕中心为中心的三角形(我用this webpage计算了质心)。基本上,我希望它看起来像是三角形围绕窗口中心顺时针或逆时针旋转,但通过改变我定义顶点的顺序,我发现它似乎是围绕我定义的最后一个顶点旋转的。

以下是我的C++代码;为简洁起见,我删除了注解。我目前没有任何输入处理--我在vscode中运行,所以我一直通过IDE终止它。

// Third-party library

# include <SDL2/SDL.h>

// Include GLAD

# include <glad/glad.h>

# include <glm/vec3.hpp>

# include <glm/mat3x3.hpp>

# include <glm/mat4x4.hpp>

# include <glm/ext/matrix_transform.hpp>

# include <glm/gtx/string_cast.hpp>

// C++ Standard Libraries

# include <iostream>

# include <fstream>

# include <vector>

# include <string>

// Screen dimensions
int gScreenHeight = 480;
int gScreenWidth  = 640;
SDL_Window* gGraphicsApplicationWindow = nullptr;
SDL_GLContext gOpenGLContext = nullptr;

// Main loop flag
bool gQuit = false;  // if true, we quit

GLuint gGraphicsPipelineShaderProgram = 0;

GLuint gVertexArrayObject = 0;
GLuint gVertexBufferObject  = 0;
GLuint gVertexBufferObject2 = 0;

glm::mat4 gVertexData(
    -0.4f, -0.4f,  0.0f, 0.0f,  // point 1 - bottom left
     0.4f, -0.4f,  0.0f, 0.0f,  // point 2 - bottom right
     0.0f,  0.8f,  0.0f, 0.0f,  // point 3 - top
     0.0f,  0.0f,  0.0f, 1.0f   // 4th dimension
);
const auto gVertexBytes = gVertexData.length() * gVertexData[0].length()
        * sizeof(gVertexData[0][0]);

std::string loadShaderAsString(const std::string& filename) {
    std::string result = "";
    std::string line = "";
    std::ifstream myFile(filename);
    if (myFile.is_open()) {
        while (std::getline(myFile, line)) {
            result += line + 'n';
        }
        myFile.close();
    }
    return result;
}

GLuint compileShader(GLuint type, const std::string& source) {
    GLuint shaderObject;
    if (type == GL_VERTEX_SHADER) {
        shaderObject = glCreateShader(GL_VERTEX_SHADER);
    } else if (type == GL_FRAGMENT_SHADER) {
        shaderObject = glCreateShader(GL_FRAGMENT_SHADER);
    }
    const char* src = source.c_str();
    glShaderSource(shaderObject, 1, &src, nullptr);
    glCompileShader(shaderObject);
    int result;
    glGetShaderiv(shaderObject, GL_COMPILE_STATUS, &result);
    if (result == GL_FALSE) {
        int length;
        glGetShaderiv(shaderObject, GL_INFO_LOG_LENGTH, &length);
        char* errorMessages = new char[length];  // Could also use alloca here.
        glGetShaderInfoLog(shaderObject, length, &length, errorMessages);
       if (type == GL_VERTEX_SHADER) {
            std::cout << "ERROR: GL_VERTEX_SHADER compilation failed!n"
                << errorMessages << "n";
        } else if (type == GL_FRAGMENT_SHADER) {
            std::cout << "ERROR: GL_FRAGMENT_SHADER compilation failed!n"
                << errorMessages << "n";
        }
        delete[] errorMessages;
        glDeleteShader(shaderObject);
        return 0;
    }
    return shaderObject;
}

GLuint createShaderProgram(const std::string& vertexShaderSource,
                           const std::string& fragmentShaderSource) {
    GLuint programObject = glCreateProgram();
    GLuint myVertexShader   = compileShader(GL_VERTEX_SHADER, vertexShaderSource);
    GLuint myFragmentShader = compileShader(GL_FRAGMENT_SHADER, fragmentShaderSource);
    glAttachShader(programObject, myVertexShader);
    glAttachShader(programObject, myFragmentShader);
    glLinkProgram(programObject);
    glValidateProgram(programObject);
    glDetachShader(programObject, myVertexShader);
    glDetachShader(programObject, myFragmentShader);
    glDeleteShader(myVertexShader);
    glDeleteShader(myFragmentShader);
    return programObject;
}

void createGraphicsPipeline() {
    std::string vertexShaderSource   = loadShaderAsString("../shaders/vert.glsl");
    std::string fragmentShaderSource = loadShaderAsString("../shaders/frag.glsl");
    gGraphicsPipelineShaderProgram = createShaderProgram(vertexShaderSource,
                                                        fragmentShaderSource);
}

void getOpenGLVersionInfo() {
    std::cout << "Vendor: " << glGetString(GL_VENDOR) << std::endl;
    std::cout << "Renderer: " << glGetString(GL_RENDERER) << std::endl;
    std::cout << "Version: " << glGetString(GL_VERSION) << std::endl;
    std::cout << "Shading Language: " << glGetString(GL_SHADING_LANGUAGE_VERSION) << std::endl;
}

void vertexSpecification() {
    const std::vector<GLfloat> vertexColors {
         1.0f,  0.0f,  0.0f,  // vertex 1 - Left
         0.0f,  1.0f,  0.0f,  // vertex 2 - Right
         0.0f,  0.0f,  1.0f   // vertex 3 - Top
    };
    glGenVertexArrays(1, &gVertexArrayObject);
    glBindVertexArray(gVertexArrayObject);
    glGenBuffers(1, &gVertexBufferObject);
    glBindBuffer(GL_ARRAY_BUFFER, gVertexBufferObject);
    glBufferData(GL_ARRAY_BUFFER,
                 gVertexBytes,
                 &gVertexData[0][0],
                 GL_DYNAMIC_DRAW);
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0,
                          gVertexData[0].length(),
                          GL_FLOAT,
                          GL_FALSE,
                          0,
                          nullptr);

    glGenBuffers(1, &gVertexBufferObject2);
    glBindBuffer(GL_ARRAY_BUFFER, gVertexBufferObject2);
    glBufferData(GL_ARRAY_BUFFER,
                vertexColors.size() * sizeof(GL_FLOAT),
                vertexColors.data(),
                GL_STATIC_DRAW);
    glEnableVertexAttribArray(1);
    glVertexAttribPointer(1, 3, GL_FLOAT,
                          GL_FALSE, 0, nullptr);
    glBindVertexArray(0);
    glDisableVertexAttribArray(0);
    glDisableVertexAttribArray(1);
}

void initializeProgram() {
    if (SDL_Init(SDL_INIT_VIDEO) < 0) {
        std::cout << "SDL could not be initialized: " <<
                  SDL_GetError();
        exit(1);
    }

    std::cout << "SDL video system is ready to gon";

    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
    SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
    SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
    gGraphicsApplicationWindow = SDL_CreateWindow("C++ SDL2 Window",
            SDL_WINDOWPOS_UNDEFINED,
            SDL_WINDOWPOS_UNDEFINED,
            gScreenWidth,
            gScreenHeight,
            SDL_WINDOW_OPENGL);
    if (gGraphicsApplicationWindow == nullptr) {
        std::cout << "SDL WIndow was not able to be created" << std::endl;
        exit(1);
    }
    gOpenGLContext = SDL_GL_CreateContext(gGraphicsApplicationWindow);
    if (gOpenGLContext == nullptr) {
        std::cout << "OpenGL context not available" << std::endl;
        exit(1);
    }
    if (!gladLoadGLLoader(SDL_GL_GetProcAddress)) {
        std::cout << "Glad was not initialized" << std::endl;
        exit(1);
    }
    getOpenGLVersionInfo();
}

void predraw() {
    static glm::vec3 zNorm(0.0f, 0.0f, 1.0f);
    gVertexData = glm::rotate(gVertexData, glm::radians(0.10f), zNorm);
    glBindBuffer(GL_ARRAY_BUFFER, gVertexBufferObject);
    glBufferData(GL_ARRAY_BUFFER,
                 gVertexBytes,
                 &gVertexData[0][0],
                 GL_DYNAMIC_DRAW);
    glDisable(GL_DEPTH_TEST);
    glDisable(GL_CULL_FACE);
    glViewport(0, 0, gScreenWidth, gScreenHeight);
    glClearColor(1.0f, 1.0f, 0.0f, 1.0f);
    glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
    glUseProgram(gGraphicsPipelineShaderProgram);
}

void draw() {
    glBindVertexArray(gVertexArrayObject);
    glBindBuffer(GL_ARRAY_BUFFER, gVertexBufferObject);
    glDrawArrays(GL_TRIANGLES, 0, 3);
    glUseProgram(0);
}

void mainLoop() {
    while (!gQuit) {
        predraw();
        draw();
        SDL_GL_SwapWindow(gGraphicsApplicationWindow);
    }
}

void cleanup() {
    SDL_DestroyWindow(gGraphicsApplicationWindow);
    SDL_Quit();
}

int main(int argc, char* argv[]) {
    initializeProgram();
    vertexSpecification();
    createGraphicsPipeline();
    mainLoop();
    cleanup();
    return 0;
}

以下是顶点着色器代码:


# version 410 core

layout(location=0) in vec4 position;
layout(location=1) in vec3 vertexColors;

out vec3 v_vertexColors;

void main()
{
   v_vertexColors = vertexColors;

   gl_Position = vec4(position.x, position.y, position.z, 1.0f);
}

和片段着色器:


# version 410 core

in vec3 v_vertexColors;

out vec4 color;

void main()
{
   color = vec4(v_vertexColors.r, v_vertexColors.g, v_vertexColors.b, 1.0f);
}

我已经看了这些matricesrotations教程,但我还没能找出我做错了什么。

dtcbnfnu

dtcbnfnu1#

必须在顶点着色器中变换顶点坐标。见LearnOpenGL - Transformations(页面底部)

使用类型为mat4的统一变量并变换顶点着色器中的顶点:


# version 410 core

layout(location=0) in vec4 position;
layout(location=1) in vec3 vertexColors;

out vec3 v_vertexColors;
uniform mat4 model_matrix;

void main()
{
   v_vertexColors = vertexColors;

   gl_Position = model_matrix * vec4(position.xyz, 1.0f);
}

安装程序后设置矩阵:

int model_loc = glGetUniformLocation(gGraphicsPipelineShaderProgram, "model_matrix")
glm::mat4 rotation_matrix(1.0f);
rotation_matrix = glm::rotate(rotation_matrix, glm::radians(angle), zNorm);
glUseProgram(gGraphicsPipelineShaderProgram);
glUniformMatrix4fv(model_loc, 1, false, glm::value_ptr(rotation_matrix));

每一帧都需要增加变量angle。例如:angle = 0.1f;

相关问题