计算机图形学(3):OpenGL对2D物体进行平移,旋转和缩放

配置OpenGL环境看第一篇文章

此代码为老师给的样例代码基础上进行修改

工程文件

效果图:
计算机图形学(3):OpenGL对2D物体进行平移,旋转和缩放_第1张图片
按WASD进行上下左右移动

按up和down进行缩放:
计算机图形学(3):OpenGL对2D物体进行平移,旋转和缩放_第2张图片
按left和right进行旋转:
计算机图形学(3):OpenGL对2D物体进行平移,旋转和缩放_第3张图片

首先全局定义要用到的一些变量:

float x_delta = 0.1f;       //每次移动距离
float x_press_num = 0;      //x偏移
float y_press_num = 0;      //y偏移
glm::vec3 size = glm::vec3(1.0f);   //物体大小
float angle = 0.0f;         //旋转角度

创建和绑定好三角形的顶点和颜色信息:

在这里插入代码片

```cpp
const GLfloat triangle[] =
    {
        -0.5f, -0.5f, +0.0f,  // left
        +1.0f, +0.0f, +0.0f,  // color

        +0.5f, -0.5f, +0.0f,  // right
        +1.0f, +0.0f, +0.0f,

        +0.0f, +0.5f, +0.0f,  // top
        +1.0f, +0.0f, +0.0f,
    };

    GLuint vaoID;
    glGenVertexArrays(1, &vaoID);
    glBindVertexArray(vaoID);  //first VAO

    GLuint vboID;
    glGenBuffers(1, &vboID);
    glBindBuffer(GL_ARRAY_BUFFER, vboID);
    glBufferData(GL_ARRAY_BUFFER, sizeof(triangle), triangle, GL_STATIC_DRAW);

    // vertex position
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), 0);
    // vertex color
    glEnableVertexAttribArray(1);
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (char*)(3 * sizeof(float)));

每次渲染初始化模型矩阵,对其进行响应的变化然后传到着色器中,最后画出三角形

glm::mat4 model = glm::mat4(1.0f);
    model = glm::rotate(model, angle, glm::vec3(0.0f, 0.0f, 1.0f));
    model = glm::translate(model, glm::vec3(x_delta * x_press_num, x_delta * y_press_num, 0.0f));
    model = glm::scale(model, glm::vec3(size));
    glUniformMatrix4fv(glGetUniformLocation(programID, "model"), 1, GL_FALSE, &model[0][0]);
    glDrawArrays(GL_TRIANGLES, 0, 6);  //render primitives from array data

定义按键事件:

void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) {
    if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
        glfwSetWindowShouldClose(window, true);

    if (key == GLFW_KEY_A && action == GLFW_PRESS) {
        x_press_num -= 1;
    }
    if (key == GLFW_KEY_D && action == GLFW_PRESS) {
        x_press_num += 1;
    }
    if (key == GLFW_KEY_W && action == GLFW_PRESS) {
        y_press_num += 1;
    }
    if (key == GLFW_KEY_S && action == GLFW_PRESS) {
        y_press_num -= 1;
    }
    if (key == GLFW_KEY_UP && action == GLFW_PRESS) {
        size += glm::vec3(0.1f);
    }
    if (key == GLFW_KEY_DOWN && action == GLFW_PRESS) {
        size -= glm::vec3(0.1f);
    }
    if (key == GLFW_KEY_LEFT && action == GLFW_PRESS) {
        angle += 1.0f;
    }
    if (key == GLFW_KEY_RIGHT && action == GLFW_PRESS) {
        angle -= 1.0f;
    }
}

完整main.cpp

#include "Dependencies/glew/glew.h"
#include "Dependencies/GLFW/glfw3.h"

#include "Dependencies/glm/glm.hpp"
#include "Dependencies/glm/gtc/matrix_transform.hpp"

#include 
#include 


GLuint programID;
float x_delta = 0.1f;       //每次移动距离
float x_press_num = 0;      //x偏移
float y_press_num = 0;      //y偏移
glm::vec3 size = glm::vec3(1.0f);   //物体大小
float angle = 0.0f;         //旋转角度

void get_OpenGL_info() {
    // OpenGL information
    const GLubyte* name = glGetString(GL_VENDOR);
    const GLubyte* renderer = glGetString(GL_RENDERER);
    const GLubyte* glversion = glGetString(GL_VERSION);
    std::cout << "OpenGL company: " << name << std::endl;
    std::cout << "Renderer name: " << renderer << std::endl;
    std::cout << "OpenGL version: " << glversion << std::endl;
}

void framebuffer_size_callback(GLFWwindow* window, int width, int height) {
    glViewport(0, 0, width, height);
}

void sendDataToOpenGL() {
    const GLfloat triangle[] =
    {
        -0.5f, -0.5f, +0.0f,  // left
        +1.0f, +0.0f, +0.0f,  // color

        +0.5f, -0.5f, +0.0f,  // right
        +1.0f, +0.0f, +0.0f,

        +0.0f, +0.5f, +0.0f,  // top
        +1.0f, +0.0f, +0.0f,
    };

    GLuint vaoID;
    glGenVertexArrays(1, &vaoID);
    glBindVertexArray(vaoID);  //first VAO

    GLuint vboID;
    glGenBuffers(1, &vboID);
    glBindBuffer(GL_ARRAY_BUFFER, vboID);
    glBufferData(GL_ARRAY_BUFFER, sizeof(triangle), triangle, GL_STATIC_DRAW);

    // vertex position
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), 0);
    // vertex color
    glEnableVertexAttribArray(1);
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (char*)(3 * sizeof(float)));

}

bool checkStatus(
    GLuint objectID,
    PFNGLGETSHADERIVPROC objectPropertyGetterFunc,
    PFNGLGETSHADERINFOLOGPROC getInfoLogFunc,
    GLenum statusType)
{
    GLint status;
    objectPropertyGetterFunc(objectID, statusType, &status);
    if (status != GL_TRUE)
    {
        GLint infoLogLength;
        objectPropertyGetterFunc(objectID, GL_INFO_LOG_LENGTH, &infoLogLength);
        GLchar* buffer = new GLchar[infoLogLength];

        GLsizei bufferSize;
        getInfoLogFunc(objectID, infoLogLength, &bufferSize, buffer);
        std::cout << buffer << std::endl;

        delete[] buffer;
        return false;
    }
    return true;
}

bool checkShaderStatus(GLuint shaderID) {
    return checkStatus(shaderID, glGetShaderiv, glGetShaderInfoLog, GL_COMPILE_STATUS);
}

bool checkProgramStatus(GLuint programID) {
    return checkStatus(programID, glGetProgramiv, glGetProgramInfoLog, GL_LINK_STATUS);
}

std::string readShaderCode(const char* fileName) {
    std::ifstream meInput(fileName);
    if (!meInput.good()) {
        std::cout << "File failed to load ... " << fileName << std::endl;
        exit(1);
    }
    return std::string(
        std::istreambuf_iterator<char>(meInput),
        std::istreambuf_iterator<char>()
    );
}

void installShaders() {
    GLuint vertexShaderID = glCreateShader(GL_VERTEX_SHADER);
    GLuint fragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);

    const GLchar* adapter[1];
    //adapter[0] = vertexShaderCode;
    std::string temp = readShaderCode("VertexShaderCode.glsl");
    adapter[0] = temp.c_str();
    glShaderSource(vertexShaderID, 1, adapter, 0);
    //adapter[0] = fragmentShaderCode;
    temp = readShaderCode("FragmentShaderCode.glsl");
    adapter[0] = temp.c_str();
    glShaderSource(fragmentShaderID, 1, adapter, 0);

    glCompileShader(vertexShaderID);
    glCompileShader(fragmentShaderID);

    if (!checkShaderStatus(vertexShaderID) || !checkShaderStatus(fragmentShaderID))
        return;

    programID = glCreateProgram();
    glAttachShader(programID, vertexShaderID);
    glAttachShader(programID, fragmentShaderID);
    glLinkProgram(programID);

    if (!checkProgramStatus(programID))
        return;
    glUseProgram(programID);

}

void initializedGL(void) {
    // run only once
    sendDataToOpenGL();
    installShaders();
}

void paintGL(void) {
    // always run
    glClearColor(0.3f, 0.3f, 0.3f, 1.0f);  //specify the background color
    glClear(GL_COLOR_BUFFER_BIT);

    glm::mat4 model = glm::mat4(1.0f);
    model = glm::rotate(model, angle, glm::vec3(0.0f, 0.0f, 1.0f));
    model = glm::translate(model, glm::vec3(x_delta * x_press_num, x_delta * y_press_num, 0.0f));
    model = glm::scale(model, glm::vec3(size));
    glUniformMatrix4fv(glGetUniformLocation(programID, "model"), 1, GL_FALSE, &model[0][0]);
    glDrawArrays(GL_TRIANGLES, 0, 6);  //render primitives from array data
}

void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) {
    if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
        glfwSetWindowShouldClose(window, true);

    if (key == GLFW_KEY_A && action == GLFW_PRESS) {
        x_press_num -= 1;
    }
    if (key == GLFW_KEY_D && action == GLFW_PRESS) {
        x_press_num += 1;
    }
    if (key == GLFW_KEY_W && action == GLFW_PRESS) {
        y_press_num += 1;
    }
    if (key == GLFW_KEY_S && action == GLFW_PRESS) {
        y_press_num -= 1;
    }
    if (key == GLFW_KEY_UP && action == GLFW_PRESS) {
        size += glm::vec3(0.1f);
    }
    if (key == GLFW_KEY_DOWN && action == GLFW_PRESS) {
        size -= glm::vec3(0.1f);
    }
    if (key == GLFW_KEY_LEFT && action == GLFW_PRESS) {
        angle += 1.0f;
    }
    if (key == GLFW_KEY_RIGHT && action == GLFW_PRESS) {
        angle -= 1.0f;
    }
}

int main(int argc, char* argv[]) {
    GLFWwindow* window;

    /* Initialize the glfw */
    if (!glfwInit()) {
        std::cout << "Failed to initialize GLFW" << std::endl;
        return -1;
    }
    /* glfw: configure; necessary for MAC */
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

#ifdef __APPLE__
    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
#endif

    /* do not allow resizing */
    glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);

    /* Create a windowed mode window and its OpenGL context */
    window = glfwCreateWindow(1600, 1600, "Hello Triangle", NULL, NULL);
    if (!window) {
        std::cout << "Failed to create GLFW window" << std::endl;
        glfwTerminate();
        return -1;
    }

    /* Make the window's context current */
    glfwMakeContextCurrent(window);
    glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
    glfwSetKeyCallback(window, key_callback);

    /* Initialize the glew */
    if (GLEW_OK != glewInit()) {
        std::cout << "Failed to initialize GLEW" << std::endl;
        return -1;
    }
    get_OpenGL_info();
    initializedGL();

    /* Loop until the user closes the window */
    while (!glfwWindowShouldClose(window)) {
        /* Render here */
        paintGL();

        /* Swap front and back buffers */
        glfwSwapBuffers(window);

        /* Poll for and process events */
        glfwPollEvents();
    }

    glfwTerminate();
    return 0;
}

顶点着色器:

#version 430

in layout(location=0) vec3 position;
in layout(location=1) vec3 vertexColor;

uniform mat4 model;

out vec3 theColor;

void main()
{
	vec4 v = vec4(position, 1.0);
	vec4 out_position = model * v;
	gl_Position = out_position;	
	theColor = vertexColor;
}

片段着色器:

#version 430

out vec4 Color;
in vec3 theColor;

void main()
{
	Color = vec4(theColor, 1.0);
}

你可能感兴趣的:(计算机图形学,算法,c++,开发语言)