雾的实现以及Opengl的数组存储与java不同的工具包BufferUtil的实现

一、雾和流动红旗的形成,Render类如下:

package com.example.user.flagdemo;
 
import android.graphics.Bitmap;
import android.opengl.GLSurfaceView;
import android.opengl.GLUtils;
 
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
 
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
 
/**
* Created by user on 2016/9/14.
*/
public class GLRendererfog implements GLSurfaceView.Renderer {
 
int textureSize = 2;
int texture[] = new int [textureSize];
private Bitmap mBitmap[];
Point [][] points = new Point[45][45];
private int wiggle_count=0;
 
//设置雾的属性参数
int fogMode[]= { GL10.GL_EXP, GL10.GL_EXP2, GL10.GL_LINEAR }; // 雾气的模式
int fogfilter= 1; // 使用哪一种雾气
float fogColor[]= {0.5f, 0.5f, 0.0f, 1.0f}; // 雾的颜色设为白色
 
public GLRendererfog(Bitmap mBitmap[])
{
this.mBitmap = mBitmap;
}
 
 
 
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
// 黑色背景
gl.glClearColor(0, 0, 0, 0);
// 启用阴影平滑
gl.glShadeModel(GL10.GL_SMOOTH);
// 启用深度测试
gl.glEnable(GL10.GL_DEPTH_TEST);
 
 
gl.glFogx(GL10.GL_FOG_MODE, fogMode[fogfilter]); // 设置雾气的模式
gl.glFogfv(GL10.GL_FOG_COLOR, fogColor,0); // 设置雾的颜色
gl.glFogf(GL10.GL_FOG_DENSITY, 0.1f); // 设置雾的密度
gl.glHint(GL10.GL_FOG_HINT, GL10.GL_DONT_CARE); // 设置系统如何计算雾气
gl.glFogf(GL10.GL_FOG_START, 1.0f); // 雾气的开始位置
gl.glFogf(GL10.GL_FOG_END, 5.0f); // 雾气的结束位置
gl.glEnable(GL10.GL_FOG); // 使用雾气
 
// 启用混合模式
gl.glEnable(GL10.GL_BLEND);
gl.glDisable(GL10.GL_DEPTH_TEST); // 关闭深度测试
//设置光线,,1.0f为全光线,a=50%
gl.glColor4f(1.0f,1.0f,1.0f,0.5f);
// 基于源象素alpha通道值的半透明混合函数
gl.glBlendFunc(GL10.GL_SRC_ALPHA,GL10.GL_ONE);
 
//启用纹理映射
gl.glClearDepthf(1.0f);
//深度测试的类型
gl.glDepthFunc(GL10.GL_LEQUAL);
//精细的透视修正
gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST);
//允许2D贴图,纹理
gl.glEnable(GL10.GL_TEXTURE_2D);
getTextures(gl);
getPoints();
 
 
// //设置光颜色
// FloatBuffer lightAmbient = BufferUtil.floatToBuffer(new float[]{
// 1f, 1f, 1f, 1f
// } );
// FloatBuffer lightDiffuse = BufferUtil.floatToBuffer(new float[]{
// 1f,1f,1f,1f
// } );
// //定义光源位置
// FloatBuffer lightPosition = BufferUtil.floatToBuffer(new float[]{
// -2f,0f,-4f,1f
// } );
//
//// //设置环境光
// gl.glLightfv(GL10.GL_LIGHT1, GL10.GL_AMBIENT, lightAmbient);
//
// //设置漫射光
// gl.glLightfv(GL10.GL_LIGHT1, GL10.GL_DIFFUSE, lightDiffuse);
//
// //设置光源位置
// gl.glLightfv(GL10.GL_LIGHT1, GL10.GL_POSITION, lightPosition);
//
// //开启一号光源
// gl.glEnable(GL10.GL_LIGHT1);
}
 
@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
float ratio = (float) width / height;
//设置OpenGL场景的大小
gl.glViewport(0, 0, width, height);
//设置投影矩阵
gl.glMatrixMode(GL10.GL_PROJECTION);
//重置投影矩阵
gl.glLoadIdentity();
// 设置视口的大小
gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10);
// 选择模型观察矩阵
gl.glMatrixMode(GL10.GL_MODELVIEW);
// 重置模型观察矩阵
gl.glLoadIdentity();
}
 
@Override
public void onDrawFrame(GL10 gl) {
// 清除屏幕和深度缓存
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
// 重置当前的模型观察矩阵
// gl.glEnable(GL10.GL_LIGHTING);
 
gl.glLoadIdentity();
gl.glTranslatef(0f , 0f , -9f);
 
FloatBuffer texCoords2 = BufferUtil.getFloatBuffer(8);
FloatBuffer vertices2 = BufferUtil.getFloatBuffer(12);;
 
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);//启用纹理映射
gl.glBindTexture(GL10.GL_TEXTURE_2D, texture[0]);
 
for (int x = 0; x < 44; x++){
for (int y = 0; y < 44; y++) {
 
//文理映射,每个点在纹理中的映射位置,文理的大小为1f
float float_x = (float) (x) / 44.0f; //生成 x 浮点值
float float_y = (float) (y) / 44.0f; //生成 Y 浮点位
float float_xb = (float) (x + 1) / 44.0f; // x 浮点值+0.0227f
float float_yb = (float) (y + 1) / 44.0f; // Y 浮点值+0.0227f
vertices2.clear();
vertices2.put(points[x][y].x);
vertices2.put(points[x][y].y);
vertices2.put(points[x][y].z);
vertices2.put(points[x][y + 1].x);
vertices2.put( points[x][y + 1].y);
vertices2.put( points[x][y + 1].z);
vertices2.put( points[x + 1][y + 1].x);
vertices2.put(points[x + 1][y + 1].y);
vertices2.put(points[x + 1][y + 1].z);
vertices2.put( points[x + 1][y].x);
vertices2.put( points[x + 1][y].y);
vertices2.put( points[x + 1][y].z);
//position是当前访问位置,因此每次put后position都是指向存储的位置的,绘图点映射必须从头开始的
vertices2.position(0);
 
texCoords2.clear();
texCoords2.put(float_x);
texCoords2.put(1 - float_y);
texCoords2.put(float_x);
texCoords2.put(1 - float_yb);
texCoords2.put( float_xb);
texCoords2.put( 1 - float_yb);
texCoords2.put( float_xb);
texCoords2.put( 1 - float_y);
texCoords2.position(0);
 
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertices2);
gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, texCoords2);
gl.glDrawArrays(GL10.GL_TRIANGLE_FAN, 0, 4);
}
}
wiggle_count++;
gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
//两帧渲染一次,正弦改变z坐标的值让红旗飘动 
float hold;
if(wiggle_count == 2)
{
for( int y = 0; y < 45; y++ )//沿 Y 平面循环
{
hold = points[0][y].z; //存储当前左侧波浪值
for (int x = 0; x < 44; x++)// 沿 x 乎面循环
{ // 当前波浪值等于其右侧的波浪值
points[x][y].z = points[x + 1][y].z;
}
points[44][y].z = hold; //刚才的位成为最左侧的波浪值
wiggle_count = 0; //计数器清零
}
wiggle_count = 0;
}
 
}
private void getTextures(GL10 gl)
{
IntBuffer intBuffer = IntBuffer.allocate(2);//申请2个纹理存储空间
// 创建纹理
gl.glGenTextures(2 , intBuffer); //创建2个纹理,绑定intuffer
texture[0] = intBuffer.get(); // 获取第一个纹理的存储指针,即纹理存储位置,位置+1
texture[1] = intBuffer.get(); //获取下一个纹理存储的位置
 
// 设置要使用的纹理
gl.glBindTexture(GL10.GL_TEXTURE_2D, texture[0]);
//生成纹理
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0 , mBitmap[0] , 0);//利用图mBitmap[0]生成纹理,存储在texture[0]
// 线形滤波
gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR);
gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
 
//生成第二个纹理
gl.glBindTexture(GL10.GL_TEXTURE_2D, texture[1]);
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0 , mBitmap[1] , 0);//利用图mBitmap[0]生成纹理,存储在texture[1]
gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR);
gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
 
}
 
public Point getPoint(int x,int y)
{
float x1=( (float)x/5.0f) -4.5f ;
float y1= ( ((float)y/5.0f)- 4.5f );
float z1 = (float) (Math.sin(((((float)x/5.0f) *40.0f)/360.0f)*
3.141592654*2.0f));
return new Point(x1,y1,z1);
}
 
public void getPoints() {
for (int x = 0; x < 45; x++)
for (int y = 0; y < 45; y++)
{
points[x][y] = getPoint( x, y);
}
}
}
 
notice:1、正弦改变z的坐标来实现红旗飘动的。
              2、当向buffer里put值时候,position的值就会自动加1,因此当存完了buffer里的值时候要将position置为0,让绘图的时候可以读取所有的点信息
 
二、将java数组或者缓冲区转化为opengl的存储方式的工具类:
package com.example.user.flagdemo;
 
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
 
/**
* Created by lenovo on 2016/9/6.
*/
public class BufferUtil {
 
 
public static FloatBuffer floatToBuffer(float[] a) {
//先初始化buffer,数组的长度*4,因为一个float占4个字节
ByteBuffer mbb = ByteBuffer.allocateDirect(a.length * 4);
//数组排序用nativeOrder,根据本地的排列顺序,指定存储方式,是1. Little endian(小头):将低序字节存储在起始地址
// 2. Big endian(大头):将高序字节存储在起始地址
mbb.order(ByteOrder.nativeOrder());
FloatBuffer mBuffer = mbb.asFloatBuffer();
mBuffer.put(a);
mBuffer.position(0);
return mBuffer;
}
// 将数组a转化为intbuffer
public static IntBuffer intToBuffer(int[] a) {
//先初始化buffer,数组的长度*4,因为一个float占4个字节
ByteBuffer mbb = ByteBuffer.allocateDirect(a.length * 4);
//数组排序用nativeOrder
mbb.order(ByteOrder.nativeOrder());
IntBuffer mBuffer2 = mbb.asIntBuffer();
mBuffer2.put(a);
mBuffer2.position(0);
return mBuffer2;
}
 
public static FloatBuffer getFloatBuffer(int length)
{
ByteBuffer mbb = ByteBuffer.allocateDirect(length * 4);
mbb.order(ByteOrder.nativeOrder());
FloatBuffer mBuffer = mbb.asFloatBuffer();
mBuffer.position(0);
return mBuffer;
}
 
public static IntBuffer getIntBuffer(int length)
{
ByteBuffer mbb = ByteBuffer.allocateDirect(length * 4);
mbb.order(ByteOrder.nativeOrder());
IntBuffer mBuffer = mbb.asIntBuffer();
mBuffer.position(0);
return mBuffer;
}
 
 
}
 
class Point{
float x;
float y;
float z;
public Point(float x, float y , float z)
{
this.x=x;
this.y=y;
this.z=z;
}
 
}
 前面2个方法是将java的float和int数组转化为对应的opengl存储方式的缓冲区,后面的2个方法是定义相对应的一定长度的opengl存储的对应的缓冲区
 
原文地址:https://www.cnblogs.com/bokeofzp/p/5967490.html