QT5 OpenGL(五,立体图形贴图)

概要

上一节,我们已经实现了立体图形每个面填充颜色,这样就显得很单调, 而如果用图片替换这种单调的颜色,这样就会让立体图形显得更为深动。


效果图展示

以y轴为中心旋转图1

这里写图片描述


以y轴为中心旋转图2

这里写图片描述


以x轴为中心旋转图1

这里写图片描述


以x轴为中心旋转图2

这里写图片描述


以x轴为中心旋转图1

这里写图片描述


部分代码

#include "openglwidget.h"

OpenglWidget::OpenglWidget(QWidget* parent)
    :QGLWidget(parent),
      m_rotateTriangle(0),
      m_rotateRectangle(0),
      m_x(0),
      m_y(0),
      m_z(0)
{
    initWidget();
}

void OpenglWidget::initializeGL()
{
    loadGLTextures();
    glEnable( GL_TEXTURE_2D );
    glShadeModel( GL_SMOOTH );
    glClearColor( 0.0, 0.0, 0.0, 0.5 );
    glClearDepth( 1.0 );
    glEnable( GL_DEPTH_TEST );
    glDepthFunc( GL_LEQUAL );
    glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST );
}

void OpenglWidget::initWidget()
{
    setGeometry( 400, 200, 640, 480 );
    setWindowTitle(tr("opengl demo"));
}

void OpenglWidget::paintGL()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glLoadIdentity();

    glTranslatef( -1.5,  0.0, -6.0 );

    glRotatef( m_x,  1.0,  0.0,  0.0 );
    glRotatef( m_y,  0.0,  1.0,  0.0 );
    glRotatef( m_z,  0.0,  0.0,  1.0 );


    glBindTexture( GL_TEXTURE_2D, textur[0] );

    glBegin( GL_QUADS );

    glTexCoord2f( 0.0, 0.0 ); glVertex3f( -1.0, -1.0,  1.0 );
    glTexCoord2f( 1.0, 0.0 ); glVertex3f(  1.0, -1.0,  1.0 );
    glTexCoord2f( 1.0, 1.0 ); glVertex3f(  1.0,  1.0,  1.0 );
    glTexCoord2f( 0.0, 1.0 ); glVertex3f( -1.0,  1.0,  1.0 );

    glTexCoord2f( 1.0, 0.0 ); glVertex3f( -1.0, -1.0, -1.0 );
    glTexCoord2f( 1.0, 1.0 ); glVertex3f( -1.0,  1.0, -1.0 );
    glTexCoord2f( 0.0, 1.0 ); glVertex3f(  1.0,  1.0, -1.0 );
    glTexCoord2f( 0.0, 0.0 ); glVertex3f(  1.0, -1.0, -1.0 );

    glTexCoord2f( 0.0, 1.0 ); glVertex3f( -1.0,  1.0, -1.0 );
    glTexCoord2f( 0.0, 0.0 ); glVertex3f( -1.0,  1.0,  1.0 );
    glTexCoord2f( 1.0, 0.0 ); glVertex3f(  1.0,  1.0,  1.0 );
    glTexCoord2f( 1.0, 1.0 ); glVertex3f(  1.0,  1.0, -1.0 );

    glTexCoord2f( 1.0, 1.0 ); glVertex3f( -1.0, -1.0, -1.0 );
    glTexCoord2f( 0.0, 1.0 ); glVertex3f(  1.0, -1.0, -1.0 );
    glTexCoord2f( 0.0, 0.0 ); glVertex3f(  1.0, -1.0,  1.0 );
    glTexCoord2f( 1.0, 0.0 ); glVertex3f( -1.0, -1.0,  1.0 );

    glTexCoord2f( 1.0, 0.0 ); glVertex3f(  1.0, -1.0, -1.0 );
    glTexCoord2f( 1.0, 1.0 ); glVertex3f(  1.0,  1.0, -1.0 );
    glTexCoord2f( 0.0, 1.0 ); glVertex3f(  1.0,  1.0,  1.0 );
    glTexCoord2f( 0.0, 0.0 ); glVertex3f(  1.0, -1.0,  1.0 );

    glTexCoord2f( 0.0, 0.0 ); glVertex3f( -1.0, -1.0, -1.0 );
    glTexCoord2f( 1.0, 0.0 ); glVertex3f( -1.0, -1.0,  1.0 );
    glTexCoord2f( 1.0, 1.0 ); glVertex3f( -1.0,  1.0,  1.0 );
    glTexCoord2f( 0.0, 1.0 ); glVertex3f( -1.0,  1.0, -1.0 );

    glEnd();

    glLoadIdentity();

    glTranslatef(  1.5,  0.0, -6.0 );

    glRotatef( m_x,  1.0,  0.0,  0.0 );
    glRotatef( m_y,  0.0,  1.0,  0.0 );
    glRotatef( m_z,  0.0,  0.0,  1.0 );


    glBegin(GL_TRIANGLES);

    //三棱柱四面贴图
    glTexCoord2f( 1, 1 ); glVertex3f( 0, 1, 0 );
    glTexCoord2f( 0, 0 ); glVertex3f(  1, -1, 1 );
    glTexCoord2f( 1, 0 ); glVertex3f(  -1, -1, 1 );

    glTexCoord2f( 1, 1 ); glVertex3f( 0, 1, 0 );
    glTexCoord2f( 0, 0 ); glVertex3f( -1.0,  -1.0, 1.0 );
    glTexCoord2f( 1, 0 ); glVertex3f(  -1.0,  -1.0, -1.0 );


    glTexCoord2f( 1, 1 ); glVertex3f( 0,  1, 0 );
    glTexCoord2f( 0, 0 ); glVertex3f( -1.0,  -1.0,  -1.0 );
    glTexCoord2f( 1, 0 ); glVertex3f(  1.0,  -1.0,  -1.0 );

    glTexCoord2f( 1, 1 ); glVertex3f( 0, 1, 0 );
    glTexCoord2f( 0, 0 ); glVertex3f(  1.0, -1.0, -1.0 );
    glTexCoord2f( 1, 0 ); glVertex3f(  1.0, -1.0,  1.0 );

    //三棱柱底面贴图
    glTexCoord2f( 0, 0 ); glVertex3f(  -1.0, -1.0, -1.0 );
    glTexCoord2f( 1, 0 ); glVertex3f(  1.0, -1.0,  -1.0 );
    glTexCoord2f( 1, 1 ); glVertex3f(  1.0, -1.0, 1.0 );

    glTexCoord2f( 1, 0 ); glVertex3f(  1.0, -1.0,  -1.0 );
    glTexCoord2f( 1, 1 ); glVertex3f(  1.0, -1.0, 1.0 );
    glTexCoord2f( 0, 1 ); glVertex3f(  -1.0, -1.0,  1.0 );

    glTexCoord2f( 1, 1 ); glVertex3f(  1.0, -1.0, 1.0 );
    glTexCoord2f( 0, 1 ); glVertex3f(  -1.0, -1.0,  1.0 );
    glTexCoord2f( 0, 0 ); glVertex3f(  -1.0, -1.0, -1.0 );

    glEnd();


    m_x += 20;
    m_y += 0;
    m_z += 0;
}

void OpenglWidget::resizeGL(int width, int height)
{
    if(0 == height) {
        height = 1;
    }

    glViewport(0, 0, (GLint)width, (GLint)height);

    glMatrixMode(GL_PROJECTION);

    glLoadIdentity();

  //  gluPerspective(45.0, (GLfloat)width/(GLfloat)height, 0.1, 100.0);

    GLdouble aspectRatio = (GLfloat)width/(GLfloat)height;
    GLdouble zNear = 0.1;
    GLdouble zFar = 100.0;

    GLdouble rFov = 45.0 * 3.14159265 / 180.0;
     glFrustum( -zNear * tan( rFov / 2.0 ) * aspectRatio,
               zNear * tan( rFov / 2.0 ) * aspectRatio,
               -zNear * tan( rFov / 2.0 ),
               zNear * tan( rFov / 2.0 ),
               zNear, zFar );

    glMatrixMode(GL_MODELVIEW);

    glLoadIdentity();
}


void OpenglWidget::loadGLTextures()
{
  QImage tex;
  QImage buf;

  if ( !buf.load(":/images/dog.png"))
  {
    qWarning( "load image failed!" );
    QImage dummy( 128, 128, QImage::Format_RGB32 );
    dummy.fill( Qt::red);
    buf = dummy;

  }

  tex = QGLWidget::convertToGLFormat( buf );
  glGenTextures( 1, &textur[0] );
  glBindTexture( GL_TEXTURE_2D, textur[0] );

  glTexImage2D( GL_TEXTURE_2D, 0, 3, tex.width(), tex.height(), 0,
      GL_RGBA, GL_UNSIGNED_BYTE, tex.bits() );

  glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
  glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
}

主要内容解析

1.相对于立体图形的直接绘图即单一的色彩, 添加了的代码:

添加了用于把图片保存在缓存中的函数

void OpenglWidget::loadGLTextures()
{
  QImage tex;
  QImage buf;

  if ( !buf.load(":/images/dog.png"))
  {
    qWarning( "load image failed!" );
    QImage dummy( 128, 128, QImage::Format_RGB32 );
    dummy.fill( Qt::red);
    buf = dummy;

  }

  tex = QGLWidget::convertToGLFormat( buf );
  glGenTextures( 1, &textur[0] );
  glBindTexture( GL_TEXTURE_2D, textur[0] );

  glTexImage2D( GL_TEXTURE_2D, 0, 3, tex.width(), tex.height(), 0,
      GL_RGBA, GL_UNSIGNED_BYTE, tex.bits() );

  glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
  glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
}

这里值得一提的是, buf.load(“:/images/dog.png”) 这里,图片load在有些电脑上,竟然不成功,目前也不知道是啥原因。不知道是跟QT版本有关,还是电脑硬件有关。

添加了代码

void OpenglWidget::initializeGL()
{
    loadGLTextures();
    glEnable( GL_TEXTURE_2D );

glEnable( GL_TEXTURE_2D );这个用于启用纹理, 不然,所显示的全为白色。

convertToGLFormat 这个函数是一个图形转换函数, 也是一个静态函数。转换后的内容,在后面获得纹理时用得上。

glGenTextures( 1, &texture[0] ); 这里第几张图片纹理的定义。

glBindTexture( GL_TEXTURE_2D, texture[0] ); 进行纹理绑定

glTexImage2D( GL_TEXTURE_2D, 0, 3, tex.width(), tex.height(), 0,
GL_RGBA, GL_UNSIGNED_BYTE, tex.bits() );
这里是纹理的创建。

2.立体图形贴图坐标的计算和转换。

这里有两个接口函数:
glTexCoord2f( x, y );
glVertex3f( x, y, z );

glTexCoord2f这个用于表示原图片的坐标,这样更容易理解,就是以 在x,y 轴的平面里面, (0,0)表示图片的左下角, (0,1) 表示左上角, (1,1)表示右上角, (1,0)表示右下角。

而对应的glVertex3f则对应为 (-1, -1) , (-1, 1) , (1, 1), (1, -1)

我们怎么来理解这种对应关系呢??

  1. 需要贴图的坐标必须一一对应,就是我们如果顺时针写, 对应的坐都要顺时针,如果逆时针写,对应的坐标都要逆时针,一一对应。

2.我们的贴图是一张图片,所以它一定是一个平面。 所以坐标从(0,0)开始,这个容易使用。而我们需要贴图的立体图形,虽然每个面是平面图形,但它在坐标系中,始终以立体图形的中心为坐标原点,所以,它是一个三维坐标,三维坐标与二维的对应,就只有以相同的平面顶点旋转顺序来对应了。

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小K小Q

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值