文章目录
一.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;"//点乘以正交投影矩阵,等于一个位置 "}" }; 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小时内删除侵权内容。