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);
...


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章