qt opengl 壓縮紋理
阿新 • • 發佈:2019-02-03
壓縮紋理與普通紋理的區別是,佔用的記憶體空間變小了;es 2.0 es3.0都支援ETC1。es 3.0支援ETC2。ETC2支援帶有透明通道的圖片,ETC1不支援透明通道。我這裡使用的是ETC1,png、jpg或其它格式轉換為ETC1的pkm格式壓縮圖片,可以用網上下載的工具。
其渲染器實現非常簡單,和渲染一幀普通圖片,流程大致相同;只是在載入紋理的時候要設定紋理格式,並載入壓縮後的資料。
其實現如下
#ifndef ETCRENDER_H #define ETCRENDER_H #include <QOpenGLExtraFunctions> #include <QOpenGLShaderProgram> #include <QOpenGLBuffer> #include <QOpenGLTexture> class EtcRender { public: EtcRender() = default; void initsize(QString pkmFilePath); void render(QOpenGLExtraFunctions *f, QMatrix4x4 &pMatrix,QMatrix4x4 &vMatrix,QMatrix4x4 &mMatrix); private: QOpenGLShaderProgram program_; QOpenGLBuffer vbo_; QOpenGLTexture *texture_{nullptr}; }; #endif // ETCRENDER_H
#include <QFile> #include "etcrender.h" void EtcRender::initsize(QString pkmFilePath) { program_.addCacheableShaderFromSourceFile(QOpenGLShader::Vertex,"vsrc.vert"); program_.addCacheableShaderFromSourceFile(QOpenGLShader::Fragment,"fsrc.frag"); program_.link(); #if 1 //設定格式並載入壓縮後的pkm資料 texture_ = new QOpenGLTexture(QOpenGLTexture::Target2D); texture_->setFormat(QOpenGLTexture::RGB8_ETC1); QFile file(pkmFilePath); if(file.open(QIODevice::ReadOnly)){ QByteArray arr = file.readAll(); texture_->setCompressedData(0,0,arr.size(),arr.data()); } #else texture_ = new QOpenGLTexture(QImage("sample.jpg")); #endif GLfloat points[]{ -1.0,-1.0,0.0, -1.0,+1.0,0.0, +1.0,+1.0,0.0, +1.0,-1.0,0.0, 0.0,+1.0, 0.0,0.0, +1.0,0.0, +1.0,+1.0 }; vbo_.create(); vbo_.bind(); vbo_.allocate(points,sizeof(points)); } void EtcRender::render(QOpenGLExtraFunctions *f, QMatrix4x4 &pMatrix, QMatrix4x4 &vMatrix, QMatrix4x4 &mMatrix) { f->glDisable(GL_CULL_FACE); f->glDisable(GL_DEPTH_TEST); //和前面文章一樣,繫結紋理,載入資料,然後繪製 program_.bind(); vbo_.bind(); f->glActiveTexture(GL_TEXTURE0 + 0); program_.setUniformValue("sTextures",0); program_.setUniformValue("uPMatrix",pMatrix); program_.setUniformValue("uVMatrix",vMatrix); program_.setUniformValue("uMMatrix",mMatrix); program_.enableAttributeArray(0); program_.enableAttributeArray(1); program_.setAttributeBuffer(0,GL_FLOAT,0,3,3 * sizeof(GLfloat)); program_.setAttributeBuffer(1,GL_FLOAT,3 * 4 * sizeof(GLfloat),2,2 *sizeof(GLfloat)); texture_->bind(0); f->glDrawArrays(GL_TRIANGLE_FAN,0,4); program_.disableAttributeArray(0); program_.disableAttributeArray(1); texture_->release(); vbo_.release(); program_.release(); }
其在widget中的使用也非常簡單,如下
#ifndef WIDGET_H #define WIDGET_H #include <QOpenGLWidget> #include "etcrender.h" class Widget : public QOpenGLWidget { Q_OBJECT public: Widget(QWidget *parent = 0); ~Widget(); protected: void initializeGL() override; void resizeGL(int w, int h) override; void paintGL()override; private: EtcRender render_; QMatrix4x4 pMatrix_; QVector3D cameraLocation_; }; #endif // WIDGET_H
#include "widget.h"
Widget::Widget(QWidget *parent)
: QOpenGLWidget(parent)
{
}
Widget::~Widget()
{
}
void Widget::initializeGL()
{
render_.initsize("bbt.pkm");
//設定視角
cameraLocation_.setX(0);
cameraLocation_.setY(0);
cameraLocation_.setZ(2);
}
void Widget::resizeGL(int w, int h)
{
pMatrix_.setToIdentity();
pMatrix_.perspective(45,float(w)/h,0.01f,100.0f);
}
void Widget::paintGL()
{
QOpenGLExtraFunctions *f = QOpenGLContext::currentContext()->extraFunctions();
f->glClearColor(0.0f,0.0f,0.0f,1.0f);
f->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
QMatrix4x4 view;
view.lookAt(cameraLocation_,QVector3D{0.0,0.0,0.0},QVector3D{0.0,1.0,0.0});
QMatrix4x4 model; //不經過任何轉換
render_.render(f,pMatrix_,view,model);
}
其shader如下
#version 330
uniform mat4 uPMatrix,uVMatrix,uMMatrix;
layout (location = 0) in vec3 aPositin;
layout (location = 1) in vec2 aTextureCoord;
smooth out vec2 vTextureCoord;
void main(void)
{
gl_Position = uPMatrix * uVMatrix * uMMatrix * vec4(aPositin,1);
vTextureCoord = aTextureCoord;
}
#version 330
uniform sampler2D sTextures;
in vec2 vTextureCoord;
out vec4 fragColor;
void main(void)
{
fragColor = texture2D(sTextures,vTextureCoord);
}
到此結束。