区块链技术博客
www.b2bchain.cn

Qt翻页效果实现(四):OpenGL图像渲染求职学习资料

本文介绍了Qt翻页效果实现(四):OpenGL图像渲染求职学习资料,有助于帮助完成毕业设计以及求职,是一篇很好的资料。

对技术面试,学习经验等有一些体会,在此分享。

OpenGL贴图

OpenGL里面的图像渲染,是通过将图片映射成纹理,然后通过顶点坐标和对应的纹理坐标映射到物体表面。

Qt翻页效果实现(四):OpenGL图像渲染

顶点坐标

这里我们只有三个屏平面,在Qt翻页效果实现(二)文章中各点的坐标,在OpenGL里面就属于顶点坐标了。
然而由于OpenGL里面的坐标系与屏幕坐标系不同,里面原点坐标在右下角。
比如上图中 P点的坐标现在才是(0,0),O点坐标是(0,h),D点坐标是(w,0)等等。

这样就需要对里面的坐标进行转换,或者重新实现了。
还有需要注意的就是当试试计算翻页位置时,传递到 compute(const QPoint &pos) 中的 pos 也要经过窗口坐标转换。
到时候要根据平常界面窗口与OpenGL窗口的相对位置来进行转换。
最简单的是平常界面窗口与OpenGL窗口大小位置相同,或者只有OpenGL窗口,则可以直接转换如下:

void XXXX::mouseMoveEvent(QMouseEvent *e) {     m_pos = QPoint(e->pos().x(), height()-e->pos().y());  // 用窗口高度减去鼠标的y()     updateGL(); }

纹理坐标

另一个需要的计算的就是求取纹理坐标。在OpenGL中,纹理坐标是归一化的,或者可以看作是向量。
比如上图中 P点的纹理坐标可以看成是(0,0),O点坐标是(0,1),D点坐标是(1,0)。
对于A点纹理坐标,则可以简单计算为 A(A.x/w, 0)。
具体细节部分就不在此详细叙述,如果不清楚的小伙伴可以百度查阅一下,有很多写的不错的文章。
在这里默认你已经具备纹理贴图的OpenGL的相关知识点。

阴影纹理

对于在Qt翻页效果实现(三)文章中提到的阴影,在OpenGL中,则可通过一维纹理实现。对应的纹理坐标也只有一个值。
比如上图中 C点阴影纹理可以看成是0,A点和B点纹理可以看成是1。

纹理创建

一维纹理创建

一维纹理可以通过一个带渐透明变高度为1像素的png图做为资源进行加载;
如果不会作图,也可以通过自己生成的一个颜色数组进行创建,具体方式图像:

void XXXX::loadGLTexture1(GLuint *texId) {     GLubyte image[256];     double n = 0;     for (int i = 0; i <= 256; i+=4)  // 颜色填充     {         if (i>=200) n+=10;         else n+=0.1;         image[i] = 255-n;         image[i+1] = 255-n;         image[i+2] = 255-n;         image[i+3] = 255;     }     glGenTextures(1, texId); // 创建纹理     glBindTexture(GL_TEXTURE_1D, *texId);      glTexImage1D(GL_TEXTURE_1D, 0, GL_RGBA,                  64, 0, GL_RGBA, GL_UNSIGNED_BYTE,                  image);      glTexParameteri(GL_TEXTURE_1D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);    // 线形滤波     glTexParameteri(GL_TEXTURE_1D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);    // 线形滤波 }

二维纹理创建

二维纹理可以直接通过加载图片生成;Qt中可以直接通过QImage生成纹理。
由于二维纹理与上面一维纹理需求不同,因为阴影只需要创建一次即可;
而对于我们翻页功能来说,随着内容的不同,加载的图片也不一样,纹理也要实时变更。

所以在创建纹理之前,我们先要创建三个纹理,对应三个区域的内容。在初始化的时候还要记得给其全部清零

GLuint m_tex[3];

绑定纹理的时候,则可以通过下面的方法,直接将QImage绑定到对应索引的纹理上面。

void XXXX::bindTexture(const QImage&img, int texId) {     //现在载入图像,并将其转换为纹理。     QImage image = img.convertToFormat(QImage::Format_RGBA8888);     if (m_tex[texId])         glDeleteTextures(1, &m_tex[texId]);     glGenTextures(1, &m_tex[texId]);// 创建纹理      glBindTexture(GL_TEXTURE_2D, m_tex[texId]);      glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,                  image.width(), image.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE,                  image.bits());      glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);    // 线形滤波     glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);    // 线形滤波 }

坐标计算

相对于Qt翻页效果实现(二)文章中只需要通过一个QPointF来保存区域的点的集合不同;
由于OpenGL中涉及到的坐标信息相对较多,则需要单独定义一个结构体来保存数据。
定义如下:

struct Vertex {     Vertex(const QPointF&pos, const QPointF&tex, qreal g):         m_pos(pos), m_texcoord(tex), m_gradient(g){}     QPointF m_pos;        // 顶点坐标     QPointF m_texcoord;   // 纹理坐标     qreal m_gradient;     // 阴影纹理坐标 };

其他功能性函数不变,只需要修改 compute(const QPoint& pos) 计算函数,
实现代码如下:
“`
void XXXX::compute(const QPoint &pos)
{
int w = m_pageRect.width();
int h = m_pageRect.height();
m_ports1.clear();
m_ports2.clear();
m_ports3.clear();
QPointF o = pos;
if (m_startCorner == TopLeft) {
QPointF s(w, h), p(0, h), a, c, d;
if (distance(o, s) > w) getClosestPointOnCircle(o, s);
if (o.y() >= h) o.setY(h);
if (o == p) {
m_ports1.append(Vertex(QPointF(0, h), QPointF(0,0), 0));
m_ports1.append(Vertex(QPointF(w, h), QPointF(1,0), 0));
m_ports1.append(Vertex(QPointF(w, 0), QPointF(1,1), 0));
m_ports1.append(Vertex(QPointF(0, 0), QPointF(0,1), 0));
return;
}

    qreal dop = distance(o,p);     qreal angle = asin((h-o.y())/dop);     qreal angle2 = 2*angle;     qreal by = h+10;      logs(dop);     logs(o);     logs(pos);      a.setY(h);     if (angle == 0) {         qreal doa = dop/2;         a.setX(doa);         c.setX(doa);         c.setY(0);         d.setX(o.x());         d.setY(0);     }     else {         qreal sinAngle2 = sin(angle2);         qreal doa = (h-o.y())/sinAngle2;         a.setX(doa);         qreal tanVal = tan(PI/2-angle);         by = tanVal*doa;          if (by <= h) {             c.setX(0);             c.setY(h-by);         }         else {             qreal cw = (by-h)/tanVal;             c.setX(cw);             c.setY(0);              qreal ddx = cos(angle2)*cw;             qreal ddy = sinAngle2*cw;             d.setX(c.x()+ddx);             d.setY(-ddy);         }     }      if (by <= h) {         qreal cv = c.y()/h;         qreal av = a.x()/w;         m_ports1.append(Vertex(a, QPointF(av,0), 0));         m_ports1.append(Vertex(s, QPointF(1,0), 0));         m_ports1.append(Vertex(QPointF(w, 0), QPointF(1,1), 0));         m_ports1.append(Vertex(QPointF(0, 0), QPointF(0,1), 0));         m_ports1.append(Vertex(c, QPointF(0,1-cv), 0));          m_ports2.append(Vertex(a, QPointF(1-av,0), 1));         m_ports2.append(Vertex(o, QPointF(1,0), 0));         m_ports2.append(Vertex(c, QPointF(1,1-cv), 1));          m_ports3.append(Vertex(a, QPointF(av,0), 1));         m_ports3.append(Vertex(c, QPointF(0,1-cv), 1));         m_ports3.append(Vertex(p, QPointF(0,0), 0));     }     else {         qreal cv = c.x()/w;         qreal av = a.x()/w;         m_ports1.append(Vertex(a, QPointF(av,0), 0));         m_ports1.append(Vertex(s, QPointF(1,0), 0));         m_ports1.append(Vertex(QPointF(w, 0), QPointF(1,1), 0));         m_ports1.append(Vertex(c, QPointF(cv,1), 0));          m_ports2.append(Vertex(a, QPointF(1-av,0), 1));         m_ports2.append(Vertex(o, QPointF(1,0), 0));         m_ports2.append(Vertex(d, QPointF(1,1), angle == 0 ? 0 : h/by/*(o.x()-d.x())/(o.x()-c.x())*/));         m_ports2.append(Vertex(c, QPointF(1-cv,1), 1));          m_ports3.append(Vertex(p, QPointF(0,0), 0));         m_ports3.append(Vertex(a, QPointF(av,0), 1));         m_ports3.append(Vertex(c, QPointF(cv,1), 1));         m_ports3.append(Vertex(QPointF(0, 0), QPointF(0,1), m_ports2[2].m_gradient));     } } else if (m_startCorner == TopRight) {     QPointF s(0, h), p(w, h), a, c, d;     if (distance(o, s) > w) getClosestPointOnCircle(o, s);     if (o.y() >= h) o.setY(h);     if (o == p) {         m_ports1.append(Vertex(QPointF(0, h), QPointF(0,0), 0));         m_ports1.append(Vertex(QPointF(w, h), QPointF(1,0), 0));         m_ports1.append(Vertex(QPointF(w, 0), QPointF(1,1), 0));         m_ports1.append(Vertex(QPointF(0, 0), QPointF(0,1), 0));         return;     }      qreal dop = distance(o,p);     qreal angle = asin((h-o.y())/dop);     qreal angle2 = 2*angle;     qreal by = h+10;      a.setY(h);     if (angle == 0) {         qreal doa = dop/2;         a.setX(w-doa);         c.setX(w-doa);         c.setY(0);         d.setX(o.x());         d.setY(0);     }     else {         qreal sinAngle2 = sin(angle2);         qreal doa = (h-o.y())/sinAngle2;         a.setX(w-doa);         qreal tanVal = tan(PI/2-angle);         by = tanVal*doa;          if (by <= h) {             c.setX(w);             c.setY(h-by);         }         else {             qreal cw = (by-h)/tanVal;             c.setX(w-cw);             c.setY(0);              qreal ddx = cos(angle2)*cw;             qreal ddy = sinAngle2*cw;             d.setX(c.x()-ddx);             d.setY(-ddy);         }     }      if (by <= h) {         qreal cv = c.y()/h;         qreal av = a.x()/w;         m_ports1.append(Vertex(s, QPointF(0,0), 0));         m_ports1.append(Vertex(a, QPointF(av,0), 0));         m_ports1.append(Vertex(c, QPointF(1,1-cv), 0));         m_ports1.append(Vertex(QPointF(w, 0), QPointF(1,1), 0));         m_ports1.append(Vertex(QPointF(0, 0), QPointF(0,1), 0));          m_ports2.append(Vertex(c, QPointF(0,1-cv), 1));         m_ports2.append(Vertex(o, QPointF(0,0), 0));         m_ports2.append(Vertex(a, QPointF(1-av,0), 1));

OpenGL贴图

OpenGL里面的图像渲染,是通过将图片映射成纹理,然后通过顶点坐标和对应的纹理坐标映射到物体表面。

Qt翻页效果实现(四):OpenGL图像渲染

顶点坐标

这里我们只有三个屏平面,在Qt翻页效果实现(二)文章中各点的坐标,在OpenGL里面就属于顶点坐标了。
然而由于OpenGL里面的坐标系与屏幕坐标系不同,里面原点坐标在右下角。
比如上图中 P点的坐标现在才是(0,0),O点坐标是(0,h),D点坐标是(w,0)等等。

这样就需要对里面的坐标进行转换,或者重新实现了。
还有需要注意的就是当试试计算翻页位置时,传递到 compute(const QPoint &pos) 中的 pos 也要经过窗口坐标转换。
到时候要根据平常界面窗口与OpenGL窗口的相对位置来进行转换。
最简单的是平常界面窗口与OpenGL窗口大小位置相同,或者只有OpenGL窗口,则可以直接转换如下:

void XXXX::mouseMoveEvent(QMouseEvent *e) {     m_pos = QPoint(e->pos().x(), height()-e->pos().y());  // 用窗口高度减去鼠标的y()     updateGL(); }

纹理坐标

另一个需要的计算的就是求取纹理坐标。在OpenGL中,纹理坐标是归一化的,或者可以看作是向量。
比如上图中 P点的纹理坐标可以看成是(0,0),O点坐标是(0,1),D点坐标是(1,0)。
对于A点纹理坐标,则可以简单计算为 A(A.x/w, 0)。
具体细节部分就不在此详细叙述,如果不清楚的小伙伴可以百度查阅一下,有很多写的不错的文章。
在这里默认你已经具备纹理贴图的OpenGL的相关知识点。

阴影纹理

对于在Qt翻页效果实现(三)文章中提到的阴影,在OpenGL中,则可通过一维纹理实现。对应的纹理坐标也只有一个值。
比如上图中 C点阴影纹理可以看成是0,A点和B点纹理可以看成是1。

纹理创建

一维纹理创建

一维纹理可以通过一个带渐透明变高度为1像素的png图做为资源进行加载;
如果不会作图,也可以通过自己生成的一个颜色数组进行创建,具体方式图像:

void XXXX::loadGLTexture1(GLuint *texId) {     GLubyte image[256];     double n = 0;     for (int i = 0; i <= 256; i+=4)  // 颜色填充     {         if (i>=200) n+=10;         else n+=0.1;         image[i] = 255-n;         image[i+1] = 255-n;         image[i+2] = 255-n;         image[i+3] = 255;     }     glGenTextures(1, texId); // 创建纹理     glBindTexture(GL_TEXTURE_1D, *texId);      glTexImage1D(GL_TEXTURE_1D, 0, GL_RGBA,                  64, 0, GL_RGBA, GL_UNSIGNED_BYTE,                  image);      glTexParameteri(GL_TEXTURE_1D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);    // 线形滤波     glTexParameteri(GL_TEXTURE_1D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);    // 线形滤波 }

二维纹理创建

二维纹理可以直接通过加载图片生成;Qt中可以直接通过QImage生成纹理。
由于二维纹理与上面一维纹理需求不同,因为阴影只需要创建一次即可;
而对于我们翻页功能来说,随着内容的不同,加载的图片也不一样,纹理也要实时变更。

所以在创建纹理之前,我们先要创建三个纹理,对应三个区域的内容。在初始化的时候还要记得给其全部清零

GLuint m_tex[3];

绑定纹理的时候,则可以通过下面的方法,直接将QImage绑定到对应索引的纹理上面。

void XXXX::bindTexture(const QImage&img, int texId) {     //现在载入图像,并将其转换为纹理。     QImage image = img.convertToFormat(QImage::Format_RGBA8888);     if (m_tex[texId])         glDeleteTextures(1, &m_tex[texId]);     glGenTextures(1, &m_tex[texId]);// 创建纹理      glBindTexture(GL_TEXTURE_2D, m_tex[texId]);      glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,                  image.width(), image.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE,                  image.bits());      glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);    // 线形滤波     glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);    // 线形滤波 }

坐标计算

相对于Qt翻页效果实现(二)文章中只需要通过一个QPointF来保存区域的点的集合不同;
由于OpenGL中涉及到的坐标信息相对较多,则需要单独定义一个结构体来保存数据。
定义如下:

struct Vertex {     Vertex(const QPointF&pos, const QPointF&tex, qreal g):         m_pos(pos), m_texcoord(tex), m_gradient(g){}     QPointF m_pos;        // 顶点坐标     QPointF m_texcoord;   // 纹理坐标     qreal m_gradient;     // 阴影纹理坐标 };

其他功能性函数不变,只需要修改 compute(const QPoint& pos) 计算函数,
实现代码如下:
“`
void XXXX::compute(const QPoint &pos)
{
int w = m_pageRect.width();
int h = m_pageRect.height();
m_ports1.clear();
m_ports2.clear();
m_ports3.clear();
QPointF o = pos;
if (m_startCorner == TopLeft) {
QPointF s(w, h), p(0, h), a, c, d;
if (distance(o, s) > w) getClosestPointOnCircle(o, s);
if (o.y() >= h) o.setY(h);
if (o == p) {
m_ports1.append(Vertex(QPointF(0, h), QPointF(0,0), 0));
m_ports1.append(Vertex(QPointF(w, h), QPointF(1,0), 0));
m_ports1.append(Vertex(QPointF(w, 0), QPointF(1,1), 0));
m_ports1.append(Vertex(QPointF(0, 0), QPointF(0,1), 0));
return;
}

    qreal dop = distance(o,p);     qreal angle = asin((h-o.y())/dop);     qreal angle2 = 2*angle;     qreal by = h+10;      logs(dop);     logs(o);     logs(pos);      a.setY(h);     if (angle == 0) {         qreal doa = dop/2;         a.setX(doa);         c.setX(doa);         c.setY(0);         d.setX(o.x());         d.setY(0);     }     else {         qreal sinAngle2 = sin(angle2);         qreal doa = (h-o.y())/sinAngle2;         a.setX(doa);         qreal tanVal = tan(PI/2-angle);         by = tanVal*doa;          if (by <= h) {             c.setX(0);             c.setY(h-by);         }         else {             qreal cw = (by-h)/tanVal;             c.setX(cw);             c.setY(0);              qreal ddx = cos(angle2)*cw;             qreal ddy = sinAngle2*cw;             d.setX(c.x()+ddx);             d.setY(-ddy);         }     }      if (by <= h) {         qreal cv = c.y()/h;         qreal av = a.x()/w;         m_ports1.append(Vertex(a, QPointF(av,0), 0));         m_ports1.append(Vertex(s, QPointF(1,0), 0));         m_ports1.append(Vertex(QPointF(w, 0), QPointF(1,1), 0));         m_ports1.append(Vertex(QPointF(0, 0), QPointF(0,1), 0));         m_ports1.append(Vertex(c, QPointF(0,1-cv), 0));          m_ports2.append(Vertex(a, QPointF(1-av,0), 1));         m_ports2.append(Vertex(o, QPointF(1,0), 0));         m_ports2.append(Vertex(c, QPointF(1,1-cv), 1));          m_ports3.append(Vertex(a, QPointF(av,0), 1));         m_ports3.append(Vertex(c, QPointF(0,1-cv), 1));         m_ports3.append(Vertex(p, QPointF(0,0), 0));     }     else {         qreal cv = c.x()/w;         qreal av = a.x()/w;         m_ports1.append(Vertex(a, QPointF(av,0), 0));         m_ports1.append(Vertex(s, QPointF(1,0), 0));         m_ports1.append(Vertex(QPointF(w, 0), QPointF(1,1), 0));         m_ports1.append(Vertex(c, QPointF(cv,1), 0));          m_ports2.append(Vertex(a, QPointF(1-av,0), 1));         m_ports2.append(Vertex(o, QPointF(1,0), 0));         m_ports2.append(Vertex(d, QPointF(1,1), angle == 0 ? 0 : h/by/*(o.x()-d.x())/(o.x()-c.x())*/));         m_ports2.append(Vertex(c, QPointF(1-cv,1), 1));          m_ports3.append(Vertex(p, QPointF(0,0), 0));         m_ports3.append(Vertex(a, QPointF(av,0), 1));         m_ports3.append(Vertex(c, QPointF(cv,1), 1));         m_ports3.append(Vertex(QPointF(0, 0), QPointF(0,1), m_ports2[2].m_gradient));     } } else if (m_startCorner == TopRight) {     QPointF s(0, h), p(w, h), a, c, d;     if (distance(o, s) > w) getClosestPointOnCircle(o, s);     if (o.y() >= h) o.setY(h);     if (o == p) {         m_ports1.append(Vertex(QPointF(0, h), QPointF(0,0), 0));         m_ports1.append(Vertex(QPointF(w, h), QPointF(1,0), 0));         m_ports1.append(Vertex(QPointF(w, 0), QPointF(1,1), 0));         m_ports1.append(Vertex(QPointF(0, 0), QPointF(0,1), 0));         return;     }      qreal dop = distance(o,p);     qreal angle = asin((h-o.y())/dop);     qreal angle2 = 2*angle;     qreal by = h+10;      a.setY(h);     if (angle == 0) {         qreal doa = dop/2;         a.setX(w-doa);         c.setX(w-doa);         c.setY(0);         d.setX(o.x());         d.setY(0);     }     else {         qreal sinAngle2 = sin(angle2);         qreal doa = (h-o.y())/sinAngle2;         a.setX(w-doa);         qreal tanVal = tan(PI/2-angle);         by = tanVal*doa;          if (by <= h) {             c.setX(w);             c.setY(h-by);         }         else {             qreal cw = (by-h)/tanVal;             c.setX(w-cw);             c.setY(0);              qreal ddx = cos(angle2)*cw;             qreal ddy = sinAngle2*cw;             d.setX(c.x()-ddx);             d.setY(-ddy);         }     }      if (by <= h) {         qreal cv = c.y()/h;         qreal av = a.x()/w;         m_ports1.append(Vertex(s, QPointF(0,0), 0));         m_ports1.append(Vertex(a, QPointF(av,0), 0));         m_ports1.append(Vertex(c, QPointF(1,1-cv), 0));         m_ports1.append(Vertex(QPointF(w, 0), QPointF(1,1), 0));         m_ports1.append(Vertex(QPointF(0, 0), QPointF(0,1), 0));          m_ports2.append(Vertex(c, QPointF(0,1-cv), 1));         m_ports2.append(Vertex(o, QPointF(0,0), 0));         m_ports2.append(Vertex(a, QPointF(1-av,0), 1));

OpenGL贴图

OpenGL里面的图像渲染,是通过将图片映射成纹理,然后通过顶点坐标和对应的纹理坐标映射到物体表面。

Qt翻页效果实现(四):OpenGL图像渲染

顶点坐标

这里我们只有三个屏平面,在Qt翻页效果实现(二)文章中各点的坐标,在OpenGL里面就属于顶点坐标了。
然而由于OpenGL里面的坐标系与屏幕坐标系不同,里面原点坐标在右下角。
比如上图中 P点的坐标现在才是(0,0),O点坐标是(0,h),D点坐标是(w,0)等等。

这样就需要对里面的坐标进行转换,或者重新实现了。
还有需要注意的就是当试试计算翻页位置时,传递到 compute(const QPoint &pos) 中的 pos 也要经过窗口坐标转换。
到时候要根据平常界面窗口与OpenGL窗口的相对位置来进行转换。
最简单的是平常界面窗口与OpenGL窗口大小位置相同,或者只有OpenGL窗口,则可以直接转换如下:

void XXXX::mouseMoveEvent(QMouseEvent *e) {     m_pos = QPoint(e->pos().x(), height()-e->pos().y());  // 用窗口高度减去鼠标的y()     updateGL(); }

纹理坐标

另一个需要的计算的就是求取纹理坐标。在OpenGL中,纹理坐标是归一化的,或者可以看作是向量。
比如上图中 P点的纹理坐标可以看成是(0,0),O点坐标是(0,1),D点坐标是(1,0)。
对于A点纹理坐标,则可以简单计算为 A(A.x/w, 0)。
具体细节部分就不在此详细叙述,如果不清楚的小伙伴可以百度查阅一下,有很多写的不错的文章。
在这里默认你已经具备纹理贴图的OpenGL的相关知识点。

阴影纹理

对于在Qt翻页效果实现(三)文章中提到的阴影,在OpenGL中,则可通过一维纹理实现。对应的纹理坐标也只有一个值。
比如上图中 C点阴影纹理可以看成是0,A点和B点纹理可以看成是1。

纹理创建

一维纹理创建

一维纹理可以通过一个带渐透明变高度为1像素的png图做为资源进行加载;
如果不会作图,也可以通过自己生成的一个颜色数组进行创建,具体方式图像:

void XXXX::loadGLTexture1(GLuint *texId) {     GLubyte image[256];     double n = 0;     for (int i = 0; i <= 256; i+=4)  // 颜色填充     {         if (i>=200) n+=10;         else n+=0.1;         image[i] = 255-n;         image[i+1] = 255-n;         image[i+2] = 255-n;         image[i+3] = 255;     }     glGenTextures(1, texId); // 创建纹理     glBindTexture(GL_TEXTURE_1D, *texId);      glTexImage1D(GL_TEXTURE_1D, 0, GL_RGBA,                  64, 0, GL_RGBA, GL_UNSIGNED_BYTE,                  image);      glTexParameteri(GL_TEXTURE_1D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);    // 线形滤波     glTexParameteri(GL_TEXTURE_1D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);    // 线形滤波 }

二维纹理创建

二维纹理可以直接通过加载图片生成;Qt中可以直接通过QImage生成纹理。
由于二维纹理与上面一维纹理需求不同,因为阴影只需要创建一次即可;
而对于我们翻页功能来说,随着内容的不同,加载的图片也不一样,纹理也要实时变更。

所以在创建纹理之前,我们先要创建三个纹理,对应三个区域的内容。在初始化的时候还要记得给其全部清零

GLuint m_tex[3];

绑定纹理的时候,则可以通过下面的方法,直接将QImage绑定到对应索引的纹理上面。

void XXXX::bindTexture(const QImage&img, int texId) {     //现在载入图像,并将其转换为纹理。     QImage image = img.convertToFormat(QImage::Format_RGBA8888);     if (m_tex[texId])         glDeleteTextures(1, &m_tex[texId]);     glGenTextures(1, &m_tex[texId]);// 创建纹理      glBindTexture(GL_TEXTURE_2D, m_tex[texId]);      glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,                  image.width(), image.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE,                  image.bits());      glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);    // 线形滤波     glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);    // 线形滤波 }

坐标计算

相对于Qt翻页效果实现(二)文章中只需要通过一个QPointF来保存区域的点的集合不同;
由于OpenGL中涉及到的坐标信息相对较多,则需要单独定义一个结构体来保存数据。
定义如下:

struct Vertex {     Vertex(const QPointF&pos, const QPointF&tex, qreal g):         m_pos(pos), m_texcoord(tex), m_gradient(g){}     QPointF m_pos;        // 顶点坐标     QPointF m_texcoord;   // 纹理坐标     qreal m_gradient;     // 阴影纹理坐标 };

其他功能性函数不变,只需要修改 compute(const QPoint& pos) 计算函数,
实现代码如下:
“`
void XXXX::compute(const QPoint &pos)
{
int w = m_pageRect.width();
int h = m_pageRect.height();
m_ports1.clear();
m_ports2.clear();
m_ports3.clear();
QPointF o = pos;
if (m_startCorner == TopLeft) {
QPointF s(w, h), p(0, h), a, c, d;
if (distance(o, s) > w) getClosestPointOnCircle(o, s);
if (o.y() >= h) o.setY(h);
if (o == p) {
m_ports1.append(Vertex(QPointF(0, h), QPointF(0,0), 0));
m_ports1.append(Vertex(QPointF(w, h), QPointF(1,0), 0));
m_ports1.append(Vertex(QPointF(w, 0), QPointF(1,1), 0));
m_ports1.append(Vertex(QPointF(0, 0), QPointF(0,1), 0));
return;
}

    qreal dop = distance(o,p);     qreal angle = asin((h-o.y())/dop);     qreal angle2 = 2*angle;     qreal by = h+10;      logs(dop);     logs(o);     logs(pos);      a.setY(h);     if (angle == 0) {         qreal doa = dop/2;         a.setX(doa);         c.setX(doa);         c.setY(0);         d.setX(o.x());         d.setY(0);     }     else {         qreal sinAngle2 = sin(angle2);         qreal doa = (h-o.y())/sinAngle2;         a.setX(doa);         qreal tanVal = tan(PI/2-angle);         by = tanVal*doa;          if (by <= h) {             c.setX(0);             c.setY(h-by);         }         else {             qreal cw = (by-h)/tanVal;             c.setX(cw);             c.setY(0);              qreal ddx = cos(angle2)*cw;             qreal ddy = sinAngle2*cw;             d.setX(c.x()+ddx);             d.setY(-ddy);         }     }      if (by <= h) {         qreal cv = c.y()/h;         qreal av = a.x()/w;         m_ports1.append(Vertex(a, QPointF(av,0), 0));         m_ports1.append(Vertex(s, QPointF(1,0), 0));         m_ports1.append(Vertex(QPointF(w, 0), QPointF(1,1), 0));         m_ports1.append(Vertex(QPointF(0, 0), QPointF(0,1), 0));         m_ports1.append(Vertex(c, QPointF(0,1-cv), 0));          m_ports2.append(Vertex(a, QPointF(1-av,0), 1));         m_ports2.append(Vertex(o, QPointF(1,0), 0));         m_ports2.append(Vertex(c, QPointF(1,1-cv), 1));          m_ports3.append(Vertex(a, QPointF(av,0), 1));         m_ports3.append(Vertex(c, QPointF(0,1-cv), 1));         m_ports3.append(Vertex(p, QPointF(0,0), 0));     }     else {         qreal cv = c.x()/w;         qreal av = a.x()/w;         m_ports1.append(Vertex(a, QPointF(av,0), 0));         m_ports1.append(Vertex(s, QPointF(1,0), 0));         m_ports1.append(Vertex(QPointF(w, 0), QPointF(1,1), 0));         m_ports1.append(Vertex(c, QPointF(cv,1), 0));          m_ports2.append(Vertex(a, QPointF(1-av,0), 1));         m_ports2.append(Vertex(o, QPointF(1,0), 0));         m_ports2.append(Vertex(d, QPointF(1,1), angle == 0 ? 0 : h/by/*(o.x()-d.x())/(o.x()-c.x())*/));         m_ports2.append(Vertex(c, QPointF(1-cv,1), 1));          m_ports3.append(Vertex(p, QPointF(0,0), 0));         m_ports3.append(Vertex(a, QPointF(av,0), 1));         m_ports3.append(Vertex(c, QPointF(cv,1), 1));         m_ports3.append(Vertex(QPointF(0, 0), QPointF(0,1), m_ports2[2].m_gradient));     } } else if (m_startCorner == TopRight) {     QPointF s(0, h), p(w, h), a, c, d;     if (distance(o, s) > w) getClosestPointOnCircle(o, s);     if (o.y() >= h) o.setY(h);     if (o == p) {         m_ports1.append(Vertex(QPointF(0, h), QPointF(0,0), 0));         m_ports1.append(Vertex(QPointF(w, h), QPointF(1,0), 0));         m_ports1.append(Vertex(QPointF(w, 0), QPointF(1,1), 0));         m_ports1.append(Vertex(QPointF(0, 0), QPointF(0,1), 0));         return;     }      qreal dop = distance(o,p);     qreal angle = asin((h-o.y())/dop);     qreal angle2 = 2*angle;     qreal by = h+10;      a.setY(h);     if (angle == 0) {         qreal doa = dop/2;         a.setX(w-doa);         c.setX(w-doa);         c.setY(0);         d.setX(o.x());         d.setY(0);     }     else {         qreal sinAngle2 = sin(angle2);         qreal doa = (h-o.y())/sinAngle2;         a.setX(w-doa);         qreal tanVal = tan(PI/2-angle);         by = tanVal*doa;          if (by <= h) {             c.setX(w);             c.setY(h-by);         }         else {             qreal cw = (by-h)/tanVal;             c.setX(w-cw);             c.setY(0);              qreal ddx = cos(angle2)*cw;             qreal ddy = sinAngle2*cw;             d.setX(c.x()-ddx);             d.setY(-ddy);         }     }      if (by <= h) {         qreal cv = c.y()/h;         qreal av = a.x()/w;         m_ports1.append(Vertex(s, QPointF(0,0), 0));         m_ports1.append(Vertex(a, QPointF(av,0), 0));         m_ports1.append(Vertex(c, QPointF(1,1-cv), 0));         m_ports1.append(Vertex(QPointF(w, 0), QPointF(1,1), 0));         m_ports1.append(Vertex(QPointF(0, 0), QPointF(0,1), 0));          m_ports2.append(Vertex(c, QPointF(0,1-cv), 1));         m_ports2.append(Vertex(o, QPointF(0,0), 0));         m_ports2.append(Vertex(a, QPointF(1-av,0), 1));

部分转自互联网,侵权删除联系

赞(0) 打赏
部分文章转自网络,侵权联系删除b2bchain区块链学习技术社区 » Qt翻页效果实现(四):OpenGL图像渲染求职学习资料
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

b2b链

联系我们联系我们