3D立方体及光照

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

 

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();
	}
    
}


 

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值