在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 }