本代码主要实现了一个旋转立方体, 并添加了光照效果。
Qt 版:
myglwidget.h
#ifndef MYGLWIDGET_H
#define MYGLWIDGET_H
#include <QGLWidget>
#include <QVector2D>
#include <QVector3D>
#include <QTimer>
class MyGLWidget : public QGLWidget
{
Q_OBJECT
public:
explicit MyGLWidget(QWidget *parent = 0);
signals:
public slots:
protected:
// Set up the rendering context, define display lists etc.:
void initializeGL();
void resizeGL(int w, int h);
void paintGL();
private:
void makeObject();
void initLighting();
GLfloat xrot; // X 旋转量
GLfloat yrot; // Y 旋转量
GLfloat zrot; // Z 旋转量
GLuint textures[6]; // 存储一个纹理
QVector<QVector3D> vertices;
QVector<QVector2D> texCoords;
QTimer *timer;
};
#endif // MYGLWIDGET_H
myglwidget.cpp
#include "myglwidget.h"
#ifndef GL_MULTISAMPLE
#define GL_MULTISAMPLE 0x809D
#endif
MyGLWidget::MyGLWidget(QWidget *parent) :
QGLWidget(parent)
{
xrot = 0.0f;
yrot = 0.0f;
zrot = 0.0f;
timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(updateGL()));
timer->start(10);
}
void MyGLWidget::initializeGL()
{
makeObject();initLighting();
glShadeModel(GL_SMOOTH); // 启用阴影平滑
glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // 黑色背景
glClearDepth(1.0f); // 设置深度缓存
glEnable(GL_CULL_FACE);
glEnable(GL_TEXTURE_2D);
glEnable(GL_DEPTH_TEST); // 启用深度测试
glDepthFunc(GL_LEQUAL); // 所作深度测试的类型
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // 告诉系统对透视进行修正
}
void MyGLWidget::resizeGL(int width, int height)
{
if (height==0) // 防止被零除
{
height=1; // 将Height设为1
}
glViewport(0, 0, width, height); // 重置当前的视口
glMatrixMode(GL_PROJECTION); // 选择投影矩阵
glLoadIdentity(); // 重置投影矩阵
// 设置视口的大小
gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f);
glMatrixMode(GL_MODELVIEW); // 选择模型观察矩阵
glLoadIdentity(); // 重置模型观察矩阵
}
void MyGLWidget::paintGL()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // 清除屏幕和深度缓存
glLoadIdentity(); // 重置当前的模型观察矩阵
glColor3f(1.0, 0.0, 1.0);
glTranslatef(0.0f,0.0f,-5.0f); // 移入屏幕 5 个单位
glRotatef(xrot,1.0f,0.0f,0.0f); // 绕X轴旋转
glRotatef(yrot,0.0f,1.0f,0.0f); // 绕Y轴旋转
glRotatef(zrot,0.0f,0.0f,1.0f); // 绕Z轴旋转
glVertexPointer(3, GL_FLOAT, 0, vertices.constData());
glTexCoordPointer(2, GL_FLOAT, 0, texCoords.constData());
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
for (int i = 0; i < 6; ++i) {
glBindTexture(GL_TEXTURE_2D, textures[i]);
glDrawArrays(GL_TRIANGLE_FAN, i * 4, 4);
}
xrot+=0.3f; // X 轴旋转
yrot+=0.2f; // Y 轴旋转
zrot+=0.4f; // Z 轴旋转
}
void MyGLWidget::initLighting()
{
GLfloat lightPos[] = { 75.0f, 0.0f, 0.0f, 1.0f };
GLfloat specular[] = { 1.0f, 1.0f, 1.0f, 1.0f};
GLfloat specref[] = { 1.0f, 1.0f, 1.0f, 1.0f };
GLfloat ambientLight[] = { 0.5f, 0.5f, 0.5f, 1.0f};
GLfloat spotDir[] = { 0.0f, 0.0f, -1.0f };
glEnable(GL_DEPTH_TEST); // Hidden surface removal
glFrontFace(GL_CCW); // Counterclockwise polygons face out
glEnable(GL_CULL_FACE); // Do not try to display the back sides
// Enable lighting
glEnable(GL_LIGHTING);
// Set up and enable light 0
// Supply a slight ambient light so the objects can be seen
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambientLight);
// The light is composed of just diffuse and specular components
glLightfv(GL_LIGHT0,GL_DIFFUSE,ambientLight);
glLightfv(GL_LIGHT0,GL_SPECULAR,specular);
glLightfv(GL_LIGHT0,GL_POSITION,lightPos);
// Specific spot effects
// Cut-off angle is 60 degrees
glLightf(GL_LIGHT0,GL_SPOT_CUTOFF,60.0f);
// Enable this light in particular
glEnable(GL_LIGHT0);
// Enable color tracking
glEnable(GL_COLOR_MATERIAL);
// Set material properties to follow glColor values
glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
// All materials hereafter have full specular reflectivity
// with a high shine
glMaterialfv(GL_FRONT, GL_SPECULAR,specref);
glMateriali(GL_FRONT, GL_SHININESS,128);
// Black background
glClearColor(0.0f, 0.0f, 0.0f, 1.0f );
}
void MyGLWidget::makeObject()
{
static const int coords[6][4][3] = {
{ { +1, -1, -1 }, { -1, -1, -1 }, { -1, +1, -1 }, { +1, +1, -1 } },
{ { +1, +1, -1 }, { -1, +1, -1 }, { -1, +1, +1 }, { +1, +1, +1 } },
{ { +1, -1, +1 }, { +1, -1, -1 }, { +1, +1, -1 }, { +1, +1, +1 } },
{ { -1, -1, -1 }, { -1, -1, +1 }, { -1, +1, +1 }, { -1, +1, -1 } },
{ { +1, -1, +1 }, { -1, -1, +1 }, { -1, -1, -1 }, { +1, -1, -1 } },
{ { -1, -1, +1 }, { +1, -1, +1 }, { +1, +1, +1 }, { -1, +1, +1 } }
};
for (int j=0; j < 6; ++j) {
textures[j] = bindTexture
(QPixmap(QString(":/images/side%1.png").arg(j + 1)), GL_TEXTURE_2D);
}
for (int i = 0; i < 6; ++i) {
for (int j = 0; j < 4; ++j) {
texCoords.append
(QVector2D(j == 0 || j == 3, j == 0 || j == 1));
vertices.append
(QVector3D(0.5 * coords[i][j][0], 0.5 * coords[i][j][1],
0.5 * coords[i][j][2]));
}
}
}
main.cpp
#include <QApplication>
#include "myglwidget.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MyGLWidget win ;
win.show();
return a.exec();
}
Android 版本:
MyRender.java
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLSurfaceView.Renderer;
import android.opengl.GLU;
import android.opengl.GLUtils;
public class MyRenderer implements Renderer {
public MyRenderer(Context ctx) {
mContext = ctx;
}
@Override
public void onDrawFrame(GL10 gl) {
// TODO Auto-generated method stub
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); // 清除屏幕和深度缓存
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity(); // 重置当前的模型观察矩阵
gl.glTranslatef(0, 0, 5);
gl.glRotatef(xrot,1.0f,0.0f,0.0f); // 绕X轴旋转
gl.glRotatef(yrot,0.0f,1.0f,0.0f); // 绕Y轴旋转
gl.glRotatef(zrot,0.0f,0.0f,1.0f); // 绕Z轴旋转
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, mTexBuffer);
for (int i = 0; i < 6; ++i) {
gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[i]);
gl.glDrawArrays(GL10.GL_TRIANGLE_FAN, i * 4, 4);
}
xrot+=0.3f; // X 轴旋转
yrot+=0.2f; // Y 轴旋转
zrot+=0.4f; // Z 轴旋转
}
@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
// TODO Auto-generated method stub
if (height==0) // 防止被零除
{
height=1; // 将Height设为1
}
gl.glViewport(0, 0, width, height); // 重置当前的视口
gl.glMatrixMode(GL10.GL_PROJECTION); // 选择投影矩阵
gl.glLoadIdentity(); // 重置投影矩阵
// 设置视口的大小
GLU.gluPerspective(gl, 45.0f,(float)width/(float)height,0.1f,100.0f);
GLU.gluLookAt(gl, 0, 0, -5, 0, 0, 0, 0, 1, 0);
gl.glMatrixMode(GL10.GL_MODELVIEW); // 选择模型观察矩阵
gl.glLoadIdentity(); // 重置模型观察矩阵
}
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
// TODO Auto-generated method stub
makeObject(gl);
initLigthing(gl);
gl.glEnable(GL10.GL_DEPTH_TEST);
gl.glEnable(GL10.GL_CULL_FACE);
gl.glFrontFace(GL10.GL_CW);
gl.glEnable(GL10.GL_TEXTURE_2D);
// gl.glEnable(GL10.GL_LIGHTING);
// gl.glEnable(GL10.GL_LIGHT0);
}
private int bindTexture(GL10 gl, int rsid) {
int[] textures = new int[1];
// 创建纹理
gl.glGenTextures(1, textures, 0);
gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER,
GL10.GL_NEAREST);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER,
GL10.GL_LINEAR);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S,
GL10.GL_CLAMP_TO_EDGE);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T,
GL10.GL_CLAMP_TO_EDGE);
gl.glTexEnvf(GL10.GL_TEXTURE_ENV, GL10.GL_TEXTURE_ENV_MODE,
GL10.GL_REPLACE);
InputStream is = mContext.getResources().openRawResource(rsid);
Bitmap bitmapTmp;
try {
bitmapTmp = BitmapFactory.decodeStream(is);
} finally {
try {
is.close();
} catch (IOException e) {
// Ignore.
}
}
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmapTmp, 0);
bitmapTmp.recycle();
return textures[0];
}
private void initLigthing(GL10 gl) {
float mat_specular[] = { 1.0f, 1.0f, 1.0f, 1.0f };
float mat_shininess[] = { 50.0f };
float light_position[] = { 0.0f, 0.0f, 1.0f, 0.0f };
float white_light[] = { 1.0f, 1.0f, 1.0f, 1.0f };
float lmodel_ambient[] = { 0.1f, 0.1f, 0.1f, 1.0f };
// gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
// gl.glShadeModel(GL10.GL_SMOOTH);
FloatBuffer specularBuffer;
ByteBuffer bb1 = ByteBuffer.allocateDirect(mat_specular.length * 4);
bb1.order(ByteOrder.nativeOrder());
specularBuffer = bb1.asFloatBuffer();
gl.glMaterialfv(GL10.GL_FRONT, GL10.GL_SPECULAR, specularBuffer);
FloatBuffer shininessBuffer;
ByteBuffer bb2 = ByteBuffer.allocateDirect(mat_shininess.length * 4);
bb2.order(ByteOrder.nativeOrder());
shininessBuffer = bb2.asFloatBuffer();
gl.glMaterialfv(GL10.GL_FRONT, GL10.GL_SHININESS, shininessBuffer);
FloatBuffer positionBuffer;
ByteBuffer bb3 = ByteBuffer.allocateDirect(light_position.length * 4);
bb3.order(ByteOrder.nativeOrder());
positionBuffer = bb3.asFloatBuffer();
gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_POSITION, positionBuffer);
FloatBuffer lightBuffer;
ByteBuffer bb4 = ByteBuffer.allocateDirect(white_light.length * 4);
bb4.order(ByteOrder.nativeOrder());
lightBuffer = bb4.asFloatBuffer();
gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_DIFFUSE, lightBuffer);
gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_SPECULAR, lightBuffer);
FloatBuffer ambientBuffer;
ByteBuffer bb5 = ByteBuffer.allocateDirect(lmodel_ambient.length * 4);
bb5.order(ByteOrder.nativeOrder());
ambientBuffer = bb5.asFloatBuffer();
gl.glLightModelfv(GL10.GL_LIGHT_MODEL_AMBIENT, ambientBuffer);
gl.glEnable(GL10.GL_LIGHTING);
gl.glEnable(GL10.GL_LIGHT0);
}
private void makeObject(GL10 gl) {
float []vertices = {
//底部
+1, -1, -1 ,
-1, -1, -1 ,
-1, +1, -1 ,
+1, +1, -1 ,
//后面
+1, +1, -1 ,
-1, +1, -1 ,
-1, +1, +1 ,
+1, +1, +1 ,
//右面
+1, -1, +1 ,
+1, -1, -1 ,
+1, +1, -1 ,
+1, +1, +1 ,
//左面
-1, -1, -1 ,
-1, -1, +1 ,
-1, +1, +1 ,
-1, +1, -1 ,
//前面
+1, -1, +1 ,
-1, -1, +1 ,
-1, -1, -1 ,
+1, -1, -1 ,
//顶面
-1, -1, +1 ,
+1, -1, +1 ,
+1, +1, +1 ,
-1, +1, +1
};
for (int i = 0; i < vertices.length; i++)
vertices[i] = (float) (0.5 * vertices[i]);
float []texcoords = {
// 前面
0.0f, 0.0f, // 纹理左下
1.0f, 0.0f, // 纹理右下
1.0f, 1.0f, // 纹理右上
0.0f, 1.0f, // 纹理左上
// 后面
1.0f, 0.0f, // 纹理右下
1.0f, 1.0f, // 纹理右上
0.0f, 1.0f, // 纹理左上
0.0f, 0.0f, // 纹理左下
// 顶面
0.0f, 1.0f, // 纹理左上
0.0f, 0.0f, // 纹理左下
1.0f, 0.0f, // 纹理右下
1.0f, 1.0f, // 纹理右上
// 底面
1.0f, 1.0f, // 纹理右上
0.0f, 1.0f, // 纹理左上
0.0f, 0.0f, // 纹理左下
1.0f, 0.0f, // 纹理右下
// 右面
1.0f, 0.0f, // 纹理右下
1.0f, 1.0f, // 纹理右上
0.0f, 1.0f, // 纹理左上
0.0f, 0.0f, // 纹理左下
// 左面
0.0f, 0.0f, // 纹理左下
1.0f, 0.0f, // 纹理右下
1.0f, 1.0f, // 纹理右上
0.0f, 1.0f // 纹理左上
};
int[] rids = { R.raw.side1, R.raw.side2, R.raw.side3, R.raw.side4, R.raw.side5, R.raw.side6 };
textures = new int[6];
for (int j=0; j < 6; ++j) {
textures[j] = bindTexture(gl, rids[j]);
}
ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length * 4);
vbb.order(ByteOrder.nativeOrder());
vertexBuffer = vbb.asFloatBuffer();
vertexBuffer.put(vertices);
vertexBuffer.position(0);
ByteBuffer tbb = ByteBuffer.allocateDirect(texcoords.length * 4);
tbb.order(ByteOrder.nativeOrder());
mTexBuffer = tbb.asFloatBuffer();
mTexBuffer.put(texcoords);
mTexBuffer.position(0);
}
private int textures[];
private FloatBuffer vertexBuffer;
private FloatBuffer mTexBuffer;
private Context mContext;
private static final float PI = 3.1415f;
private float xrot = 0;
private float yrot = 0;
private float zrot = 0;
}
Activity
import android.app.Activity;
import android.opengl.GLSurfaceView;
import android.os.Bundle;
public class TextureTestActivity extends Activity {
private GLSurfaceView mView;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mView = new GLSurfaceView(this);
mView.setRenderer(new MyRenderer(this));
setContentView(mView);
}
@Override
protected void onResume() {
super.onResume();
mView.onResume();
}
@Override
protected void onPause() {
super.onPause();
mView.onPause();
}
}
924

被折叠的 条评论
为什么被折叠?



