怎么用openGL多边形 GL在深度相机人前的地面上画一个正方形

OpenGLES demo - 4. GL中的三角形
原创文章,转载请注明连接 http://blog.csdn.net/hoytgm/article/details/
第二个demo的时候我们画了一个三角形,三角形是OpenGLES,OpenGL和Direct3D中最基本的元素。在Direct3D中一个三角形也被称作为primitive,也就是一个图形元。确实,在图形学的世界中,不管你看到任何东西,最后都是由一个一个的三角形构成的。了解的朋友也许会问线,一般来说,即使开发者画的是一条线,在显卡的驱动或者是硬件的的实现上也是由两个三角形构成,这样的话,如果开发者需要画一条宽的线,那么很简单了,扩大构成这条线的三角形就可以了。
在图形学中,一般会用到三种画三角形的方式,triangles,triangle strip和triangle fan。这三种方式对应到OpenGLES中就是GL_TRIANGLES, GL_TRIANGLE_STRIP和GL_TRIANGLE_FAN。
Triangles是指三角形列表,每三个点构成一个三角形。如果开发者想画两个三角形的话,那么就需要提供6个顶点。因为Triangles方式没有共享点的问题,每个三角形都由独立的三个点构成。因此要画的三角形个数和顶点的关系为 triangles * 3 = vertices。
我们以第二章的代码为基础,如果我们需要画一个矩形,那么需要提供6个顶点,同时将glDrawArrays的最后一个参数由3改为6。
float vertices[] =
-0.5f, -0.5f, 0.5f, 1.0f,
0.5f, -0.5f, 0.5f, 1.0f,
-0.5f, 0.5f, 0.5f, 1.0f,
0.5f, -0.5f, 0.5f, 1.0f,
-0.5f, 0.5f, 0.5f, 1.0f,
0.5f, 0.5f, 0.5f, 1.0f,
glDrawArrays(GL_TRIANGLES, 0, 6);
Triangle strip是三角形带,第一个三角形由前三个顶点构成,第二个三角形的三个顶点由一个新的顶点和第一个三角形的后两个顶点构成。同理,后面的三角形都按第二个三角形的规则构成。比如我们有5个顶点,分别按顺序编号为1,2,3,4,5,那么第一个三角形由1,2,3构成,第二个三角形由2,3,4构成,第三个三角形由3,4,5构成,如下图所示
放到代码里面,我们如果需要画一个矩形,则只需要4个顶点,同时将glDrawArrays的最后一个参数改为4。
float vertices[] =
-0.5f, -0.5f, 0.5f, 1.0f,
0.5f, -0.5f, 0.5f, 1.0f,
-0.5f, 0.5f, 0.5f, 1.0f,
0.5f, 0.5f, 0.5f, 1.0f,
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
Triangle fan是三角扇形,第一个三角形由三个顶点构成,第二个三角形由第一个三角形的第一个顶点和最后一个顶点外加一个新的顶点构成。以后的三角形,都需要第一个三角形的第一个顶点,同时保留最近的一个顶点,然后再加上一个新的顶点。还是1,2,3,4,5个顶点,第一个三角形由1,2,3构成,第二个三角形由1,3,4构成,第三个三角形则由1,4,5构成,如图
代码中,我们画一个矩形仍然需要4个顶点,只不过顺序需要变一下
float vertices[] =
0.5f, -0.5f, 0.5f, 1.0f,
-0.5f, -0.5f, 0.5f, 1.0f,
-0.5f, 0.5f, 0.5f, 1.0f,
0.5f, 0.5f, 0.5f, 1.0f,
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
代码已上传,资源地址 http://download.csdn.net/detail/hoytgm/7546293,欢迎大家交流~~~
没有更多推荐了,OpenGLES---画一个矩形
RectShader
画东西的几种类型
引用Shader中的属性(自己在Shader中写的一些需要传值的类型) glGetU/A...
设置Shader数据(Shader什么类型就用什么类型设置内容) glU/V...
-- RectShader
#include &gles2/gl2.h&
#include &assert.h&
class ShaderId
ShaderId(){id=-1;};
class ShaderVeual
ShaderVeual(){_programId=-1;}
_programId;
class RectShader
RectShader(){
_position=-1;
_color=-1;
void shaderInit(){
const char* vs
"p"//制定float的精度(lowp低精度)
"attribute
"void main()"
vec4(_position,0,1);"
gl_Position =
const char* ps
"void main()"
gl_FragColor
shaderveual=createProgram(vs,ps);
//获取属性的位置
= glGetAttribLocation(shaderveual._programId, "_position");
= glGetUniformLocation(shaderveual._programId,"_color");
= glGetUniformLocation(shaderveual._programId,"_MVP");
void begin(){
// 使用程序
glUseProgram(shaderveual._programId);
//启用顶点数组
glEnableVertexAttribArray(_position);
void end(){
//禁用顶点数组
glDisableVertexAttribArray(_position);
// 使用完成
glUseProgram(0);
virtual ShaderVeual createProgram( const char* vertex,const char* fragment ){
if (vertex){
// 创建Shader (GL_VERTEX_SHADER 顶点Shader,GL_FRAGMENT_SHADER 像素Shader)
program._vertex.id
= glCreateShader( GL_VERTEX_SHADER );
//制定shader的源代码
glShaderSource( program._vertex.id, 1, &vertex, 0 );
//编译Shader
glCompileShader( program._vertex.id );
//检查编译状态
/** 获取Shader编译状态
* GL_COMPILE_STATUS
* GL_INFO_LOG_LENGTH
* GL_SHADER_SOURCE_LENGTH
* GL_SHADER_COMPILER
glGetShaderiv( program._vertex.id, GL_COMPILE_STATUS, &compileStatus );
compileStatus == GL_FALSE;
if( error ){//如果编译失败
GLchar messages[256];
//获取编译日志
glGetShaderInfoLog( program._vertex.id, sizeof(messages), 0,messages);
//提升错误框
assert( messages && 0 != 0);
if (fragment){
* GL_FRAGMENT_SHADER 片段Shader/像素Shader
* glCreateShader( GL_VERTEX_SHADER );
program._fragment.id
= glCreateShader( GL_FRAGMENT_SHADER );
glShaderSource( program._fragment.id, 1, &fragment, 0 ); //制定shader的源代码
glCompileShader( program._fragment.id );//编译Shader
glGetShaderiv( program._fragment.id, GL_COMPILE_STATUS, &compileStatus );//获取编译状态
compileStatus == GL_FALSE;
if( error ){
GLchar messages[256];
glGetShaderInfoLog( program._fragment.id, sizeof(messages), 0,messages);//获取Shader编译日志
assert( messages && 0 != 0);
//创建一个程序(加载 vs ps)
program._programId
glCreateProgram( );
if (program._vertex.id) {
glAttachShader( program._programId, program._vertex.id);//加载 vs
if (program._fragment.id){
glAttachShader( program._programId, program._fragment.id);//加载 ps
glLinkProgram( program._programId );
GLint linkS
glGetProgramiv( program._programId, GL_LINK_STATUS, &linkStatus );//获取链接程序状态
if (linkStatus == GL_FALSE){
GLchar messages[256];
glGetProgramInfoLog( program._programId, sizeof(messages), 0, messages);
glUseProgram(program._programId);//使用 shads
} while(false);
if (error){
if (program._fragment.id != -1){
glDeleteShader(program._fragment.id);//删除像素Shader
program._fragment.id =
if (program._vertex.id != -1){
glDeleteShader(program._vertex.id);//删除顶点Shader
program._vertex.id
if (program._programId != -1){
glDeleteProgram(program._programId);//删除程序
program._programId
};---RectWin 窗口
#include "AppWin.hpp"
#include&vector&
#include &EGL/egl.h&
#include &gles2/gl2.h&
#include "freeImage/FreeImage.h"
#include "CELLMath.hpp"
#include "RectShader.hpp"
class RectWin :public AppWin
protected:
_ // 视口 宽度
_// 视口 高度
EGLDisplay _
EGLContext _
EGLSurface _
RectWin(HINSTANCE hInstance):AppWin(hInstance){}
virtual ~RectWin(){}
void destroy(){
if (_display != EGL_NO_DISPLAY){//当前的Display 不等于null
//清楚绑定的 Surface Context
eglMakeCurrent(_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
if (_context != EGL_NO_CONTEXT){//不等于空Context
//销毁上下文
eglDestroyContext(_display, _context);
if (_surface != EGL_NO_SURFACE){//不等于空Surface
//销毁Surface
eglDestroySurface(_display, _surface);
//终止Dispay
eglTerminate(_display);
//把 Display Context Surface 设置成初始化
EGL_NO_DISPLAY;
EGL_NO_CONTEXT;
EGL_NO_SURFACE;
bool glInit(){
//1:获取 Display
_display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
//2:初始化 egl
EGL//返回主版本号
EGL//返回次版本号
eglInitialize(_display, &major, &minor);
//3:选择 Config
const EGLint attribs[] ={
//属性是一对一的初始化(类似与key-&value)
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,//把数据画到窗口上
EGL_BLUE_SIZE, 8,//R 占8个比特位
EGL_GREEN_SIZE, 8,//G 占8个比特位
EGL_RED_SIZE, 8, //B 占8个比特位
EGL_DEPTH_SIZE,24,//深度值 占24个比特位
画图的深度值 (前后顺序的层)
//这个机构结束了
format(0);
EGLint numConfigs(0);
//让EGL为你选择一个配置
eglChooseConfig(_display, attribs, &_config, 1, &numConfigs);
//可以查询某个配置的某个属性
eglGetConfigAttrib(_display, _config, EGL_NATIVE_VISUAL_ID, &format);
//4:创建 Surface
_surface = eglCreateWindowSurface(_display, _config, _hWnd, NULL);
//5:创建上下文对象
EGLint attr[] ={ EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE, EGL_NONE };
//创建上下文对象
EGLContext _context = eglCreateContext(_display, _config, EGL_NO_CONTEXT, attr);
//6:查看 Display Surface Context 是否创建成功
if (eglMakeCurrent(_display, _surface, _surface, _context) == EGL_FALSE){
//查询Suface的属性 获取Suface中的宽高
eglQuerySurface(_display, _surface, EGL_WIDTH,
eglQuerySurface(_display, _surface, EGL_HEIGHT, &_height);
bool ini(){
if(!glInit()){}
shader.shaderInit();
void renderer(){
//GL_DEPTH_BUFFER_BIT 深度缓冲区
//GL_STENCIL_BUFFER_BIT 模版缓冲区
//GL_COLOR_BUFFER_BIT 颜色缓冲区
//清楚缓冲
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//设置视口的大小
glViewport(0,0,_width,_height);
CELL::matrix4 project=CELL::ortho&float&(0,(float)_width,(float)_height,0,-100,100);
//CELL::matrix4 project=CELL::lookAt(CELL::float3(0,0,5),CELL::float3(0,0,0),CELL::float3(0,1,0));
shader.begin();
float x=100;
float y=200;
float w=50;
float h=50;
//逆时针给坐标点,顺时针会出问题
CELL::float2 pos[]={
CELL::float2(x,y),
CELL::float2(x,y+h),
CELL::float2(x+w,y),
CELL::float2(x+w,y+h)
/** 给Uniform变量赋值
* @param location 变量
* @param count 值数量(当前数据里面有几个值 1,2,3,4)
* @param transpose 是否转置(true,false)
* @param value 赋值数据
glUniformMatrix4fv(shader._MVP,1,false,project.data());
//给Uniform变量赋值
glUniform4f(shader._color,1,0,0,1);
/** 设置顶点属性
* @param indx 属性id
* @param size 值数量(2,3,4)
* @param type 数据类型 (GL_UNSIGNED_BYTE,GL_FLOAT...)
* @param normalized
规格化(false,true)
* @param stride 偏移量(数据的偏移量)
* @param ptr
glVertexAttribPointer(shader._position,2,GL_FLOAT,false,sizeof(CELL::float2),pos);
glDrawArrays(GL_TRIANGLE_STRIP,0,4);
shader.end();
eglSwapBuffers(_display,_surface);
源码下载地址 (不是完整工程,只有用到的工程文件)
http://pan.baidu.com/s/1geVargZ
rect.zip(源码工程)
http://pan.baidu.com/s/1geVargZ
OpenGL_ES.zip(源码工程)
-- 画东西的几种类型
#define GL_POINTS
点 n/2个点,n是点数
#define GL_LINES
线(两个点确定一条线,点的数据必须是2的整数倍)
#define GL_LINE_STRIP 线带,
首尾不相连接(线带,假如有3个点:第1个的点和第2个点的相连,第2个点和第3条线,第3个点不和第1个点连接-&首尾不相连接)
#define GL_LINE_LOOP 线环,首尾相连(线环,假如有3个点:第1个的点和第2个点的相连,第2个点和第3条线,第3个点和第1个点连接-&首尾连接)
#define GL_TRIANGLES
三角形 (三个点画一个三角形,点的数据必须是3的整数倍)
#define GL_TRIANGLE_STRIP 三角形带, n-2个三角形,n是点数 (假如有4个点,可以画2个三角形,前三个点是一个三角形,后一个点和离它近的两个点组成一个三角形)
#define GL_TRIANGLE_FAN
三角形扇 (例画圆,圆心是一点,圆周长上一点,在圆周长上一点,在圆周长上一点,...
前三个点是一个三角形,后一个周长上的点和圆心点和上一个周长上的一点又组成一个三角形...
画n个三角形组成一个圆)
/*** 绘制数组
* @param mode 绘画的模式(点,线,三角形)
* @param first 顶点数组 第几个开始
* @param count 顶点数组 大小
GL_APICALL void GL_APIENTRY glDrawArrays (GLenum mode, GLint first, GLsizei count);
/**绘制元素
绘制模式(GL_TRIANGLES三角形...)
count 绘制数据大小(绘制多少个点)
数据类型(GL_UNSIGNED_BYTE ...)
0:顶点缓冲和索引缓冲数据都用
indexBuf:用顶点缓冲区数据不要索引缓冲区数据,就把索引数据传入
GL_APICALL void GL_APIENTRY glDrawElements (GLenum mode, GLsizei count, GLenum type, const GLvoid* indices);
引用Shader中的属性(自己在Shader中写的一些需要传值的类型) glGetU/A...
const char* vs
"attribute
= glGetAttribLocation(shaderveual._programId, "_position");
设置Shader数据(Shader什么类型就用什么类型设置内容) glU/V...
//逆时针给坐标点,顺时针会出问题
CELL::float2 pos[]={
CELL::float2(x,y),
CELL::float2(x,y+h),
CELL::float2(x+w,y),
CELL::float2(x+w,y+h)
glVertexAttribPointer(shader._position,2,GL_FLOAT,false,sizeof(CELL::float2),pos);
glDrawArrays(GL_TRIANGLE_STRIP,0,4);
用openGL ES绘制圆角矩形的实现
OpenglES2.0 for Android:来画个矩形吧
canvas画一个简单的红色矩形
OpenGL学习1—画一个矩形
利用shader绘制矩形网格
【cocos2d-x 2.x 学习与应用总结】14: 自定义shader绘制混合颜色的矩形
没有更多推荐了,【图文】Open GL_百度文库
您的浏览器Javascript被禁用,需开启后体验完整功能,
享专业文档下载特权
&赠共享文档下载特权
&10W篇文档免费专享
&每天抽奖多种福利
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
阅读已结束,下载本文到电脑
定制HR最喜欢的简历
你可能喜欢机智的女王大人的老公的博客
Open GL ES 三角形绘制
Open GL ES 三角形绘制
画三角形是open GL ES中最简单的入门项目,下面讲解具体的流程,方便自己总结工具类,没有别的意思。
在Android项目中引进open GL
为了使用OpenGL ES 2.0 API,需要添加如下声明:
&uses-feature android:glEsVersion="0x" android:required="true" /&
创建GLSurfaceView
GLSurfaceView是用来放置图形view的容器。所有的东西都是绘制在GLSurfaceView上面的,就相当于画布的概念,
这里先实现一个GLSurfaceView。扩展自GLSurfaceView,实现自己的MyGLSurfaceView
public class MyGLSurfaceView extends GLSurfaceView {
private Context mC
public MyGLSurfaceView(Context context) {
super(context);
public MyGLSurfaceView(Context context, AttributeSet attrs) {
super(context, attrs);
创建Render
Renderer类(渲染器类),即 GLSurfaceView.Renderer的实现类,它控制了与它相关联的 GLSurfaceView 上绘制什么。
需要实现一下接口:
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
public void onSurfaceChanged(GL10 gl, int width, int height) {
public void onDrawFrame(GL10 gl) {
onSurfaceCreated()函数在surface创建的时候调用,所以初始化的工作在里面完成。
onSurfaceChanged()函数在surface发生改变的时候调用;
onDrawFrame()函数是完成surfaceview上面显示内容的绘制,每一帧的绘制都会去调用。
基础参数设置
private final int mStrideBytes = 7 * 4;
private final int mPositionOffset = 0;
private final int mPositionDataSize = 3;
private final int mColorOffset = 3;
private final int mColorDataSize = 4;
mStrideBytes是指定buffer在读取数据的时候一次读取多少,7表示个数,7个数据, 4表示字节,7*4表示一次读取多少字节的数据。
-0.5f, -0.25f, 0.0f,
1.0f, 0.0f, 0.0f, 1.0f,
mPositionOffset表示顶点坐标的偏移量
mPositionDataSize表示顶底每个顶点坐标用多少个数据表示,三个:-0.5f, -0.25f, 0.0f,
mColorOffset读取颜色数据时的偏移量,因为顶点坐标用3个数据表示,所以偏移量为3
mColorDataSize表示多少个数据表示一个颜色,4个参数分别为ARGB
顶点坐标和颜色坐标
private final float vertexData[] = {
-0.5f, -0.25f, 0.0f,
1.0f, 0.0f, 0.0f, 1.0f,
0.5f, -0.25f, 0.0f,
0.0f, 0.0f, 1.0f, 1.0f,
0.0f, 0.f, 0.0f,
0.0f, 1.0f, 0.0f, 1.0f
可以看到,每组数据有7个,前面3个表示位置坐标,后面4个表示颜色值,可以结合前面的参数设置来理解。
这个数据是程序传入openGL的数据。
创建Buffer存放数据
private FloatBuffer mShaderDateB
private FloatBuffer getVertexBuffer(float[] data) {
ByteBuffer vbb = ByteBuffer.allocateDirect(data.length * 4);
vbb.order(ByteOrder.nativeOrder());
FloatBuffer vertexBuffer = vbb.asFloatBuffer();
vertexBuffer.put(data);
vertexBuffer.position(0);
return vertexB
上面代码中的注释已经很清楚了,里面的代码大多数是固定的写法。
Matrix的设置
openGL 中有三个类型份额举证,分别是:
* Model Matrix
* View Matrix
* Projection Matrix
由于这几个概念很绕,是个人都要糊弄一会儿才能搞清楚,下面就这几个矩阵,好好的糊弄糊弄。
所谓的坐标变换,就是将一个坐标系下的坐标,在另外一个坐标系中表示出来。
下图中世界坐标系下的相机:
将相机定位在(1,0,1,1)(注意这个地方是用4维向量来表示,最后一个维度取值只能为0或者1,1表示点,0表示向量)。
照相机的指向可以用 n = (-1,0,-1,0) 用原点坐标(0,0,0,1)减去相机坐标得到的。同时设置照相机的观察正向和世界坐标系下的
y轴的方向一致, v = (0,1,0,0), 此时,利用向量的叉乘可以得到 相机坐标系下的第三个坐标轴的方向,u =
计算得到u = (1,0,-1,0) ,这样照相机自己构成的坐标系为(u, v, n, P).
这个东西就是将坐标从世界坐标转换到相机坐标的矩阵,那世界坐标的原点为例(0,0,0,1), 有
在opengl中,数据从用户构建的局部坐标系,经过一系列的处理,最终渲染在屏幕上面,主要经过了一下过程:
Open gl中只定义了裁剪坐标系、规范化设备坐标系以及屏幕坐标系,而局部坐标系、世界坐标系和相机坐标系是为了
方便用户的,用户在OpenGL中的转换如下:
从坐标来看,就是一下过程
下图中茶壶在Model Matrix中的定义
世界坐标系下的茶壶:
从世界坐标系到相机坐标系
为什么要将世界坐标系转化到相机坐标系,我们最终看到的就是相机拍到的,而不是上帝视角下看到的一切(纯属个人理解,不喜勿喷)。
从相机坐标系到裁剪坐标系,通过投影完成的。分为正交投影和透视投影两种。
最后读下来还是感觉很晕,的确很晕。那这些东西和上面提到的三个矩阵有什么关系呢?
基本上就是: Model Matrix是模型坐标系转换到世界坐标系用,View Matrix就是视图坐标系,用来转换到相机坐标系用的,Projection Matrix转化裁剪坐标系的。
ES中坐标系矩阵的计算
计算模型矩阵,里面调用了rotateM接口
private float[] mModelMatrix = new float[16];
private void initModelMatrix() {
long time = SystemClock.uptimeMillis() % 10000L;
float angleInDegrees = (360.0f / 10000.0f) * ((int) time);
Matrix.setIdentityM(mModelMatrix, 0);
Matrix.rotateM(mModelMatrix, 0, angleInDegrees, 0.0f, 0.0f, 1.0f);
计算ViewMatrix,需要设置相机的位置,相机观察的方向,以及相机的观察正向向量
private float[] mViewMatrix = new float[16];
private void initViewMatrix() {
final float eyeX = 0.0f;
final float eyeY = 0.0f;
final float eyeZ = 1.5f;
final float lookX = 0.0f;
final float lookY = 0.0f;
final float lookZ = -5.0f;
final float upX = 0.0f;
final float upY = 1.0f;
final float upZ = 0.0f;
Matrix.setLookAtM(mViewMatrix, 0, eyeX, eyeY, eyeZ, lookX, lookY, lookZ, upX, upY, upZ);
投影矩阵,设置关于远近 以及投影屏幕的大小等属性。
private float[] mProjectionMatrix = new float[16];
private void initProjectionMatrix(int width, int height) {
GLES20.glViewport(0, 0, width, height);
final float ratio = (float) width /
final float left = -
final float right =
final float bottom = -1.0f;
final float top = 1.0f;
final float near = 1.0f;
final float far = 10.0f;
Matrix.frustumM(mProjectionMatrix, 0, left, right, bottom, top, near, far);
Shader数据传入
使用工具类:
public static int compileShader(final int shaderType, final String shaderSource) {
int shaderHandle = GLES20.glCreateShader(shaderType);
if (shaderHandle != 0) {
GLES20.glShaderSource(shaderHandle, shaderSource);
GLES20.glCompileShader(shaderHandle);
final int[] compileStatus = new int[1];
GLES20.glGetShaderiv(shaderHandle, GLES20.GL_COMPILE_STATUS, compileStatus, 0);
if (compileStatus[0] == 0) {
Log.e(TAG, "Error compiling shader: " + GLES20.glGetShaderInfoLog(shaderHandle));
GLES20.glDeleteShader(shaderHandle);
shaderHandle = 0;
if (shaderHandle == 0) {
throw new RuntimeException("Error creating shader.");
return shaderH
shaderType为两种,一种是GLES20.GL_VERTEX_SHADER,一种是GLES20.GL_FRAGMENT_SHADER。最终返回的是shader的句柄,后面要用到这个句柄传入参数,
vertexShader
uniform mat4 u_MVPM
attribute vec4 a_P
attribute vec4 a_C
varying vec4 v_C
void main() {
v_Color = a_C
gl_Position = u_MVPMatrix * a_P
fragmentShader
precision mediump float;
varying vec4 v_C
void main() {
gl_FragColor = v_C
变量,这些变量是在shader中定义的,这里的名称和c语言中定义的名称一致。通过这个个名称获取变量,传入参数
private String[] mAttributes = {
"u_MVPMatrix",
"a_Position",
public static int createAndLinkProgram(final int vertexShaderHandle, final int fragmentShaderHandle, final String[] attributes) {
int programHandle = GLES20.glCreateProgram();
if (programHandle != 0) {
GLES20.glAttachShader(programHandle, vertexShaderHandle);
GLES20.glAttachShader(programHandle, fragmentShaderHandle);
if (attributes != null) {
final int size = attributes.
for (int i = 0; i & i++) {
GLES20.glBindAttribLocation(programHandle, i, attributes[i]);
GLES20.glLinkProgram(programHandle);
final int[] linkStatus = new int[1];
GLES20.glGetProgramiv(programHandle, GLES20.GL_LINK_STATUS, linkStatus, 0);
if (linkStatus[0] == 0) {
Log.e(TAG, "Error compiling program: " + GLES20.glGetProgramInfoLog(programHandle));
GLES20.glDeleteProgram(programHandle);
programHandle = 0;
if (programHandle == 0) {
throw new RuntimeException("Error creating program.");
return programH
最后一步,绘制图形
onSurfaceCreated函数主要是做初始化用的。
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
GLES20.glClearColor(0f, 0f, 0f, 0f);
initViewMatrix();
initShader();
private void initShader() {
int vertexShaderHandle = ShaderHelper.compileShader(GLES20.GL_VERTEX_SHADER, TextResourceReader.readTextFileFromResource(mContext, R.raw.vertex_shader));
int fragmentShaderHandle = ShaderHelper.compileShader(GLES20.GL_FRAGMENT_SHADER, TextResourceReader.readTextFileFromResource(mContext, R.raw.fragment_shader));
int programHandle = ShaderHelper.createAndLinkProgram(vertexShaderHandle, fragmentShaderHandle, mAttributes);
mMVPMatrixHandle = GLES20.glGetUniformLocation(programHandle, "u_MVPMatrix");
mPositionHandle = GLES20.glGetAttribLocation(programHandle, "a_Position");
mColorHandle = GLES20.glGetAttribLocation(programHandle, "a_Color");
GLES20.glUseProgram(programHandle);
onSurfaceChanged()函数
public void onSurfaceChanged(GL10 gl, int width, int height) {
initProjectionMatrix(width, height);
onDrawFrame()绘制
public void onDrawFrame(GL10 gl) {
GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
initModelMatrix();
drawFrame(mShaderDateBuffer);
private void drawFrame(final FloatBuffer frameBuffer) {
frameBuffer.position(mPositionOffset);
GLES20.glVertexAttribPointer(mPositionHandle, mPositionDataSize, GLES20.GL_FLOAT, false,
mStrideBytes, frameBuffer);
GLES20.glEnableVertexAttribArray(mPositionHandle);
frameBuffer.position(mColorOffset);
GLES20.glVertexAttribPointer(mColorHandle, mColorDataSize, GLES20.GL_FLOAT, false,
mStrideBytes, frameBuffer);
GLES20.glEnableVertexAttribArray(mColorHandle);
Matrix.multiplyMM(mMVPMatrix, 0, mViewMatrix, 0, mModelMatrix, 0);
Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mMVPMatrix, 0);
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mMVPMatrix, 0);
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 3);
GLES20.glVertexAttribPointer(mPositionHandle, mPositionDataSize, GLES20.GL_FLOAT, false,
mStrideBytes, frameBuffer)
mPositionHandle是GLES20.glGetAttribLocation(programHandle, "a_Position");绑定的变量,mPositionDataSize表示position坐标的数据个数,
也就是多少个数据表示一个坐标,mStrideBytes表示每次读取多少字节数据。
同样地,GLES20.glVertexAttribPointer(mColorHandle, mColorDataSize, GLES20.GL_FLOAT, false,mStrideBytes, frameBuffer);
是传入color数据。
Matrix.multiplyMM是计算MVP矩阵。
glDrawArrays参数详解
在OpenGl中所有的图形都是通过分解成三角形的方式进行绘制。
绘制图形通过GL10类中的glDrawArrays方法实现,
该方法原型:
glDrawArrays(int mode, int first,int count)
*参数1:有三种取值
1.GL_TRIANGLES:每三个顶之间绘制三角形,之间不连接
2.GL_TRIANGLE_FAN:以V0V1V2,V0V2V3,V0V3V4,……的形式绘制三角形
3.GL_TRIANGLE_STRIP:顺序在每三个顶点之间均绘制三角形。这个方法可以保证从相同的方向上所有三角形均被绘制。以V0V1V2,V1V2V3,V2V3V4……的形式绘制三角形
*参数2:从数组缓存中的哪一位开始绘制,一般都定义为0
*参数3:顶点的数量
MainActivity
MainActivity中增加opengl版本支持相关代码。
private MyGLSurfaceView mGLSurfaceV
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final ActivityManager activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
final ConfigurationInfo configurationInfo = activityManager.getDeviceConfigurationInfo();
final boolean supportsEs2 = configurationInfo.reqGlEsVersion &= 0x20000;
if (supportsEs2)
mGLSurfaceView.setEGLContextClientVersion(2);
mGLSurfaceView.setRenderer(new MyRender(this));
setContentView(mGLSurfaceView);
private void initGL() {
mGLSurfaceView = new MyGLSurfaceView(this);
protected void onPause() {
super.onPause();
mGLSurfaceView.onPause();
protected void onResume() {
super.onResume();
mGLSurfaceView.onResume();
画一个三角形和写一个Hello World一样难!!!
References
没有更多推荐了,

我要回帖

更多关于 2017年光场相机三代 的文章

 

随机推荐