内容简介:旁白:上集说到,为了获取黑龙宝藏,勇者集结,共闯第五副本:1.第一关卡:
旁白:上集说到,为了获取黑龙宝藏,勇者集结,共闯 黑龙洞穴
经过一路艰辛,终于过了第四副本,前面还有什么困难等待着他们?一起收看
第五副本: 龙之图阵
1.第一关卡: 画一个矩形
NPC:隐藏任务,解谜: GLES20.GL_TRIANGLE_STRIP 绘制方式
2->3->4 ,在绘制
1->2->3
因为 2->3->4 的三角形被 1->2->3 的等三角形遮住了,后来居上是编程的共识
static float sCoo[] = { //以逆时针顺序
-0.5f, 0.5f, 0.0f, // 左上
-0.5f, -0.5f, 0.0f, // 左下
0.5f, -0.5f, 0.0f, // 右下
0.5f, 0.5f, 0.0f, //右上
};
float colors[] = new float[]{
1f, 1f, 0.0f, 1.0f,//黄
0.05882353f, 0.09411765f, 0.9372549f, 1.0f,//蓝
0.19607843f, 1.0f, 0.02745098f, 1.0f,//绿
1.0f, 0.0f, 1.0f, 1.0f,//紫色
};
---->[Rectangle#draw]---------
//绘制三角形
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
复制代码
怎么能让 1->2->3 和 2->3->4 不会重叠?--点调下顺序就行了
1->2->4->3
static float sCoo[] = { //以逆时针顺序
-0.5f, 0.5f, 0.0f, // 1.
-0.5f, -0.5f, 0.0f, // 2.
0.5f, 0.5f, 0.0f, //4.
0.5f, -0.5f, 0.0f, // 3.
};
复制代码
2.第二关卡: 画五边形
先按照 p1->p2->p3->p4->p5 的顺序,看有什么效果
意料之内,先把 p1->p2->p3->p4 四点画完,再画第五点
怎么调点呢?恩...好吧,哥要开始吹牛了
我这么随便一想,在满足正方形的条件下,动一下p5点,就行了,然后让p5上漂
static float sCoo[] = { //以逆时针顺序
-0.5f, 0.5f, 0.0f, // p1
0.0f, 0.8f, 0.0f, //p5
-0.5f, -0.5f, 0.0f, // p2
0.5f, 0.5f, 0.0f, //p4
0.5f, -0.5f, 0.0f, // p3
};
复制代码
再多边形也可以用三角形拼出来,不过感觉有点麻烦
解密: GL_TRIANGLE_STRIP :相邻三个顶点绘制一个三角形
3.第三关卡:索引五边形-- glDrawElements
我就想来着,应该有控制三角形顶点的东西,不然调起来很麻烦
3.1.缓冲的简单封装
缓冲顶点数据的套路基本一致,封个方法在GLUtils里吧,
暂时float(4字节)和short(2字节),其他的遇到再说
/**
* float数组缓冲数据
* @param vertexs 顶点
* @return 获取浮点形缓冲数据
*/
public static FloatBuffer getFloatBuffer(float[] vertexs) {
FloatBuffer buffer;
///每个浮点数:坐标个数* 4字节
ByteBuffer qbb = ByteBuffer.allocateDirect(vertexs.length * 4);
//使用本机硬件设备的字节顺序
qbb.order(ByteOrder.nativeOrder());
// 从字节缓冲区创建浮点缓冲区
buffer = qbb.asFloatBuffer();
// 将坐标添加到FloatBuffer
buffer.put(vertexs);
//设置缓冲区以读取第一个坐标
buffer.position(0);
return buffer;
}
/**
* short数组缓冲数据
* @param vertexs short 数组
* @return 获取short缓冲数据
*/
public static ShortBuffer getShortBuffer(short[] vertexs) {
ShortBuffer buffer;
ByteBuffer qbb = ByteBuffer.allocateDirect(vertexs.length * 2);
qbb.order(ByteOrder.nativeOrder());
buffer = qbb.asShortBuffer();
buffer.put(vertexs);
buffer.position(0);
return buffer;
}
复制代码
3.2:自己控制三角形的形成
咱们从0开始数数,怎么控制点,看图你应该能知道
static float sCoo[] = { //以逆时针顺序
-0.5f, 0.5f, 0.0f, // p0
-0.5f, -0.5f, 0.0f, // p1
0.5f, -0.5f, 0.0f, // p2
0.5f, 0.5f, 0.0f, //p3
0.0f, 0.8f, 0.0f, //p4
};
//索引数组
private short[] idx = {
0, 4, 3,
1, 3, 0,
1, 2, 3
};
//索引缓冲
idxBuffer = GLUtils.getShortBuffer(idx);
//绘制
GLES20.glDrawElements(GLES20.GL_TRIANGLES, idx.length,
GLES20.GL_UNSIGNED_SHORT, idxBuffer);
复制代码
4.第四关卡:六边形
先转六边形应该没有什么大问题了
static float sCoo[] = { //以逆时针顺序
-0.5f, 0.5f, 0.0f, // p0
-1.0f, 0.0f, 0.0f, // p1
-0.5f, -0.5f, 0.0f, // p2
0.5f, -0.5f, 0.0f, //p3
1.0f, 0.0f, 0.0f, //p4
0.5f, 0.5f, 0.0f, //p5
};
//索引数组
private short[] idx = {
0, 1, 5,
1, 5, 2,
2, 5, 4,
2, 3, 4
};
复制代码
第六副本: 龙之空间
到这来,咱们几乎都是在平面,先转要变立体了
守关boss要发大招了,勇士们,hold住
1.第一关卡:沿着y轴旋转起来
关于变换第一集讲了一些,忘了的可以回去看看
下面是转一圈的效果,感觉少了一半
//围绕y轴旋转 Matrix.setRotateM(mOpMatrix, 0, currDeg, 0, 1, 0); 复制代码
我让她一边移动一边旋转,好像可以看出一点东西
不过是转起来了,等到转讲视野的时候再详细论述吧
Matrix.setRotateM(mOpMatrix, 0, currDeg, 0, 1, 0); Matrix.translateM(mOpMatrix, 0, currDeg/360.f, 0,0); 复制代码
1.第二关卡:空间面
貌似一直z轴我们都是0,动一下呗,纸上和ps上还是各有优点的
纸上画起来有感觉(但误差很大),ps里复用强,先看 p0,p1,p2,p3 面
先从p0点(-0.5,0.5,0.5)入手,然后根据对称关系,或目测确定其他点,
//点位数组
static float sCoo[] = {
-0.5f, 0.5f, 0.5f,//p0
-0.5f, -0.5f, 0.5f,//p1
-0.5f, -0.5f, -0.5f,//p2
-0.5f, 0.5f, -0.5f,//p3
}
//索引数组
private short[] idx = {
0, 1, 3,
1, 2, 3,
}
float colors[] = new float[]{
1f, 1f, 0.0f, 1.0f,//黄
0.05882353f, 0.09411765f, 0.9372549f, 1.0f,//蓝
0.19607843f, 1.0f, 0.02745098f, 1.0f,//绿
1.0f, 0.0f, 1.0f, 1.0f,//紫色
}
复制代码
2.第二关卡:第二面
一面完成了,第二面 p4、p5、p6、p7 就好办了,可以看出来p0,p1和p4,p5是一样的
索引稍微画画也能看出规律,颜色再来那四个,就不贴了
可以看出和我们画的有点出入,貌似是视口的问题,但不影响图形本身
static float sCoo[] = {
-0.5f, 0.5f, 0.5f,//p0
-0.5f, -0.5f, 0.5f,//p1
-0.5f, -0.5f, -0.5f,//p2
-0.5f, 0.5f, -0.5f,//p3
-0.5f, 0.5f, 0.5f,//p4
-0.5f, -0.5f, 0.5f,//p5
0.5f, -0.5f, 0.5f,//p6
0.5f, 0.5f, 0.5f,//p7
//索引数组
private short[] idx = {
0, 1, 3,
1, 2, 3,
0+4, 1+4, 3+4,
1+4, 2+4, 3+4,
复制代码
3.第三关卡:其他面
为了方便表述,我给每个面取了名字,分别是: A、B、C、D、E、F
static float sCoo[] = {
//A面
-0.5f, 0.5f, 0.5f,//p0
-0.5f, -0.5f, 0.5f,//p1
-0.5f, -0.5f, -0.5f,//p2
-0.5f, 0.5f, -0.5f,//p3
//B面
-0.5f, 0.5f, 0.5f,//p4
-0.5f, -0.5f, 0.5f,//p5
0.5f, -0.5f, 0.5f,//p6
0.5f, 0.5f, 0.5f,//p7
//C面
0.5f, 0.5f, 0.5f,//p8
0.5f, -0.5f, 0.5f,//p9
0.5f, -0.5f, -0.5f,//p10
0.5f, 0.5f, -0.5f,//p11
//D面
-0.5f, 0.5f, 0.5f,//p12
0.5f, 0.5f, 0.5f,//p13
0.5f, 0.5f, -0.5f,//p14
-0.5f, 0.5f, -0.5f,//p15
//E面
-0.5f, -0.5f, 0.5f,//p16
0.5f, -0.5f, 0.5f,//p17
0.5f, -0.5f, -0.5f,//p18
-0.5f, -0.5f, -0.5f,//p19
//F面
-0.5f, 0.5f, -0.5f,//p20
-0.5f, -0.5f, -0.5f,//p21
0.5f, -0.5f, -0.5f,//p22
0.5f, 0.5f, -0.5f,//p23
};
//索引数组
private short[] idx = {
0, 1, 3,//A
1, 2, 3,
0 + 4, 1 + 4, 3 + 4,//B
1 + 4, 2 + 4, 3 + 4,
0 + 4 * 2, 1 + 4 * 2, 3 + 4 * 2,//C
1 + 4 * 2, 2 + 4 * 2, 3 + 4 * 2,
0 + 4 * 3, 1 + 4 * 3, 3 + 4 * 3,//D
1 + 4 * 3, 2 + 4 * 3, 3 + 4 * 3,
0 + 4 * 4, 1 + 4 * 4, 3 + 4 * 4,//E
1 + 4 * 4, 2 + 4 * 4, 3 + 4 * 4,
0 + 4 * 5, 1 + 4 * 5, 3 + 4 * 5,//F
1 + 4 * 5, 2 + 4 * 5, 3 + 4 * 5,
};
float colors[] = new float[]{
//A
1f, 1f, 0.0f, 1.0f,//黄
0.05882353f, 0.09411765f, 0.9372549f, 1.0f,//蓝
0.19607843f, 1.0f, 0.02745098f, 1.0f,//绿
1.0f, 0.0f, 1.0f, 1.0f,//紫色
//B
1f, 1f, 0.0f, 1.0f,//黄
0.05882353f, 0.09411765f, 0.9372549f, 1.0f,//蓝
0.19607843f, 1.0f, 0.02745098f, 1.0f,//绿
1.0f, 0.0f, 1.0f, 1.0f,//紫色
//C
1f, 1f, 0.0f, 1.0f,//黄
0.05882353f, 0.09411765f, 0.9372549f, 1.0f,//蓝
0.19607843f, 1.0f, 0.02745098f, 1.0f,//绿
1.0f, 0.0f, 1.0f, 1.0f,//紫色
//D
1f, 1f, 0.0f, 1.0f,//黄
0.05882353f, 0.09411765f, 0.9372549f, 1.0f,//蓝
0.19607843f, 1.0f, 0.02745098f, 1.0f,//绿
1.0f, 0.0f, 1.0f, 1.0f,//紫色
//E
1f, 1f, 0.0f, 1.0f,//黄
0.05882353f, 0.09411765f, 0.9372549f, 1.0f,//蓝
0.19607843f, 1.0f, 0.02745098f, 1.0f,//绿
1.0f, 0.0f, 1.0f, 1.0f,//紫色
//F
1f, 1f, 0.0f, 1.0f,//黄
0.05882353f, 0.09411765f, 0.9372549f, 1.0f,//蓝
0.19607843f, 1.0f, 0.02745098f, 1.0f,//绿
1.0f, 0.0f, 1.0f, 1.0f,//紫色
};
复制代码
第七副本: 龙之逆鳞
第六副本中的立方体并不怎么让人满意,视角不怎么好,
这一副本就来再看看相机和投影以及矩阵
1.第一关卡:调整相机
一开始眼睛在(0, 0, -3),看下图你就知道为什么画的时候面有问题了
因为相机在后面,而且很正,所以看着就很正...
// 设置相机位置(视图矩阵)
Matrix.setLookAtM(mViewMatrix, 0,
0, 0, -3,
0f, 0f, 0f,
0f, 1.0f, 0.0f);
复制代码
现在调到后上方(2,2,-5)
// 设置相机位置(视图矩阵)
Matrix.setLookAtM(mViewMatrix, 0,
2f, 2f, -5.0f,
0f, 0f, 0f,
0f, 1.0f, 0.0f);
复制代码
2.第二关卡:旋转试图,按纸上的视口绘制
//初始化变换矩阵 Matrix.setRotateM(mOpMatrix, 0, 130, 0, 1, 0); 复制代码
然后再来看绘制的流程,就和纸上的一致了,所以视口很重要
第八副本: 龙之盛装 LEVEL1
颜色多没劲,咱们来贴图,经历了这么多,回头看看,感慨良多 这个副本将简单认识贴图,以后还会有高级的 龙之盛装
1.第一关卡:三角形贴图
百度了一个小时,愣是没有把贴图整明白,叙述的逻辑性欠佳,都是贴个代码完事,
贴个完整的还好,但都是一段一段的代码...
现在我来捋一遍,最简单的三角形贴图的流程,先把视野移到(0,0,-3) 不然肯定变形
1.1:片元代码 rect_texture.frag
precision mediump float;
varying vec2 aCoordinate;//贴图坐标系
uniform sampler2D vTexture;//贴图
void main() {
gl_FragColor=texture2D(vTexture,aCoordinate);
}
复制代码
1.2:顶点代码: rect_texture.vert
attribute vec3 vPosition;//顶点坐标
uniform mat4 uMVPMatrix; //总变换矩阵
attribute vec2 vCoordinate;//贴图顶点坐标
varying vec2 aCoordinate;//贴图顶点坐标--片元变量
void main() {
gl_Position = uMVPMatrix*vec4(vPosition,1);
aCoordinate=vCoordinate;
}
复制代码
1.3:贴图三角形: TextureRectangle
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texId); 两行代码贴图
其余的基本一致,下面最重要的是这个贴图id如何获取
/**
* 作者:张风捷特烈<br/>
* 时间:2019/1/9 0009:20:09<br/>
* 邮箱:1981462002@qq.com<br/>
* 说明:贴图测试
*/
public class TextureRectangle {
private static final String TAG = "Triangle";
private Context mContext;
private int mProgram;//OpenGL ES 程序
private int mPositionHandle;//位置句柄
private int mColorHandle;//颜色句柄
private int muMVPMatrixHandle;//顶点变换矩阵句柄
private FloatBuffer vertexBuffer;//顶点缓冲
private final int vertexStride = COORDS_PER_VERTEX * 4; // 3*4=12
static final int COORDS_PER_VERTEX = 3;//数组中每个顶点的坐标数
static final int c = 1;//数组中每个顶点的坐标数
static float sCoo[] = { //以逆时针顺序
-c, c, 0.0f, // p0
-c, -c, 0.0f, // p1
c, -c, 0.0f, // p2
};
private final float[] textureCoo = {
0.0f,0.0f,
0.0f,1.0f,
1.0f,0.0f,
};
static final int TEXTURE_PER_VERTEX = 2;//数组中每个顶点的坐标数
private final int vertexTextureStride = TEXTURE_PER_VERTEX * 4; // 4*4=16
private ShortBuffer idxBuffer;
//索引数组
private short[] idx = {
1, 2, 3,
};
private FloatBuffer mTextureCooBuffer;
public TextureRectangle(Context context) {
mContext = context;
//初始化顶点字节缓冲区
bufferData();//缓冲顶点数据
initProgram();//初始化OpenGL ES 程序
}
/**
* 缓冲数据
*/
private void bufferData() {
vertexBuffer = GLUtil.getFloatBuffer(sCoo);
mTextureCooBuffer = GLUtil.getFloatBuffer(textureCoo);
idxBuffer = GLUtil.getShortBuffer(idx);
}
/**
* 初始化OpenGL ES 程序
*/
private void initProgram() {
////顶点着色
int vertexShader = GLUtil.loadShaderAssets(mContext,
GLES20.GL_VERTEX_SHADER, "rect_texture.vert");
//片元着色
int fragmentShader = GLUtil.loadShaderAssets(mContext,
GLES20.GL_FRAGMENT_SHADER, "rect_texture.frag");
mProgram = GLES20.glCreateProgram();//创建空的OpenGL ES 程序
GLES20.glAttachShader(mProgram, vertexShader);//加入顶点着色器
GLES20.glAttachShader(mProgram, fragmentShader);//加入片元着色器
GLES20.glLinkProgram(mProgram);//创建可执行的OpenGL ES项目
//获取顶点着色器的vPosition成员的句柄
mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");
//获取片元着色器的vColor成员的句柄
mColorHandle = GLES20.glGetAttribLocation(mProgram, "vCoordinate");
//获取程序中总变换矩阵uMVPMatrix成员的句柄
muMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
}
public void draw(float[] mvpMatrix, int texId ) {
// 将程序添加到OpenGL ES环境中
GLES20.glUseProgram(mProgram);
//启用三角形顶点的句柄
GLES20.glEnableVertexAttribArray(mPositionHandle);
//启用三角形顶点颜色的句柄
GLES20.glEnableVertexAttribArray(mColorHandle);
//顶点矩阵变换
GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, mvpMatrix, 0);
//准备三角顶点坐标数据
GLES20.glVertexAttribPointer(
mPositionHandle,//int indx, 索引
COORDS_PER_VERTEX,//int size,大小
GLES20.GL_FLOAT,//int type,类型
false,//boolean normalized,//是否标准化
vertexStride,// int stride,//跨度
vertexBuffer);// java.nio.Buffer ptr//缓冲
//准备三角顶点颜色数据
GLES20.glVertexAttribPointer(
mColorHandle,
TEXTURE_PER_VERTEX,
GLES20.GL_FLOAT,
false,
vertexTextureStride,
mTextureCooBuffer);
//绑定纹理
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texId);
//绘制
GLES20.glDrawElements(GLES20.GL_TRIANGLES, idx.length, GLES20.GL_UNSIGNED_SHORT, idxBuffer);
//禁用顶点数组:
//禁用index指定的通用顶点属性数组。
// 默认情况下,禁用所有客户端功能,包括所有通用顶点属性数组。
// 如果启用,将访问通用顶点属性数组中的值,
// 并在调用顶点数组命令(如glDrawArrays或glDrawElements)时用于呈现
GLES20.glDisableVertexAttribArray(mPositionHandle);
}
}
复制代码
1.4:加载纹理
我在GLUtil中封装了两个方法
/**
* 资源id 加载纹理
* @param ctx 上下文
* @param resId 资源id
* @return 纹理id
*/
public static int loadTexture(Context ctx, int resId) {
Bitmap bitmap = BitmapFactory.decodeResource(ctx.getResources(), resId);
return loadTexture(ctx, bitmap);
}
/**
* bitmap 加载纹理
* @param ctx 上下文
* @param bitmap bitmap
* @return 纹理id
*/
public static int loadTexture(Context ctx, Bitmap bitmap) {
//生成纹理ID
int[] textures = new int[1];
//(产生的纹理id的数量,纹理id的数组,偏移量)
GLES20.glGenTextures(1, textures, 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_CLAMP_TO_EDGE);
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
//实际加载纹理(纹理类型,纹理的层次,纹理图像,纹理边框尺寸)
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
bitmap.recycle(); //纹理加载成功后释放图片
return textureId;
}
复制代码
1.5:使用纹理 GLRenderer.java
private int textureId; ---->[GLRenderer#onSurfaceCreated]------ textureId = GLUtil.loadTexture(mContext, R.mipmap.mian_a);//初始化纹理 ---->[GLRenderer#onDrawFrame]------ mTextureRectangle.draw(mMVPMatrix,textureId);//绘制时使用纹理 复制代码
2.第二关卡:矩形纹理
这是一道送分题,没别的,坐标改改就行了
static float sCoo[] = { //以逆时针顺序
-c, c, 0.0f, // p0
-c, -c, 0.0f, // p1
c, -c, 0.0f, // p2
c, c, 0.0f, //p3
};
private final float[] textureCoo = {
0.0f,0.0f,
0.0f,1.0f,
1.0f,0.0f,
1.0f,1.0f,
};
//索引数组
private short[] idx = {
1, 2, 3,
0, 1, 3,
};
复制代码
有兴趣的可以动动贴图坐标系的点看一下,自己了解一下贴图坐标系
以上所述就是小编给大家介绍的《Android多媒体之GL-ES战记第二集--谜团立方》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Learn Python the Hard Way
Zed Shaw / Example Product Manufacturer / 2011
This is a very beginner book for people who want to learn to code. If you can already code then the book will probably drive you insane. It's intended for people who have no coding chops to build up t......一起来看看 《Learn Python the Hard Way》 这本书的介绍吧!