Develop and Download Open Source Software

Browse Subversion Repository

Contents of /trunk/CShadowVolume.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 7 - (show annotations) (download) (as text)
Wed Sep 21 10:25:11 2011 UTC (12 years, 7 months ago) by okadu
File MIME type: text/x-c++src
File size: 8069 byte(s)
[okadu] 計測コード

1 #include "stdafx.h"
2 #include "CJobTimer.h"
3 #include "CShadowVolume.h"
4 #include "CScene.h"
5 #include "CEnvPlugin.h"
6
7 // 内部定数
8 const int TRI_DUMP_MAX_MAX = 21845; // 三角形ダンプ最大値の最大値
9 const float SHADOW_INF_DIST = 1.0e10f; // シャドウボリューム無限遠点
10
11 // 外部グローバル
12 extern bool g_HidefCaptureFlag;
13 extern int g_HidefBufferSize;
14
15 /*
16 * コンストラクタ
17 */
18 CTriDumpS::CTriDumpS(
19 int trinum // 四角形数
20 ){
21 m_TriNum = trinum;
22 if(m_TriNum>TRI_DUMP_MAX_MAX) m_TriNum = TRI_DUMP_MAX_MAX;
23 m_Count = 0;
24 m_Buffer = new VTX_S[m_TriNum*3];
25 m_Next = NULL;
26 }
27
28 /*
29 * コンストラクタ
30 */
31 CTriDumpS::CTriDumpS(
32 CTriDumpS *src // 引き継ぎ元
33 ){
34 m_TriNum = src->m_TriNum;
35 m_Count = src->m_Count;
36 m_Buffer = src->m_Buffer;
37 m_Next = src->m_Next;
38 }
39
40 /*
41 * デストラクタ
42 */
43 CTriDumpS::~CTriDumpS(){
44 DELETE_A(m_Buffer);
45 DELETE_V(m_Next);
46 }
47
48 /*
49 * バッファ追加
50 */
51 void CTriDumpS::Feed(){
52 m_Next = new CTriDumpS(this);
53 m_Count = 0;
54 m_Buffer = new VTX_S[m_TriNum*3];
55 }
56
57 /*
58 * プリミティブ追加
59 */
60 void CTriDumpS::Add(
61 VEC3 p1, VEC3 p2, VEC3 p3 // 頂点
62 ){
63 if(m_Count==m_TriNum) Feed();
64 VTX_S *buf = &m_Buffer[m_Count*3];
65 *buf = p1; buf++;
66 *buf = p2; buf++;
67 *buf = p3; buf++;
68 m_Count++;
69 }
70
71 /*
72 * 即描画
73 */
74 void CTriDumpS::Preview(
75 VEC3 p1, VEC3 p2, VEC3 p3 // 頂点
76 ){
77 VTX_S prev[3], *buf = prev;
78 *buf = p1; buf++;
79 *buf = p2; buf++;
80 *buf = p3; buf++;
81 sv3.pDev->SetVertexShader(FVF_S);
82 sv3.pDev->DrawPrimitiveUP(D3DPT_TRIANGLELIST, 1, prev, sizeof(VTX_S));
83 }
84
85 /*
86 * バーテックス準備
87 */
88 void CTriDumpS::PrepareVertex(){
89 m_Vertex.Create(m_Buffer, FVF_S, m_Count*3*sizeof(VTX_S));
90 if(m_Next) m_Next->PrepareVertex();
91 }
92
93 /*
94 * レンダリング
95 */
96 void CTriDumpS::Render(
97 bool drawup // DrawPrimitiveUp を使用
98 ){
99 devSetTexture(0, NULL);
100 if(drawup){
101 sv3.pDev->SetVertexShader(FVF_S);
102 sv3.pDev->DrawPrimitiveUP(D3DPT_TRIANGLELIST, m_Count, m_Buffer, sizeof(VTX_S));
103 }else{
104 m_Vertex.RenderTL();
105 }
106 if(m_Next) m_Next->Render(drawup);
107 }
108
109 ////////////////////////////////////////////////////////////////////////////////
110 ////////////////////////////////////////////////////////////////////////////////
111
112 /*
113 * コンストラクタ
114 */
115 CShadowVolume::CShadowVolume(){
116 m_FaceVolume = NULL;
117 }
118
119 /*
120 * デストラクタ
121 */
122 CShadowVolume::~CShadowVolume(){
123 DELETE_V(m_FaceVolume);
124 }
125
126 /*
127 * リセット
128 */
129 void CShadowVolume::Reset(){
130 DELETE_V(m_FaceVolume);
131 m_FaceVolume = new CTriDumpS(TRI_DUMP_MAX);
132 }
133
134 /*
135 * メッシュから生成
136 */
137 void CShadowVolume::BuildFromMesh(
138 CObject *obj, // オブジェクト
139 VEC3 vLight // ライト方向
140 ){
141 TIMER_RAII("CShadowVolume::BuildFromMesh()");
142
143 CMesh *udxMesh = obj->GetMesh();
144 if(!udxMesh) return;
145 udxMesh->MaskMatFlag(1);
146 LPD3DXMESH pMesh = udxMesh->GetObject();
147
148 VEC3 vLocal = V3WorldToLocal(&vLight, obj);
149 MTX4 mtxWorld = obj->GetWMatrix();
150
151 UINT fvfSize = D3DXGetFVFVertexSize(pMesh->GetFVF());
152
153 BYTE* pVertices = NULL;
154 WORD* pIndices = NULL;
155 DWORD* pAttributes = NULL;
156
157 // バッファをロック
158 if(FAILED(pMesh->LockVertexBuffer(D3DLOCK_READONLY, (BYTE **)&pVertices))){
159 return;
160 }
161 if(FAILED(pMesh->LockIndexBuffer(D3DLOCK_READONLY, (BYTE **)&pIndices))){
162 pMesh->UnlockVertexBuffer();
163 return;
164 }
165 if(FAILED(pMesh->LockAttributeBuffer(D3DLOCK_READONLY, &pAttributes))){
166 pMesh->UnlockVertexBuffer();
167 pMesh->UnlockIndexBuffer();
168 return;
169 }
170 DWORD dwNumVertices = pMesh->GetNumVertices();
171 DWORD dwNumFaces = pMesh->GetNumFaces();
172
173 DWORD i, j;
174 m_TempIndex.clear();
175 for(i = 0; i<dwNumFaces; i++){
176 if(udxMesh->GetMatFlag(pAttributes[i])) continue;
177 WORD wFace0 = pIndices[3*i+0];
178 WORD wFace1 = pIndices[3*i+1];
179 WORD wFace2 = pIndices[3*i+2];
180 VEC3 v0 = *(VEC3 *)(pVertices+fvfSize*wFace0);
181 VEC3 v1 = *(VEC3 *)(pVertices+fvfSize*wFace1);
182 VEC3 v2 = *(VEC3 *)(pVertices+fvfSize*wFace2);
183
184 VEC3 vNormal;
185 V3Cross(&vNormal, &(v2-v1), &(v1-v0));
186 if(V3Dot(&vNormal, &vLocal)>=0.0f){
187 m_TempIndex.push_back(CEdgeIndex(wFace0, wFace1));
188 m_TempIndex.push_back(CEdgeIndex(wFace1, wFace2));
189 m_TempIndex.push_back(CEdgeIndex(wFace2, wFace0));
190 }
191 }
192
193 sort(m_TempIndex.begin(), m_TempIndex.end());
194
195 DWORD dwNumEdges = m_TempIndex.size();
196 for(i = 0; i<dwNumEdges; i++){
197 CEdgeIndex edge = m_TempIndex[i];
198 int cnt = 1;
199 for(; i<dwNumEdges-1; i++){
200 int cmp = edge.Compare(m_TempIndex[i+1]);
201 if(!cmp) break;
202 cnt += cmp;
203 }
204 if(!cnt) continue;
205 VEC3 v1, tv1 = *(VEC3 *)(pVertices+fvfSize*edge.m_Index1);
206 VEC3 v2, tv2 = *(VEC3 *)(pVertices+fvfSize*edge.m_Index2);
207 if(cnt<0){
208 cnt = -cnt;
209 D3DXVec3TransformCoord(&v2, &tv1, &mtxWorld);
210 D3DXVec3TransformCoord(&v1, &tv2, &mtxWorld);
211 }else{
212 D3DXVec3TransformCoord(&v1, &tv1, &mtxWorld);
213 D3DXVec3TransformCoord(&v2, &tv2, &mtxWorld);
214 }
215 for(j = 0; j<cnt; j++) m_FaceVolume->Add(v1, v2, vLight*SHADOW_INF_DIST);
216 }
217
218 // バッファのロックを解除
219 pMesh->UnlockVertexBuffer();
220 pMesh->UnlockIndexBuffer();
221 pMesh->UnlockAttributeBuffer();
222 }
223
224 /*
225 * 境界辺を追加
226 */
227 void CShadowVolume::AddFaceEdge(
228 VEC3 &v1, VEC3 &v2, // 頂点
229 VEC3 &vLight // 光源方向
230 ){
231 m_FaceVolume->Add(v1, v2, vLight*SHADOW_INF_DIST);
232 }
233
234 /*
235 * レンダリング
236 */
237 void CShadowVolume::Render(){
238 // いろいろ設定
239 devSetState( D3DRS_ZENABLE, TRUE );
240 devSetState( D3DRS_ZWRITEENABLE, FALSE );
241 devSetState( D3DRS_STENCILENABLE, TRUE );
242 devSetState( D3DRS_SHADEMODE, D3DSHADE_FLAT );
243
244 // ステンシルテストは常にパス
245 devSetState( D3DRS_STENCILFUNC, D3DCMP_ALWAYS );
246 devSetState( D3DRS_STENCILZFAIL, D3DSTENCILOP_KEEP );
247 devSetState( D3DRS_STENCILFAIL, D3DSTENCILOP_KEEP );
248
249 // Z テストがパスするところだけインクリメント
250 devSetState( D3DRS_STENCILREF, 0x1 );
251 devSetState( D3DRS_STENCILMASK, 0xffffffff );
252 devSetState( D3DRS_STENCILWRITEMASK, 0xffffffff );
253 devSetState( D3DRS_STENCILPASS, D3DSTENCILOP_INCR );
254
255 // フレームバッファには描かない(ステンシルのみ描く)
256 devSetState( D3DRS_ALPHABLENDENABLE, TRUE );
257 devSetState( D3DRS_SRCBLEND, D3DBLEND_ZERO );
258 devSetState( D3DRS_DESTBLEND, D3DBLEND_ONE );
259
260 // シャドウボリュームの手前面を描画
261 devTransform( &sv3.mtxFront );
262 m_FaceVolume->Render( true );
263
264 // Z テストがパスするところだけデクリメント
265 devSetState( D3DRS_STENCILPASS, D3DSTENCILOP_DECR );
266
267 // カリングを逆にして奥面を描画
268 devSetState( D3DRS_CULLMODE, D3DCULL_CW );
269 devTransform( &sv3.mtxFront );
270 m_FaceVolume->Render( true );
271
272 // 設定を戻す
273 devSetState( D3DRS_SHADEMODE, D3DSHADE_GOURAUD );
274 devSetState( D3DRS_CULLMODE, D3DCULL_CCW );
275 devSetState( D3DRS_ZWRITEENABLE, TRUE );
276 devSetState( D3DRS_STENCILENABLE, FALSE );
277 devSetState( D3DRS_ALPHABLENDENABLE, FALSE );
278 }
279
280 /*
281 * 描画
282 */
283 void CShadowVolume::Draw(
284 D3DCOLOR color // shadow color
285 ){
286 // いろいろ設定
287 devSetState( D3DRS_ZENABLE, FALSE );
288 devSetState( D3DRS_STENCILENABLE, TRUE );
289 devSetState( D3DRS_FOGENABLE, FALSE );
290 devSetState( D3DRS_ALPHABLENDENABLE, TRUE );
291 devSetState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA );
292 devSetState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );
293
294 devSetTexState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
295 devSetTexState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
296 devSetTexState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE );
297 devSetTexState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
298 devSetTexState( 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE );
299 devSetTexState( 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE );
300
301 // ステンシルバッファの値が 1 以上のところは影
302 devSetState( D3DRS_STENCILREF, 0x1 );
303 devSetState( D3DRS_STENCILFUNC, D3DCMP_LESSEQUAL );
304 devSetState( D3DRS_STENCILPASS, D3DSTENCILOP_KEEP );
305
306 // 影部分を暗くする
307 if(g_HidefCaptureFlag) Fill2DRect(0, 0, g_HidefBufferSize, g_HidefBufferSize, color);
308 else Fill2DRect(0, 0, g_DispWidth, g_DispHeight, color);
309
310 // 設定を戻す
311 devSetState( D3DRS_ZENABLE, TRUE );
312 devSetState( D3DRS_STENCILENABLE, FALSE );
313 //devSetState( D3DRS_FOGENABLE, TRUE );
314 devSetState( D3DRS_ALPHABLENDENABLE, FALSE );
315 }

Back to OSDN">Back to OSDN
ViewVC Help
Powered by ViewVC 1.1.26