OpenGLES---画一个矩形

Posted GameCocos2dx

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OpenGLES---画一个矩形相关的知识,希望对你有一定的参考价值。

{目录
	RectShader  
	RectWin  窗口
	画东西的几种类型
	引用Shader中的属性(自己在Shader中写的一些需要传值的类型) glGetU/A...
	设置Shader数据(Shader什么类型就用什么类型设置内容) glU/V...
}

-- RectShader

#include <gles2/gl2.h>
#include <assert.h>

typedef     int uniform;
typedef     int attribute;
typedef		int location; 


class ShaderId
{
public:
	ShaderId(){id=-1;};
public:
	int id;
}; 

class ShaderVeual
{
public:
	ShaderVeual(){_programId=-1;}
public:
	int  _programId;
	ShaderId  _vertex;
	ShaderId  _fragment;
};

class RectShader
{
public:
	ShaderVeual shaderveual;

	attribute   _position;
	uniform		_color;
	uniform     _MVP;

public :
	RectShader(){
		_position=-1;
		_color=-1;
		_MVP=-1;
	}

	void shaderInit(){
		const char* vs  = {
			"precision  lowp float;"//制定float的精度(lowp低精度)
			"uniform    mat4    _MVP;"
			"attribute  vec2    _position;"
			"void main()"
			"{"
			"   vec4    pos =   vec4(_position,0,1);"
			"   gl_Position =   _MVP * pos;"
			"}"
		};
		const char* ps  = {
			"precision lowp float;"
			"uniform    vec4   _color;"
			"void main()"
			"{"
			"   gl_FragColor    =  _color;"
			"}"
		};
		shaderveual=createProgram(vs,ps);
		//获取属性的位置
		_position   = glGetAttribLocation(shaderveual._programId, "_position");
		_color		= glGetUniformLocation(shaderveual._programId,"_color");
		_MVP        = 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 ){
        ShaderVeual   program;
        bool  error   =   false;
        do{
            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 );

				//检查编译状态
                GLint   compileStatus;
				/** 获取Shader编译状态
				* GL_COMPILE_STATUS  编译状态
				* GL_INFO_LOG_LENGTH                0x8B84
				* GL_SHADER_SOURCE_LENGTH           0x8B88
				* GL_SHADER_COMPILER                0x8DFA
				*/
                glGetShaderiv( program._vertex.id, GL_COMPILE_STATUS, &compileStatus );
                error   =   compileStatus == GL_FALSE;
                if( error ){//如果编译失败
                    GLchar messages[256];
					//获取编译日志
                    glGetShaderInfoLog( program._vertex.id, sizeof(messages), 0,messages);
					//提升错误框
                    assert( messages && 0 != 0);
                    break;
                }
            }
			//编译ps
            if (fragment){
				/***
				* GL_FRAGMENT_SHADER 片段Shader/像素Shader
				* glCreateShader( GL_VERTEX_SHADER );
			    *@reruen 
				****/
                program._fragment.id   = glCreateShader( GL_FRAGMENT_SHADER );
                glShaderSource( program._fragment.id, 1, &fragment, 0 );	//制定shader的源代码
                glCompileShader( program._fragment.id );//编译Shader

                GLint   compileStatus;
                glGetShaderiv( program._fragment.id, GL_COMPILE_STATUS, &compileStatus );//获取编译状态
                error   =   compileStatus == GL_FALSE;

                if( error ){
                    GLchar messages[256];
                    glGetShaderInfoLog( program._fragment.id, sizeof(messages), 0,messages);//获取Shader编译日志
                    assert( messages && 0 != 0);
                    break;
                }
            }

			//创建一个程序(加载 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 linkStatus;
            glGetProgramiv( program._programId, GL_LINK_STATUS, &linkStatus );//获取链接程序状态
            if (linkStatus == GL_FALSE){
                GLchar messages[256];
                glGetProgramInfoLog( program._programId, sizeof(messages), 0, messages);
                break;
            }
            glUseProgram(program._programId);//使用 shads

        } while(false);

        if (error){
            if (program._fragment.id != -1){
                glDeleteShader(program._fragment.id);//删除像素Shader
                program._fragment.id =   0;
            }
            if (program._vertex.id != -1){
                glDeleteShader(program._vertex.id);//删除顶点Shader
                program._vertex.id   =   0;
            }
            if (program._programId != -1){
                glDeleteProgram(program._programId);//删除程序
                program._programId          =   0;
            }
        }
        return  program;
	}
};

---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:
	int         _width; // 视口 宽度
	int         _height;// 视口 高度

	EGLDisplay _display;
	EGLContext _context;
	EGLSurface _surface;
	EGLConfig  _config;

	RectShader  shader;

public:
	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 设置成初始化
		_display    =   EGL_NO_DISPLAY;
		_context    =   EGL_NO_CONTEXT;
		_surface    =   EGL_NO_SURFACE;
	}
	bool glInit(){
		//1:获取 Display
		_display = eglGetDisplay(EGL_DEFAULT_DISPLAY);

		//2:初始化 egl
		EGLint  major;//返回主版本号
		EGLint  minor;//返回次版本号
		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个比特位  画图的深度值 (前后顺序的层)
			EGL_NONE  //这个机构结束了
		};
		EGLint 	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){
			return false;
		}

		//查询Suface的属性 获取Suface中的宽高
		eglQuerySurface(_display, _surface, EGL_WIDTH,  &_width);
		eglQuerySurface(_display, _surface, EGL_HEIGHT, &_height);

		return true;
	}

	bool ini(){
		if(!glInit()){return false;}
		shader.shaderInit();
		return true;
	}
	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);

/**绘制元素
 * @param  mode  绘制模式(GL_TRIANGLES三角形...)
 * @param  count 绘制数据大小(绘制多少个点)
 * @param  type  数据类型(GL_UNSIGNED_BYTE ...)
 * @param  indices 
 *         			0:顶点缓冲和索引缓冲数据都用
 *                 	indexBuf:用顶点缓冲区数据不要索引缓冲区数据,就把索引数据传入
 * @return 
 */
GL_APICALL void GL_APIENTRY glDrawElements (GLenum mode, GLsizei count, GLenum type, const GLvoid* indices);
 
 

引用Shader中的属性(自己在Shader中写的一些需要传值的类型) glGetU/A...

类似这样

typedef     int attribute;
attribute   _position;
const char* vs  = {
	...
	"attribute  vec2    _position;"
	...
};
_position   = 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);
...


以上是关于OpenGLES---画一个矩形的主要内容,如果未能解决你的问题,请参考以下文章

OpenglES2.0 for Android:来画个矩形吧

使用C++代码直接在IMFMediaBuffer上画一个矩形

C# WPF 怎么画点?怎么画矩形?

MFC怎么绘制一个圆角矩形

vb代码之------画一个半透明矩形

OpenCV的鼠标操作——用鼠标画矩形(代码解读)