本文的代码是 LearnOpenGL 中对应代码,这里提供学习,大家喜欢的可去官方网站去看看:
LearnOpenGL-CNhttps://learnopengl-cn.readthedocs.io/zh/latest/本章为加载纹理,qt有自己简单的封装方式,可以更快的加载,代码简洁,但是为了学习,本章采用了。
纹理(Textures) 艺术家和程序员更喜欢使用纹理(Texture)。 纹理是一个2D图片(也有1D和3D), 它用来添加物体的细节; 这就像有一张绘有砖块的图片贴到你的3D的房子上, 你的房子看起来就像一堵砖
墙。 因为我们可以在一张图片上插入足够多的细节, 这样物体就会拥有很多细节而不用增加
额外的顶点。
纹理坐标:
加载纹理图:
这里使用的是 LearnOpenGL 提供的stb_image.h 文件,用它来加载数据。
基本使用:
#define STB_IMAGE_IMPLEMENTATION #include "stb_image.h"
使用这个头文件,你要定义宏,不然你对应的函数使用不了。
图形运行:
原图:
如果你只是加载数据,图片是反过来的。可以顶点着色器修改对应的y值。
顶点着色器#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aColor;
layout (location = 2) in vec2 aTexCoord;
out vec3 ourColor;
out vec2 TexCoord;
void main()
{
gl_Position = vec4(aPos, 1.0);
ourColor = aColor;
TexCoord = vec2(aTexCoord.x,1- aTexCoord.y);
}
这里用了 1- aTexCoord.y 就是把y反过来。
片段着色器#version 330 core
out vec4 FragColor;
in vec3 ourColor;
in vec2 TexCoord;
// texture sampler
uniform sampler2D texture1;
void main()
{
FragColor = texture(texture1, TexCoord);
}
绑定纹理:
//绑定纹理
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture); // all upcoming GL_TEXTURE_2D operations now have effect on this texture object
设置环绕模式:
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); // set texture wrapping to GL_REPEAT (default wrapping method)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
// set texture filtering parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
加载纹理到缓存:
unsigned char *data = stbi_load("G:/dataQt/OpenglLearn/chap03/triangleTextures/brickwall.jpg",&width,&height,&nrChannels,0);
//unsigned char *data = stbi_load("brickwall.jpg",&width,&height,&nrChannels,0);
if(data)
{
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);
}
else
{
qDebug() << "Failed to load texture" ;
}
stbi_image_free(data);
全部代码段:
提示:在使用stbi_load 函数时候,在qt中不能写相对路径,不然找不到图片。
#ifndef BKQOPENGLW_H #define BKQOPENGLW_H #include#include #include class BKQOpenglW : public QOpenGLWidget, QOpenGLFunctions_3_3_Core { Q_OBJECT public: enum Shape{None,Rect,circle,Triangle}; explicit BKQOpenglW(QWidget *parent = nullptr); ~BKQOpenglW(); void drawShapes(Shape shape); void setWireFrame(bool b); protected: virtual void initializeGL(); virtual void resizeGL(int w, int h); virtual void paintGL(); signals: public slots: private: unsigned int VBO, VAO,EBO; Shape m_Shape; QOpenGLShaderProgram shaderProgram; unsigned int texture; }; #endif // BKQOPENGLW_H
对应cpp:
#include "bkqopenglw.h" #include写在后面的话:#include #define STB_IMAGE_IMPLEMENTATION #include "stb_image.h" float vertices[] = { // positions // colors // texture coords 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, // top right 0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // bottom right -0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // bottom left -0.5f, 0.5f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f // top left }; unsigned int indices[] = { // note that we start from 0! 0, 1, 3, // first Triangle 1, 2, 3 // second Triangle }; BKQOpenglW::BKQOpenglW(QWidget *parent) : QOpenGLWidget(parent) { } BKQOpenglW::~BKQOpenglW() { makeCurrent(); glDeleteVertexArrays(1,&VAO); glDeleteBuffers(1,&VBO); doneCurrent(); } void BKQOpenglW::drawShapes(BKQOpenglW::Shape shape) { m_Shape = shape; update(); } void BKQOpenglW::setWireFrame(bool b) { makeCurrent(); if(b) { glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); } else { glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); } update(); doneCurrent(); } void BKQOpenglW::initializeGL() { initializeOpenGLFunctions(); // shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex,vertexShaderSource); // shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment,fragmentShaderSource); shaderProgram.addShaderFromSourceFile(QOpenGLShader::Vertex,":/shader/shader.vs"); shaderProgram.addShaderFromSourceFile(QOpenGLShader::Fragment,":/shader/shader.fs"); shaderProgram.link(); glGenVertexArrays(1, &VAO); glGenBuffers(1, &VBO); // bind the Vertex Array Object first, then bind and set vertex buffer(s), and then configure vertex attributes(s). 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), nullptr); glEnableVertexAttribArray(0); glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float))); glEnableVertexAttribArray(1); // texture coord attribute glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float))); glEnableVertexAttribArray(2); //绑定纹理 glGenTextures(1, &texture); glBindTexture(GL_TEXTURE_2D, texture); // all upcoming GL_TEXTURE_2D operations now have effect on this texture object // set the texture wrapping parameters glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); // set texture wrapping to GL_REPEAT (default wrapping method) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); // set texture filtering parameters glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); int width, height, nrChannels; unsigned char *data = stbi_load("G:/dataQt/OpenglLearn/chap03/triangleTextures/brickwall.jpg",&width,&height,&nrChannels,0); //unsigned char *data = stbi_load("brickwall.jpg",&width,&height,&nrChannels,0); if(data) { glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data); glGenerateMipmap(GL_TEXTURE_2D); } else { qDebug() << "Failed to load texture" ; } stbi_image_free(data); // note that this is allowed, the call to glVertexAttribPointer registered VBO as the vertex attribute's bound vertex buffer object so afterwards we can safely unbind glBindBuffer(GL_ARRAY_BUFFER, 0); // You can unbind the VAO afterwards so other VAO calls won't accidentally modify this VAO, but this rarely happens. Modifying other // VAOs requires a call to glBindVertexArray anyways so we generally don't unbind VAOs (nor VBOs) when it's not directly necessary. glBindVertexArray(0); } void BKQOpenglW::resizeGL(int w, int h) { glViewport(0,0,w,h); } void BKQOpenglW::paintGL() { glClearColor(0.2f, 0.3f, 0.3f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); shaderProgram.bind(); glBindVertexArray(VAO); glBindTexture(GL_TEXTURE_2D, texture); switch (m_Shape) { case Triangle: glDrawArrays(GL_TRIANGLES,0,3); break; case Rect: glDrawElements(GL_TRIANGLES,6,GL_UNSIGNED_INT,0); break; default: break; } }
喜欢我博客的小伙伴们,也同时想在qt上学习opengl的伙伴,可以关注与点赞博客,让我们共同进步吧。



