初次提交
This commit is contained in:
@@ -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>
|
||||
@@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>Sample6_3</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>
|
||||
@@ -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
|
||||
@@ -0,0 +1,14 @@
|
||||
<?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.Sample6_3">
|
||||
<application android:icon="@drawable/icon" android:label="@string/app_name">
|
||||
<activity android:label="@string/app_name" android:name=".Sample6_3_Activity">
|
||||
<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>
|
||||
@@ -0,0 +1,26 @@
|
||||
precision mediump float;
|
||||
uniform float uR;
|
||||
varying vec3 vPosition;//接收从顶点着色器过来的顶点位置
|
||||
varying vec4 vDiffuse;//接收从顶点着色器过来的散射光分量
|
||||
void main()
|
||||
{
|
||||
vec3 color;
|
||||
float n = 8.0;//一个坐标分量分的总份数
|
||||
float span = 2.0*uR/n;//每一份的长度
|
||||
//每一维在立方体内的行列数
|
||||
int i = int((vPosition.x + uR)/span);
|
||||
int j = int((vPosition.y + uR)/span);
|
||||
int k = int((vPosition.z + uR)/span);
|
||||
//计算当点应位于白色块还是黑色块中
|
||||
int whichColor = int(mod(float(i+j+k),2.0));
|
||||
if(whichColor == 1) {//奇数时为红色
|
||||
color = vec3(0.678,0.231,0.129);//红色
|
||||
}
|
||||
else {//偶数时为白色
|
||||
color = vec3(1.0,1.0,1.0);//白色
|
||||
}
|
||||
//最终颜色
|
||||
vec4 finalColor=vec4(color,0);
|
||||
//给此片元颜色值
|
||||
gl_FragColor=finalColor*vDiffuse;
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
uniform mat4 uMVPMatrix; //总变换矩阵
|
||||
uniform mat4 uMMatrix; //变换矩阵(包括平移、旋转、缩放)
|
||||
uniform vec3 uLightLocation; //光源位置
|
||||
attribute vec3 aPosition; //顶点位置
|
||||
attribute vec3 aNormal; //顶点法向量
|
||||
varying vec3 vPosition; //用于传递给片元着色器的顶点位置
|
||||
varying vec4 vDiffuse; //用于传递给片元着色器的散射光分量
|
||||
void pointLight ( //散射光光照计算的方法
|
||||
in vec3 normal, //法向量
|
||||
inout vec4 diffuse, //散射光计算结果
|
||||
in vec3 lightLocation, //光源位置
|
||||
in vec4 lightDiffuse //散射光强度
|
||||
){
|
||||
vec3 normalTarget=aPosition+normal; //计算变换后的法向量
|
||||
vec3 newNormal=(uMMatrix*vec4(normalTarget,1)).xyz-(uMMatrix*vec4(aPosition,1)).xyz;
|
||||
newNormal=normalize(newNormal); //对法向量规格化
|
||||
//计算从表面点到光源位置的向量vp
|
||||
vec3 vp= normalize(lightLocation-(uMMatrix*vec4(aPosition,1)).xyz);
|
||||
vp=normalize(vp); //规格化vp
|
||||
float nDotViewPosition=max(0.0,dot(newNormal,vp)); //求法向量与vp向量的点积与0的最大值
|
||||
diffuse=lightDiffuse*nDotViewPosition; //计算散射光的最终强度
|
||||
}
|
||||
void main(){
|
||||
gl_Position = uMVPMatrix * vec4(aPosition,1); //根据总变换矩阵计算此次绘制此顶点的位置
|
||||
vec4 diffuseTemp=vec4(0.0,0.0,0.0,0.0);
|
||||
pointLight(normalize(aNormal), diffuseTemp, uLightLocation, vec4(0.8,0.8,0.8,1.0));
|
||||
vDiffuse=diffuseTemp; //将散射光最终强度传给片元着色器
|
||||
vPosition = aPosition; //将顶点的位置传给片元着色器
|
||||
}
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -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
|
||||
@@ -0,0 +1,26 @@
|
||||
/* 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.Sample6_3;
|
||||
|
||||
public final class R {
|
||||
public static final class attr {
|
||||
}
|
||||
public static final class drawable {
|
||||
public static final int icon=0x7f020000;
|
||||
}
|
||||
public static final class id {
|
||||
public static final int SeekBar01=0x7f050001;
|
||||
public static final int main_liner=0x7f050000;
|
||||
}
|
||||
public static final class layout {
|
||||
public static final int main=0x7f030000;
|
||||
}
|
||||
public static final class string {
|
||||
public static final int app_name=0x7f040000;
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 4.0 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.7 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 2.5 KiB |
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:id="@+id/main_liner"
|
||||
>
|
||||
<SeekBar
|
||||
android:id="@+id/SeekBar01"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:max="100"
|
||||
android:progress="0"
|
||||
>
|
||||
</SeekBar>
|
||||
</LinearLayout>
|
||||
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="app_name">Sample6_3</string>
|
||||
</resources>
|
||||
@@ -0,0 +1,185 @@
|
||||
package com.bn.Sample6_3;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import static com.bn.Sample6_3.Constant.*;
|
||||
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.FloatBuffer;
|
||||
import java.util.ArrayList;
|
||||
import android.opengl.GLES20;
|
||||
|
||||
//球
|
||||
public class Ball {
|
||||
int mProgram;// 自定义渲染管线着色器程序id
|
||||
int muMVPMatrixHandle;// 总变换矩阵引用
|
||||
int muMMatrixHandle;//位置、旋转变换矩阵引用
|
||||
int maPositionHandle; // 顶点位置属性引用
|
||||
int muRHandle;// 球的半径属性引用
|
||||
int maNormalHandle; //顶点法向量属性引用
|
||||
int maLightLocationHandle;//光源位置属性引用
|
||||
|
||||
|
||||
String mVertexShader;// 顶点着色器
|
||||
String mFragmentShader;// 片元着色器
|
||||
|
||||
FloatBuffer mVertexBuffer;// 顶点坐标数据缓冲
|
||||
FloatBuffer mNormalBuffer;//顶点法向量数据缓冲
|
||||
int vCount = 0;
|
||||
float yAngle = 0;// 绕y轴旋转的角度
|
||||
float xAngle = 0;// 绕x轴旋转的角度
|
||||
float zAngle = 0;// 绕z轴旋转的角度
|
||||
float r = 0.8f;
|
||||
public Ball(MySurfaceView mv) {
|
||||
// 初始化顶点坐标与着色数据
|
||||
initVertexData();
|
||||
// 初始化shader
|
||||
initShader(mv);
|
||||
}
|
||||
|
||||
// 初始化顶点坐标数据的方法
|
||||
public void initVertexData() {
|
||||
// 顶点坐标数据的初始化================begin============================
|
||||
ArrayList<Float> alVertix = new ArrayList<Float>();// 存放顶点坐标的ArrayList
|
||||
final int angleSpan = 10;// 将球进行单位切分的角度
|
||||
for (int vAngle = -90; vAngle < 90; vAngle = vAngle + angleSpan)// 垂直方向angleSpan度一份
|
||||
{
|
||||
for (int hAngle = 0; hAngle <= 360; hAngle = hAngle + angleSpan)// 水平方向angleSpan度一份
|
||||
{// 纵向横向各到一个角度后计算对应的此点在球面上的坐标
|
||||
float x0 = (float) (r * UNIT_SIZE
|
||||
* Math.cos(Math.toRadians(vAngle)) * Math.cos(Math
|
||||
.toRadians(hAngle)));
|
||||
float y0 = (float) (r * UNIT_SIZE
|
||||
* Math.cos(Math.toRadians(vAngle)) * Math.sin(Math
|
||||
.toRadians(hAngle)));
|
||||
float z0 = (float) (r * UNIT_SIZE * Math.sin(Math
|
||||
.toRadians(vAngle)));
|
||||
|
||||
float x1 = (float) (r * UNIT_SIZE
|
||||
* Math.cos(Math.toRadians(vAngle)) * Math.cos(Math
|
||||
.toRadians(hAngle + angleSpan)));
|
||||
float y1 = (float) (r * UNIT_SIZE
|
||||
* Math.cos(Math.toRadians(vAngle)) * Math.sin(Math
|
||||
.toRadians(hAngle + angleSpan)));
|
||||
float z1 = (float) (r * UNIT_SIZE * Math.sin(Math
|
||||
.toRadians(vAngle)));
|
||||
|
||||
float x2 = (float) (r * UNIT_SIZE
|
||||
* Math.cos(Math.toRadians(vAngle + angleSpan)) * Math
|
||||
.cos(Math.toRadians(hAngle + angleSpan)));
|
||||
float y2 = (float) (r * UNIT_SIZE
|
||||
* Math.cos(Math.toRadians(vAngle + angleSpan)) * Math
|
||||
.sin(Math.toRadians(hAngle + angleSpan)));
|
||||
float z2 = (float) (r * UNIT_SIZE * Math.sin(Math
|
||||
.toRadians(vAngle + angleSpan)));
|
||||
|
||||
float x3 = (float) (r * UNIT_SIZE
|
||||
* Math.cos(Math.toRadians(vAngle + angleSpan)) * Math
|
||||
.cos(Math.toRadians(hAngle)));
|
||||
float y3 = (float) (r * UNIT_SIZE
|
||||
* Math.cos(Math.toRadians(vAngle + angleSpan)) * Math
|
||||
.sin(Math.toRadians(hAngle)));
|
||||
float z3 = (float) (r * UNIT_SIZE * Math.sin(Math
|
||||
.toRadians(vAngle + angleSpan)));
|
||||
|
||||
// 将计算出来的XYZ坐标加入存放顶点坐标的ArrayList
|
||||
alVertix.add(x1);
|
||||
alVertix.add(y1);
|
||||
alVertix.add(z1);
|
||||
alVertix.add(x3);
|
||||
alVertix.add(y3);
|
||||
alVertix.add(z3);
|
||||
alVertix.add(x0);
|
||||
alVertix.add(y0);
|
||||
alVertix.add(z0);
|
||||
|
||||
alVertix.add(x1);
|
||||
alVertix.add(y1);
|
||||
alVertix.add(z1);
|
||||
alVertix.add(x2);
|
||||
alVertix.add(y2);
|
||||
alVertix.add(z2);
|
||||
alVertix.add(x3);
|
||||
alVertix.add(y3);
|
||||
alVertix.add(z3);
|
||||
}
|
||||
}
|
||||
vCount = alVertix.size() / 3;// 顶点的数量为坐标值数量的1/3,因为一个顶点有3个坐标
|
||||
|
||||
// 将alVertix中的坐标值转存到一个float数组中
|
||||
float vertices[] = new float[vCount * 3];
|
||||
for (int i = 0; i < alVertix.size(); i++) {
|
||||
vertices[i] = alVertix.get(i);
|
||||
}
|
||||
|
||||
// 创建顶点坐标数据缓冲
|
||||
// vertices.length*4是因为一个整数四个字节
|
||||
ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length * 4);
|
||||
vbb.order(ByteOrder.nativeOrder());// 设置字节顺序
|
||||
mVertexBuffer = vbb.asFloatBuffer();// 转换为int型缓冲
|
||||
mVertexBuffer.put(vertices);// 向缓冲区中放入顶点坐标数据
|
||||
mVertexBuffer.position(0);// 设置缓冲区起始位置
|
||||
// 特别提示:由于不同平台字节顺序不同数据单元不是字节的一定要经过ByteBuffer
|
||||
// 转换,关键是要通过ByteOrder设置nativeOrder(),否则有可能会出问题
|
||||
|
||||
//创建绘制顶点法向量缓冲
|
||||
ByteBuffer nbb = ByteBuffer.allocateDirect(vertices.length*4);
|
||||
nbb.order(ByteOrder.nativeOrder());//设置字节顺序
|
||||
mNormalBuffer = nbb.asFloatBuffer();//转换为float型缓冲
|
||||
mNormalBuffer.put(vertices);//向缓冲区中放入顶点坐标数据
|
||||
mNormalBuffer.position(0);//设置缓冲区起始位置
|
||||
}
|
||||
|
||||
// 初始化shader
|
||||
public void initShader(MySurfaceView mv) {
|
||||
// 加载顶点着色器的脚本内容
|
||||
mVertexShader = ShaderUtil.loadFromAssetsFile("vertex.sh",
|
||||
mv.getResources());
|
||||
// 加载片元着色器的脚本内容
|
||||
mFragmentShader = ShaderUtil.loadFromAssetsFile("frag.sh",
|
||||
mv.getResources());
|
||||
// 基于顶点着色器与片元着色器创建程序
|
||||
mProgram = ShaderUtil.createProgram(mVertexShader, mFragmentShader);
|
||||
// 获取程序中顶点位置属性引用
|
||||
maPositionHandle = GLES20.glGetAttribLocation(mProgram, "aPosition");
|
||||
// 获取程序中总变换矩阵引用
|
||||
muMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
|
||||
//获取位置、旋转变换矩阵引用
|
||||
muMMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMMatrix");
|
||||
// 获取程序中球半径引用
|
||||
muRHandle = GLES20.glGetUniformLocation(mProgram, "uR");
|
||||
//获取程序中顶点法向量属性引用
|
||||
maNormalHandle= GLES20.glGetAttribLocation(mProgram, "aNormal");
|
||||
//获取程序中光源位置引用
|
||||
maLightLocationHandle=GLES20.glGetUniformLocation(mProgram, "uLightLocation");
|
||||
}
|
||||
|
||||
public void drawSelf() {
|
||||
MatrixState.rotate(xAngle, 1, 0, 0);//绕X轴转动
|
||||
MatrixState.rotate(yAngle, 0, 1, 0);//绕Y轴转动
|
||||
MatrixState.rotate(zAngle, 0, 0, 1);//绕Z轴转动
|
||||
// 制定使用某套着色器程序
|
||||
GLES20.glUseProgram(mProgram);
|
||||
// 将最终变换矩阵传入着色器程序
|
||||
GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false,
|
||||
MatrixState.getFinalMatrix(), 0);
|
||||
//将位置、旋转变换矩阵传入着色器程序
|
||||
GLES20.glUniformMatrix4fv(muMMatrixHandle, 1, false, MatrixState.getMMatrix(), 0);
|
||||
// 将半径尺寸传入着色器程序
|
||||
GLES20.glUniform1f(muRHandle, r * UNIT_SIZE);
|
||||
//将光源位置传入着色器程序
|
||||
GLES20.glUniform3fv(maLightLocationHandle, 1, MatrixState.lightPositionFB);
|
||||
|
||||
// 将顶点位置数据传入渲染管线
|
||||
GLES20.glVertexAttribPointer(maPositionHandle, 3, GLES20.GL_FLOAT,
|
||||
false, 3 * 4, mVertexBuffer);
|
||||
//将顶点法向量数据传入渲染管线
|
||||
GLES20.glVertexAttribPointer(maNormalHandle, 3, GLES20.GL_FLOAT, false,
|
||||
3 * 4, mNormalBuffer);
|
||||
// 启用顶点位置数据
|
||||
GLES20.glEnableVertexAttribArray(maPositionHandle);
|
||||
GLES20.glEnableVertexAttribArray(maNormalHandle);// 启用顶点法向量数据
|
||||
// 绘制球
|
||||
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vCount);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.bn.Sample6_3;
|
||||
|
||||
public class Constant
|
||||
{
|
||||
//单位尺寸
|
||||
public static final float UNIT_SIZE=1f;
|
||||
//计算GLSurfaceView的宽高比
|
||||
public static float ratio;
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
package com.bn.Sample6_3;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.FloatBuffer;
|
||||
|
||||
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 lightPositionFB;
|
||||
//保护变换矩阵的栈
|
||||
static float[][] mStack=new float[10][16];
|
||||
static int stackTop=-1;
|
||||
|
||||
public static void setInitStack()//获取不变换初始矩阵
|
||||
{
|
||||
currMatrix=new float[16];
|
||||
Matrix.setRotateM(currMatrix, 0, 0, 1, 0, 0);
|
||||
}
|
||||
|
||||
public static void pushMatrix()//保护变换矩阵
|
||||
{
|
||||
stackTop++;
|
||||
for(int i=0;i<16;i++)
|
||||
{
|
||||
mStack[stackTop][i]=currMatrix[i];
|
||||
}
|
||||
}
|
||||
|
||||
public static void popMatrix()//恢复变换矩阵
|
||||
{
|
||||
for(int i=0;i<16;i++)
|
||||
{
|
||||
currMatrix[i]=mStack[stackTop][i];
|
||||
}
|
||||
stackTop--;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
//设置摄像机
|
||||
static ByteBuffer llbb= ByteBuffer.allocateDirect(3*4);
|
||||
static float[] cameraLocation=new float[3];//摄像机位置
|
||||
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
|
||||
);
|
||||
}
|
||||
|
||||
//设置透视投影参数
|
||||
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);
|
||||
}
|
||||
|
||||
//获取具体物体的总变换矩阵
|
||||
static float[] mMVPMatrix=new float[16];
|
||||
public static float[] getFinalMatrix()
|
||||
{
|
||||
Matrix.multiplyMM(mMVPMatrix, 0, mVMatrix, 0, currMatrix, 0);
|
||||
Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, mMVPMatrix, 0);
|
||||
return mMVPMatrix;
|
||||
}
|
||||
|
||||
//获取具体物体的变换矩阵
|
||||
public static float[] getMMatrix()
|
||||
{
|
||||
return currMatrix;
|
||||
}
|
||||
//设置灯光位置的方法
|
||||
static ByteBuffer llbbL = ByteBuffer.allocateDirect(3*4);
|
||||
public static void setLightLocation(float x,float y,float z)
|
||||
{
|
||||
llbbL.clear();
|
||||
|
||||
lightLocation[0]=x;
|
||||
lightLocation[1]=y;
|
||||
lightLocation[2]=z;
|
||||
|
||||
llbbL.order(ByteOrder.nativeOrder());//设置字节顺序
|
||||
lightPositionFB=llbbL.asFloatBuffer();
|
||||
lightPositionFB.put(lightLocation);
|
||||
lightPositionFB.position(0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
package com.bn.Sample6_3;
|
||||
import javax.microedition.khronos.egl.EGLConfig;
|
||||
import javax.microedition.khronos.opengles.GL10;
|
||||
import android.content.Context;
|
||||
import android.opengl.GLES20;
|
||||
import android.opengl.GLSurfaceView;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
class MySurfaceView extends GLSurfaceView
|
||||
{
|
||||
private final float TOUCH_SCALE_FACTOR = 180.0f/320;//角度缩放比例
|
||||
private SceneRenderer mRenderer;//场景渲染器
|
||||
Ball ball;//球
|
||||
float lightOffset=-4;//灯光的位置或方向的偏移量
|
||||
private float mPreviousY;//上次的触控位置Y坐标
|
||||
private float mPreviousX;//上次的触控位置X坐标
|
||||
public MySurfaceView(Context context) {
|
||||
super(context);
|
||||
this.setEGLContextClientVersion(2); //设置使用OPENGL ES2.0
|
||||
mRenderer = new SceneRenderer(); //创建场景渲染器
|
||||
setRenderer(mRenderer); //设置渲染器
|
||||
setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);//设置渲染模式为主动渲染
|
||||
}
|
||||
//触摸事件回调方法
|
||||
@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位移
|
||||
ball.yAngle += dx * TOUCH_SCALE_FACTOR;//设置填充椭圆绕y轴旋转的角度
|
||||
ball.xAngle+= dy * TOUCH_SCALE_FACTOR;//设置填充椭圆绕x轴旋转的角度
|
||||
}
|
||||
mPreviousY = y;//记录触控笔位置
|
||||
mPreviousX = x;//记录触控笔位置
|
||||
return true;
|
||||
}
|
||||
private class SceneRenderer implements GLSurfaceView.Renderer
|
||||
{
|
||||
|
||||
public void onDrawFrame(GL10 gl)
|
||||
{
|
||||
//清除深度缓冲与颜色缓冲
|
||||
GLES20.glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
|
||||
//初始化光源位置
|
||||
MatrixState.setLightLocation(lightOffset, 0, 1.5f);
|
||||
//保护现场
|
||||
MatrixState.pushMatrix();
|
||||
//绘制球
|
||||
MatrixState.pushMatrix();
|
||||
MatrixState.translate(-1.2f, 0, 0);
|
||||
ball.drawSelf();
|
||||
MatrixState.popMatrix();
|
||||
//绘制球
|
||||
MatrixState.pushMatrix();
|
||||
MatrixState.translate(1.2f, 0, 0);
|
||||
ball.drawSelf();
|
||||
MatrixState.popMatrix();
|
||||
//恢复现场
|
||||
MatrixState.popMatrix();
|
||||
}
|
||||
|
||||
public void onSurfaceChanged(GL10 gl, int width, int height) {
|
||||
//设置视窗大小及位置
|
||||
GLES20.glViewport(0, 0, width, height);
|
||||
//计算GLSurfaceView的宽高比
|
||||
Constant.ratio = (float) width / height;
|
||||
// 调用此方法计算产生透视投影矩阵
|
||||
MatrixState.setProjectFrustum(-Constant.ratio, Constant.ratio, -1, 1, 20, 100);
|
||||
// 调用此方法产生摄像机9参数位置矩阵
|
||||
MatrixState.setCamera(0, 0f, 30, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
|
||||
|
||||
//初始化变换矩阵
|
||||
MatrixState.setInitStack();
|
||||
}
|
||||
|
||||
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
|
||||
//设置屏幕背景色RGBA
|
||||
GLES20.glClearColor(0f,0f,0f, 1.0f);
|
||||
//创建球对象
|
||||
ball=new Ball(MySurfaceView.this);
|
||||
//打开深度检测
|
||||
GLES20.glEnable(GLES20.GL_DEPTH_TEST);
|
||||
//打开背面剪裁
|
||||
GLES20.glEnable(GLES20.GL_CULL_FACE);
|
||||
}
|
||||
}
|
||||
public void setLightOffset(float lightOffset) {
|
||||
this.lightOffset = lightOffset;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package com.bn.Sample6_3;
|
||||
import android.app.Activity;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.os.Bundle;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.SeekBar;
|
||||
|
||||
public class Sample6_3_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);
|
||||
this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);//设置为横屏
|
||||
// 初始化GLSurfaceView
|
||||
mGLSurfaceView = new MySurfaceView(this);
|
||||
// 切换到主界面
|
||||
setContentView(R.layout.main);
|
||||
LinearLayout ll = (LinearLayout) findViewById(R.id.main_liner);
|
||||
ll.addView(mGLSurfaceView);
|
||||
//普通拖拉条被拉动的处理代码
|
||||
SeekBar sb=(SeekBar)this.findViewById(R.id.SeekBar01);
|
||||
sb.setOnSeekBarChangeListener(
|
||||
new SeekBar.OnSeekBarChangeListener()
|
||||
{
|
||||
@Override
|
||||
public void onProgressChanged(SeekBar seekBar, int progress,
|
||||
boolean fromUser) {
|
||||
mGLSurfaceView.setLightOffset((seekBar.getMax()/2.0f-progress)/(seekBar.getMax()/2.0f)*-4);
|
||||
}
|
||||
@Override
|
||||
public void onStartTrackingTouch(SeekBar seekBar) { }
|
||||
@Override
|
||||
public void onStopTrackingTouch(SeekBar seekBar) { }
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
mGLSurfaceView.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
mGLSurfaceView.onPause();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
package com.bn.Sample6_3;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user