{目錄
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);
...