QT中学习Opengl---(纹理环绕方式与过滤)
前言:
本文的代码是 LearnOpenGL 中对应代码,这里提供学习,大家喜欢的可去官方网站去看看:
LearnOpenGL-CNhttps://learnopengl-cn.readthedocs.io/zh/latest/本章简单使用不同的环绕方式,来显示不同的纹理方案。
Texture Wrapping
纹理坐标通常的范围是从(0, 0)到(1, 1), 如果我们把纹理坐标设置为范围以外会发生什么?
OpenGL默认的行为是重复这个纹理图像(我们简单地忽略浮点纹理坐标的整数部分), 但
OpenGL提供了更多的选择:
环绕方式 | 描述 |
GL_REPEAT | 纹理的默认行为, 重复纹理图像 |
GL_MIRRORED_REPEAT | 和 GL_REPEAT 一样, 除了重复的图片是镜像放置的 |
GL_CLAMP_TO_EDGE |
纹理坐标会在0到1之间, 超出的部分会重复纹理坐标的 边缘, 就是边缘被拉伸 |
GL_CLAMP_TO_BORDER | 超出的部分是用户指定的边缘的颜色 |
对应的图标状况:
前面提到的选项都可以使用 glTexParameter 函数单独设置每个坐标轴 s 、 t (如果是使用3D
纹理那么还有一个 r )它们和 x 、 y ( z )是相等的。
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
如果我们选择 GL_CLAMP_TO_BORDER 选项, 我们还要指定一个边缘的颜色。 这次使
用 glTexParameter 函数的 fv 后缀形式, 加上 GL_TEXTURE_BORDER_COLOR 作为选项, 这个函数需要我们传递一个边缘颜色的float数组作为颜色值:
float borderColor[] = { 1.0f, 1.0f, 0.0f, 1.0f };
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor);
例子:
顶点坐标:
float vertices[] = {// positions // colors // texture coords0.8f, 0.8f, 0.0f, 1.0f, 0.0f, 0.0f, 2.0f, 2.0f, // top right0.8f, -0.8f, 0.0f, 0.0f, 1.0f, 0.0f, 2.0f, 0.0f, // bottom right-0.8f, -0.8f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // bottom left-0.8f, 0.8f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 2.0f // top left};unsigned int indices[] = { // note that we start from 0!0, 1, 3, // first Triangle1, 2, 3 // second Triangle
};
这里纹理我们不在是1 1, 写出纹理超出部分。
顶点着色器写法:
#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, aTexCoord.y);
}
片段着色器
#version 330 core
out vec4 FragColor;in vec3 ourColor;
in vec2 TexCoord;// texture samplers
uniform sampler2D texture1;
uniform sampler2D texture2;void main()
{// linearly interpolate between both textures (80% container, 20% awesomeface)//FragColor = mix(texture(texture1, TexCoord), texture(texture2, TexCoord), 0.2);FragColor =texture(texture2,TexCoord);
}
这里我们使用了纹理2
GL_CLAMP_TO_BORDER:
float borderColor[] = { 1.0f, 1.0f, 0.0f, 1.0f };
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); // we want to repeat the awesomeface pattern so we kept it at GL_REPEAT
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor);
glDrawElements(GL_TRIANGLES,6,GL_UNSIGNED_INT,0);
效果:
我们可以看到,超出部分都用黄色代替了。
GL_CLAMP_TO_EDGE
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); // we want to repeat the awesomeface pattern so we kept it at GL_REPEAT
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
GL_MIRRORED_REPEAT:
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,GL_MIRRORED_REPEAT); // we want to repeat the awesomeface pattern so we kept it at GL_REPEATglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,GL_MIRRORED_REPEAT);
效果:
GL_REPEAT:
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,GL_REPEAT); // we want to repeat the awesomeface pattern so we kept it at GL_REPEATglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,GL_REPEAT);
所有代码:
#ifndef BKQOPENGLW_H
#define BKQOPENGLW_H#include <QOpenGLWidget>
#include <QOpenGLFunctions_3_3_Core>
#include <QOpenGLShaderProgram>
#include <QOpenGLTexture>
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;
QOpenGLTexture *pTexture;
QOpenGLTexture *pTexture2;
};#endif // BKQOPENGLW_H
对应cpp:
#include "bkqopenglw.h"
#include<iostream>
#include <QDebug>#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"float vertices[] = {// positions // colors // texture coords0.8f, 0.8f, 0.0f, 1.0f, 0.0f, 0.0f, 2.0f, 2.0f, // top right0.8f, -0.8f, 0.0f, 0.0f, 1.0f, 0.0f, 2.0f, 0.0f, // bottom right-0.8f, -0.8f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // bottom left-0.8f, 0.8f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 2.0f // top left};unsigned int indices[] = { // note that we start from 0!0, 1, 3, // first Triangle1, 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);//绑定eboglBindBuffer(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 attributeglVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float)));glEnableVertexAttribArray(2);//绑定纹理glEnable(GL_BLEND);glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);pTexture = new QOpenGLTexture(QImage(":/images/images/brickwall.jpg").mirrored());pTexture2 = new QOpenGLTexture(QImage(":/images/images/awesomeface.png").mirrored());shaderProgram.bind();shaderProgram.setUniformValue("texture1",0);shaderProgram.setUniformValue("texture2",1);// 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 unbindglBindBuffer(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);float borderColor[] = { 1.0f, 1.0f, 0.0f, 1.0f };shaderProgram.bind();glBindVertexArray(VAO);switch (m_Shape) {case Triangle:glDrawArrays(GL_TRIANGLES,0,3);break;case Rect:pTexture->bind(0);pTexture2->bind(1);//默认为GL_REPEAT 重复 GL_MIRRORED_REPEAT镜像 GL_CLAMP_TO_EDGE 边缘拉伸 GL_CLAMP_TO_BORDER 超出部分使用用户定义glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,GL_REPEAT); // we want to repeat the awesomeface pattern so we kept it at GL_REPEATglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,GL_REPEAT);
// glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor);glDrawElements(GL_TRIANGLES,6,GL_UNSIGNED_INT,0);break;default:break;}}
纹理过滤(Texture Filtering)
GL_NEAREST(Nearest Neighbor Filtering, 邻近过滤) 是一种OpenGL默认的纹理过滤方式。 当设置为 GL_NEAREST 的时候, OpenGL选择最接近纹理坐标中心点的那个像素。 下图你
会看到四个像素, 加号代表纹理坐标。 左上角的纹理像素是距离纹理坐标最近的那个, 这样它就会选择这个作为采样颜色:
GL_LINEAR((Bi)linear Filtering, 线性过滤) 它会从纹理坐标的临近纹理像素进行计算, 返
回一个多个纹理像素的近似值。 一个纹理像素距离纹理坐标越近, 那么这个纹理像素对最终
的采样颜色的影响越大。 下面你会看到临近像素返回的混合颜色:
基本区别:
使用方式:
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
最后的话:
每天写代码时间不多,上班时间还是比较长,写博客不易,喜欢的朋友,可以关注偶。
QT中学习Opengl---(纹理环绕方式与过滤)相关推荐
- 在Qt中使用OpenGL(四)
前言 在Qt中使用OpenGL(一) 在Qt中使用OpenGL(二) 在Qt中使用OpenGL(三) 在之前的文章中,我们通过一个最简单的例子完成了在Qt中使用OpenGL绘图的全过程,然后又使用了纹 ...
- Qt中的OpenGL
Qt还是本人可移植GUI程序开发的首选,不过Qt开发普通的应用程序是行,但是据说效率太低,以至于像某些人说的那种刷新看得到一条条横线?这点我比较纳闷,就我使用的感觉,虽然Qt不以效率著称,但是事实上有 ...
- QT中使用OpenGL绘制图形
Qt Creator中的3D绘图及动画教程(参照NeHe) 刚刚学习了Qt Creator,发现Qt提供了QtOpenGL模块,对OpenGL做了不错的封装,这使得我们可以很轻松地在Qt程序中使用Op ...
- Qt中使用OpenGL进行绘图
Qt Creator中的3D绘图及动画教程(参照NeHe) 刚刚学习了Qt Creator,发现Qt提供了QtOpenGL模块,对OpenGL做了不错的封装,这使得我们可以很轻松地在Qt程序中使用Op ...
- 在Qt中使用OpenGL(三)
前言 在Qt中使用OpenGL(一) 在Qt中使用OpenGL(二) 在之前的文章中,我们首先了解了在Qt中使用OpenGL的全流程,然后我们使用了一个最简单的例子将这个流程给过了一遍. 那么,在本篇 ...
- qt 中 使用 opengl 上下文 (context) 相关的注意事项
qt 中 使用 opengl 相关的注意事项 本人移植了一个glut到qt的项目,前期没有注意相关的上下文的使用,导致相关的显示混乱. 解决方案 makeCurrent();在每一个类函数中加上这一句 ...
- 在Qt中使用OpenGL(二)
前言 在Qt中使用OpenGL(一) 在上一篇文章中,我们结合了一个实际的例子了解了在Qt中使用OpenGL的全部过程.但是肯定对于初次接触的人来说哪怕知道了整个过程,依旧是两眼一抹黑的搞不懂到底要怎 ...
- word默认文字环绕方式是什么_在Word 2010文档中设置图片文字环绕方式
默认情况下,插入到Word 2010文档中的图片作为字符插入到Word 2010文档中,其位置随着其他字符的改变而改变,用户不能自由移动图片.而通过为图片设置文字环绕方式,则可以自由移动图片的位置,操 ...
- 在 Lazarus 中学习 OpenGL
在 Lazarus 中学习 OpenGL 教学网站 https://learnopengl-cn.github.io/ API 查询 https://docs.gl/ 创建窗口 Lazarus 可以在 ...
最新文章
- 解决“错误 D8016 “/ZI”和“/Gy-”命令行选项不兼容 ”问题
- Java 8 - 收集器Collectors_分组groupingBy
- Java中将CST格式的时间字符串进行格式化
- 微信小程序学习笔记(五)
- 山海伏妖录java_山海伏妖录攻略大全 剧情结局加点妖兽大全
- css 列表相关的属性 列表前的小点点 0302
- VB6中给数组赋值的限制
- 自动驾驶“老司机”拼车技,MIT的这个比赛已经飙到了时速123公里
- 支持python的云虚拟主机_云虚拟主机运行python(能运行python的主机)
- i++和++i哪个效率高
- 引入的噪声程度:曝光时间,模拟增益,数字增益的不同
- 一篇就明白什么是H3C?
- 你知道吗?计算机界也有诺贝尔奖!
- Android studio设计app登录界面
- 第十六届全国大学智能车竞赛华东赛区成绩汇总
- 【洛谷】P1008 [NOIP1998 普及组] 三连击
- idea导入子工程module
- “泰迪杯”挑战赛 -利用非侵入式负荷检测进行高效率数据挖掘(完整数学模型)
- 如何进阶Java之道?首先得知道层层递进的四种软件架构
- GitBook建立本地Book及导入别人Book