3D立方体及光照

来源:互联网 发布:cms源码 编辑:程序博客网 时间:2024/06/10 15:53

 本代码主要实现了一个旋转立方体, 并添加了光照效果。

 

Qt 版:

myglwidget.h

#ifndef MYGLWIDGET_H#define MYGLWIDGET_H#include <QGLWidget>#include <QVector2D>#include <QVector3D>#include <QTimer>class MyGLWidget : public QGLWidget{    Q_OBJECTpublic:    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();    GLfloatxrot;// X 旋转量    GLfloatyrot;// Y 旋转量    GLfloatzrot;// Z 旋转量    GLuinttextures[6];// 存储一个纹理    QVector<QVector3D> vertices;    QVector<QVector2D> texCoords;    QTimer *timer;};#endif // MYGLWIDGET_H


myglwidget.cpp

#include "myglwidget.h"#ifndef GL_MULTISAMPLE#define GL_MULTISAMPLE  0x809D#endifMyGLWidget::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;}@Overridepublic 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 轴旋转}@Overridepublic 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();// 重置模型观察矩阵}@Overridepublic void onSurfaceCreated(GL10 gl, EGLConfig config) {// TODO Auto-generated method stubmakeObject(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);    }    @Overrideprotected void onResume() {super.onResume();mView.onResume();}@Overrideprotected void onPause() {super.onPause();mView.onPause();}    }