亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

貓都能學會的Unity3D Shader入門指南(一)

2019-11-09 18:33:29
字體:
來源:轉載
供稿:網友

Unity Shader教程

動機

自己使用Unity3D也有一段時間了,但是很多時候是流于表面,更多地是把這個引擎簡單地用作腳本控制,而對更深入一些的層次幾乎沒有了解。雖然說Unity引擎設計的初衷就是創建簡單的不需要開發者操心的誰都能用的3D引擎,但是只是膚淺的使用,可能是無法達到隨心所欲的境地的,因此,這種狀況必須改變!從哪里開始呢,貌似有句話叫做會寫Shader的都是高手,于是,想大概看看從Shader開始能不能使自己到達的層次能再深入一些吧,再于是,有了這個系列(希望我能堅持寫完它,雖然應該會拖個半年左右)。

Unity3D的所有渲染工作都離不開著色器(Shader),如果你和我一樣最近開始對Shader編程比較感興趣的話,可能你和我有著同樣的困惑:如何開始?Unity3D提供了一些Shader的手冊和文檔(比如這里,這里和這里),但是一來內容比較分散,二來學習階梯稍微陡峭了些。這對于像我這樣之前完全沒有接觸過有關內容的新人來說是相當不友好的。國內外雖然也有一些Shader的介紹和心得,但是也同樣存在內容分散的問題,很多教程前一章就只介紹了基本概念,接下來馬上就搬出一個超復雜的例子,對于很多基本的用法并沒有解釋。也許對于Shader熟練使用的開發者來說是沒有問題,但是我相信像我這樣的入門者也并不在少數。在多方尋覓無果后,我覺得有必要寫一份教程,來以一個入門者的角度介紹一些Shader開發的基本步驟。其實與其說是教程,倒不如說是一份自我總結,希望能夠幫到有需要的人。

所以,本“教程”的對象是

總的來說是新接觸Shader開發的人:也許你知道什么是Shader,也會使用別人的Shader,但是僅限于知道一些基本的內建Shader名字,從來沒有打開它們查看其源碼。想要更多了解Shader和有需求要進行Shader開發的開發者,但是之前并沒有Shader開發的經驗。

當然,因為我本身在Shader開發方面也是一個不折不扣的大菜鳥,本文很多內容也只是在自己的理解加上一些可能不太靠譜的求證和總結。本文中的示例應該會有更好的方式來實現,因此您是高手并且恰巧路過的話,如果有好的方式來實現某些內容,懇請您不吝留下評論,我會對本文進行不斷更新和維護。

一些基本概念

Shader和Material

如果是進行3D游戲開發的話,想必您對著兩個詞不會陌生。Shader(著色器)實際上就是一小段程序,它負責將輸入的Mesh(網格)以指定的方式和輸入的貼圖或者顏色等組合作用,然后輸出。繪圖單元可以依據這個輸出來將圖像繪制到屏幕上。輸入的貼圖或者顏色等,加上對應的Shader,以及對Shader的特定的參數設置,將這些內容(Shader及輸入參數)打包存儲在一起,得到的就是一個Material(材質)。之后,我們便可以將材質賦予合適的renderer(渲染器)來進行渲染(輸出)了。

所以說Shader并沒有什么特別神奇的,它只是一段規定好輸入(顏色,貼圖等)和輸出(渲染器能夠讀懂的點和顏色的對應關系)的程序。而Shader開發者要做的就是根據輸入,進行計算變換,產生輸出而已。

Shader大體上可以分為兩類,簡單來說

表面著色器(Surface Shader) - 為你做了大部分的工作,只需要簡單的技巧即可實現很多不錯的效果。類比卡片機,上手以后不太需要很多努力就能拍出不錯的效果。片段著色器(Fragment Shader) - 可以做的事情更多,但是也比較難寫。使用片段著色器的主要目的是可以在比較低的層級上進行更復雜(或者針對目標設備更高效)的開發。

因為是入門文章,所以之后的介紹將主要集中在表面著色器上。

Shader程序的基本結構

因為著色器代碼可以說專用性非常強,因此人為地規定了它的基本結構。一個普通的著色器的結構應該是這樣的:一段Shader程序的結構

首先是一些屬性定義,用來指定這段代碼將有哪些輸入。接下來是一個或者多個的子著色器,在實際運行中,哪一個子著色器被使用是由運行的平臺所決定的。子著色器是代碼的主體,每一個子著色器中包含一個或者多個的Pass。在計算著色時,平臺先選擇最優先可以使用的著色器,然后依次運行其中的Pass,然后得到輸出的結果。最后指定一個回滾,用來處理所有Subshader都不能運行的情況(比如目標設備實在太老,所有Subshader中都有其不支持的特性)。

需要提前說明的是,在實際進行表面著色器的開發時,我們將直接在Subshader這個層次上寫代碼,系統將把我們的代碼編譯成若干個合適的Pass。廢話到此為止,下面讓我們真正實際進入Shader的世界吧。

Hello Shader

百行文檔不如一個實例,下面給出一段簡單的Shader代碼,然后根據代碼來驗證下上面說到的結構和闡述一些基本的Shader語法。因為本文是針對Unity3D來寫Shader的,所以也使用Unity3D來演示吧。首先,新建一個Shader,可以在PRoject面板中找到,Create,選擇Shader,然后將其命名為Diffuse Texture

在Unity3D中新建一個Shader

隨便用個文本編輯器打開剛才新建的Shader:

Shader "Custom/Diffuse Texture" {    Properties {        _MainTex ("Base (RGB)", 2D) = "white" {}    }    SubShader {        Tags { "RenderType"="Opaque" }        LOD 200        CGPROGRAM        #pragma surface surf Lambert        sampler2D _MainTex;        struct Input {            float2 uv_MainTex;        };        void surf (Input IN, inout SurfaceOutput o) {            half4 c = tex2D (_MainTex, IN.uv_MainTex);            o.Albedo = c.rgb;            o.Alpha = c.a;        }        ENDCG    }     FallBack "Diffuse"}

如果您之前沒怎么看過Shader代碼的話,估計細節上會看不太懂。但是有了上面基本結構的介紹,您應該可以識別出這個Shader的構成,比如一個Properties部分,一個SubShader,以及一個FallBack。另外,第一行只是這個Shader的聲明并為其指定了一個名字,比如我們的實例Shader,你可以在材質面板選擇Shader時在對應的位置找到這個Shader。

在Unity3D中找到剛才新建的Shader

接下來我們講逐句講解這個Shader,以期明了每一個語句的意義。

屬性

Properties{}中定義著色器屬性,在這里定義的屬性將被作為輸入提供給所有的子著色器。每一條屬性的定義的語法是這樣的:

_Name("Display Name", type) = defaultValue[{options}]

_Name - 屬性的名字,簡單說就是變量名,在之后整個Shader代碼中將使用這個名字來獲取該屬性的內容Display Name - 這個字符串將顯示在Unity的材質編輯器中作為Shader的使用者可讀的內容type - 這個屬性的類型,可能的type所表示的內容有以下幾種:Color - 一種顏色,由RGBA(紅綠藍和透明度)四個量來定義;2D - 一張2的階數大小(256,512之類)的貼圖。這張貼圖將在采樣后被轉為對應基于模型UV的每個像素的顏色,最終被顯示出來;Rect - 一個非2階數大小的貼圖;Cube - 即Cube map texture(立方體紋理),簡單說就是6張有聯系的2D貼圖的組合,主要用來做反射效果(比如天空盒和動態反射),也會被轉換為對應點的采樣;Range(min, max) - 一個介于最小值和最大值之間的浮點數,一般用來當作調整Shader某些特性的參數(比如透明度渲染的截止值可以是從0至1的值等);Float - 任意一個浮點數;Vector - 一個四維數;defaultValue 定義了這個屬性的默認值,通過輸入一個符合格式的默認值來指定對應屬性的初始值(某些效果可能需要某些特定的參數值來達到需要的效果,雖然這些值可以在之后在進行調整,但是如果默認就指定為想要的值的話就省去了一個個調整的時間,方便很多)。Color - 以0~1定義的rgba顏色,比如(1,1,1,1);2D/Rect/Cube - 對于貼圖來說,默認值可以為一個代表默認tint顏色的字符串,可以是空字符串或者"white","black","gray","bump"中的一個Float,Range - 某個指定的浮點數Vector - 一個4維數,寫為 (x,y,z,w)另外還有一個{option},它只對2D,Rect或者Cube貼圖有關,在寫輸入時我們最少要在貼圖之后寫一對什么都不含的空白的{},當我們需要打開特定選項時可以把其寫在這對花括號內。如果需要同時打開多個選項,可以使用空白分隔??赡艿倪x擇有ObjectLinear, EyeLinear, SphereMap, CubeReflect, CubeNormal中的一個,這些都是OpenGL中TexGen的模式,具體的留到后面有機會再說。

所以,一組屬性的申明看起來也許會是這個樣子的

//Define a color with a default value of semi-transparent blue_MainColor ("Main Color", Color) = (0,0,1,0.5)//Define a texture with a default of white_Texture ("Texture", 2D) = "white" {}

現在看懂上面那段Shader(以及其他所有Shader)的Properties部分應該不會有任何問題了。接下來就是SubShader部分了。

Tags

表面著色器可以被若干的標簽(tags)所修飾,而硬件將通過判定這些標簽來決定什么時候調用該著色器。比如我們的例子中SubShader的第一句

Tags { "RenderType"="Opaque" }

告訴了系統應該在渲染非透明物體時調用我們。Unity定義了一些列這樣的渲染過程,與RenderType是Opaque相對應的顯而易見的是"RenderType" = "Transparent",表示渲染含有透明效果的物體時調用。在這里Tags其實暗示了你的Shader輸出的是什么,如果輸出中都是非透明物體,那寫在Opaque里;如果想渲染透明或者半透明的像素,那應該寫在Transparent中。

另外比較有用的標簽還有"IgnoreProjector"="True"(不被Projectors影響),"ForceNoShadowCasting"="True"(從不產生陰影)以及"Queue"="xxx"(指定渲染順序隊列)。這里想要著重說一下的是Queue這個標簽,如果你使用Unity做過一些透明和不透明物體的混合的話,很可能已經遇到過不透明物體無法呈現在透明物體之后的情況。這種情況很可能是由于Shader的渲染順序不正確導致的。Queue指定了物體的渲染順序,預定義的Queue有:

Background - 最早被調用的渲染,用來渲染天空盒或者背景Geometry - 這是默認值,用來渲染非透明物體(普通情況下,場景中的絕大多數物體應該是非透明的)AlphaTest - 用來渲染經過Alpha Test的像素,單獨為AlphaTest設定一個Queue是出于對效率的考慮Transparent - 以從后往前的順序渲染透明物體Overlay - 用來渲染疊加的效果,是渲染的最后階段(比如鏡頭光暈等特效)

這些預定義的值本質上是一組定義整數,Background = 1000, Geometry = 2000, AlphaTest = 2450, Transparent = 3000,最后Overlay = 4000。在我們實際設置Queue值時,不僅能使用上面的幾個預定義值,我們也可以指定自己的Queue值,寫成類似這樣:"Queue"="Transparent+100",表示一個在Transparent之后100的Queue上進行調用。通過調整Queue值,我們可以確保某些物體一定在另一些物體之前或者之后渲染,這個技巧有時候很有用處。

LOD

LOD很簡單,它是Level of Detail的縮寫,在這里例子里我們指定了其為200(其實這是Unity的內建Diffuse著色器的設定值)。這個數值決定了我們能用什么樣的Shader。在Unity的Quality Settings中我們可以設定允許的最大LOD,當設定的LOD小于SubShader所指定的LOD時,這個SubShader將不可用。Unity內建Shader定義了一組LOD的數值,我們在實現自己的Shader的時候可以將其作為參考來設定自己的LOD數值,這樣在之后調整根據設備圖形性能來調整畫質時可以進行比較精確的控制。

VertexLit及其系列 = 100Decal, Reflective VertexLit = 150Diffuse = 200Diffuse Detail, Reflective Bumped Unlit, Reflective Bumped VertexLit = 250Bumped, Specular = 300Bumped Specular = 400Parallax = 500Parallax Specular = 600

Shader本體

前面雜項說完了,終于可以開始看看最主要的部分了,也就是將輸入轉變為輸出的代碼部分。為了方便看,請容許我把上面的SubShader的主題部分抄寫一遍

CGPROGRAM#pragma surface surf Lambertsampler2D _MainTex;struct Input {    float2 uv_MainTex;};void surf (Input IN, inout SurfaceOutput o) {    half4 c = tex2D (_MainTex, IN.uv_MainTex);    o.Albedo = c.rgb;    o.Alpha = c.a;}ENDCG

還是逐行來看,首先是CGPROGRAM。這是一個開始標記,表明從這里開始是一段CG程序(我們在寫Unity的Shader時用的是Cg/HLSL語言)。最后一行的ENDCG與CGPROGRAM是對應的,表明CG程序到此結束。

接下來是是一個編譯指令:#pragma surface surf Lambert,它聲明了我們要寫一個表面Shader,并指定了光照模型。它的寫法是這樣的

#pragma surface surfaceFunction lightModel [optionalparams]

surface - 聲明的是一個表面著色器surfaceFunction - 著色器代碼的方法的名字lightModel - 使用的光照模型。

所以在我們的例子中,我們聲明了一個表面著色器,實際的代碼在surf函數中(在下面能找到該函數),使用Lambert(也就是普通的diffuse)作為光照模型。

接下來一句sampler2D _MainTex;,sampler2D是個啥?其實在CG中,sampler2D就是和texture所綁定的一個數據容器接口。等等..這個說法還是太復雜了,簡單理解的話,所謂加載以后的texture(貼圖)說白了不過是一塊內存存儲的,使用了RGB(也許還有A)通道,且每個通道8bits的數據。而具體地想知道像素與坐標的對應關系,以及獲取這些數據,我們總不能一次一次去自己計算內存地址或者偏移,因此可以通過sampler2D來對貼圖進行操作。更簡單地理解,sampler2D就是GLSL中的2D貼圖的類型,相應的,還有sampler1D,sampler3D,samplerCube等等格式。

解釋通了sampler2D是什么之后,還需要解釋下為什么在這里需要一句對_MainTex的聲明,之前我們不是已經在Properties里聲明過它是貼圖了么。答案是我們用來實例的這個shader其實是由兩個相對獨立的塊組成的,外層的屬性聲明,回滾等等是Unity可以直接使用和編譯的ShaderLab;而現在我們是在CGPROGRAM...ENDCG這樣一個代碼塊中,這是一段CG程序。對于這段CG程序,要想訪問在Properties中所定義的變量的話,必須使用和之前變量相同的名字進行聲明。于是其實sampler2D _MainTex;做的事情就是再次聲明并鏈接了_MainTex,使得接下來的CG程序能夠使用這個變量。

終于可以繼續了。接下來是一個struct結構體。相信大家對于結構體已經很熟悉了,我們先跳過之,直接看下面的的surf函數。上面的#pragma段已經指出了我們的著色器代碼的方法的名字叫做surf,那沒跑兒了,就是這段代碼是我們的著色器的工作核心。我們已經說過不止一次,著色器就是給定了輸入,然后給出輸出進行著色的代碼。CG規定了聲明為表面著色器的方法(就是我們這里的surf)的參數類型和名字,因此我們沒有權利決定surf的輸入輸出參數的類型,只能按照規定寫。這個規定就是第一個參數是一個Input結構,第二個參數是一個inout的SurfaceOutput結構。

它們分別是什么呢?Input其實是需要我們去定義的結構,這給我們提供了一個機會,可以把所需要參與計算的數據都放到這個Input結構中,傳入surf函數使用;SurfaceOutput是已經定義好了里面類型輸出結構,但是一開始的時候內容暫時是空白的,我們需要向里面填寫輸出,這樣就可以完成著色了。先仔細看看INPUT吧,現在可以跳回來看上面定義的INPUT結構體了:

struct Input {    float2 uv_MainTex;};

作為輸入的結構體必須命名為Input,這個結構體中定義了一個float2的變量…你沒看錯我也沒打錯,就是float2,表示浮點數的float后面緊跟一個數字2,這又是什么意思呢?其實沒什么魔法,float和vec都可以在之后加入一個2到4的數字,來表示被打包在一起的2到4個同類型數。比如下面的這些定義:

//Define a 2d vector variablevec2 coordinate;//Define a color variablefloat4 color;//Multiply out a colorfloat3 multipliedColor = color.rgb * coordinate.x;

在訪問這些值時,我們即可以只使用名稱來獲得整組值,也可以使用下標的方式(比如.xyzw,.rgba或它們的部分比如.x等等)來獲得某個值。在這個例子里,我們聲明了一個叫做uv_MainTex的包含兩個浮點數的變量。

如果你對3D開發稍有耳聞的話,一定不會對uv這兩個字母感到陌生。UV mapping的作用是將一個2D貼圖上的點按照一定規則映射到3D模型上,是3D渲染中最常見的一種頂點處理手段。在CG程序中,我們有這樣的約定,在一個貼圖變量(在我們例子中是_MainTex)之前加上uv兩個字母,就代表提取它的uv值(其實就是兩個代表貼圖上點的二維坐標 )。我們之后就可以在surf程序中直接通過訪問uv_MainTex來取得這張貼圖當前需要計算的點的坐標值了。

如果你堅持看到這里了,那要恭喜你,因為離最后成功讀完一個Shader只有一步之遙。我們回到surf函數,它的兩有參數,第一個是Input,我們已經明白了:在計算輸出時Shader會多次調用surf函數,每次給入一個貼圖上的點坐標,來計算輸出。第二個參數是一個可寫的SurfaceOutput,SurfaceOutput是預定義的輸出結構,我們的surf函數的目標就是根據輸入把這個輸出結構填上。SurfaceOutput結構體的定義如下

struct SurfaceOutput {    half3 Albedo;     //像素的顏色    half3 Normal;     //像素的法向值    half3 Emission;   //像素的發散顏色    half Specular;    //像素的鏡面高光    half Gloss;       //像素的發光強度    half Alpha;       //像素的透明度};

這里的half和我們常見float與double類似,都表示浮點數,只不過精度不一樣。也許你很熟悉單精度浮點數(float或者single)和雙精度浮點數(double),這里的half指的是半精度浮點數,精度最低,運算性能相對比高精度浮點數高一些,因此被大量使用。

在例子中,我們做的事情非常簡單:

half4 c = tex2D (_MainTex, IN.uv_MainTex);o.Albedo = c.rgb;o.Alpha = c.a;

這里用到了一個tex2d函數,這是CG程序中用來在一張貼圖中對一個點進行采樣的方法,返回一個float4。這里對_MainTex在輸入點上進行了采樣,并將其顏色的rbg值賦予了輸出的像素顏色,將a值賦予透明度。于是,著色器就明白了應當怎樣工作:即找到貼圖上對應的uv點,直接使用顏色信息來進行著色,over。

接下來...

我想現在你已經能讀懂一些最簡單的Shader了,接下來我推薦的是參考Unity的Surface Shader Examples多接觸一些各種各樣的基本Shader。在這篇教程的基礎上,配合一些google的工作,完全看懂這個shader示例頁面應該不成問題。如果能做到無壓力看懂,那說明你已經有良好的基礎可以前進到Shader的更深的層次了(也許等不到我的下一篇教程就可以自己開始動手寫些效果了);如果暫時還是有困難,那也沒有關系,Shader學習絕對是一個漸進的過程,因為有很多約定和常用技巧,多積累和實踐自然會進步并掌握。

在接下來的教程里,打算通過介紹一些實際例子以及從基礎開始實際逐步動手實現一個復雜一點的例子,讓我們能看到shader在真正使用中的威力。我希望能盡快寫完這個系列,但是無奈時間確實有限,所以我也不知道什么時候能出爐...寫好的時候我會更改這段內容并指向新的文章。您要是擔心錯過的話,也可以使用郵件訂閱或者訂閱本站的rss(雖然Google Reader已經關了- -)。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
日本久久久久亚洲中字幕| 日韩大陆毛片av| 国产mv免费观看入口亚洲| 亚洲一区美女视频在线观看免费| 精品人伦一区二区三区蜜桃网站| 久久手机免费视频| 亚洲第一中文字幕| 日韩有码视频在线| 97精品国产97久久久久久免费| 欧美一级淫片videoshd| 欧美在线观看www| 亚洲精品在线观看www| 精品国产欧美一区二区五十路| 日韩精品欧美国产精品忘忧草| 成人亲热视频网站| 欧美乱大交做爰xxxⅹ性3| 欧美xxxx综合视频| 欧美成人亚洲成人日韩成人| 在线成人激情黄色| 国产欧美一区二区三区在线看| 欧美中文在线观看国产| 欧美性猛交99久久久久99按摩| 日韩中文字幕免费看| 国产美女久久精品| 亚洲中国色老太| 亚洲人成在线电影| 日韩中文字幕不卡视频| 九九热r在线视频精品| 欧美成人国产va精品日本一级| 成人黄色免费片| 美女久久久久久久| 日韩免费不卡av| 亚洲在线观看视频| 国产精品福利观看| 欧美疯狂做受xxxx高潮| 66m—66摸成人免费视频| 欧美高清自拍一区| 亚洲精品乱码久久久久久金桔影视| 国产午夜精品视频免费不卡69堂| 成人激情视频在线| 国产精品美女无圣光视频| 久久精品视频一| 久久91精品国产91久久跳| 亚洲欧美日韩国产中文专区| 日韩三级影视基地| 一区二区三区视频免费| 久久免费精品日本久久中文字幕| 最近更新的2019中文字幕| 亚洲bt欧美bt日本bt| 欧美亚洲第一区| 亚洲综合av影视| 欧美裸体xxxx极品少妇| 亚洲电影免费观看高清完整版在线观看| 亚洲男人天堂2023| 91免费精品视频| 成人在线视频福利| 性欧美激情精品| 精品中文字幕在线2019| 亚洲午夜精品久久久久久性色| 亚洲成人精品av| 91高清视频免费| 777777777亚洲妇女| 欧美激情亚洲综合一区| 久久久精品一区| 91精品国产色综合久久不卡98| 97在线视频免费观看| 成人日韩在线电影| 欧美日韩精品在线视频| 2023亚洲男人天堂| 欧美性猛交xxxx黑人| 欧美激情奇米色| 亚洲欧美色婷婷| 亚洲日本aⅴ片在线观看香蕉| 精品中文字幕在线观看| 久久99视频精品| 国产z一区二区三区| 国产在线精品一区免费香蕉| 欧美精品videofree1080p| 一区二区三欧美| 日韩在线观看视频免费| 亚洲综合中文字幕68页| 精品国产视频在线| 国产日韩欧美成人| 国产精品成av人在线视午夜片| 成人中文字幕+乱码+中文字幕| 色视频www在线播放国产成人| 欧美电影免费观看电视剧大全| 亚洲第一偷拍网| 国产99久久精品一区二区 夜夜躁日日躁| 欧美日韩国产一区在线| 在线观看国产精品日韩av| 亚洲国产精品久久精品怡红院| 欧美日韩在线视频一区二区| 91九色在线视频| 欧美精品18videosex性欧美| 国产成人亚洲综合91精品| 成人欧美一区二区三区在线| 国产精品久久久久久久电影| 国产精品网址在线| 亚洲精品日韩丝袜精品| 97免费中文视频在线观看| 亚洲国产精品人人爽夜夜爽| 欧美成人精品在线播放| 91精品国产91久久久久| 色悠悠久久88| 久久久久久久久久av| 国产精品色悠悠| 精品久久久久久中文字幕一区奶水| 清纯唯美亚洲激情| 亚洲一区二区三区xxx视频| 日韩在线精品视频| 欧美一级大片在线观看| 精品久久久久久久中文字幕| 中日韩美女免费视频网站在线观看| 色偷偷综合社区| 色在人av网站天堂精品| 欧美精品18videos性欧美| 国产成人中文字幕| 美女少妇精品视频| 色噜噜国产精品视频一区二区| 另类视频在线观看| 亚洲无限乱码一二三四麻| 久久精品成人欧美大片古装| 亲爱的老师9免费观看全集电视剧| 色999日韩欧美国产| 欧美日韩国产一区在线| 亚洲人免费视频| 羞羞色国产精品| 日韩av片免费在线观看| 国产成人+综合亚洲+天堂| 2018日韩中文字幕| 国产精品久久久久久av福利| 最新69国产成人精品视频免费| 911国产网站尤物在线观看| 国产精品99久久99久久久二8| 国产精品影院在线观看| 国产精品九九九| 久久99久久99精品免观看粉嫩| 欧美网站在线观看| 国产一区二区欧美日韩| 亚洲欧美在线磁力| 国产成人avxxxxx在线看| 日韩亚洲欧美中文高清在线| 欧美激情精品久久久| 一个人www欧美| 欧美限制级电影在线观看| 一区二区三区视频观看| 久久精品夜夜夜夜夜久久| 插插插亚洲综合网| 中文字幕日韩高清| 国产成人精品视频| 国产精品丝袜久久久久久不卡| 亚洲图片制服诱惑| 亚洲欧洲免费视频| 久久国产精品首页| 欧美成人中文字幕在线| 中文字幕亚洲天堂| 国产精品久久久999| 国产丝袜高跟一区| 久久久精品在线| 日本欧美精品在线| 91丝袜美腿美女视频网站| 91亚洲一区精品| 国产91精品久久久久|