一、概述
使用OpenGL将纹理与颜色混合输出。ps:此处并无实际的意义只是单纯的为了好玩。
步骤:
1.定义顶点坐标、颜色、纹理及顶点索引
float vertices[] = { // ---- 位置 ---- -----颜色----- - 纹理坐标 - 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, // 右上 1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // 右下 -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // 左下 -1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f // 左上 };
顶点索引
unsigned int indices[] = { 0, 1, 3, // first triangle 1, 2, 3 // second triangle };
2.创建及绑定VAO、VBO、EBO
//创建VAO、VBO、EBO 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); ////EBO glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
3.告知显卡应该如何解析vertices中定义的数据
////告知显卡顶点数据如何解析 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0); glEnableVertexAttribArray(0); ////告知显卡颜色坐标如何解析 glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float))); glEnableVertexAttribArray(1); ////告知显卡纹理坐标如何解析 glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float))); glEnableVertexAttribArray(2);
4.创建纹理、绑定纹理、并将纹理数据发送给GPU
////创建纹理 glGenTextures(1, &texture); glBindTexture(GL_TEXTURE_2D, texture); //设置纹理环绕方式 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_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); stbi_set_flip_vertically_on_load(true); //生成纹理 int width, height, mChannels; QString path = getTexturePath("similing_face.png"); unsigned char* data = stbi_load(path.toStdString().c_str(), &width, &height, &mChannels, 0); if (data) { qDebug() << "图片加载成功,width=" << width << ",height=" << height; glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); glGenerateMipmap(GL_TEXTURE_2D); } else { qDebug() << "图像数据加载失败"; } stbi_image_free(data);
5.定义顶点着色器及片元着色器代码
//顶点着色器 #version 330 core layout (location = 0) in vec3 aPos; layout (location = 1) in vec3 aColor; layout (location = 2) in vec2 aTexCoord; out vec2 ourTexCoord; out vec3 ourColor; void main(void) { gl_Position = vec4(aPos,1.0f); ourTexCoord = aTexCoord; ourColor = aColor; } //片元着色器 #version 330 core out vec4 FragColor; in vec2 ourTexCoord; in vec3 ourColor; uniform sampler2D ourTexture; void main() { FragColor = texture(ourTexture,ourTexCoord)*vec4(ourColor,1.0f); }
6.编译着色器代码
GLuint BaseOpenGLWindow::buildAttachShaderAndReturnProgramId(QString vertexResPath, QString fragmentResPath) { //编译顶点着色器和片元着色器 GLuint vertexShader = getShaderId(GL_VERTEX_SHADER, vertexResPath); GLuint fragmentShader = getShaderId(GL_FRAGMENT_SHADER, fragmentResPath); GLuint programId = glCreateProgram(); glAttachShader(programId, vertexShader); glAttachShader(programId, fragmentShader); glLinkProgram(programId); getLinkProgramErrorInfo(programId); glDeleteShader(vertexShader); glDeleteShader(fragmentShader); return programId; } void BaseOpenGLWindow::getLinkProgramErrorInfo(GLuint programId) { int success; char infoLog[512]; glGetProgramiv(programId, GL_LINK_STATUS, &success); if (!success) { glGetProgramInfoLog(programId, 512, NULL, infoLog); qDebug() << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog; } } GLuint BaseOpenGLWindow::getShaderId(GLenum shaderType, QString resPath) { //创建顶点着色器 unsigned int shaderId = glCreateShader(shaderType); QFile vertexShaderFile(resPath); if (!vertexShaderFile.open(QIODevice::ReadOnly)) { qDebug() << "Cannot open vertex shader file for reading"; } QString verQStr = vertexShaderFile.readAll(); std::string verStdStr = verQStr.toStdString(); const char* vertexStr = verStdStr.c_str(); qDebug() << "vertexStr-------------" << vertexStr; vertexShaderFile.flush(); vertexShaderFile.close(); glShaderSource(shaderId, 1, &vertexStr, NULL); glCompileShader(shaderId); getCompileShaderErrorInfo(shaderId); return shaderId; } void BaseOpenGLWindow::getCompileShaderErrorInfo(GLuint shaderId) { int success; char infoLog[512]; glGetShaderiv(shaderId, GL_COMPILE_STATUS, &success); if (!success) { glGetShaderInfoLog(shaderId, 512, NULL, infoLog); qDebug() << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog; } }
7.绘制
void GLTextureColorWindow::paintGL() { glBindVertexArray(VAO); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, texture); glUseProgram(programId); //glUniform1i(glGetUniformLocation(programId, "ourTexture"), 0); glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); }
二、完整代码示例
1.GLTextureColorWindow.h
#pragma once #include "BaseOpenGLWindow.h" #ifndef STB_IMAGE_H #define STB_IMAGE_H #include "../../stb_image.h" #endif // STB_IMAGE_H class GLTextureColorWindow : public BaseOpenGLWindow { Q_OBJECT public: GLTextureColorWindow(QWidget *parent = nullptr); ~GLTextureColorWindow(); protected: virtual void initializeGL();//初始化OpenGL virtual void resizeGL(int w, int h);//ResizeWindow大小 virtual void paintGL();//绘制OpenGL private: unsigned int VAO, VBO, EBO; unsigned int texture, texture1, texture2; GLuint programId; };
2.GLTextureColorWindow.cpp
#include "GLTextureColorWindow.h" GLTextureColorWindow::GLTextureColorWindow(QWidget *parent) : BaseOpenGLWindow(parent) { this->setWindowTitle("贴图与颜色混合"); } void GLTextureColorWindow::initializeGL() { this->initializeOpenGLFunctions(); glClearColor(1.0f, 1.0f, 1.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); float vertices[] = { // ---- 位置 ---- -----颜色----- - 纹理坐标 - 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, // 右上 1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // 右下 -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // 左下 -1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f // 左上 }; unsigned int indices[] = { 0, 1, 3, // first triangle 1, 2, 3 // second triangle }; //创建VAO、VBO、EBO 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); ////EBO 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(float), (void*)0); glEnableVertexAttribArray(0); ////告知显卡颜色坐标如何解析 glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float))); glEnableVertexAttribArray(1); ////告知显卡纹理坐标如何解析 glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float))); glEnableVertexAttribArray(2); ////创建纹理 glGenTextures(1, &texture); glBindTexture(GL_TEXTURE_2D, texture); //设置纹理环绕方式 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_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); stbi_set_flip_vertically_on_load(true); //生成纹理 int width, height, mChannels; QString path = getTexturePath("similing_face.png"); unsigned char* data = stbi_load(path.toStdString().c_str(), &width, &height, &mChannels, 0); if (data) { qDebug() << "图片加载成功,width=" << width << ",height=" << height; glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); glGenerateMipmap(GL_TEXTURE_2D); } else { qDebug() << "图像数据加载失败"; } stbi_image_free(data); //小程序 programId = buildAttachShaderAndReturnProgramId(":/QtForOpenCV4Tool/shader/texture_color.vert", ":/QtForOpenCV4Tool/shader/texture_color.frag"); } void GLTextureColorWindow::resizeGL(int w, int h) { glViewport(0, 0, w, h); } void GLTextureColorWindow::paintGL() { glBindVertexArray(VAO); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, texture); glUseProgram(programId); //glUniform1i(glGetUniformLocation(programId, "ourTexture"), 0); glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); } GLTextureColorWindow::~GLTextureColorWindow() { }
标签:颜色混合,1.0,QT,OpenGL,0.0,void,TEXTURE,纹理,GL From: https://www.cnblogs.com/tony-yang-flutter/p/18376618