文章目錄
一.shader
二.API
三.調用說明
四.擼代碼
一.shader
二.API
//創建shader,返回shader Id //param: //GL_VERTEX_SHADER 定點shader //GL_FRAGMENT_SHADER像素shader glCreateShader(GLenum type); //設置shader來源 //param //shader:shader 的id //count:數量 //string:內容 //length: 如果length為NULL,則認為每個字符串都以null結尾。如果length不是NULL,則它指向包含字符串的每個相應元素的字符串長度的數組。 glShaderSource (GLuint shader, GLsizei count, const GLchar** string, const GLint* length); //編譯shader //傳入shaderId glCompileShader(GLuint shader) //獲取shader狀態 //shaderId //查看GL_COMPILE_STATUS //返回參數 glGetShaderiv(GLuint shader, GLenum pname, GLint* params); //獲取shader日志 glGetShaderInfoLog (GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog); //創建program,返回id glCreateProgram( ); //關聯shader到program上 glAttachShader(GLuint program, GLuint shader) //鏈接program glLinkProgram(GLuint program); //獲取program信息 glGetProgramiv(GLuint program, GLenum pname, GLint* params); //獲取program日志 glGetProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog); //使用program glUseProgram(GLuint program); //方式shader對象 glDeleteShader (GLuint shader); //刪除program對象 glDeleteProgram (GLuint program); //獲取屬性位置,這樣CPU和GPU的變量就互通了。 //我們可以傳入我們的變量 glGetAttribLocation (GLuint program, const GLchar* name) glGetUniformLocation (GLuint program, const GLchar* name);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
//Uniform 全局變量
uniforms保存由應用程序傳遞給著色器的只讀常量數據。在頂點著色器中,這些數據通常是變換矩陣,光照參數,顏色等。由 uniform 修飾符修飾的變量屬于全局變量,該全局性對頂點著色器與片元著色器均可見,也就是說,這兩個著色器如果被連接到同一個應用程序中,它們共享同一份 uniform 全局變量集。因此如果在這兩個著色器中都聲明了同名的 uniform 變量,要保證這對同名變量完全相同:同名+同類型,因為它們實際是同一個變量。此外,uniform 變量存儲在常量存儲區,因此限制了 uniform 變量的個數,OpenGL ES 2.0 也規定了所有實現應該支持的最大頂點著色器 uniform 變量個數不能少于 128 個,最大的片元著色器 uniform 變量個數不能少于 16 個。
//Attribute 局部變量
由 vertext array 提供的頂點數據,如空間位置,法向量,紋理坐標以及頂點顏色,它是針對每一個頂點的數據。屬性只在頂點著色器中才有,片元著色器中沒有屬性。屬性可以理解為針對每一個頂點的輸入數據。OpenGL ES 2.0 規定了所有實現應該支持的最大屬性個數不能少于 8 個。
三.調用說明
1.首先需要創建窗口,可以參考之前的博客
2.opengl es初始化
3.創建program對象,創建頂點shader,像素shader,編譯shader,鏈接shader
4.使用glGetAttribLocation/glGetUniformLocation/glGetUniformLocation
關聯shader中的變量
5.把shader attach到program對象中,調用glUseProgram 使用program對象
6.使用glEnableVertexAttribArray 開啟數組傳值
7.使用glUniformMatrix4fv/glUniform4f/glVertexAttribPointer 把變量的值傳入shader
8.glDrawArrays畫圖形
9.關閉傳值,關閉shader
glDisableVertexAttribArray(_position);
glUseProgram(0);
10.eglSwapBuffers 顯示到屏幕上
注意:
Uniform
Attribute
的意義
四.擼代碼
CELLShader.hpp
#pragma once #include class ShaderId { public: ShaderId() { _shaderId = -1; } int _shaderId; }; /** * 程序 */ class ProgramId { public: int _programId; ShaderId _vertex; ShaderId _fragment; public: ProgramId() { _programId = -1; } public: /** * 加載函數 */ bool createProgram( const char* vertex,const char* fragment ) { bool error = false; do { //頂點shader if (vertex) { _vertex._shaderId = glCreateShader( GL_VERTEX_SHADER ); glShaderSource( _vertex._shaderId, 1, &vertex, 0 ); glCompileShader( _vertex._shaderId ); GLint compileStatus; glGetShaderiv( _vertex._shaderId, GL_COMPILE_STATUS, &compileStatus ); error = compileStatus == GL_FALSE; if( error ) { GLchar messages[256]; glGetShaderInfoLog( _vertex._shaderId, sizeof(messages), 0,messages); assert( messages && 0 != 0); break; } } //像素shader if (fragment) { _fragment._shaderId = glCreateShader( GL_FRAGMENT_SHADER ); glShaderSource( _fragment._shaderId, 1, &fragment, 0 ); glCompileShader( _fragment._shaderId ); GLint compileStatus; glGetShaderiv( _fragment._shaderId, GL_COMPILE_STATUS, &compileStatus ); error = compileStatus == GL_FALSE; if( error ) { GLchar messages[256]; glGetShaderInfoLog( _fragment._shaderId, sizeof(messages), 0,messages); assert( messages && 0 != 0); break; } } _programId = glCreateProgram( ); if (_vertex._shaderId) { glAttachShader( _programId, _vertex._shaderId); } if (_fragment._shaderId) { glAttachShader( _programId, _fragment._shaderId); } glLinkProgram( _programId ); GLint linkStatus; glGetProgramiv( _programId, GL_LINK_STATUS, &linkStatus ); if (linkStatus == GL_FALSE) { GLchar messages[256]; glGetProgramInfoLog( _programId, sizeof(messages), 0, messages); break; } glUseProgram(_programId); } while(false); if (error) { if (_fragment._shaderId) { glDeleteShader(_fragment._shaderId); _fragment._shaderId = 0; } if (_vertex._shaderId) { glDeleteShader(_vertex._shaderId); _vertex._shaderId = 0; } if (_programId) { glDeleteProgram(_programId); _programId = 0; } } return true; } /** * 使用程序 */ virtual void begin() { glUseProgram(_programId); } /** * 使用完成 */ virtual void end() { glUseProgram(0); } }; class PROGRAM_P2_C4 :public ProgramId { public: typedef int attribute; typedef int uniform; public: attribute _position; uniform _color; uniform _MVP; public: PROGRAM_P2_C4() { _position = -1; _color = -1; _MVP = -1; } ~PROGRAM_P2_C4() { } /// 初始化函數 virtual bool initialize() { const char* vs = { "precision lowp float; " "uniform mat4 _MVP;" "attribute vec2 _position;" "void main()" "{" " vec4 pos = vec4(_position,0,1);" " gl_Position = _MVP * pos;"http://點乘以正交投影矩陣,等于一個位置 "}" }; const char* ps = { "precision lowp float; " "uniform vec4 _color;" "void main()" "{" " gl_FragColor = _color;" "}" }; bool res = createProgram(vs,ps); if(res) { //關聯cpu與 gpu變量 _position = glGetAttribLocation(_programId,"_position"); _color = glGetUniformLocation(_programId,"_color"); _MVP = glGetUniformLocation(_programId,"_MVP"); } return res; } /** * 使用程序 */ virtual void begin() { glUseProgram(_programId); glEnableVertexAttribArray(_position); } /** * 使用完成 */ virtual void end() { glDisableVertexAttribArray(_position); glUseProgram(0); } };
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
CELLWinapp.hpp
#pragma once #include #include #include #include #include "CELLMath.hpp" #include "CELLShader.hpp" namespace CELL { class CELLWinApp { public: //! 實例句柄 HINSTANCE _hInstance; //! 窗口句柄 HWND _hWnd; //! 窗口的高度 int _width; //! 窗口的寬度 int _height; /// for gles2.0 EGLConfig _config; EGLSurface _surface; EGLContext _context; EGLDisplay _display; //! 增加shader PROGRAM_P2_C4 _shader; public: CELLWinApp(HINSTANCE hInstance) :_hInstance(hInstance) { WNDCLASSEX winClass; winClass.lpszClassName = _T("CELLWinApp"); winClass.cbSize = sizeof(winClass); winClass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; winClass.lpfnWndProc = wndProc; winClass.hInstance = hInstance; winClass.hIcon = 0; winClass.hIconSm = 0; winClass.hCursor = LoadCursor(hInstance, IDC_ARROW); winClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); winClass.lpszMenuName = NULL; winClass.cbClsExtra = 0; winClass.cbWndExtra = 0; RegisterClassEx(&winClass); } virtual ~CELLWinApp() { UnregisterClass(_T("CELLWinApp"),_hInstance); } /** * 初始化 OpenGLES2.0 */ bool initOpenGLES20() { const EGLint attribs[] = { EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_BLUE_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_RED_SIZE, 8, EGL_DEPTH_SIZE,24, EGL_NONE }; EGLint format(0); EGLint numConfigs(0); EGLint major; EGLint minor; //! 1 _display = eglGetDisplay(EGL_DEFAULT_DISPLAY); //! 2init eglInitialize(_display, &major, &minor); //! 3 eglChooseConfig(_display, attribs, &_config, 1, &numConfigs); eglGetConfigAttrib(_display, _config, EGL_NATIVE_VISUAL_ID, &format); //! 4 _surface = eglCreateWindowSurface(_display, _config, _hWnd, NULL); //! 5 EGLint attr[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE, EGL_NONE }; _context = eglCreateContext(_display, _config, 0, attr); //! 6 if (eglMakeCurrent(_display, _surface, _surface, _context) == EGL_FALSE) { return false; } eglQuerySurface(_display, _surface, EGL_WIDTH, &_width); eglQuerySurface(_display, _surface, EGL_HEIGHT, &_height); return true; } /** * 銷毀OpenGLES2.0 */ void destroyOpenGLES20() { if (_display != EGL_NO_DISPLAY) { eglMakeCurrent(_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); if (_context != EGL_NO_CONTEXT) { eglDestroyContext(_display, _context); } if (_surface != EGL_NO_SURFACE) { eglDestroySurface(_display, _surface); } eglTerminate(_display); } _display = EGL_NO_DISPLAY; _context = EGL_NO_CONTEXT; _surface = EGL_NO_SURFACE; } protected: static LRESULT CALLBACK wndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { CELLWinApp* pThis = (CELLWinApp*)GetWindowLong(hWnd,GWL_USERDATA); if (pThis) { return pThis->onEvent(hWnd,msg,wParam,lParam); } if (WM_CREATE == msg) { CREATESTRUCT* pCreate = (CREATESTRUCT*)lParam; SetWindowLong(hWnd,GWL_USERDATA,(DWORD_PTR)pCreate->lpCreateParams); } return DefWindowProc( hWnd, msg, wParam, lParam ); } public: /** * 事件函數 */ virtual LRESULT onEvent(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { case WM_CLOSE: case WM_DESTROY: { ::PostQuitMessage(0); } break; case WM_MOUSEMOVE: break; default: return DefWindowProc( hWnd, msg, wParam, lParam ); } return S_OK; } virtual void render() { //! 清空緩沖區 glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); //! 視口,在Windows窗口指定的位置和大小上繪制OpenGL內容 glViewport(0,0,_width,_height); //! 創建一個投影矩陣 /正交投影 CELL::matrix4 screenProj = CELL::ortho(0,float(_width),float(_height),0,-100.0f,100); _shader.begin(); { float x = 100; float y = 100; float w = 100; float h = 100; //頂點位置 CELL::float2 pos[] = { CELL::float2(x,y), CELL::float2(x + w,y), CELL::float2(y,y + h), CELL::float2(x + w, y + h), }; //傳入正交矩陣,uniform是定量不會被改變 glUniformMatrix4fv(_shader._MVP, 1, false, screenProj.data()); //傳入顏色 glUniform4f(_shader._color,1,0,0,1); //傳入頂點坐標,傳入的頂點坐標會根據數量 決定調用次數 glVertexAttribPointer(_shader._position,2,GL_FLOAT,false,sizeof(CELL::float2),pos); glDrawArrays(GL_TRIANGLE_STRIP,0,4); } _shader.end(); } /** * 主函數 */ int main(int width,int height) { _hWnd = CreateWindowEx( NULL, _T("CELLWinApp"), _T("CELLWinApp"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, width, height, NULL, NULL, _hInstance, this ); if (_hWnd == 0) { return -1; } UpdateWindow(_hWnd); ShowWindow(_hWnd,SW_SHOW); if (!initOpenGLES20()) { return false; } _shader.initialize(); MSG msg = {0}; while(msg.message != WM_QUIT) { if (msg.message == WM_DESTROY || msg.message == WM_CLOSE) { break; } /** * 有消息,處理消息,無消息,則進行渲染繪制 */ if( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) ) { TranslateMessage( &msg ); DispatchMessage( &msg ); } else { render(); eglSwapBuffers(_display,_surface); } } /** * 銷毀OpenGLES20 */ destroyOpenGLES20(); return 0; } }; }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
main.cpp
#include "CELLWinApp.hpp" int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) { UNREFERENCED_PARAMETER(hPrevInstance); UNREFERENCED_PARAMETER(hInstance); UNREFERENCED_PARAMETER(lpCmdLine); UNREFERENCED_PARAMETER(nCmdShow); CELL::CELLWinApp app(hInstance); app.main(800,600); return 0; }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
namespace CELL { //正交投影 template tmat4x4 ortho ( valType left, valType right, valType bottom, valType top, valType zNear, valType zFar ) { tmat4x4 res(1); res[0][0] = valType(2) / (right - left); res[1][1] = valType(2) / (top - bottom); res[2][2] = - valType(2) / (zFar - zNear); res[3][0] = - (right + left) / (right - left); res[3][1] = - (top + bottom) / (top - bottom); res[3][2] = - (zFar + zNear) / (zFar - zNear); return res; } // template struct tvec2 { typedef T value_type; typedef std::size_t size_type; typedef tvec2 type; value_type x; value_type y; value_type & operator[](size_type i) { assert(i < this->length()); return (&x)[i]; } value_type const & operator[]( size_type i ) const { assert(i < this->length()); return (&x)[i]; } tvec2() : x(value_type(0)), y(value_type(0)) {} tvec2(tvec2 const & v) : x(v.x), y(v.y) {} tvec2(value_type const & s) : x(s), y(s) {} tvec2(value_type const & s1, value_type const & s2) : x(s1), y(s2) {} template tvec2(U const & x) : x(value_type(x)), y(value_type(x)) {} template tvec2(U const & a, V b) : x(value_type(a)), y(value_type(b)) {} template tvec2(tvec2 const & v) : x(value_type(v.x)), y(value_type(v.y)) {} tvec2 & operator= (tvec2 const & v) { this->x = v.x; this->y = v.y; return *this; } template tvec2 & operator= (tvec2 const & v) { this->x = T(v.x); this->y = T(v.y); return *this; } template tvec2 & operator+=(U const & s) { this->x += T(s); this->y += T(s); return *this; } template tvec2 & operator+=(tvec2 const & v) { this->x += T(v.x); this->y += T(v.y); return *this; } template tvec2 & operator-=(U const & s) { this->x -= T(s); this->y -= T(s); return *this; } typedef tvec2 float2; template tvec2 & operator-=(tvec2 const & v) { this->x -= T(v.x); this->y -= T(v.y); return *this; } template tvec2 & operator*=(U s) { this->x *= T(s); this->y *= T(s); return *this; } template tvec2 & operator*=(tvec2 const & v) { this->x *= T(v.x); this->y *= T(v.y); return *this; } template tvec2 & operator/=(U s) { this->x /= T(s); this->y /= T(s); return *this; } template tvec2 & operator/=(tvec2 const & v) { this->x /= T(v.x); this->y /= T(v.y); return *this; } tvec2 & operator++() { ++ this->x; ++ this->y; return *this; } tvec2 & operator--() { --this->x; --this->y; return *this; } void makeCeil( tvec2 cmp ) { if( cmp.x > x ) x = cmp.x; if( cmp.y > y ) y = cmp.y; } void makeFloor( tvec2 cmp ) { if( cmp.x < x ) x = cmp.x; if( cmp.y < y ) y = cmp.y; } }; }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148

149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
Elasticsearch OpenGL
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。