QT5 Opengl (八,绘制雾的效果)

概要

在一些场景里面,我们有时雾要一些雾的衬托,这样就会让场景看起来更真实一点。这篇文章就是主要讲怎么绘制出雾的效果。


效果图


第一种样式的雾

这里写图片描述


第二种样式的雾

这里写图片描述


第三种样式的雾

这里写图片描述


深度比较低的雾

这里写图片描述


淡红色的雾

这里写图片描述


在原来基础上加的代码

.h文件

#ifndef OPENGLWIDGET_H
#define OPENGLWIDGET_H
#include <QtOpenGL>

class OpenglWidget : public QGLWidget
{
public:
    OpenglWidget(QWidget* parent = 0);

protected:
  void initConnection();
  void initializeGL();
  void initWidget();
  void paintGL();
  void resizeGL(int width, int height);

  void loadGLTextures();

  void keyPressEvent( QKeyEvent *e );

private slots:



private:
  GLfloat m_rotateTriangle;
  GLfloat m_rotateRectangle;

  GLfloat m_x;
  GLfloat m_y;
  GLfloat m_z;

  GLuint textur[3];

  GLfloat m_zoom;

  GLfloat m_xSpeed;
  GLfloat m_ySpeed;
  GLfloat m_zSpeed;

  bool m_openLight;

  GLuint m_choiceTexture;
  bool m_mixTogether;

  GLuint m_fog;

};

#endif // OPENGLWIDGET_H

.cpp文件

#include "openglwidget.h"


GLfloat lightAmbient[4] = { 0.5, 0.5, 0.5, 1.0 };
GLfloat lightDiffuse[4] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat lightPosition[4] = { 0.0, 0.0, 2.0, 1.0 };

GLuint fogMode[3] = { GL_EXP, GL_EXP2, GL_LINEAR };
//GLfloat fogColor[4] = { 0.5, 0.5, 0.5, 1.0 };

GLfloat fogColor[4] = { 0.2, 0, 0, 1.0 };

OpenglWidget::OpenglWidget(QWidget* parent)
    :QGLWidget(parent),
      m_rotateTriangle(0),
      m_rotateRectangle(0),
      m_x(0),
      m_y(0),
      m_z(0),
      m_zoom(-6),
      m_xSpeed(10),
      m_ySpeed(10),
      m_zSpeed(10),
      m_choiceTexture(0),
      m_openLight(false),
      m_mixTogether(false),
      m_fog(0)

{
    initWidget();
}

void OpenglWidget::initializeGL()
{
    loadGLTextures();
    glEnable( GL_TEXTURE_2D );
    glShadeModel( GL_SMOOTH );
  //  glClearColor( 0.0, 0.0, 0.0, 0.5 );
    glClearColor( 0.5, 0.5, 0.5, 1 );

    glClearDepth( 1.0 );
    glEnable( GL_DEPTH_TEST );
    glDepthFunc( GL_LEQUAL );
    glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST );

    glLightfv( GL_LIGHT1, GL_AMBIENT, lightAmbient );
    glLightfv( GL_LIGHT1, GL_DIFFUSE, lightDiffuse );
    glLightfv( GL_LIGHT1, GL_POSITION, lightPosition );

    glEnable( GL_LIGHT1 );

    glFogi( GL_FOG_MODE, fogMode[m_fog] );
    glFogfv( GL_FOG_COLOR, fogColor );
    glFogf( GL_FOG_DENSITY, 0.2 );
    glHint( GL_FOG_HINT, GL_NICEST );
    glFogf( GL_FOG_START, -3.0 );
    glFogf( GL_FOG_END, 6.0 );
    glEnable( GL_FOG );

    glColor4f(1, 1, 1, 0.5);
    glBlendFunc( GL_SRC_ALPHA, GL_ONE );
}

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, m_zoom );

    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[m_choiceTexture] );

    glBegin( GL_QUADS );

    glNormal3f( 0.0, 0.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 );

    glNormal3f( 0.0, 0.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 );

    glNormal3f( 0.0, 1.0, 0.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 );

    glNormal3f( 0.0, -1.0, 0.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 );

    glNormal3f( 1.0, 0.0, 0.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 );

    glNormal3f( -1.0, 0.0, 0.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, m_zoom );

    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 += m_xSpeed;
    m_y += m_ySpeed;
    m_z += m_zSpeed;
}

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( 3, &textur[0] );

  //纹理一
  glBindTexture( GL_TEXTURE_2D, textur[0] );
  glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
  glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
  glTexImage2D( GL_TEXTURE_2D, 0, 3, tex.width(), tex.height(), 0,
      GL_RGBA, GL_UNSIGNED_BYTE, tex.bits() );


  //纹理二
  glBindTexture( GL_TEXTURE_2D, textur[1] );
  glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
  glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
  glTexImage2D( GL_TEXTURE_2D, 0, 3, tex.width(), tex.height(), 0,
      GL_RGBA, GL_UNSIGNED_BYTE, tex.bits() );


  //纹理三
  glBindTexture( GL_TEXTURE_2D, textur[2] );
  glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
  glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST_MIPMAP_NEAREST );
  //gluBuild2DMipmaps( GL_TEXTURE_2D, GL_RGB, tex.width(), tex.height(), GL_RGBA, GL_UNSIGNED_BYTE, tex.bits() );
  glTexImage2D( GL_TEXTURE_2D, 0, 3, tex.width(), tex.height(), 0,
      GL_RGBA, GL_UNSIGNED_BYTE, tex.bits() );

}



void OpenglWidget::keyPressEvent( QKeyEvent *e )
{
  switch ( e->key() )
  {
  case Qt::Key_L:
    m_openLight = !m_openLight;
    if ( !m_openLight )
    {
      glDisable( GL_LIGHTING );
    }
    else
    {
      glEnable( GL_LIGHTING );
    }
    updateGL();
    break;

  case Qt::Key_F:
    m_choiceTexture += 1;;
    if ( m_choiceTexture > 2 )
    {
      m_choiceTexture = 0;
    }
    updateGL();
    break;

  case Qt::Key_W:
    m_zoom -= (GLfloat)0.2;
    updateGL();
    break;

  case Qt::Key_S:
    m_zoom += (GLfloat)0.2;
    updateGL();
    break;

  case Qt::Key_Up:
    m_xSpeed -= 1;
    updateGL();
    break;

  case Qt::Key_Down:
    m_xSpeed += 1;
    updateGL();
    break;

  case Qt::Key_Right:
    m_ySpeed += 1;
    updateGL();
    break;

  case Qt::Key_Left:
    m_ySpeed -= 1;
    updateGL();
    break;

  case Qt::Key_A:
    m_zSpeed += 1;
    updateGL();
    break;

  case Qt::Key_D:
    m_zSpeed -= 1;
    updateGL();
    break;

  case Qt::Key_M:
    m_mixTogether = !m_mixTogether;
    if ( m_mixTogether ) {
      glEnable( GL_BLEND );
      glDisable( GL_DEPTH_TEST );
    }
    else {
      glDisable( GL_BLEND );
      glEnable( GL_DEPTH_TEST );
    }
    updateGL();
    break;

   case Qt::Key_G:
    m_fog += 1;;
    if ( m_fog > 2 ){
      m_fog = 0;
    }
    glFogi( GL_FOG_MODE, fogMode[m_fog] );
    updateGL();
    break;


  case Qt::Key_Escape:
    close();
    break;

  }
}

重点解析

相对于原来的代码, 有关雾的代码主要有:

在.h文件里面添加了一个雾的种类的变量。
GLuint m_fog;


在.cpp文件里面设置了雾的种类和颜色
GLuint fogMode[3] = { GL_EXP, GL_EXP2, GL_LINEAR };
//GLfloat fogColor[4] = { 0.5, 0.5, 0.5, 1.0 };
GLfloat fogColor[4] = { 0.2, 0, 0, 1.0 };



在initializeGL()函数里面设置了场景的背景色彩为灰色
glClearColor( 0.5, 0.5, 0.5, 1 );

    glFogi( GL_FOG_MODE, fogMode[m_fog] );
    //选择雾的样式,这里默认为第一种GL_EXP

    glFogfv( GL_FOG_COLOR, fogColor );
    //设置雾的颜色

    glFogf( GL_FOG_DENSITY, 0.2 );
    //设置雾的浓度

    glHint( GL_FOG_HINT, GL_NICEST );
    //选择渲染效果

    glFogf( GL_FOG_START, -3.0 );
    glFogf( GL_FOG_END, 6.0 );
    //雾开始与结束的位置

    glEnable( GL_FOG );
    //允许雾的使用


   case Qt::Key_G:
    m_fog += 1;;
    if ( m_fog > 2 ){
      m_fog = 0;
    }
    glFogi( GL_FOG_MODE, fogMode[m_fog] );
    updateGL();
    break;
    //这里添加了键盘事件,用来选择不同样式的雾。


所以雾的效果,还是主要靠调用opengl的接口。











评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小K小Q

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

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

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

打赏作者

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

抵扣说明:

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

余额充值