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

  C++博客 :: 首頁 :: 聯系 ::  :: 管理
  163 Posts :: 4 Stories :: 350 Comments :: 0 Trackbacks

常用鏈接

留言簿(48)

我參與的團隊

搜索

  •  

積分與排名

  • 積分 - 402530
  • 排名 - 59

最新評論

閱讀排行榜

評論排行榜

歡迎來到另一個有些復雜的課程,陰影。這一課的效果好的有些讓人不可思議,陰影可以變形,混合在其他的物體上。
這一課要求你必須對OpenGL比較了解,它假設你知道許多OpenGL的知識,你必須知道蒙板緩存,基本的OpenGL步驟。如果你對這些不太熟悉,我建議你可以看看前面的教程。當然,在這一課里,我們用到了很多數學知識,請準備好一本數學手冊在你的身邊。
首先我們定義陰影體可以延伸的距離。 
  

// 定義陰影體可以延伸的距離
#define INFINITY 100

  
 下面定義一個3D頂點結構 
  

// 3D頂點結構
struct sPoint
{
 GLfloat x, y, z;
};

  
 定義一個平面結構 
  

// 平面方程為: ax + by + cz + d = 0
struct sPlaneEq
{
 GLfloat a, b, c, d;
};

  
 下面定義一個用來投影的三角形的結構
3個整形索引指定了模型中三角形的三個頂點
第二個變量指定了三角形面的法線
平面方程描述了三角所在的平面
臨近的3個頂點索引,指定了與這個三角形相鄰的三個頂點
最后一個變量指定這個三角形是否投出陰影
 
  

// 描述一個模型表面的結構
struct sPlane
{
 unsigned int p[3];   // 3個整形索引指定了模型中三角形的三個頂點
 sPoint normals[3];   // 第二個變量指定了三角形面的法線
 unsigned int neigh[3];   // 與本三角形三個邊相鄰的面的索引
 sPlaneEq PlaneEq;   // 平面方程描述了三角所在的平面
 bool visible;   // 最后一個變量指定這個三角形是否投出陰影?
};

  
 最后我們用下面的結構描述一個產生陰影的物體。 
  

struct glObject{ GLuint nPlanes, nPoints; sPoint points[100]; sPlane planes[200];};
  
 下面的代碼用來讀取模型,它的代碼本身就解釋了它的功能。它從文件中讀取數據,并把頂點和索引存儲在上面定義的結構中,并把所有的臨近頂點初始化為-1,它代表這沒有任何頂點與它相鄰,我們將在以后計算它。 
  

bool readObject( const char *filename, glObject*o)
{
  FILE *file;
  unsigned int i;

  file = fopen(st, "r");
  if (!file) return FALSE;
  //讀取頂點
  fscanf(file, "%d", &(o->nPoints));
  for (i=1;i<=o->nPoints;i++){
    fscanf(file, "%f", &(o->points[i].x));
    fscanf(file, "%f", &(o->points[i].y));
    fscanf(file, "%f", &(o->points[i].z));
  }
  //讀取三角形面
  fscanf(file, "%d", &(o->nPlanes));
  for (i=0;inPlanes;i++){
    fscanf(file, "%d", &(o->planes[i].p[0]));
    fscanf(file, "%d", &(o->planes[i].p[1]));
    fscanf(file, "%d", &(o->planes[i].p[2]));
 //讀取每個頂點的法線
    fscanf(file, "%f", &(o->planes[i].normals[0].x));
    fscanf(file, "%f", &(o->planes[i].normals[0].y));
    fscanf(file, "%f", &(o->planes[i].normals[0].z));
    fscanf(file, "%f", &(o->planes[i].normals[1].x));
    fscanf(file, "%f", &(o->planes[i].normals[1].y));
    fscanf(file, "%f", &(o->planes[i].normals[1].z));
    fscanf(file, "%f", &(o->planes[i].normals[2].x));
    fscanf(file, "%f", &(o->planes[i].normals[2].y));
    fscanf(file, "%f", &(o->planes[i].normals[2].z));
  }
 return true;
}

  
 現在從setConnectivity函數開始,事情變得越來越復雜了,這個函數用來查找每個面的相鄰的頂點,下面是它的偽代碼:
 
  

對于模型中的每一個面A 對于面A中的每一條邊  如果我們不只到這條邊相鄰的頂點   那么對于模型中除了面A外的每一個面B    對于面B中的每一條邊     如果面A的邊和面B的邊是同一條邊,那么這兩個面相鄰      設置面A和面B的相鄰屬性
  
 下面的代碼完成上面偽代碼中最后兩行的內容,你先獲得每個面中邊的兩個頂點,然后檢測他們是否相鄰,如果是則設置各自的相鄰頂點信息 
  

 int vertA1 = pFaceA->vertexIndices[edgeA];
 int vertA2 = pFaceA->vertexIndices[( edgeA+1 )%3];

 int vertB1 = pFaceB->vertexIndices[edgeB];
 int vertB2 = pFaceB->vertexIndices[( edgeB+1 )%3];

 // 測試他們是否為同一邊,如果是則設置相應的相鄰頂點信息
 if (( vertA1 == vertB1 && vertA2 == vertB2 ) || ( vertA1 == vertB2 && vertA2 == vertB1 ))
 {
  pFaceA->neighbourIndices[edgeA] = faceB;
  pFaceB->neighbourIndices[edgeB] = faceA;
  edgeFound = true;
  break;
 }

  
 完整的SetConnectivity函數的代碼如下 
  


// 設置相鄰頂點信息
inline void SetConnectivity(glObject *o){
 unsigned int p1i, p2i, p1j, p2j;
 unsigned int P1i, P2i, P1j, P2j;
 unsigned int i,j,ki,kj;

 //對于模型中的每一個面A
 for(i=0;inPlanes-1;i++)
 {
  //對于除了此面的其它的面B
  for(j=i+1;jnPlanes;j++)
  {
   //對于面A中的每一個相鄰的頂點
   for(ki=0;ki<3;ki++)
   {
    //如果這個相鄰的頂點沒有被設置
    if(!o->planes[i].neigh[ki])
    {
     for(kj=0;kj<3;kj++)
     {
      p1i=ki;
      p1j=kj;
      p2i=(ki+1)%3;
      p2j=(kj+1)%3;

      p1i=o->planes[i].p[p1i];
      p2i=o->planes[i].p[p2i];
      p1j=o->planes[j].p[p1j];
      p2j=o->planes[j].p[p2j];
    
      //如果面A的邊P1i->P1j和面B的邊P2i->P2j為同一條邊,則又下面的公式的P1i=P1j,并且P2i=P2j
      P1i=((p1i+p2i)-abs(p1i-p2i))/2;
      P2i=((p1i+p2i)+abs(p1i-p2i))/2;
      P1j=((p1j+p2j)-abs(p1j-p2j))/2;
      P2j=((p1j+p2j)+abs(p1j-p2j))/2;

      //記錄與這個邊相鄰的面的索引
      if((P1i==P1j) && (P2i==P2j))
      {
       o->planes[i].neigh[ki] = j+1;  
       o->planes[j].neigh[kj] = i+1;  
      }
     }
    }
   }
  }
 }
}

  
 下面的函數用來繪制模型 
  

// 繪制模型,像以前一樣它繪制組成模型的三角形
void drawObject( const ShadowedObject& object )
{
 glBegin( GL_TRIANGLES );
 for ( int i = 0; i < object.nFaces; i++ )
 {
  const Face& face = object.pFaces[i];

  for ( int j = 0; j < 3; j++ )
  {
   const Point3f& vertex = object.pVertices[face.vertexIndices[j]];

   glNormal3f( face.normals[j].x, face.normals[j].y, face.normals[j].z );
   glVertex3f( vertex.x, vertex.y, vertex.z );
  }
 }
 glEnd();
}

  
 下面的函數用來計算平面的方程參數 
  

void calculatePlane( const ShadowedObject& object, Face& face )
{
 // 獲得平面的三個頂點
 const Point3f& v1 = object.pVertices[face.vertexIndices[0]];
 const Point3f& v2 = object.pVertices[face.vertexIndices[1]];
 const Point3f& v3 = object.pVertices[face.vertexIndices[2]];

 face.planeEquation.a = v1.y*(v2.z-v3.z) + v2.y*(v3.z-v1.z) + v3.y*(v1.z-v2.z);
 face.planeEquation.b = v1.z*(v2.x-v3.x) + v2.z*(v3.x-v1.x) + v3.z*(v1.x-v2.x);
 face.planeEquation.c = v1.x*(v2.y-v3.y) + v2.x*(v3.y-v1.y) + v3.x*(v1.y-v2.y);
 face.planeEquation.d = -( v1.x*( v2.y*v3.z - v3.y*v2.z ) +
    v2.x*(v3.y*v1.z - v1.y*v3.z) +
    v3.x*(v1.y*v2.z - v2.y*v1.z) );
}

  
 你還可以呼吸么?好的,我們繼續:) 接下來你將學習如何去投影,castShadow函數幾乎用到了所有OpenGL的功能,完成這個函數后,把它傳遞到doShadowPass函數來通過兩個渲染通道繪制出陰影.
首先,我們看看哪些面面對著燈光,我們可以通過燈光位置和平面方程計算出.如果燈光到平面的位置大于0,則位于燈光的上方,否則位于燈光的下方(如果有什么問題,翻一下你高中的解析幾何). 
  

void castShadow( ShadowedObject& object, GLfloat *lightPosition )
{
 // 設置哪些面在燈光的前面
 for ( int i = 0; i < object.nFaces; i++ )
 {
  const Plane& plane = object.pFaces[i].planeEquation;

  GLfloat side = plane.a*lightPosition[0]+
   plane.b*lightPosition[1]+
   plane.c*lightPosition[2]+
   plane.d;

  if ( side > 0 )
   object.pFaces[i].visible = true;
  else
   object.pFaces[i].visible = false;
 }

  
 下面設置必要的狀態來渲染陰影.
首先,禁用燈光和繪制顏色,因為我們不計算光照,這樣可以節約計算量.
接著,設置深度緩存,深度測試還是需要的,但我們不希望我們的陰影體向實體一樣具有深度,所以關閉深度緩存.
最后我們啟用蒙板緩存,讓陰影體的位置在蒙板中被設置為1. 
  

 glDisable( GL_LIGHTING );     // 關閉燈光
 glColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE );  // 關閉顏色緩存的寫入 
 glDepthFunc( GL_LEQUAL );     // 設置深度比較函數
 glDepthMask( GL_FALSE );     // 關閉深度緩存的寫入 
 glEnable( GL_STENCIL_TEST );    // 使用蒙板緩存
 glStencilFunc( GL_ALWAYS, 1, 0xFFFFFFFFL );   // 設置蒙板函數

  
 現在到了陰影被實際渲染得地方了,我們使用了下面提到的doShadowPass函數,它用來繪制陰影體的邊界面.我們通過兩個步驟來繪制陰影體,首先使用前向面增加陰影體在蒙板緩存中的值,接著使用后向面減少陰影體在蒙板緩存中的值. 
  

 // 如果是逆時針(即面向視點)的多邊形,通過了蒙板和深度測試,則把蒙板的值增加1
 glFrontFace( GL_CCW );
 glStencilOp( GL_KEEP, GL_KEEP, GL_INCR );
 doShadowPass( object, lightPosition );
 // 如果是順時針(即背向視點)的多邊形,通過了蒙板和深度測試,則把蒙板的值減少1
 glFrontFace( GL_CW );
 glStencilOp( GL_KEEP, GL_KEEP, GL_DECR );
 doShadowPass( object, lightPosition );

  
 為了更好的理解這兩個步驟,我建議你把第二步注釋掉看看效果,如下所示:

 
圖 1: 步驟1 圖 2: 步驟2


最后一步就是把陰影體所在的位置繪制上陰影的顏色 
  

 glFrontFace( GL_CCW );
 glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE ); 

 // 把陰影繪制上顏色
 glColor4f( 0.0f, 0.0f, 0.0f, 0.4f );
 glEnable( GL_BLEND );
 glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
 glStencilFunc( GL_NOTEQUAL, 0, 0xFFFFFFFFL );
 glStencilOp( GL_KEEP, GL_KEEP, GL_KEEP );
 glPushMatrix();
 glLoadIdentity();
 glBegin( GL_TRIANGLE_STRIP );
  glVertex3f(-0.1f, 0.1f,-0.10f);
  glVertex3f(-0.1f,-0.1f,-0.10f);
  glVertex3f( 0.1f, 0.1f,-0.10f);
  glVertex3f( 0.1f,-0.1f,-0.10f);
 glEnd();
 glPopMatrix();
}

  
 下面的部分我們繪制構成陰影體邊界的四邊形,當我們循環所有的三角形面的時候,我們檢測它是否是邊界邊,如果是我們繪制從燈光到這個邊界邊的射線,并衍生它用來構成四邊形.
這里要用一個蠻力,我們檢測物體模型中每一個三角形面,找出其邊界并連接燈光到邊界的直線,把直線延長出一定的距離,構成陰影體.

下面的代碼完成這些功能,它看起來并沒有想象的復雜.
 
  

void doShadowPass(glObject *o, float *lp)
{
 unsigned int i, j, k, jj;
 unsigned int p1, p2;
 sPoint   v1, v2;

 //對模型中的每一個面
 for (i=0; inPlanes;i++)
 { 
  //如果面在燈光的前面
  if (o->planes[i].visible)
  {
   //對于被燈光照射的面的每一個相鄰的面
   for (j=0;j<3;j++)
   {
    k = o->planes[i].neigh[j];
    //如果面不存在,或不被燈光照射,那么這個邊是邊界
    if ((!k) || (!o->planes[k-1].visible))
    {
     // 獲得面的兩個頂點
     p1 = o->planes[i].p[j];
     jj = (j+1)%3;
     p2 = o->planes[i].p[jj];

     //計算邊的頂點到燈光的方向,并放大100倍
     v1.x = (o->points[p1].x - lp[0])*100;
     v1.y = (o->points[p1].y - lp[1])*100;
     v1.z = (o->points[p1].z - lp[2])*100;

     v2.x = (o->points[p2].x - lp[0])*100;
     v2.y = (o->points[p2].y - lp[1])*100;
     v2.z = (o->points[p2].z - lp[2])*100;
     
     //繪制構成陰影體邊界的面
     glBegin(GL_TRIANGLE_STRIP);
      glVertex3f(o->points[p1].x,
         o->points[p1].y,
         o->points[p1].z);
      glVertex3f(o->points[p1].x + v1.x,
         o->points[p1].y + v1.y,
         o->points[p1].z + v1.z);

      glVertex3f(o->points[p2].x,
         o->points[p2].y,
         o->points[p2].z);
      glVertex3f(o->points[p2].x + v2.x,
         o->points[p2].y + v2.y,
         o->points[p2].z + v2.z);
     glEnd();
    }
   }
  }
 }

}


  
 既然我們已經能繪制陰影了,那么我們開始繪制我們的場景吧 
  

bool drawGLScene()
{
 GLmatrix16f Minv;
 GLvector4f wlp, lp;

 // 清空緩存
 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);

 glLoadIdentity();       // 設置燈光,并繪制球
 glTranslatef(0.0f, 0.0f, -20.0f);    
 glLightfv(GL_LIGHT1, GL_POSITION, LightPos);   
 glTranslatef(SpherePos[0], SpherePos[1], SpherePos[2]);  
 gluSphere(q, 1.5f, 32, 16);     
  
 下面我們計算燈光在物體坐標系中的位置 
  

 glLoadIdentity();      
 glRotatef(-yrot, 0.0f, 1.0f, 0.0f);    
 glRotatef(-xrot, 1.0f, 0.0f, 0.0f);    
 glTranslatef(-ObjPos[0], -ObjPos[1], -ObjPos[2]);  
 glGetFloatv(GL_MODELVIEW_MATRIX,Minv);    // 計算從世界坐標系變化到物體坐標系中的坐標
 lp[0] = LightPos[0];      // 保存燈光的位置
 lp[1] = LightPos[1];      
 lp[2] = LightPos[2];      
 lp[3] = LightPos[3];      
 VMatMult(Minv, lp);      // 計算最后燈光的位置

  
 下面繪制房間,物體和它的陰影 
  

 glLoadIdentity();  
 glTranslatef(0.0f, 0.0f, -20.0f);    
 DrawGLRoom();       // 繪制房間
 glTranslatef(ObjPos[0], ObjPos[1], ObjPos[2]);   
 glRotatef(xrot, 1.0f, 0.0f, 0.0f);    
 glRotatef(yrot, 0.0f, 1.0f, 0.0f);    
 DrawGLObject(obj);       // 繪制物體
 CastShadow(&obj, lp);      // 繪制物體的陰影

  
 下面的代碼繪制一個黃色的球代表了燈光的位置 
  

 glColor4f(0.7f, 0.4f, 0.0f, 1.0f);    
 glDisable(GL_LIGHTING);      
 glDepthMask(GL_FALSE);      
 glTranslatef(lp[0], lp[1], lp[2]);    
 gluSphere(q, 0.2f, 16, 8);     
 glEnable(GL_LIGHTING);      
 glDepthMask(GL_TRUE);      
  
 最后設置物體的控制 
  

 xrot += xspeed;       // 增加X軸選擇速度
 yrot += yspeed;       // 增加Y軸選擇速度

 glFlush();       // 強制OpenGL完成所有的命令
 return TRUE;       // 成功返回
}

  
 繪制房間墻面 
  

void DrawGLRoom()        // 繪制房間(盒裝)
{
 glBegin(GL_QUADS);       // 繪制四邊形
  // 地面
  glNormal3f(0.0f, 1.0f, 0.0f);    // 法線向上
  glVertex3f(-10.0f,-10.0f,-20.0f);   
  glVertex3f(-10.0f,-10.0f, 20.0f);   
  glVertex3f( 10.0f,-10.0f, 20.0f);   
  glVertex3f( 10.0f,-10.0f,-20.0f);   
  // 天花板
  glNormal3f(0.0f,-1.0f, 0.0f);    // 法線向下
  glVertex3f(-10.0f, 10.0f, 20.0f);   
  glVertex3f(-10.0f, 10.0f,-20.0f);   
  glVertex3f( 10.0f, 10.0f,-20.0f);   
  glVertex3f( 10.0f, 10.0f, 20.0f);   
  // 前面
  glNormal3f(0.0f, 0.0f, 1.0f);    // 法線向后
  glVertex3f(-10.0f, 10.0f,-20.0f);   
  glVertex3f(-10.0f,-10.0f,-20.0f);   
  glVertex3f( 10.0f,-10.0f,-20.0f);   
  glVertex3f( 10.0f, 10.0f,-20.0f);   
  // 后面
  glNormal3f(0.0f, 0.0f,-1.0f);    // 法線向前
  glVertex3f( 10.0f, 10.0f, 20.0f);   
  glVertex3f( 10.0f,-10.0f, 20.0f);   
  glVertex3f(-10.0f,-10.0f, 20.0f);   
  glVertex3f(-10.0f, 10.0f, 20.0f);   
  // 左面
  glNormal3f(1.0f, 0.0f, 0.0f);    // 法線向右
  glVertex3f(-10.0f, 10.0f, 20.0f);   
  glVertex3f(-10.0f,-10.0f, 20.0f);   
  glVertex3f(-10.0f,-10.0f,-20.0f);   
  glVertex3f(-10.0f, 10.0f,-20.0f);   
  // 右面
  glNormal3f(-1.0f, 0.0f, 0.0f);    // 法線向左
  glVertex3f( 10.0f, 10.0f,-20.0f);   
  glVertex3f( 10.0f,-10.0f,-20.0f);  
  glVertex3f( 10.0f,-10.0f, 20.0f);   
  glVertex3f( 10.0f, 10.0f, 20.0f);   
 glEnd();        // 結束繪制
}

  
 下面的函數完成矩陣M與向量V的乘法M=M*V
 
  

void VMatMult(GLmatrix16f M, GLvector4f v)
{
 GLfloat res[4];       // 保存中間計算結果
 res[0]=M[ 0]*v[0]+M[ 4]*v[1]+M[ 8]*v[2]+M[12]*v[3];
 res[1]=M[ 1]*v[0]+M[ 5]*v[1]+M[ 9]*v[2]+M[13]*v[3];
 res[2]=M[ 2]*v[0]+M[ 6]*v[1]+M[10]*v[2]+M[14]*v[3];
 res[3]=M[ 3]*v[0]+M[ 7]*v[1]+M[11]*v[2]+M[15]*v[3];
 v[0]=res[0];       // 把結果保存在V中
 v[1]=res[1];
 v[2]=res[2];
 v[3]=res[3];       
}

  
 下面的函數用來初始化模型對象 
  

int InitGLObjects()       // 初始化模型對象
{
 if (!ReadObject("Data/Object2.txt", &obj))    // 讀取模型數據
 {
  return FALSE;      // 返回失敗
 }

 SetConnectivity(&obj);      // 設置相鄰頂點的信息

 for ( int i=0;i < obj.nPlanes;i++)     // 計算每個面的平面參數
  CalcPlane(obj, &obj.planes[i]);   

 return TRUE;       //成功返回
}


  
 其他的函數我們不做過多解釋了,這會分散你的注意力,好好享受陰影帶給你的快感吧.
下面還有一些說明:
球體不會產生陰影,因為我們沒有設置其投影.
如果你發現程序很慢,買塊好的顯卡吧.

最后我希望你喜歡它,如果有什么好的建議,請告訴我.
 

posted on 2007-12-20 11:52 sdfasdf 閱讀(1535) 評論(4)  編輯 收藏 引用 所屬分類: OPENGL

Feedback

# re: NEHE的OPENGL中文教程 第27課 影子 2007-12-20 20:49 學海一人
繼續努力  回復  更多評論
  

# re: NEHE的OPENGL中文教程 第27課 影子 2007-12-20 21:12 修遠
頂一下,老兄  回復  更多評論
  

# re: NEHE的OPENGL中文教程 第27課 影子 2008-05-04 20:28 kxlsc1985
glStencilFunc(GL_NOTEQUAL, 0, 0xffffffff);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
glPushMatrix();
glLoadIdentity();
、、、、、、、、、、、、、、、、
glBegin(GL_TRIANGLE_STRIP);
glVertex3f(-0.1f, 0.1f,-0.1f);
glVertex3f(-0.1f,-0.1f,-0.1f);
glVertex3f( 0.1f, 0.1f,-0.1f);
glVertex3f( 0.1f,-0.1f,-0.1f);
glEnd();
glPopMatrix();
glDisable(GL_BLEND);
、、、、、、、、、、、、、、、
不懂為什么要畫矩形  回復  更多評論
  

# re: NEHE的OPENGL中文教程 第27課 影子 2008-05-04 20:30 kxlsc1985
是3dobject.h文件中的最后一部分  回復  更多評論
  

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            欧美在线视频不卡| 国内精品久久久久久久影视麻豆 | 亚洲无限av看| 久久综合伊人77777尤物| 亚洲老司机av| 免费观看30秒视频久久| 国产精品日韩欧美一区| 一区二区不卡在线视频 午夜欧美不卡'| 香蕉免费一区二区三区在线观看| 亚洲激情在线观看视频免费| 亚洲欧美日韩精品久久| 国产精品国产三级国产专播品爱网| 亚洲精品国产精品国自产在线 | 美女免费视频一区| 国产一区清纯| 久久嫩草精品久久久久| 久久成人精品| 极品少妇一区二区三区| 老司机午夜精品视频| 久久狠狠一本精品综合网| 国产色产综合产在线视频| 欧美一级久久久久久久大片| 国产精品99久久久久久宅男| 欧美网站在线| 亚洲欧美激情诱惑| 欧美一区1区三区3区公司| 国产日韩欧美麻豆| 欧美中文字幕不卡| 欧美一级大片在线观看| 在线国产欧美| 亚洲精品久久久久久久久久久| 欧美黑人在线播放| 亚洲午夜91| 性欧美在线看片a免费观看| 国产一级一区二区| 久久综合999| 欧美激情综合网| 欧美一区91| 久久久久一区| 亚洲视频碰碰| 久久久国际精品| 91久久国产精品91久久性色| 91久久午夜| 国产精品五区| 欧美va亚洲va香蕉在线| 欧美精品系列| 久久久999成人| 欧美freesex8一10精品| 中日韩高清电影网| 欧美一区国产一区| 日韩亚洲在线观看| 欧美专区福利在线| 日韩一区二区久久| 久久精品国产免费看久久精品| 国模 一区 二区 三区| 久久综合色8888| 欧美高清在线观看| 日韩午夜精品| 噜噜噜噜噜久久久久久91| 欧美本精品男人aⅴ天堂| 亚洲欧美中文日韩在线| 老司机精品视频网站| 亚洲欧美日韩系列| 欧美激情a∨在线视频播放| 欧美一区二区视频97| 免费亚洲一区二区| 久久久久久亚洲精品中文字幕| 欧美日韩www| 欧美成人免费播放| 韩国欧美一区| 亚洲欧美中文日韩在线| 一级成人国产| 欧美成人一区二区| 久久综合九色九九| 国产伦精品一区二区三区四区免费 | 99精品99| 亚洲国产高清一区二区三区| 亚洲欧美日韩精品在线| 亚洲一区亚洲二区| 欧美日韩在线视频一区| 亚洲精品久久视频| 亚洲精品一区二区三区樱花 | 欧美极品一区| 欧美成年人在线观看| 国产欧美高清| 亚洲一区亚洲| 午夜宅男久久久| 欧美午夜精品一区| 一本色道久久综合亚洲精品婷婷 | 黄色日韩网站视频| 午夜精品剧场| 午夜影视日本亚洲欧洲精品| 国产精品高潮呻吟| 亚洲特级片在线| 午夜在线不卡| 国产伦精品免费视频| 99国产精品久久久| 中文一区在线| 国产精品电影在线观看| 一道本一区二区| 亚洲午夜在线视频| 国产精品日韩精品| 午夜日韩福利| 狼人天天伊人久久| 亚洲动漫精品| 欧美美女操人视频| 日韩一区二区免费高清| 亚洲无限av看| 国产日韩欧美电影在线观看| 久久精品综合| 欧美黑人在线观看| 亚洲中字在线| 久久久99精品免费观看不卡| 久久久久久久一区二区三区| 国产日韩欧美在线看| 久久精品人人| 欧美激情女人20p| 亚洲精品日产精品乱码不卡| 欧美精品日韩精品| 亚洲午夜黄色| 免费成人性网站| 亚洲免费观看高清完整版在线观看熊| 农村妇女精品| 一区二区激情| 久久久久久国产精品一区| 在线成人激情| 欧美精品电影| 羞羞答答国产精品www一本| 久久久91精品国产| 夜夜嗨av一区二区三区网站四季av | 欧美在线免费看| 国产一区二区三区视频在线观看 | 国产色综合网| 裸体一区二区| 中文久久精品| 美女视频网站黄色亚洲| 日韩午夜av在线| 国产亚洲一区精品| 欧美日韩a区| 久久久.com| 一区二区三区欧美在线观看| 麻豆精品视频在线| 先锋资源久久| 在线视频精品一| 国产一区二区三区久久悠悠色av| 久久亚洲私人国产精品va| 亚洲国产天堂久久综合| 久久av一区二区三区漫画| 亚洲日本成人| 国语自产精品视频在线看抢先版结局 | 久久久国产成人精品| 99在线|亚洲一区二区| 卡通动漫国产精品| 香蕉亚洲视频| 99re国产精品| 亚洲国产日韩综合一区| 国产一区在线免费观看| 国产精品二区二区三区| 欧美国产精品va在线观看| 久久精品视频99| 午夜精品久久久久久| 99在线热播精品免费| 亚洲黄色免费| 亚洲成色999久久网站| 久久国产精品久久国产精品| 这里只有视频精品| 亚洲精品视频中文字幕| 在线视频国内自拍亚洲视频| 国产一区二区三区在线观看视频| 国产精品久久久久77777| 欧美日韩国产三级| 欧美日韩一区二区三区在线视频| 牛牛影视久久网| 欧美va亚洲va国产综合| 久久精品视频亚洲| 久久久一本精品99久久精品66| 亚洲欧美日韩综合aⅴ视频| 99精品视频免费观看| 欧美在线视频免费| 亚洲一区二区三区欧美| 亚洲美女毛片| 亚洲欧洲三级| 亚洲国内自拍| 在线精品福利| 亚洲精品一区二区三区av| 亚洲精选视频在线| 在线视频亚洲欧美| 亚洲性夜色噜噜噜7777| 亚洲欧美日韩天堂一区二区| 亚洲欧美国产制服动漫| 午夜精品偷拍| 久久久久成人网| 蜜桃久久av一区| 麻豆乱码国产一区二区三区| 你懂的亚洲视频| 亚洲人成网站在线播| 在线亚洲欧美| 久久精品国产99国产精品| 久久综合久久综合这里只有精品 | 国产性天天综合网|