初次提交

This commit is contained in:
2022-09-19 18:05:01 +08:00
commit 57051fc44b
5401 changed files with 325410 additions and 0 deletions

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="src" path="gen"/>
<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
<classpathentry kind="output" path="bin"/>
</classpath>

View File

@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>Sample13_4</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>com.android.ide.eclipse.adt.ApkBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>com.android.ide.eclipse.adt.AndroidNature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

View File

@@ -0,0 +1,12 @@
#Wed Jan 05 21:56:15 CST 2011
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=1.6
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.source=1.6

View File

@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
android:versionCode="1"
android:versionName="1.0" package="com.bn.Sample13_4">
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".Sample13_4_Activity"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
<uses-sdk android:targetSdkVersion="8"></uses-sdk>
</manifest>

View File

@@ -0,0 +1,10 @@
precision mediump float;
uniform sampler2D sTexture;//纹理内容数据
//接收从顶点着色器过来的参数
varying vec2 vTextureCoord;
void main()
{
//给此片元颜色值
gl_FragColor = texture2D(sTexture, vTextureCoord);
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,22 @@
uniform mat4 uMVPMatrix; //总变换矩阵
attribute vec3 aPosition; //顶点位置
attribute vec3 bPosition; //顶点位置
attribute vec3 cPosition; //顶点位置
attribute vec2 aTexCoor; //顶点纹理坐标
uniform float uBfb;//变化百分比
varying vec2 vTextureCoord;
void main()
{
vec3 tv;
if(uBfb<=1.0)
{
tv=mix(aPosition,bPosition,uBfb);
}
else
{
tv=mix(bPosition,cPosition,uBfb-1.0);
}
gl_Position = uMVPMatrix * vec4(tv,1);
vTextureCoord = aTexCoor;//将接收的纹理坐标传递给片元着色器
}

View File

@@ -0,0 +1,13 @@
# This file is automatically generated by Android Tools.
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
#
# This file must be checked in Version Control Systems.
#
# To customize properties used by the Ant build system use,
# "build.properties", and override values to adapt the script to your
# project structure.
# Indicates whether an apk should be generated for each density.
split.density=false
# Project target.
target=android-8

View File

@@ -0,0 +1,20 @@
/* AUTO-GENERATED FILE. DO NOT MODIFY.
*
* This class was automatically generated by the
* aapt tool from the resource data it found. It
* should not be modified by hand.
*/
package com.bn.Sample13_4;
public final class R {
public static final class attr {
}
public static final class drawable {
public static final int icon=0x7f020000;
public static final int ttt=0x7f020001;
}
public static final class string {
public static final int app_name=0x7f030000;
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">Sample13_4</string>
</resources>

View File

@@ -0,0 +1,10 @@
package com.bn.Sample13_4;
//常量类
public class Constant
{
public static final float MAX_S_QHC=1.0f;//青花瓷最大S纹理坐标
public static final float MAX_T_QHC=0.746f;//青花瓷最大T纹理坐标
public static final float MAX_S_GHXP=1.0f;//国画小品最大S纹理坐标
public static final float MAX_T_GHXP=1.0f;//国画小品最大T纹理坐标
}

View File

@@ -0,0 +1,198 @@
package com.bn.Sample13_4;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import android.opengl.GLES20;
//加载后的物体——仅携带顶点信息,颜色随机
public class GledeForDraw
{
int mProgram;//自定义渲染管线着色器程序id
int muMVPMatrixHandle;//总变换矩阵引用
int maPositionHandle1; //顶点位置属性引用
int maPositionHandle2; //顶点位置属性引用
int maPositionHandle3; //顶点位置属性引用
int maTexCoorHandle; //顶点纹理坐标属性引用
int muBfbHandle;//变化百分比引用
String mVertexShader;//顶点着色器代码脚本
String mFragmentShader;//片元着色器代码脚本
FloatBuffer mVertexBuffer1;//顶点坐标数据缓冲
FloatBuffer mVertexBuffer2;//顶点坐标数据缓冲
FloatBuffer mVertexBuffer3;//顶点坐标数据缓冲
FloatBuffer mTexCoorBuffer;//顶点纹理坐标数据缓冲
float[][] glede_one;
float[] glede_two;
float[] glede_three;
int vCount=0;
int operator=1;
float span=0.15f;
float bfbCurr=0f;
public GledeForDraw(MySurfaceView mv)
{
//初始化顶点坐标与着色数据
initVertexData(mv);
//初始化shader
intShader(mv);
new Thread()
{
@Override
public void run()
{
while(true)
{
bfbCurr=bfbCurr+operator*span;
if(bfbCurr>2.0f)
{
bfbCurr=2.0f;
operator=-operator;
}
else if(bfbCurr<0)
{
bfbCurr=0;
operator=-operator;
}
try
{
Thread.sleep(50);
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
}.start();
}
//初始化顶点坐标与着色数据的方法
public void initVertexData(MySurfaceView mv)
{
glede_one=LoadUtil.loadFromFileVertexOnly("laoying01.obj",mv);
glede_two=LoadUtil.loadFromFileVertexOnly("laoying02.obj",mv)[0];
glede_three=LoadUtil.loadFromFileVertexOnly("laoying03.obj",mv)[0];
//========================1=========================================
vCount=glede_one.length/3;
//创建顶点坐标数据缓冲
//vertices.length*4是因为一个整数四个字节
ByteBuffer vbb = ByteBuffer.allocateDirect(glede_one[0].length*4);
vbb.order(ByteOrder.nativeOrder());//设置字节顺序
mVertexBuffer1 = vbb.asFloatBuffer();//转换为Float型缓冲
mVertexBuffer1.put(glede_one[0]);//向缓冲区中放入顶点坐标数据
mVertexBuffer1.position(0);//设置缓冲区起始位置
//====================2==========================
vCount=glede_two.length/3;
//创建顶点坐标数据缓冲
//vertices.length*4是因为一个整数四个字节
vbb = ByteBuffer.allocateDirect(glede_two.length*4);
vbb.order(ByteOrder.nativeOrder());//设置字节顺序
mVertexBuffer2 = vbb.asFloatBuffer();//转换为Float型缓冲
mVertexBuffer2.put(glede_two);//向缓冲区中放入顶点坐标数据
mVertexBuffer2.position(0);//设置缓冲区起始位置
//---------------------------------3-----------------------------
vCount=glede_three.length/3;
//创建顶点坐标数据缓冲
//vertices.length*4是因为一个整数四个字节
vbb = ByteBuffer.allocateDirect(glede_three.length*4);
vbb.order(ByteOrder.nativeOrder());//设置字节顺序
mVertexBuffer3 = vbb.asFloatBuffer();//转换为Float型缓冲
mVertexBuffer3.put(glede_three);//向缓冲区中放入顶点坐标数据
mVertexBuffer3.position(0);//设置缓冲区起始位置
//------------------纹理-----------------------------------------
ByteBuffer tbb = ByteBuffer.allocateDirect(glede_one[1].length*4);
tbb.order(ByteOrder.nativeOrder());//设置字节顺序
mTexCoorBuffer = tbb.asFloatBuffer();//转换为Float型缓冲
mTexCoorBuffer.put(glede_one[1]);//向缓冲区中放入顶点纹理坐标数据
mTexCoorBuffer.position(0);//设置缓冲区起始位置
//特别提示由于不同平台字节顺序不同数据单元不是字节的一定要经过ByteBuffer
//转换关键是要通过ByteOrder设置nativeOrder(),否则有可能会出问题
//顶点纹理坐标数据的初始化================end============================
}
//初始化shader
public void intShader(MySurfaceView mv)
{
//加载顶点着色器的脚本内容
mVertexShader=ShaderUtil.loadFromAssetsFile("vertex.sh", mv.getResources());
//加载片元着色器的脚本内容
mFragmentShader=ShaderUtil.loadFromAssetsFile("frag.sh", mv.getResources());
//基于顶点着色器与片元着色器创建程序
mProgram = ShaderUtil.createProgram(mVertexShader, mFragmentShader);
//获取程序中顶点位置属性引用
maPositionHandle1 = GLES20.glGetAttribLocation(mProgram, "aPosition");
maPositionHandle2 = GLES20.glGetAttribLocation(mProgram, "bPosition");
maPositionHandle3 = GLES20.glGetAttribLocation(mProgram, "cPosition");
//获取程序中总变换矩阵引用
muMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
//获取程序中顶点纹理坐标属性引用
maTexCoorHandle= GLES20.glGetAttribLocation(mProgram, "aTexCoor");
//变化百分比引用
muBfbHandle= GLES20.glGetUniformLocation(mProgram, "uBfb");
}
public void drawSelf(int texId)
{
//制定使用某套shader程序
GLES20.glUseProgram(mProgram);
//将最终变换矩阵传入shader程序
GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, MatrixState.getFinalMatrix(), 0);
//将变化百分比传入shader程序
GLES20.glUniform1f(muBfbHandle, bfbCurr);
System.out.println(bfbCurr);
//将顶点位置数据
GLES20.glVertexAttribPointer
(
maPositionHandle1,
3,
GLES20.GL_FLOAT,
false,
3*4,
mVertexBuffer1
);
//将顶点位置数据
GLES20.glVertexAttribPointer
(
maPositionHandle2,
3,
GLES20.GL_FLOAT,
false,
3*4,
mVertexBuffer2
);
//将顶点位置数据传入渲染管线
GLES20.glVertexAttribPointer
(
maPositionHandle3,
3,
GLES20.GL_FLOAT,
false,
3*4,
mVertexBuffer3
);
//将顶点纹理坐标数据传入渲染管线
GLES20.glVertexAttribPointer
(
maTexCoorHandle,
2,
GLES20.GL_FLOAT,
false,
2*4,
mTexCoorBuffer
);
//启用顶点位置、法向量、纹理坐标数据
GLES20.glEnableVertexAttribArray(maPositionHandle1);
GLES20.glEnableVertexAttribArray(maPositionHandle2);
GLES20.glEnableVertexAttribArray(maPositionHandle3);
GLES20.glEnableVertexAttribArray(maTexCoorHandle);
//绑定纹理
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texId);
//绘制加载的物体
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vCount);
}
}

View File

@@ -0,0 +1,131 @@
package com.bn.Sample13_4;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import android.util.Log;
import static com.bn.Sample13_4.Constant.*;
public class LoadUtil
{
//从obj文件中加载携带顶点信息的物体并自动计算每个顶点的平均法向量
public static float[][] loadFromFileVertexOnly(String fname,MySurfaceView mv)
{
float [][] gledeInfo=new float[2][];
//原始顶点坐标列表--直接从obj文件中加载
ArrayList<Float> alv=new ArrayList<Float>();
//顶点组装面索引列表--根据面的信息从文件中加载
ArrayList<Integer> alFaceIndex=new ArrayList<Integer>();
//结果顶点坐标列表--按面组织好
ArrayList<Float> alvResult=new ArrayList<Float>();
//平均前各个索引对应的点的法向量集合Map
//原始纹理坐标列表
ArrayList<Float> alt=new ArrayList<Float>();
//纹理坐标结果列表
ArrayList<Float> altResult=new ArrayList<Float>();
try
{
InputStream in=mv.getResources().getAssets().open(fname);
InputStreamReader isr=new InputStreamReader(in);
BufferedReader br=new BufferedReader(isr);
String temps=null;
//扫面文件,根据行类型的不同执行不同的处理逻辑
while((temps=br.readLine())!=null)
{
//用空格分割行中的各个组成部分
String[] tempsa=temps.split("[ ]+");
if(tempsa[0].trim().equals("v"))
{//此行为顶点坐标
//若为顶点坐标行则提取出此顶点的XYZ坐标添加到原始顶点坐标列表中
alv.add(Float.parseFloat(tempsa[1]));
alv.add(Float.parseFloat(tempsa[2]));
alv.add(Float.parseFloat(tempsa[3]));
}
else if(tempsa[0].trim().equals("vt"))
{
alt.add(Float.parseFloat(tempsa[1])*MAX_S_GHXP);
alt.add(Float.parseFloat(tempsa[2])*MAX_T_GHXP);
}
else if(tempsa[0].trim().equals("f"))
{
int[] index=new int[3];//三个顶点索引值的数组
//计算第0个顶点的索引并获取此顶点的XYZ三个坐标
index[0]=Integer.parseInt(tempsa[1].split("/")[0])-1;
float x0=alv.get(3*index[0]);
float y0=alv.get(3*index[0]+1);
float z0=alv.get(3*index[0]+2);
alvResult.add(x0);
alvResult.add(y0);
alvResult.add(z0);
//计算第1个顶点的索引并获取此顶点的XYZ三个坐标
index[1]=Integer.parseInt(tempsa[2].split("/")[0])-1;
float x1=alv.get(3*index[1]);
float y1=alv.get(3*index[1]+1);
float z1=alv.get(3*index[1]+2);
alvResult.add(x1);
alvResult.add(y1);
alvResult.add(z1);
//计算第2个顶点的索引并获取此顶点的XYZ三个坐标
index[2]=Integer.parseInt(tempsa[3].split("/")[0])-1;
float x2=alv.get(3*index[2]);
float y2=alv.get(3*index[2]+1);
float z2=alv.get(3*index[2]+2);
alvResult.add(x2);
alvResult.add(y2);
alvResult.add(z2);
//记录此面的顶点索引
alFaceIndex.add(index[0]);
alFaceIndex.add(index[1]);
alFaceIndex.add(index[2]);
//将纹理坐标组织到结果纹理坐标列表中
//第0个顶点的纹理坐标
int indexTex=Integer.parseInt(tempsa[1].split("/")[1])-1;
altResult.add(alt.get(indexTex*2));
altResult.add(alt.get(indexTex*2+1));
//第1个顶点的纹理坐标
indexTex=Integer.parseInt(tempsa[2].split("/")[1])-1;
altResult.add(alt.get(indexTex*2));
altResult.add(alt.get(indexTex*2+1));
//第2个顶点的纹理坐标
indexTex=Integer.parseInt(tempsa[3].split("/")[1])-1;
altResult.add(alt.get(indexTex*2));
altResult.add(alt.get(indexTex*2+1));
}
}
//生成顶点数组
int size=alvResult.size();
float[] vXYZ=new float[size];
for(int i=0;i<size;i++)
{
vXYZ[i]=alvResult.get(i);
}
//生成纹理数组
size=altResult.size();
float[] tST=new float[size];
for(int i=0;i<size;i++)
{
if(i%2==1){
tST[i]=1-altResult.get(i);
}else
tST[i]=altResult.get(i);
}
gledeInfo[0]=vXYZ;
gledeInfo[1]=tST;
}
catch(Exception e)
{
Log.d("load error", "load error");
e.printStackTrace();
}
return gledeInfo;
}
}

View File

@@ -0,0 +1,144 @@
package com.bn.Sample13_4;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.util.*;
import android.opengl.Matrix;
//存储系统矩阵状态的类
public class MatrixState
{
private static float[] mProjMatrix = new float[16];//4x4矩阵 投影用
private static float[] mVMatrix = new float[16];//摄像机位置朝向9参数矩阵
private static float[] currMatrix;//当前变换矩阵
public static float[] lightLocation=new float[]{0,0,0};//定位光光源位置
public static FloatBuffer cameraFB;
public static FloatBuffer lightPositionFB;
public static Stack<float[]> mStack=new Stack<float[]>();//保护变换矩阵的栈
public static void setInitStack()//获取不变换初始矩阵
{
currMatrix=new float[16];
Matrix.setRotateM(currMatrix, 0, 0, 1, 0, 0);
}
public static void pushMatrix()//保护变换矩阵
{
mStack.push(currMatrix.clone());
}
public static void popMatrix()//恢复变换矩阵
{
currMatrix=mStack.pop();
}
public static void translate(float x,float y,float z)//设置沿xyz轴移动
{
Matrix.translateM(currMatrix, 0, x, y, z);
}
public static void rotate(float angle,float x,float y,float z)//设置绕xyz轴移动
{
Matrix.rotateM(currMatrix,0,angle,x,y,z);
}
//设置摄像机
public static void setCamera
(
float cx, //摄像机位置x
float cy, //摄像机位置y
float cz, //摄像机位置z
float tx, //摄像机目标点x
float ty, //摄像机目标点y
float tz, //摄像机目标点z
float upx, //摄像机UP向量X分量
float upy, //摄像机UP向量Y分量
float upz //摄像机UP向量Z分量
)
{
Matrix.setLookAtM
(
mVMatrix,
0,
cx,
cy,
cz,
tx,
ty,
tz,
upx,
upy,
upz
);
float[] cameraLocation=new float[3];//摄像机位置
cameraLocation[0]=cx;
cameraLocation[1]=cy;
cameraLocation[2]=cz;
ByteBuffer llbb = ByteBuffer.allocateDirect(3*4);
llbb.order(ByteOrder.nativeOrder());//设置字节顺序
cameraFB=llbb.asFloatBuffer();
cameraFB.put(cameraLocation);
cameraFB.position(0);
}
//设置透视投影参数
public static void setProjectFrustum
(
float left, //near面的left
float right, //near面的right
float bottom, //near面的bottom
float top, //near面的top
float near, //near面距离
float far //far面距离
)
{
Matrix.frustumM(mProjMatrix, 0, left, right, bottom, top, near, far);
}
//设置正交投影参数
public static void setProjectOrtho
(
float left, //near面的left
float right, //near面的right
float bottom, //near面的bottom
float top, //near面的top
float near, //near面距离
float far //far面距离
)
{
Matrix.orthoM(mProjMatrix, 0, left, right, bottom, top, near, far);
}
//获取具体物体的总变换矩阵
public static float[] getFinalMatrix()
{
float[] mMVPMatrix=new float[16];
Matrix.multiplyMM(mMVPMatrix, 0, mVMatrix, 0, currMatrix, 0);
Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, mMVPMatrix, 0);
return mMVPMatrix;
}
//获取具体物体的变换矩阵
public static float[] getMMatrix()
{
return currMatrix;
}
//设置灯光位置的方法
public static void setLightLocation(float x,float y,float z)
{
lightLocation[0]=x;
lightLocation[1]=y;
lightLocation[2]=z;
ByteBuffer llbb = ByteBuffer.allocateDirect(3*4);
llbb.order(ByteOrder.nativeOrder());//设置字节顺序
lightPositionFB=llbb.asFloatBuffer();
lightPositionFB.put(lightLocation);
lightPositionFB.position(0);
}
}

View File

@@ -0,0 +1,156 @@
package com.bn.Sample13_4;
import java.io.IOException;
import java.io.InputStream;
import android.opengl.GLSurfaceView;
import android.opengl.GLES20;
import android.opengl.GLUtils;
import android.view.MotionEvent;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import com.bn.Sample13_4.R;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
class MySurfaceView extends GLSurfaceView
{
private final float TOUCH_SCALE_FACTOR = 180.0f/320;//角度缩放比例
private SceneRenderer mRenderer;//场景渲染器
private float mPreviousY;//上次的触控位置Y坐标
private float mPreviousX;//上次的触控位置X坐标
int textureId;//系统分配的纹理id
public MySurfaceView(Context context) {
super(context);
this.setEGLContextClientVersion(2); //设置使用OPENGL ES2.0
mRenderer = new SceneRenderer(); //创建场景渲染器
setRenderer(mRenderer); //设置渲染器
setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);//设置渲染模式为主动渲染
this.setKeepScreenOn(true);
}
//触摸事件回调方法
@Override
public boolean onTouchEvent(MotionEvent e)
{
float y = e.getY();
float x = e.getX();
switch (e.getAction()) {
case MotionEvent.ACTION_MOVE:
float dy = y - mPreviousY;//计算触控笔Y位移
float dx = x - mPreviousX;//计算触控笔X位移
mRenderer.yAngle += dx * TOUCH_SCALE_FACTOR;//设置沿x轴旋转角度
mRenderer.zAngle+= dy * TOUCH_SCALE_FACTOR;//设置沿z轴旋转角度
requestRender();//重绘画面
}
mPreviousY = y;//记录触控笔位置
mPreviousX = x;//记录触控笔位置
return true;
}
private class SceneRenderer implements GLSurfaceView.Renderer
{
float yAngle;//绕Y轴旋转的角度
float zAngle; //绕Z轴旋转的角度
//从指定的obj文件中加载对象
GledeForDraw glede1;
public void onDrawFrame(GL10 gl)
{
//清除深度缓冲与颜色缓冲
GLES20.glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
//坐标系推远
MatrixState.pushMatrix();
MatrixState.translate(0, -5f, -40f);
//绕Y轴、Z轴旋转
MatrixState.rotate(yAngle, 0, 1, 0);
MatrixState.rotate(zAngle, 1, 0, 0);
//若加载的物体部位空则绘制物体
if(glede1!=null)
{
glede1.drawSelf(textureId);
}
MatrixState.popMatrix();
}
public void onSurfaceChanged(GL10 gl, int width, int height) {
//设置视窗大小及位置
GLES20.glViewport(0, 0, width, height);
//计算GLSurfaceView的宽高比
float ratio = (float) width / height;
//调用此方法计算产生透视投影矩阵
MatrixState.setProjectFrustum(-ratio, ratio, -1, 1, 2, 100);
//调用此方法产生摄像机9参数位置矩阵
MatrixState.setCamera(0,0,0,0f,0f,-1f,0f,1.0f,0.0f);
}
public void onSurfaceCreated(GL10 gl, EGLConfig config)
{
//设置屏幕背景色RGBA
GLES20.glClearColor(1.0f,1.0f,1.0f,1.0f);
//打开深度检测
GLES20.glEnable(GLES20.GL_DEPTH_TEST);
//关闭背面剪裁
GLES20.glDisable(GLES20.GL_CULL_FACE);
//初始化变换矩阵
MatrixState.setInitStack();
glede1=new GledeForDraw(MySurfaceView.this);//创建雄鹰
//加载纹理
textureId=initTexture(R.drawable.ttt);
}
}
public int initTexture(int drawableId)//textureId
{
//生成纹理ID
int[] textures = new int[1];
GLES20.glGenTextures
(
1, //产生的纹理id的数量
textures, //纹理id的数组
0 //偏移量
);
int textureId=textures[0];
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureId);
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER,GLES20.GL_NEAREST);
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,GLES20.GL_TEXTURE_MAG_FILTER,GLES20.GL_LINEAR);
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S,GLES20.GL_REPEAT);
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T,GLES20.GL_REPEAT);
//通过输入流加载图片===============begin===================
InputStream is = this.getResources().openRawResource(drawableId);
Bitmap bitmapTmp;
try
{
bitmapTmp = BitmapFactory.decodeStream(is);
}
finally
{
try
{
is.close();
}
catch(IOException e)
{
e.printStackTrace();
}
}
//通过输入流加载图片===============end=====================
//实际加载纹理
GLUtils.texImage2D
(
GLES20.GL_TEXTURE_2D, //纹理类型在OpenGL ES中必须为GL10.GL_TEXTURE_2D
0, //纹理的层次0表示基本图像层可以理解为直接贴图
bitmapTmp, //纹理图像
0 //纹理边框尺寸
);
bitmapTmp.recycle(); //纹理加载成功后释放图片
return textureId;
}
}

View File

@@ -0,0 +1,42 @@
package com.bn.Sample13_4;
import android.app.Activity;
import android.content.pm.ActivityInfo;
import android.os.Bundle;
import android.view.Window;
import android.view.WindowManager;
public class Sample13_4_Activity extends Activity {
private MySurfaceView mGLSurfaceView;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
//设置为全屏
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN ,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
//设置为横屏模式
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
//初始化GLSurfaceView
mGLSurfaceView = new MySurfaceView(this);
setContentView(mGLSurfaceView);
mGLSurfaceView.requestFocus();//获取焦点
mGLSurfaceView.setFocusableInTouchMode(true);//设置为可触控
}
@Override
protected void onResume() {
super.onResume();
mGLSurfaceView.onResume();
}
@Override
protected void onPause() {
super.onPause();
mGLSurfaceView.onPause();
}
}

View File

@@ -0,0 +1,126 @@
package com.bn.Sample13_4;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import android.content.res.Resources;
import android.opengl.GLES20;
import android.util.Log;
//加载顶点Shader与片元Shader的工具类
public class ShaderUtil
{
//加载制定shader的方法
public static int loadShader
(
int shaderType, //shader的类型 GLES20.GL_VERTEX_SHADER GLES20.GL_FRAGMENT_SHADER
String source //shader的脚本字符串
)
{
//创建一个新shader
int shader = GLES20.glCreateShader(shaderType);
//若创建成功则加载shader
if (shader != 0)
{
//加载shader的源代码
GLES20.glShaderSource(shader, source);
//编译shader
GLES20.glCompileShader(shader);
//存放编译成功shader数量的数组
int[] compiled = new int[1];
//获取Shader的编译情况
GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compiled, 0);
if (compiled[0] == 0)
{//若编译失败则显示错误日志并删除此shader
Log.e("ES20_ERROR", "Could not compile shader " + shaderType + ":");
Log.e("ES20_ERROR", GLES20.glGetShaderInfoLog(shader));
GLES20.glDeleteShader(shader);
shader = 0;
}
}
return shader;
}
//创建shader程序的方法
public static int createProgram(String vertexSource, String fragmentSource)
{
//加载顶点着色器
int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexSource);
if (vertexShader == 0)
{
return 0;
}
//加载片元着色器
int pixelShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentSource);
if (pixelShader == 0)
{
return 0;
}
//创建程序
int program = GLES20.glCreateProgram();
//若程序创建成功则向程序中加入顶点着色器与片元着色器
if (program != 0)
{
//向程序中加入顶点着色器
GLES20.glAttachShader(program, vertexShader);
checkGlError("glAttachShader");
//向程序中加入片元着色器
GLES20.glAttachShader(program, pixelShader);
checkGlError("glAttachShader");
//链接程序
GLES20.glLinkProgram(program);
//存放链接成功program数量的数组
int[] linkStatus = new int[1];
//获取program的链接情况
GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, linkStatus, 0);
//若链接失败则报错并删除程序
if (linkStatus[0] != GLES20.GL_TRUE)
{
Log.e("ES20_ERROR", "Could not link program: ");
Log.e("ES20_ERROR", GLES20.glGetProgramInfoLog(program));
GLES20.glDeleteProgram(program);
program = 0;
}
}
return program;
}
//检查每一步操作是否有错误的方法
public static void checkGlError(String op)
{
int error;
while ((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR)
{
Log.e("ES20_ERROR", op + ": glError " + error);
throw new RuntimeException(op + ": glError " + error);
}
}
//从sh脚本中加载shader内容的方法
public static String loadFromAssetsFile(String fname,Resources r)
{
String result=null;
try
{
InputStream in=r.getAssets().open(fname);
int ch=0;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
while((ch=in.read())!=-1)
{
baos.write(ch);
}
byte[] buff=baos.toByteArray();
baos.close();
in.close();
result=new String(buff,"UTF-8");
result=result.replaceAll("\\r\\n","\n");
}
catch(Exception e)
{
e.printStackTrace();
}
return result;
}
}