青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

WisKeyのLullaby

huangwei.pro 『我失去了一只臂膀』「就睜開了一只眼睛」

  C++博客 :: 首頁 :: 聯系 :: 聚合  :: 管理
  12 Posts :: 0 Stories :: 23 Comments :: 0 Trackbacks

公告

“我該走哪條路?”
“這取決于你要去哪里。”
“我只想能到某個地方。”
“只要你走的夠遠,你始終能到達那個地方。”

Home: huangwei.pro
E-Mail: sir.huangwei [at] gmail.com
09.6 畢業于杭州電子科技大學
進入網易杭州研究院工作至今

常用鏈接

留言簿(1)

我參與的團隊

搜索

  •  

積分與排名

  • 積分 - 51846
  • 排名 - 450

最新評論

閱讀排行榜

評論排行榜

http://huangwei.pro/2015-05/modern-opengl1/

modern-opengl
modern-opengl

譯序

早前學OpenGL的時候還是1.x版本,用的都是glVertexglNormal等固定管線API。后來工作需要接觸DirectX9,shader也只是可選項而已,跟固定管線一起混用著。現在工作內容是手機游戲,又轉到OpenGL ES,發現OpenGL的世界已經完全不同了,OpenGL ES 2.0版本開始就不再支持固定管線,只支持可編程管線。

pipe2.0
pipe2.0

國內很多資料教程參差不齊,舊式接口滿天飛。在知乎看到這一系列教程,覺著挺好,就想著一邊學順便翻譯下。畢竟手游市場的機遇和競爭壓力都在同比猛漲,多了解OpenGL ES肯定沒有壞處。浮躁功利的環境下更需要懷著一顆寧靜致遠的心去提高自身功底,長路漫漫,與君共勉。

歡迎大家,這是現代OpenGL教程系列的第一篇。所有代碼都是開源的,你可以在GitHub上下載:https://github.com/tomdalling/opengl-series

通過這篇教程,你將會學到如何在Windows下用Visual Studio 2013或Mac下用Xcode搭建OpenGL 3.2工程。該應用包含一個頂點著色器(vertex shader),一個片段著色器(fragment shader)和使用VAO和VBO來繪制的三角形。該工程使用GLEW來訪問OpenGL API,用GLFW來處理窗口創建和輸入,還有使用GLM進行矩陣/矢量相關的數學運算。

這聽上去有點無聊,但搭建這樣的工程確實挺麻煩的,尤其對于初學者。只要解決完這問題,我們就可以開始玩些有趣的東西了。

[TOC]

獲取代碼

所有例子代碼的zip打包可以從這里獲取:https://github.com/tomdalling/opengl-series/archive/master.zip

這一系列文章中所使用的代碼都存放在:https://github.com/tomdalling/opengl-series。你可以在頁面中下載zip,加入你會git的話,也可以復制該倉庫。

本文代碼你可以在source/01_project_skeleton目錄里找到。使用OSX系統的,可以打開根目錄里的opengl-series.xcodeproj,選擇本文工程。使用Windows系統的,可以在Visual Studio 2013里打開opengl-series.sln,選擇相應工程。

工程里已包含所有依賴,所以你不需要再安裝或者配置額外的東西。如果有任何編譯或運行上的問題,請聯系我。

關于兼容性的提醒

本文使用OpenGL 3.2,但我會嘗試保持如下兼容:

  • 向后兼容OpenGL 2.1
  • 向前兼容OpenGL 3.X和4.X
  • 兼容Android和iOS的OpenGL ES 2.0

因為OpenGL和GLSL存在許多不同版本,本文代碼不一定能做到100%上述兼容。我希望能兼容99%,并且不同版本之間只要輕微修改即可。

想要了解OpenGL和GLSL不同版本間的區別,這里很好得羅列了兼容列表

Visual Studio下安裝

代碼在Windows 7 32位系統,Visual Studio Express 2013(免費)下創建和測試。你應該可以打開解決方案并成功編譯所有工程。如果有問題請聯系我,或者將補丁發我,我會更新工程。

Xcode下安裝

Xcode工程實在OSX 10.10系統,Xcode 6.1下創建并測試的。打開Xcode工程應該可以成功編譯所有目標。加入你無法成功編譯請聯系我。

Linux下安裝

Linux是基于SpartanJ。我在Ubuntu 12.04下簡單測試通過。

  • 安裝GLM,GLFW和GLEW:
    sudo aptitude install libglm-dev libglew-dev libglfw-dev
  • 進入工程目錄:cd platforms/linux/01_project_skeleto
  • 運行makefile:make
  • 運行可執行文件:bin/01_project_skeleton-debug

GLEW, GLFW和GLM介紹

現在你有了工程,就讓我們開始介紹下工程所用到的開源庫和為啥需要這些。

The OpenGL Extension Wrangler (GLEW)是用來訪問OpenGL 3.2 API函數的。不幸的是你不能簡單的使用#include <GL/gl.h>來訪問OpenGL接口,除非你想用舊版本的OpenGL。在現代OpenGL中,API函數是在運行時(run time)確定的,而非編譯期(compile time)。GLEW可以在運行時加載OpenGL API。

GLFW允許我們跨平臺創建窗口,接受鼠標鍵盤消息。OpenGL不處理這些窗口創建和輸入,所以就需要我們自己動手。我選擇GLFW是因為它很小,并且容易理解。

OpenGL Mathematics (GLM)是一個數學庫,用來處理矢量和矩陣等幾乎其它所有東西。舊版本OpenGL提供了類似glRotateglTranslateglScale等函數,在現代OpenGL中,這些函數已經不存在了,我們需要自己處理所有的數學運算。GLM能在后續教程里提供很多矢量和矩陣運算上幫助。

在這系列的所有教程中,我們還編寫了一個小型庫tdogl用來重用C++代碼。這篇教程會包含tdogl::Shadertdogl::Program用來加載,編譯和鏈接shaders。

什么是Shaders?

Shaders在現代OpenGL中是個很重要的概念。應用程序離不開它,除非你理解了,否則這些代碼也沒有任何意義。

Shaders是一段GLSL小程序,運行在GPU上而非CPU。它們使用OpenGL Shading Language (GLSL)語言編寫,看上去像C或C++,但卻是另外一種不同的語言。使用shader就像你寫個普通程序一樣:寫代碼,編譯,最后鏈接在一起才生成最終的程序。

Shaders并不是個很好的名字,因為它不僅僅只做著色。只要記得它們是個用不同的語言寫的,運行在顯卡上的小程序就行。

在舊版本的OpenGL中,shaders是可選的。在現代OpenGL中,為了能在屏幕上顯示出物體,shaders是必須的。

為可能近距離了解shaders和圖形渲染管線,我推薦Durian Software的相關文章The Graphics Pipeline chapter

主程序Shader程序
語言 C++ GLSL
主函數 int main(int, char**); void main();
運行于 CPU GPU
需要編譯?
需要鏈接?

那shaders實際上干了啥?這取決于是哪種shader。

Vertex Shaders

Vertex shader主要用來將點(x,y,z坐標)變換成不同的點。頂點只是幾何形狀中的一個點,一個點叫vectex,多個點叫vertices(發音為ver-tuh-seez)。在本教程中,我們的三角形需要三個頂點(vertices)組成。

Vertex Shader的GLSL代碼如下:

#version 150 in vec3 vert; void main() { // does not alter the vertices at all gl_Position = vec4(vert, 1); }

第一行#version 150告訴OpenGL這個shader使用GLSL版本1.50.

第二行in vec3 vert;告訴shader需要那一個頂點作為輸入,放入變量vert

第三行定義函數main,這是shader運行入口。這看上去像C,但GLSL中main不需要帶任何參數,并且不用返回void。

第四行gl_Position = vec4(vert, 1);將輸入的頂點直接輸出,變量gl_Position是OpenGL定義的全局變量,用來存儲vertex shader的輸出。所有vertex shaders都需要對gl_Position進行賦值。

gl_Position是4D坐標(vec4),但vert是3D坐標(vec3),所以我們需要將vert轉換為4D坐標vec4(vert, 1)。第二個的參數1是賦值給第四維坐標。我們會在后續教程中學到更多關于4D坐標的東西。但現在,我們只要知道第四維坐標是1即可,i可以忽略它就把它當做3D坐標來對待。

Vertex Shader在本文中沒有做任何事,后續我們會修改它來處理動畫,攝像機和其它東西。

Fragment Shaders

Fragment shader的主要功能是計算每個需要繪制的像素點的顏色。

一個"fragment"基本上就是一個像素,所以你可以認為片段著色器(fragment shader)就是像素著色器(pixel shader)。在本文中每個片段都是一像素,但這并不總是這樣的。你可以更改某個OpenGL設置,以便得到比像素更小的片段,之后的文章我們會講到這個。

本文所使用的fragment shader代碼如下:

#version 150 out vec4 finalColor; void main() { //set every drawn pixel to white finalColor = vec4(1.0, 1.0, 1.0, 1.0); }

再次,第一行#version 150告訴OpenGL這個shader使用的是GLSL 1.50。

第二行finalColor = vec4(1.0, 1.0, 1.0, 1.0);將輸出變量設為白色。vec4(1.0, 1.0, 1.0, 1.0)是創建一個RGBA顏色,并且紅綠藍和alpha都設為最大值,即白色。

現在,就能用shader在OpenGL中繪制出了純白色。在之后的文章中,我們還會加入不同顏色和貼圖。貼圖就是你3D模型上的圖像。

編譯和鏈接Shaders

在C++中,你需要對你的.cpp文件進行編譯,然后鏈接到一起組成最終的程序。OpenGL的shaders也是這么回事。

在這篇文章中用到了兩個可復用的類,是用來處理shaders的編譯和鏈接:tdogl::Shadertdogl::Program。這兩個類代碼不多,并且有詳細的注釋,我建議你閱讀源碼并且去鏈接OpenGL是如何工作的。

什么是VBO和VAO?

當shaders運行在GPU,其它代碼運行在CPU時,你需要有種方式將數據從CPU傳給GPU。在本文中,我們傳送了一個三角的三個頂點數據,但在更大的工程中3D模型會有成千上萬個頂點,顏色,貼圖坐標和其它東西。

這就是我們為什么需要Vertex Buffer Objects (VBOs)和Vertex Array Objects (VAOs)。VBO和VAO用來將C++程序的數據傳給shaders來渲染。

在舊版本的OpenGL中,是通過glVertexglTexCoordglNormal函數把每幀數據發送給GPU的。在現代OpenGL中,所有數據必須通過VBO在渲染之前發送給顯卡。當你需要渲染某些數據時,通過設置VAO來描述該獲取哪些VBO數據推送給shader變量。

Vertex Buffer Objects (VBOs)

第一步我們需要從內存里上傳三角形的三個頂點到顯存中。這就是VBO該干的事。VBO其實就是顯存的“緩沖區(buffers)” - 一串包含各種二進制數據的字節區域。你能上傳3D坐標,顏色,甚至是你喜歡的音樂和詩歌。VBO不關心這些數據是啥,因為它只是對內存進行復制。

Vertex Array Objects (VAOs)

第二步我們要用VBO的數據在shaders中渲染三角形。請記住VBO只是一塊數據,它不清楚這些數據的類型。而告訴OpenGL這緩沖區里是啥類型數據,這事就歸VAO管。

VAO對VBO和shader變量進行了連接。它描述了VBO所包含的數據類型,還有該傳遞數據給哪個shader變量。在OpenGL所有不準確的技術名詞中,“Vertex Array Object”是最爛的一個,因為它根本沒有解釋VAO該干的事。

你回頭看下本文的vertex shader(在文章的前面),你就能發現我們只有一個輸入變量vert。在本文中,我們用VAO來說明“hi,OpenGL,這里的VBO有3D頂點,我想要你在vertex shader時,發三個頂點數據給vert變量。”

在后續的文章中,我們會用VAO來說“hi,OpenGL,這里的VBO有3D頂點,顏色,貼圖坐標,我想要你在shader時,發頂點數據給vert變量,發顏色數據給vertColor變量,發貼圖坐標給vertTexCoord變量。”

給使用上個OpenGL版本的用戶的提醒

假如你在舊版本的OpenGL中使用了VBO但沒有用到VAO,你可能會不認同VAO的描述。你會爭論說“頂點屬性”可以用glVertexAttribPointer將VBO和shaders連接起來,而不是用VAO。這取決于你是否認為頂點屬性應該是VAO“內置(inside)”的(我是這么認為的),或者說它們是否是VAO外置的一個全局狀態。3.2內核和我用的AIT驅動中,VAO不是可選項 - 沒有VAO的封裝glEnableVertexAttribArrayglVertexAttribPointerglDrawArrays都會導致GL_INVALID_OPERATION錯誤。這就是為啥我認為頂點屬性應該內置于VAO,而非全局狀態的原因。3.2內核手冊也說VAO是必須的,但我只聽說ATI驅動會拋錯誤。下面描述引用自OpenGL 3.2內核手冊

所有與頂點處理有關的數據定義都應該封裝在VAO里。
一般VAO邊界包含所有更改vertex array狀態的命令,比如VertexAttribPointer和EnableVertexAttribArray;所有使用vertex array進行繪制的命令,比如DrawArrays和DrawElements;所有對vertex array狀態進行查詢的命令(見第6章)。

不管怎樣,我也知道為啥會有人認為頂點屬性應該放在VAO外部。glVertexAttribPointer出現早于VAO,在這段時間里頂點屬性一直被認為是全局狀態。你應該能看得出VAO是一種改變全局狀態的有效方法。我更傾向于認為是這樣:假如你沒有創建VAO,那OpenGL通過了一個默認的全局VAO。所以當你使用glVertexAttribPointer時,你仍然是在VAO內修改頂點屬性,只不過現在從默認的VAO變成你自己創建的VAO。

這里有更多的討論:http://www.opengl.org/discussion_boards/showthread.php/174577-Questions-on-VAOs

代碼解釋

終于!理論已經說完了,我們開始編碼。OpenGL對于初學者而言不是特別友好,但如果你理解了之前所介紹的概念(shaders,VBO,VAO)那你就沒啥問題。

打開main.cpp,我們從main()函數開始。

首先,我們初始化GLFW:

glfwSetErrorCallback(OnError); if(!glfwInit()) throw std::runtime_error("glfwInit failed");

glfwSetErrorCallback(OnError)這一行告訴GLFW當錯誤發生時調用OnError函數。OnError函數會拋一個包含錯誤信息的異常,我們能從中發現哪里出錯了。

然后我們用GLFW創建一個窗口。

glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2); glfwWindowHint(GLFW_RESIZABLE, GL_FALSE); gWindow = glfwCreateWindow((int)SCREEN_SIZE.x, (int)SCREEN_SIZE.y, "OpenGL Tutorial", NULL, NULL); if(!gWindow) throw std::runtime_error("glfwCreateWindow failed. Can your hardware handle OpenGL 3.2?");

該窗口包含一個向前兼容的OpenGL 3.2內核上下文。假如glfwCreateWindow失敗了,你應該降低OpenGL版本。

創建窗口最后一步,我們應該設置一個“當前”OpenGL上下文給剛創建的窗口:

glfwMakeContextCurrent(gWindow);

無論我們調用哪個OpenGL函數,都會影響到“當前上下文”。我們只會用到一個上下文,所以設置完后,就別管它了。理論上來說,我們可以有多個窗口,且每個窗口都可以有自己的上下文。

現在我們窗口有了OpenGL上下文變量,我們需要初始化GLEW以便訪問OpenGL接口。

glewExperimental = GL_TRUE; //stops glew crashing on OSX :-/ if(glewInit() != GLEW_OK) throw std::runtime_error("glewInit failed");

這里的GLEW與OpenGL內核有點小問題,設置glewExperimental就可以修復,但希望再未來永遠不要發生。

我們也可以用GLEW再次確認3.2版本是否存在:

if(!GLEW_VERSION_3_2) throw std::runtime_error("OpenGL 3.2 API is not available.");

LoadShaders函數中,我們使用本教程提供的tdogl::Shadertdogl::Program兩個類編譯和鏈接了vertex shader和fragment shader。

std::vector<tdogl::Shader> shaders; shaders.push_back(tdogl::Shader::shaderFromFile(ResourcePath("vertex-shader.txt"), GL_VERTEX_SHADER)); shaders.push_back(tdogl::Shader::shaderFromFile(ResourcePath("fragment-shader.txt"), GL_FRAGMENT_SHADER)); gProgram = new tdogl::Program(shaders);

LoadTriangle函數中,我們創建了一個VAO和VBO。這是第一步,創建和綁定新的VAO:

glGenVertexArrays(1, &gVAO); glBindVertexArray(gVAO);

然后我們創建和綁定新的VBO:

glGenBuffers(1, &gVBO); glBindBuffer(GL_ARRAY_BUFFER, gVBO);

接著,我們上傳一些數據到VBO中。這些數據就是三個頂點,每個頂點包含三個GLfloat

GLfloat vertexData[] = { // X Y Z 0.0f, 0.8f, 0.0f, -0.8f,-0.8f, 0.0f, 0.8f,-0.8f, 0.0f, }; glBufferData(GL_ARRAY_BUFFER, sizeof(vertexData), vertexData, GL_STATIC_DRAW);

現在緩沖區包含了三角形的三個頂點,是時候開始設置VAO了。首先,我們應該啟用shader程序中的vert變量。這些變量能被開啟或關閉,默認情況下是關閉的,所以我們需要開啟它。vert變量是一個“屬性變量(attribute variable)”,這也是為何OpenGL函數名稱中有帶“Attrib”。我們可以在后續的文章中看到更多類型。

glEnableVertexAttribArray(gProgram->attrib("vert"));

VAO設置最復雜的部分就是下個函數:glVertexAttribPointer。讓我們先調用該函數,等會解釋。

glVertexAttribPointer(gProgram->attrib("vert"), 3, GL_FLOAT, GL_FALSE, 0, NULL);

第一個參數,gProgram->attrib("vert"),這就是那個需要上傳數據的shder變量。在這個例子中,我們需要發數據給vertshader變量。

第二個參數,3表明每個頂點需要三個數字。

第三個參數,GL_FLOAT說明三個數字是GLfloat類型。這非常重要,因為GLdouble類型的數據大小跟它是不同的。

第四個參數,GL_FALSE說明我們不需要對浮點數進行“歸一化”,假如我們使用了歸一化,那這個值會被限定為最小0,最大1。我們不需要對我們的頂點進行限制,所以這個參數為false。

第五個參數,0,該參數可以在頂點之間有間隔時使用,設置參數為0,表示數據之間沒有間隔。

第六個參數,NULL,假如我們的數據不是從緩沖區頭部開始的話,可以設置這個參數來指定。設置該參數為NULL,表示我們的數據從VBO的第一個字節開始。

現在VBO和VAO都設置完成,我們需要對它們進行解綁定,防止一不小心被哪里給更改了。

glBindBuffer(GL_ARRAY_BUFFER, 0); glBindVertexArray(0);

到此,shader,VBO和VAO都準備好了。我們可以開始在Render函數里繪制了。

首先,我們先清空下屏幕,讓它變成純黑色:

glClearColor(0, 0, 0, 1); // black glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

然后告訴OpenGL我們要開始使用VAO和shader了:

glUseProgram(gProgram->object()); glBindVertexArray(gVAO);

最后,我們繪制出三角形:

glDrawArrays(GL_TRIANGLES, 0, 3);

調用glDrawArrays函數說明我們需要繪制三角形,從第0個頂點開始,有3個頂點被發送到shader。OpenGL會在當前VAO范圍內確定該從哪里獲取頂點。

頂點將會從VBO中取出并發送到vertex shader。然后三角形內的每個像素會發送給fragment shader。接著fragment shader將每個像素變成白色。歡呼!

現在繪制結束了,為了安全起見,我們需要將shader和VAO進行解綁定:

glBindVertexArray(0); glUseProgram(0);

最后一件事,在我們看到三角形之前需要切換幀緩沖:

glfwSwapBuffers(gWindow);

在幀緩沖被交換前,我們會繪制到一個不可見的離屏(off-screen)幀緩沖區。當我們調用glfwSwapBuffers時,離屏緩沖會變成屏幕緩沖,所以我們就能在窗口上看見內容了。

進一步閱讀

在后續文章中,我們會對三角形進行貼圖。之后,你會學到一點矩陣變換知識,就可以使用vertex shader來實現3D立方體旋轉。

在這之后,我們開始創建3D場景并提交多個物體。

更多現代OpenGL資料

不幸的是,我不得不跳過很多內容,防止本教程的篇幅過長。后面還有很多好的現代OpenGL資料能滿足你的求知欲:

譯者更多內容請移步huangwei.pro

posted on 2015-05-21 14:11 威士忌 閱讀(5885) 評論(3)  編輯 收藏 引用

Feedback

# re: 現代OpenGL教程 01 - 入門指南 2015-05-21 20:47 miragekiller
源代碼斷行就比較完美了  回復  更多評論
  

# re: 現代OpenGL教程 01 - 入門指南 2015-06-03 14:21 Khan
真應該支持 markdown 了  回復  更多評論
  

# re: 現代OpenGL教程 01 - 入門指南 2016-03-18 18:13 小被子

告訴OpenGL我們要開始使用VAO和shader了,
glUseProgram(gProgram->object()); glBindVertexArray(gVAO);這里為什么又要綁定VAO ,假如這里需要綁定,前面為什么又要解除綁定?  回復  更多評論
  


只有注冊用戶登錄后才能發表評論。
網站導航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            欧美一区二区在线免费观看| 在线亚洲成人| 欧美日韩国产片| 久久久天天操| 国产精品久久国产三级国电话系列| 久久中文久久字幕| 国产乱码精品一区二区三| 亚洲精品欧美激情| 亚洲国产裸拍裸体视频在线观看乱了中文 | 老司机午夜精品视频在线观看| 欧美日韩一区二区视频在线 | 欧美黄色成人网| 国内成人精品2018免费看| 一区二区三区四区五区精品| 亚洲精品美女| 亚洲午夜精品网| 香蕉久久一区二区不卡无毒影院 | 欧美高清不卡| 亚洲欧美影院| 久久午夜精品一区二区| 日韩视频在线你懂得| 亚洲午夜小视频| 激情综合色综合久久综合| 亚洲欧洲综合另类| 国产精品欧美久久久久无广告| 久久久国产精品亚洲一区| 美女视频网站黄色亚洲| 亚洲综合日韩在线| 久久久久久成人| 一区二区三区成人| 久久久精品2019中文字幕神马| 亚洲精品视频一区| 午夜影院日韩| 一区二区三区欧美| 久久亚洲午夜电影| 亚洲欧美卡通另类91av| 美女精品视频一区| 欧美影院在线播放| 欧美日韩亚洲视频| 欧美xart系列高清| 国产一二精品视频| 国产精品99久久久久久久久| 亚洲国产高清高潮精品美女| 亚洲一区二区三区精品在线| 亚洲人成网站777色婷婷| 亚洲欧美一区二区三区极速播放| 日韩视频二区| 久久蜜桃av一区精品变态类天堂| 亚洲欧美国产日韩中文字幕| 欧美国产精品中文字幕| 久久亚洲免费| 国产一区二区三区黄| 亚洲午夜久久久| 一本一本a久久| 欧美国产欧美亚洲国产日韩mv天天看完整 | 在线观看精品一区| 欧美一区1区三区3区公司| 亚洲一区二区三区四区在线观看 | 久久久精品一区| 亚洲国产美女| 欧美一区二区在线免费观看| 在线观看亚洲专区| 欧美日韩视频在线一区二区| 亚洲欧美色一区| 欧美激情综合| 欧美在线不卡视频| 亚洲精品少妇30p| 国产亚洲二区| 欧美天天在线| 亚洲欧洲一级| 午夜欧美大尺度福利影院在线看 | 欧美一区二区三区视频免费| 亚洲高清不卡在线| 国产精品永久| 欧美日韩天堂| 中国av一区| 欧美少妇一区| 亚洲综合精品自拍| 欧美中文字幕视频在线观看| 久久国产精品99精品国产| 欧美激情一区二区三区四区| 国户精品久久久久久久久久久不卡 | 亚洲六月丁香色婷婷综合久久| 亚洲区中文字幕| 欧美精品一区视频| 亚洲一区三区电影在线观看| 欧美专区在线观看| 亚洲成人在线视频播放| 亚洲免费中文字幕| 日韩视频永久免费| 亚洲欧美中文字幕| 亚洲成人直播| 欧美日韩一区不卡| 午夜免费电影一区在线观看| 美女黄毛**国产精品啪啪| 亚洲欧洲一区| 国产精品一二三视频| 欧美亚洲色图校园春色| 欧美高清在线一区| 亚洲亚洲精品三区日韩精品在线视频 | 亚洲国产精品一区二区www在线 | 国产精品免费aⅴ片在线观看| 亚洲影院污污.| 欧美成年人网站| 亚洲欧美日韩国产成人精品影院| 国产综合色一区二区三区| 裸体一区二区| 亚洲午夜免费福利视频| 免费看亚洲片| 午夜久久黄色| 一本色道**综合亚洲精品蜜桃冫| 国产精品网站在线观看| 欧美va日韩va| 久久精品官网| 亚洲手机成人高清视频| 嫩草影视亚洲| 久久精品盗摄| 午夜视频久久久久久| 最新日韩在线视频| 国产综合视频| 国产乱肥老妇国产一区二 | 欧美一区二区三区四区在线| 亚洲欧洲一区二区三区久久| 久久精品久久综合| 亚洲一区高清| 在线亚洲自拍| 日韩亚洲欧美成人一区| 激情综合网址| 激情国产一区| 国产日韩欧美二区| 欧美色图天堂网| 欧美理论大片| 欧美精品1区| 欧美不卡高清| 欧美国产欧美亚州国产日韩mv天天看完整| 久久成人国产精品| 亚洲欧美激情视频| 亚洲一区精品电影| 亚洲五月婷婷| 亚洲欧美日韩一区二区| 中文无字幕一区二区三区| 99国产精品视频免费观看一公开| 欧美激情在线有限公司| 欧美成ee人免费视频| 麻豆精品在线播放| 免费成人黄色av| 亚洲成人中文| 亚洲国产欧美一区二区三区久久 | 日韩视频欧美视频| 亚洲人成艺术| 宅男精品视频| 午夜精品免费视频| 欧美伊人久久久久久久久影院| 性做久久久久久久免费看| 欧美一级视频一区二区| 久久精品动漫| 欧美~级网站不卡| 亚洲第一搞黄网站| 亚洲精品美女在线观看| 99人久久精品视频最新地址| 香蕉久久一区二区不卡无毒影院 | 欧美福利一区二区| 欧美黑人在线播放| 亚洲国产成人一区| 999在线观看精品免费不卡网站| 99精品免费视频| 亚洲欧美在线aaa| 久久久久久久久综合| 欧美www视频| 欧美日韩中文字幕精品| 国产精品视频精品视频| 国产在线麻豆精品观看| 亚洲国产日韩欧美综合久久| 一本不卡影院| 久久爱www久久做| 欧美国产日本在线| 亚洲私人影院在线观看| 久久久精品一区| 国产精品99免视看9| 国内外成人免费激情在线视频网站| 亚洲电影网站| 亚洲欧美日本另类| 免费亚洲网站| 亚洲一区二区三区国产| 久久在线播放| 国产精品羞羞答答| 亚洲人成77777在线观看网| 亚洲男女毛片无遮挡| 欧美成人免费网站| 亚洲视频免费看| 女人色偷偷aa久久天堂| 国产精品久久久久秋霞鲁丝| 亚洲电影免费在线| 亚洲在线观看免费视频| 欧美va天堂在线| 欧美在线日韩| 国产精品区一区二区三| 亚洲欧洲精品一区二区三区不卡| 新67194成人永久网站| 最新热久久免费视频|