Opengl es2.0 学习笔记(三)shader的使用

网友投稿 808 2022-05-30

文章目录

一.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

Opengl es2.0 学习笔记(三)shader的使用

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小时内删除侵权内容。

上一篇:Docker的容器编排
下一篇:【Pytorch】(一)张量(tensor)
相关文章