Opengl es2.0 學習筆記(三)shader的使用

      網友投稿 920 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

      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

      Opengl es2.0 學習筆記(三)shader的使用

      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小時內刪除侵權內容。

      上一篇:什么是數字營銷?初學者終極指南
      下一篇:如何利用Excel函數快速根據原紙噸位價計算紙箱價格
      相關文章
      久久国产亚洲高清观看| 亚洲VA中文字幕无码一二三区| 亚洲视频一区在线| 久久人午夜亚洲精品无码区| 亚洲一本之道高清乱码| 亚洲韩国—中文字幕| 亚洲小说区图片区另类春色| 亚洲av无码专区在线观看下载| 亚洲AV无码国产剧情| 亚洲综合一区无码精品| 亚洲乱码一二三四区麻豆| 亚洲视频在线播放| 亚洲第一香蕉视频| 亚洲视频免费在线播放| 亚洲神级电影国语版| 亚洲免费电影网站| 亚洲国产精品专区| 亚洲一区AV无码少妇电影| 亚洲人成色在线观看| 亚洲日韩在线中文字幕综合| 亚洲成a人一区二区三区| 国产亚洲综合久久| 精品亚洲视频在线观看| 国产成人精品日本亚洲专区61| 久久激情亚洲精品无码?V| 亚洲午夜久久久影院| 亚洲AV无码国产精品色午友在线 | 2048亚洲精品国产| 亚洲日韩国产精品第一页一区| 亚洲自偷自偷偷色无码中文| 国产av无码专区亚洲av果冻传媒 | 91亚洲国产成人精品下载| 亚洲免费在线播放| 亚洲国产精品久久久久秋霞影院| 456亚洲人成影院在线观| 亚洲AV无码专区国产乱码不卡| 亚洲高清视频一视频二视频三| 久久亚洲国产成人影院网站 | 久久夜色精品国产噜噜亚洲a| 亚洲熟妇AV一区二区三区浪潮| 国产成人精品亚洲一区|