天天看點

[圖形學]基于平面方程的陰影計算

一個三維物體繪制出來之後,打上光照就很具有真實感了,但是如果一個物體沒有影子,那麼是一個很可怕的事情。那麼我們如何把一個物體的影子加上呢,本文會介紹一種方法,可以讓三維物體的影子投影到指定的平面上。如何繪制下面的花瓶可以參考我的另一個文章:opengl繪制花瓶

程式示範連結:https://download.csdn.net/download/qq_31804159/10383046

實作結果:

[圖形學]基于平面方程的陰影計算

下面介紹一下原理:

1、如下圖,我們定義光源為平行光,其方向為 l 向量,下圖的p表示一個三維物體上的一點,n表示目标平面的法線,s表示p點投影到目标平面的點。Ax+By+Cz+D=0即為目标平面的方程,

[圖形學]基于平面方程的陰影計算

具體計算如下(下圖從老師那裡盜的

[圖形學]基于平面方程的陰影計算

):

[圖形學]基于平面方程的陰影計算

這裡強調一下最後一步,我們把一個3*3的投影矩陣轉換成4*4的矩陣是因為我們要使用齊次坐标,齊次坐标是将一個原本是n維的向量用一個n+1維向量來表示,如二維點 (1,2) 在齊次坐标中即可标示成 (1,2,1) 或 (2,4,2)。我們把3*3的投影矩陣轉換到到4*4的矩陣時擴大了k倍,k表示縮放系數。則我們最終得到投影點的坐标s應為(Qx/w,Qy/w,Qz/w ); 這一過程我們稱為歸一化處理。

2、我們通過上面的計算公式我們可以得到投影矩陣,下面矩陣可以直接使用:

[圖形學]基于平面方程的陰影計算

        那麼我們隻要讓模型的每個點pi均乘以這個矩陣,那我們就可以得到投影點si.

下面是代碼具體實作:

 3、 定義一些變量

QMatrix4x4 ProjectMat;  //定義投影矩陣
    QVector3D lightPos;    //定義燈的位置
    QVector<QVector3D> project_vertexs;//投影點的集合
   
           

4、構造投影矩陣

void BuildShaderMat(float a, float b, float c, float d, QVector3D lpos)
{
    float lx = lpos.x();
    float ly = lpos.y();
    float lz = lpos.z();
    float k = a*lx+b*ly+c*lz;
    float mat[16] = {b*ly+c*lz,-b*lx,-c*lx,-d*lx,
                     -a*ly , a*lx+c*lz,-c*ly,-d*ly,
                     -a*lz , -b*lz,a*lx+b*ly, -d*lz,
                     0,0,0,k
    };
   QMatrix4x4 pmat(mat);
   ProjectMat = pmat;
}


           

5.計算投影點

void BuildShader()
{
   for( int i =0; i< m_vertex.size(); i++)
   {
       QVector4D p =  m_vertex[i].toVector4D();
       p.setW(1);
       p = ProjectMat*p;
       QVector3D sp(p.x()/p.w(),p.y()/p.w(),p.z()/p.w()); 
       project_vertexs.push_back(sp);
   }
}


           

6、繪制陰影

void drawShader()
{
    glDisable(GL_TEXTURE_2D);
    glDisable(GL_LIGHTING);
    glBegin(GL_QUADS);
    glColor3f(0.6,0.6,0.6);
    for( int i= 0; i<project_vertexs.size(); i++)
      {

        glVertex3f(project_vertexs[i].x(),project_vertexs[i].y(),project_vertexs[i].z());
    }
    glEnd();
    glBegin(GL_POLYGON);
    glEnd();
     glEnable(GL_TEXTURE_2D);
     glEnable(GL_LIGHTING);
}
           

 然後分别調用以上函數即可完成陰影的生成

本例參考源碼連結:https://download.csdn.net/download/qq_31804159/10383051

繼續閱讀