欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

OpenGL学习之矩阵变换实例

程序员文章站 2022-07-04 09:08:40
...

开发环境:

xcode

第三方库:

glfw、glew、glm、SOIL

代码:

1. ShaderAdmin.hpp

//
//  ShaderAdmin.hpp
//  GL_Program
//
//

#ifndef ShaderAdmin_hpp
#define ShaderAdmin_hpp

#include <stdio.h>
#include <fstream>
#include <sstream>
#include <iostream>
#include <GL/glew.h>

using namespace std;
class ShaderAdmin
{
public:
    //着色器ID;
    GLuint m_program;
    //构造器读取并构建着色器
    ShaderAdmin(const GLchar *vertexPath,const GLchar *fragmentPath);
    ~ShaderAdmin();
    //加载纹理资源
    void Use();
private:
    void compileShader(const GLchar *vShaderCode,const GLchar *fShaderCode);
    void getCompileShaderErrorLog(GLuint shader);
    void getLinkShaderProgramErrorLog(GLuint shaderProgram);
};

#endif /* ShaderAdmin_hpp */

2. ShaderAdmin.cpp

//
//  ShaderAdmin.cpp
//  GL_Program
//
//  Created by LiYong on 2018/3/12.
//  Copyright © 2018年 feiyu. All rights reserved.
//

#include "ShaderAdmin.hpp"

ShaderAdmin::ShaderAdmin(const GLchar *vertexPath,const GLchar *fragmentPath)
{
    // 1. 从文件路径中获取顶点/片段着色器
    string vertexCode;
    string fragmentCode;
    ifstream vShaderFile;
    ifstream fShaderFile;
    //保证ifstream对象可以抛出异常
    vShaderFile.exceptions(ifstream::badbit);
    fShaderFile.exceptions(ifstream::badbit);
    try
    {
        //打开文件
        vShaderFile.open(vertexPath);
        fShaderFile.open(fragmentPath);
        if (!vShaderFile.is_open()||!fShaderFile.is_open())
        {
            cout << "无法打开文件!" << endl;
            return;
        }
        stringstream vShaderStream,fShaderStream;
        //读取文件的缓冲内容到流中
        vShaderStream << vShaderFile.rdbuf();
        fShaderStream << fShaderFile.rdbuf();
        //关闭文件
        vShaderFile.close();
        fShaderFile.close();
        //转换流至字符串
        vertexCode = vShaderStream.str();
        fragmentCode = fShaderStream.str();
    }
    catch (ifstream::failure e)
    {
        cout << "ERROR::SHADER::FILE_NOT_SUCCESFULLY_READ" << endl;
    }

    const GLchar *vShaderCode = vertexCode.c_str();
    const GLchar *fShaderCode = fragmentCode.c_str();
    compileShader(vShaderCode, fShaderCode);
}
ShaderAdmin::~ShaderAdmin()
{

}
void ShaderAdmin::Use()
{
    glUseProgram(this->m_program);
}
void ShaderAdmin::compileShader(const GLchar *vShaderCode, const GLchar *fShaderCode)
{
    GLuint vShader,fShader;

    vShader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vShader,1,&vShaderCode,NULL);
    glCompileShader(vShader);
    getCompileShaderErrorLog(vShader);

    fShader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fShader,1,&fShaderCode,NULL);
    glCompileShader(fShader);
    getCompileShaderErrorLog(fShader);

    m_program = glCreateProgram();
    glAttachShader(m_program,vShader);
    glAttachShader(m_program,fShader);
    glLinkProgram(m_program);
    getLinkShaderProgramErrorLog(m_program);

    glDeleteShader(vShader);
    glDeleteShader(fShader);
}
void ShaderAdmin::getCompileShaderErrorLog(GLuint shader)
{
    GLint sucess;
    GLchar infoLog[512];
    glGetShaderiv(shader,GL_COMPILE_STATUS,&sucess);
    if (!sucess)
    {
        glGetShaderInfoLog(shader, 512, NULL, infoLog);
        std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
    }
}
void ShaderAdmin::getLinkShaderProgramErrorLog(GLuint shaderProgram)
{
    GLint success;
    GLchar infoLog[512];
    glGetProgramiv(shaderProgram,GL_LINK_STATUS,&success);
    if (!success)
    {
        glGetShaderInfoLog(shaderProgram,512,NULL,infoLog);
    }
}

3. TextureAdmin.hpp

//
//  texture.hpp
//  GL_Program


#ifndef TextureAdmin_hpp
#define TextureAdmin_hpp

#include <stdio.h>
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <SOIL/SOIL.h>
#include <iostream>

using namespace std;

class TextureAdmin
{
public:
    TextureAdmin(const string imagePath);
    ~TextureAdmin();

    //绑定纹理单元
    void BindTexture();


public:
    //纹理ID
    GLuint m_pTexture;
};

#endif /* texture_hpp */

4. TextureAdmin.cpp

//
//  texture.cpp
//  GL_Program
//
//  Created by LiYong on 2018/3/13.
//  Copyright © 2018年 feiyu. All rights reserved.
//

#include "TextureAdmin.hpp"
TextureAdmin::TextureAdmin(const string imagePath)
{
    glGenTextures(1, &m_pTexture);
    glBindTexture(GL_TEXTURE_2D, m_pTexture);

    //设置纹理的采样方式
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

    //设置纹理的过滤方式
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

    //加载纹理图片
    int width , height;
    unsigned char *image = SOIL_load_image(imagePath.data(), &width, &height, 0, SOIL_LOAD_RGB);
    glTexImage2D(GL_TEXTURE_2D, 0,GL_RGB, width, height,0, GL_RGB, GL_UNSIGNED_BYTE, image);
    glGenerateMipmap(GL_TEXTURE_2D);
    SOIL_free_image_data(image);
    glBindTexture(GL_TEXTURE_2D, 0);
}

TextureAdmin::~TextureAdmin()
{

}

void TextureAdmin::BindTexture()
{
    glBindTexture(GL_TEXTURE_2D, m_pTexture);
}

4. main.cpp


#include <iostream>
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include "ShaderAdmin.hpp"
#include "TextureAdmin.hpp"

#include <glm/glm.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <glm/gtc/matrix_transform.hpp>


#define WIDTH 800
#define HEIGHT 600
#define TITLE "OpenGL"
#define NUM 2

using namespace std;


GLuint VAO,VBO,EBO;
GLuint VAOs[NUM],VBOs[NUM],EBOs[NUM];
void initGL();
void initGLForOSX();
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode);

void renderRectangle();

int main(int argc, const char * argv[]) {

//    initGL();
    initGLForOSX();

    GLFWwindow *win = glfwCreateWindow(WIDTH, HEIGHT, TITLE, nullptr, nullptr);
    if (!win)
    {
        printf("Failed to create GLFW window!\n");
        glfwTerminate();
        return NULL;
    }

    glfwMakeContextCurrent(win);
    glfwSetKeyCallback(win, key_callback);

    glewExperimental = GL_TRUE;
    if(glewInit() != GLEW_OK)
    {
        printf("Failed to initialize GLEW !\n");
    }

    int nWidth,nHeight;
    glfwGetFramebufferSize(win, &nWidth, &nHeight);
    glViewport(0, 0, nWidth, nHeight);

    ShaderAdmin shader("Shaders/vShader.vsh","Shaders/fShader.fsh");
    renderRectangle();

    TextureAdmin texture("Image/container.jpg");
    TextureAdmin texture2("Image/awesomeface.png");

    while (!glfwWindowShouldClose(win))
    {
        glfwPollEvents();
        glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);

        //**纹理单元0
        glActiveTexture(GL_TEXTURE0);
        texture.BindTexture();
        glUniform1i(glGetUniformLocation(shader.m_program,"ourTexture"),0);

        //**纹理单元1
        glActiveTexture(GL_TEXTURE1);
        texture2.BindTexture();
        glUniform1i(glGetUniformLocation(shader.m_program,"ourTexture2"),1);

        shader.Use();
        glBindVertexArray(VAO);

        //创建变换矩阵
        //1.第一个纹理
        glm::mat4 trans;

        trans = glm::translate(trans, glm::vec3(0.5f, -0.5f, 0.0f));
        trans = glm::rotate(trans,(GLfloat)sin(glfwGetTime()) * 10.0f, glm::vec3(0.0f, 1.0f, 0.0f));

        GLuint transform = glGetUniformLocation(shader.m_program,"transform");
        glUniformMatrix4fv(transform,1,GL_FALSE,glm::value_ptr(trans));

        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);

        //2.第二个纹理
        glm::mat4 trans1;

        trans1 = glm::translate(trans1, glm::vec3(-0.5f, 0.5f, 0.0f));
        GLfloat scale = sin(glfwGetTime());
        trans1 = glm::scale(trans1, glm::vec3(scale,scale,scale));
        GLuint transform1 = glGetUniformLocation(shader.m_program,"transform");
        glUniformMatrix4fv(transform1,1,GL_FALSE,glm::value_ptr(trans1));

        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
        glBindVertexArray(0);

        glfwSwapBuffers(win);
    }

    return 0;
}
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode)
{
    // 当用户按下ESC键,我们设置window窗口的WindowShouldClose属性为true
    // 关闭应用程序
    if(key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
        glfwSetWindowShouldClose(window, GL_TRUE);
}
void renderRectangle()
{
    GLfloat vertices[] = {
        //    ---- 位置 ----       ---- 颜色 ----     - 纹理坐标 -
        0.5f,  0.5f, 0.0f,   1.0f, 0.0f, 0.0f,   1.0f, 1.0f,   // 右上
        0.5f, -0.5f, 0.0f,   0.0f, 1.0f, 0.0f,   1.0f, 0.0f,   // 右下
        -0.5f, -0.5f, 0.0f,   0.0f, 0.0f, 1.0f,   0.0f, 0.0f,   // 左下
        -0.5f,  0.5f, 0.0f,   1.0f, 1.0f, 0.0f,   0.0f, 1.0f    // 左上
    };
    GLuint indices[] = {
        0,1,2,
        2,3,0
    };

    glGenVertexArrays(1,&VAO);
    glGenBuffers(1,&VBO);
    glGenBuffers(1,&EBO);

    glBindVertexArray(VAO);

    glBindBuffer(GL_ARRAY_BUFFER,VBO);
    glBufferData(GL_ARRAY_BUFFER,sizeof(vertices),vertices,GL_STATIC_DRAW);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,EBO);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER,sizeof(indices),indices,GL_STATIC_DRAW);
    //位置属性
    glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,8 * sizeof(GLfloat),(GLvoid *)0);
    glEnableVertexAttribArray(0);

    //颜色属性
    glVertexAttribPointer(1,3,GL_FLOAT,GL_FALSE,8 * sizeof(GLfloat),(GLvoid *)(3*sizeof(GLfloat)));
    glEnableVertexAttribArray(1);

    //纹理坐标
    glVertexAttribPointer(2,2,GL_FLOAT,GL_FALSE,8 * sizeof(GLfloat),(GLvoid *)(6*sizeof(GLfloat)));
    glEnableVertexAttribArray(2);

    glBindBuffer(GL_ARRAY_BUFFER,0);
    glBindVertexArray(0);

}
void initGL()
{
    glfwInit();
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
}
void initGLForOSX()
{
    glfwInit();
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
    //Mac环境必须添加下面这行才能生效
    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
}

4. 顶点着色器

#version 330 core
layout (location = 0) in vec3 position;
layout (location = 1) in vec3 color;
layout (location = 2) in vec2 texCoord;

out vec3 ourColor;
out vec2 TexCoord;

uniform mat4 transform;

void main()
{
    gl_Position = transform * vec4(position, 1.0f);
    ourolor = color;
    TexCoord = texCoord;
}

5. 片段着色器

#version 330 core
in vec3 ourColor;
in vec2 TexCoord;

out vec4 color;

uniform sampler2D ourTexture;
uniform sampler2D ourTexture2;

void main()
{
    color = mix(texture(ourTexture, TexCoord),texture(ourTexture2,TexCoord),0.2);
    color = color*vec4(ourColor,1.0);
}

实现demo

相关标签: xcode