您的位置:首页 > 编程语言 > Qt开发

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

2016-04-08 23:22 387 查看
概要

效果图
第一种样式的雾

第二种样式的雾

第三种样式的雾

深度比较低的雾

淡红色的雾

在原来基础上加的代码

重点解析

概要

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

效果图

第一种样式的雾



第二种样式的雾



第三种样式的雾



深度比较低的雾



淡红色的雾



在原来基础上加的代码

.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的接口。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: