Introduction to my galaxy engine 3: Local light model

在deferred shading中,对于局部光源,我们是需要建立一个它的光照范围的模型,然后再通过深度和模板检测来获取受光照影响的物体(类似shadow volumn中用到的方法)。以下是两个常用局部光源的模型:点光源模型的一个球体(也可以用cube或者square近似代替),spot light 是一个cone模型, 平行光模型可以用cube模型。需要注意的是所有模型都是封闭的。如果光源是动态产生的话,例如例子系统中粒子的光源,这些模型也可以在geometirc shader生成。

以下是模型的截图:

以下是程序代码:步骤主要分为两步(生成顶点位置,生成顶点的索引)

  1 void CGeomCreator::CreateSphere(float fRadius, size_t iRings, size_t iSegments, const D3DXVECTOR3& Pos)
  2 {
  3     //suppose the sphere is located at coord center
  4     m_iVertexNum = iRings * iSegments + 2;
  5     m_pModel = new ModelType[m_iVertexNum];
  6     size_t iCurVertex = 0;
  7 
  8     float fDeltaRing = PI / (iRings + 1);
  9     float fDeltaSegment = 2 * PI / iSegments;
 10 
 11     //top point
 12     m_pModel[iCurVertex].Pos = D3DXVECTOR3(Pos.x, Pos.y + fRadius, Pos.z);
 13     ++iCurVertex;
 14     //middle points
 15     for (size_t i = 0; i < iRings; ++i)
 16     {
 17         float y = Pos.y + fRadius * cos(fDeltaRing * (i + 1));
 18         float r = fRadius * sin(fDeltaRing * (i + 1));
 19 
 20         for (size_t j = 0; j < iSegments; ++j)
 21         {
 22             float x = Pos.x + r * cos(fDeltaSegment * j);
 23             float z = Pos.z + r * sin(fDeltaSegment * j);
 24 
 25             m_pModel[iCurVertex].Pos = D3DXVECTOR3(x, y, z);
 26             ++iCurVertex;
 27         }
 28     }
 29     //botom point
 30     m_pModel[iCurVertex].Pos = D3DXVECTOR3(Pos.x, Pos.y - fRadius, Pos.z);
 31 
 32     //generate index
 33     m_iIndexNum = iSegments * 3 * 2 + iSegments * 3 * 2 * (iRings - 1);//top + button + middle
 34     m_pIndces = new DWORD[m_iIndexNum];
 35 
 36     size_t iCurIndex = 0;
 37     for (size_t i = 0; i <= iRings; ++i)//<=
 38     {
 39         for (size_t j = 0; j < iSegments; ++j)
 40         {
 41             if(i ==0)//top
 42             {
 43                 m_pIndces[iCurIndex] = 0;    
 44                 ++iCurIndex;
 45                 if(j < iSegments - 1)
 46                     m_pIndces[iCurIndex] = 1 + (j + 1);
 47                 else
 48                     m_pIndces[iCurIndex] = 1;
 49                 ++iCurIndex;
 50                 m_pIndces[iCurIndex] =    1 + j;
 51                 ++iCurIndex;
 52             }
 53             else if(i == iRings)//bottom
 54             {
 55                 size_t iLastVertex = m_iVertexNum - 1;
 56                 size_t iStartVertex = 1 + (iRings - 1) * iSegments + j;
 57 
 58                 m_pIndces[iCurIndex] = iStartVertex;
 59                 ++iCurIndex;
 60                 if(j < iSegments - 1)
 61                     m_pIndces[iCurIndex] = iStartVertex + 1;
 62                 else
 63                     m_pIndces[iCurIndex] = 1 + (iRings - 1) * iSegments;//j back to 0
 64                 ++iCurIndex;
 65                 m_pIndces[iCurIndex] = iLastVertex;
 66                 ++iCurIndex;
 67             }
 68             else//middle of sphere
 69             {
 70                 size_t iStartVertex = 1 + (i - 1) * iSegments + j;
 71 
 72                 m_pIndces[iCurIndex] = iStartVertex;
 73                 ++iCurIndex;
 74                 if(j < iSegments - 1)
 75                     m_pIndces[iCurIndex] = iStartVertex + iSegments + 1;
 76                 else
 77                     m_pIndces[iCurIndex] = iStartVertex + 1;//iSegments back to 0
 78                 ++iCurIndex;
 79                 m_pIndces[iCurIndex] = iStartVertex + iSegments;
 80                 ++iCurIndex;
 81 
 82                 m_pIndces[iCurIndex] = iStartVertex;
 83                 ++iCurIndex;
 84                 if(j < iSegments - 1)
 85                     m_pIndces[iCurIndex] = iStartVertex + 1; 
 86                 else
 87                     m_pIndces[iCurIndex] = 1 + (i - 1) * iSegments;//j back to 0
 88                 ++iCurIndex;
 89                 if(j < iSegments - 1)
 90                     m_pIndces[iCurIndex] = iStartVertex + 1 + iSegments;
 91                 else
 92                     m_pIndces[iCurIndex] = iStartVertex + 1;//iSegments back to 0
 93                 ++iCurIndex;
 94             }
 95         }
 96     }
 97 }
 98 
 99 void CGeomCreator::CreateCone(float fRadius , float fHeight, size_t iSegments, const D3DXVECTOR3& Pos)
100 {
101     //suppose the bottom of the sphere is located at xz coord center
102     m_iVertexNum = iSegments + 2;
103     m_pModel = new ModelType[m_iVertexNum];
104     size_t iCurVertex = 0;
105     float fDeltaSegment = 2 * PI / iSegments;
106 
107     //top point
108     m_pModel[iCurVertex].Pos = D3DXVECTOR3(Pos.x, Pos.y, Pos.z);
109     ++iCurVertex;
110     //middle points
111     for (size_t i = 0; i < iSegments; ++i)
112     {
113         float x = cos(fDeltaSegment * i) * fRadius;
114         float z = sin(fDeltaSegment * i) * fRadius;
115         m_pModel[iCurVertex].Pos = D3DXVECTOR3(Pos.x + x, Pos.y - fHeight, Pos.z + z);
116         ++iCurVertex;
117     }
118     //bottom point
119     m_pModel[iCurVertex].Pos = D3DXVECTOR3(Pos.x, Pos.y - fHeight, Pos.z);
120 
121     m_iIndexNum = iSegments * 3 * 2;
122     m_pIndces = new DWORD[m_iIndexNum];
123     size_t iCurIndex = 0;
124     //top
125     for (size_t i = 0; i < iSegments; ++i)
126     {
127         m_pIndces[iCurIndex] = 0;
128         ++iCurIndex;
129         if(i < iSegments - 1)
130             m_pIndces[iCurIndex] = 1 + i + 1;
131         else
132             m_pIndces[iCurIndex] = 1;
133         ++iCurIndex;
134         m_pIndces[iCurIndex] = 1 + i;
135         ++iCurIndex;
136     }
137     //bottom
138     for (size_t i = 0; i < iSegments; ++i)
139     {
140         m_pIndces[iCurIndex] = 1 + i;
141         ++iCurIndex;
142         if(i < iSegments - 1)
143             m_pIndces[iCurIndex] = 1 + i + 1;
144         else
145             m_pIndces[iCurIndex] = 1;
146         ++iCurIndex;
147         m_pIndces[iCurIndex] = m_iVertexNum -1;
148         ++iCurIndex;
149     }
150 }
原文地址:https://www.cnblogs.com/RobinG/p/2515959.html