NoiseGenerator.cpp
上传用户:henghua
上传日期:2007-11-14
资源大小:7655k
文件大小:14k
源码类别:

游戏引擎

开发平台:

Visual C++

  1. #include "NoiseGenerator.h"
  2. #include <xmmintrin.h>
  3. #include <math.h>
  4. #include "tools.h"
  5. CNoiseGenerator::CNoiseGenerator(int sX, int sY, CConfiguration *cfg, const LPDIRECT3DDEVICE9 dev)
  6. {
  7. // 初始化参数
  8. device = dev;
  9. sizeX = sX, sizeY = sY;
  10. config = cfg;
  11. time = 0.0;
  12. lastTime = timeGetTime();
  13. A= 0.3f;
  14. InitializeVertices(); // 初始化顶点场数组
  15. InitializeOriginalNoise(); // 生成原始的噪声场
  16. LoadEffects(); // 加载效果
  17. InitializeTextures(); // 初始化创建纹理
  18. }
  19. // 初始化顶点场数组
  20. void CNoiseGenerator::InitializeVertices()
  21. {
  22. // 先给创建的顶点场数组赋予法向量和纹理坐标
  23. noiseVertices = new SEAVERTEX[sizeX*sizeY];
  24. int v, u;
  25. for(v=0; v<sizeY; v++)
  26. for(u=0; u<sizeX; u++)
  27. {
  28. noiseVertices[v*sizeX + u].nx = 0.0f;
  29. noiseVertices[v*sizeX + u].ny = 1.0f;
  30. noiseVertices[v*sizeX + u].nz = 0.0f;
  31. noiseVertices[v*sizeX + u].tu = (float)u/(sizeX-1);
  32. noiseVertices[v*sizeX + u].tv = (float)v/(sizeY-1);
  33. }
  34. }
  35. // 生成原始的噪声场--16*16*256的三维场
  36. void CNoiseGenerator::InitializeOriginalNoise()
  37. {
  38. float tempNoise[256*256], temp;
  39. int i;
  40. for(int i=0; i<(256*256); i++)
  41. {
  42. temp = (float) rand()/RAND_MAX;
  43. tempNoise[i] = 4*(temp - 0.5f);   // 生成[-2,2]区间内的随机数
  44. }
  45. int frame, v, u;
  46. int v0, v1, v2, u0, u1, u2, f;
  47. for(frame=0; frame<256; frame++)
  48. {
  49. for(v=0; v<16; v++)
  50. {
  51. for(u=0; u<16; u++)
  52. {
  53. v0 = ((v-1)&15)*16,  v1 = v*16,  v2 = ((v+1)&15)*16,  u0 = ((u-1)&15),  u1 = u, u2 = ((u+1)&15),  f  = frame*256;
  54. temp = (1.0f/14.0f) * ( tempNoise[f + v0 + u0] + tempNoise[f + v0 + u1] + tempNoise[f + v0 + u2] + // 进行一次滤波平滑
  55. tempNoise[f + v1 + u0] + 6.0f*tempNoise[f + v1 + u1] + tempNoise[f + v1 + u2] +
  56. tempNoise[f + v2 + u0] + tempNoise[f + v2 + u1] + tempNoise[f + v2 + u2]);
  57.   
  58. OriginalNoise[frame*256 + v*16 + u] = (1<<14)*temp;
  59. }
  60. }
  61. }
  62. }
  63. // 加载效果
  64. void CNoiseGenerator::LoadEffects()
  65. {
  66. char *errortext;
  67. LPD3DXBUFFER errors;
  68. D3DXHANDLE hTechnique;
  69. D3DXCreateEffectFromFile(device, "fx\HeightShader.fx", 
  70. NULL, NULL, 0, NULL, &hMapEffect, &errors );
  71. if (errors != NULL){
  72. errortext = (char*) errors->GetBufferPointer();
  73. MessageBox(NULL, errortext, "hMapEffect", MB_OK);
  74. }
  75. hMapEffect->FindNextValidTechnique(NULL, &hTechnique);    
  76. hMapEffect->SetTechnique(hTechnique);
  77. D3DXCreateEffectFromFile(device, "fx\NormalShader.fx", 
  78. NULL, NULL, 0, NULL, &nMapEffect, &errors );
  79. if (errors != NULL){
  80. errortext = (char*) errors->GetBufferPointer();
  81. MessageBox(NULL, errortext, "nMapEffect", MB_OK);
  82. }
  83. nMapEffect->FindNextValidTechnique(NULL, &hTechnique);    
  84. nMapEffect->SetTechnique(hTechnique);
  85. }
  86. // 初始化创建纹理
  87. void CNoiseGenerator::InitializeTextures()
  88. {
  89. device->CreateTexture(128,128,0,D3DUSAGE_DYNAMIC, D3DFMT_L16, D3DPOOL_DEFAULT, &(LoadedFinalNoise[0]),NULL);
  90. device->CreateTexture(128,128,0,D3DUSAGE_DYNAMIC, D3DFMT_L16, D3DPOOL_DEFAULT, &(LoadedFinalNoise[1]),NULL);
  91. device->CreateTexture(128,128,0,D3DUSAGE_DYNAMIC, D3DFMT_L16, D3DPOOL_DEFAULT, &(trailHeightMap),NULL);
  92. device->CreateTexture(512,1024,1,D3DUSAGE_RENDERTARGET, D3DFMT_A16B16G16R16, D3DPOOL_DEFAULT, &(heightMap),NULL);
  93. device->CreateTexture(512,1024,1,D3DUSAGE_AUTOGENMIPMAP|D3DUSAGE_RENDERTARGET, D3DFMT_A16B16G16R16, D3DPOOL_DEFAULT, &(normalMap),NULL);
  94. device->CreateDepthStencilSurface( 512, 1024, D3DFMT_D24S8, D3DMULTISAMPLE_NONE, 0, true, &depthstencil, NULL );
  95. }
  96. CNoiseGenerator::~CNoiseGenerator()
  97. {
  98. delete [] noiseVertices;
  99. }
  100. bool CNoiseGenerator::UpdateNoise(const D3DXMATRIXA16 *extension, CBoatWave *pWave)
  101. {
  102. TimeGoing(); // 控制时间轴的进度
  103. UpdateTransitionalNoise(); // 更新产生过渡噪声场
  104. UpdateFinalNoise(); // 更新产生最终噪声场
  105. UpdateVerticesCoordinate(extension, pWave); // 更新产生顶点场的坐标, 填满初始化时创建的顶点数组
  106. LoadNoiseToTextures();
  107. LoadTrailToTexture(pWave);
  108. return true;
  109. }
  110. // 控制时间轴的进度
  111. void CNoiseGenerator::TimeGoing()
  112. {
  113. DWORD thisTime = timeGetTime();
  114. double interval = thisTime - lastTime;
  115. static double INTERVAL=0.0;
  116. interval *= 0.0014;
  117. INTERVAL = 0.99*INTERVAL + 0.01 * interval; // 这样控制时间进度可以有效避免因桢间时间差带来的不稳定
  118. lastTime = thisTime;
  119. time += INTERVAL;
  120. }
  121. // 更新产生过渡噪声场--16*16*8的三维场
  122. void CNoiseGenerator::UpdateTransitionalNoise()
  123. {
  124. int i, j, k;
  125. float varyScales[8];
  126. for(i=0; i<8; i++)
  127. {
  128. varyScales[i] = A*powf(0.51f,1.0f*i); // 0.3和0.51的意义,在于总体幅度控制与各幅度尺度层级的控制
  129. }
  130. unsigned int patch[3];
  131. float scope[3];
  132. for(i=0; i<8; i++)
  133. {
  134. double integer, fraction;
  135. fraction = modf(time*pow(1.31, i),&integer); // 1.31的意义,在于各时间尺度层级的控制
  136. int itg = (int)integer;
  137. scope[0] = varyScales[i]*(pow(sin((fraction+2)*D3DX_PI/3),2));
  138. scope[1] = varyScales[i]*(pow(sin((fraction+1)*D3DX_PI/3),2));
  139. scope[2] = varyScales[i]*(pow(sin((fraction)*D3DX_PI/3),2));
  140. patch[0] = (itg) & 255;
  141. patch[1] = (itg+1) & 255;
  142. patch[2] = (itg+2) & 255;
  143. for(j=0; j<256; j++)
  144. {
  145. TransitionalNoise[ j + 256 * i ] = ( ((scope[0] * OriginalNoise[j + 256 * patch[0]])) + 
  146. ((scope[1] * OriginalNoise[j + 256 * patch[1]])) + 
  147. ((scope[2] * OriginalNoise[j + 256 * patch[2]])) ) / 3;
  148. }
  149. }
  150. }
  151. // 更新产生最终噪声场--128*128*2的三维场,即2个片场,其中这两个片的幅度层级一大一小
  152. void CNoiseGenerator::UpdateFinalNoise()
  153. {
  154. int i, j, k, t;
  155. int sampleScale, scales[3]={8, 4, 2}, ik, ij, a, b, pitch;
  156. for(i=0; i<2; i++)
  157. {
  158. for(j=0; j<128; j++)
  159. for(k=0; k<128; k++)
  160. {
  161. FinalNoise[j*128+k+i*128*128] =  TransitionalNoise[(2*i+3)*256 + (j&15)*16 + (k&15)];
  162. for(t=0; t<3; t++)
  163. {
  164. sampleScale = scales[t];
  165. ik = k/sampleScale, ij = j/sampleScale, a = k&(sampleScale-1), b = j&(sampleScale-1), pitch = 2*i+t;
  166. FinalNoise[j*128+k+i*128*128] += ((sampleScale-a)*(sampleScale-b)*TransitionalNoise[pitch*256 + ((ij)&15)*16 + ((ik)&15)] +
  167. a        *(sampleScale-b)*TransitionalNoise[pitch*256 + ((ij)&15)*16 + ((ik+1)&15)] +
  168.   (sampleScale-a)*      b        *TransitionalNoise[pitch*256 + ((ij+1)&15)*16 + ((ik)&15)] +
  169. a        *      b        *TransitionalNoise[pitch*256 + ((ij+1)&15)*16 + ((ik+1)&15)]) / (sampleScale*sampleScale);
  170. };
  171. }
  172. }
  173. }
  174. // 更新产生顶点场的坐标, 填满初始化时创建的顶点数组
  175. void CNoiseGenerator::UpdateVerticesCoordinate(const D3DXMATRIXA16 *extension, CBoatWave *pWave)
  176. {
  177. // 这个四个顶角约束了绘制的范围而不使人感觉的差异, 从而大大的提高了渲染效率
  178. corner00 = CalculateWorldPosition(D3DXVECTOR2(0.0f,0.0f),extension);
  179. corner10 = CalculateWorldPosition(D3DXVECTOR2(+1.0f,0.0f),extension);
  180. corner01 = CalculateWorldPosition(D3DXVECTOR2(0.0f,+1.0f),extension);
  181. corner11 = CalculateWorldPosition(D3DXVECTOR2(+1.0f,+1.0f),extension);
  182. float magnifying = 4096 * 0.38 ; // 0.38的意义控制有显著差异的波峰谷距,即噪声场对可见海面的描述细节的尺度
  183. D3DXVECTOR4 coordinate;
  184. int i, j, k;
  185. float u, v;
  186. k = 0;
  187. for(i=0; i<sizeY; i++)
  188. {
  189. v = i / float(sizeY-1);
  190. for(j=0; j<sizeX; j++)
  191. {
  192. u = j / float(sizeX-1);
  193. // 对每个顶点需由四个顶角插值求出各个x,z坐标
  194. coordinate = (1.0f-v)*( (1.0f-u)*corner00 + u*corner10 ) + v*( (1.0f-u)*corner01 + u*corner11 );
  195. coordinate /= coordinate.w;
  196. noiseVertices[k].x = coordinate.x;
  197. noiseVertices[k].z = coordinate.z;
  198. // 由求得的x,z坐标得到相应点的高度值
  199. noiseVertices[k].y = GetHeight((int)(magnifying*coordinate.x), (int)(magnifying*coordinate.z) ) 
  200. + pWave->GetHeight(magnifying*coordinate.x, magnifying*coordinate.z) * 0.1 ;
  201. k++;
  202. }
  203. }
  204. // 再次使平滑
  205. for(i=1; i<(sizeY-1); i++)
  206. for(j=1; j<(sizeX-1); j++)
  207. {
  208. noiseVertices[i*sizeX + j].y = 0.2f * (noiseVertices[i*sizeX + j].y + noiseVertices[i*sizeX + (j+1)].y + 
  209. noiseVertices[i*sizeX + (j-1)].y +  noiseVertices[(i+1)*sizeX + j].y + noiseVertices[(i-1)*sizeX + j].y);
  210. }
  211. }
  212. // 由屏幕坐标计算得到世界坐标
  213. D3DXVECTOR4 CNoiseGenerator::CalculateWorldPosition(D3DXVECTOR2 screenPos, const D3DXMATRIXA16 *extension)
  214. {
  215. D3DXVECTOR4 origin(screenPos.x,screenPos.y,0,1);
  216. D3DXVECTOR4 direction(screenPos.x,screenPos.y,1,1);
  217. D3DXVec4Transform( &origin, &origin, extension );
  218. D3DXVec4Transform( &direction, &direction, extension );
  219. direction -= origin;    
  220. float l = - origin.y / direction.y;
  221. D3DXVECTOR4 worldPos = origin + direction * l;    
  222. return worldPos;
  223. }
  224. // 加载噪声场值到纹理
  225. void CNoiseGenerator::LoadNoiseToTextures()
  226. {
  227. D3DLOCKED_RECT locked;
  228. unsigned short *data;
  229. int tempData[128*128], offset, levels, pitch;
  230. HRESULT hr;
  231. int i, v, u, j, k;
  232. for(i=0; i<2; i++)
  233. {
  234. offset = 128*128*i;
  235. hr = LoadedFinalNoise[i]->LockRect( 0, &locked, NULL, D3DLOCK_DISCARD );
  236. data = (unsigned short*)locked.pBits;
  237. for(k=0; k<128*128; k++){
  238. tempData[k] = FinalNoise[k+offset];
  239. data[k] = 32768+tempData[k];
  240. }
  241. LoadedFinalNoise[i]->UnlockRect( 0 );
  242. // 该纹理采用MIP
  243. levels = LoadedFinalNoise[i]->GetLevelCount();
  244. LoadedFinalNoise[i]->UnlockRect( 1 );
  245. for(j=1; j<levels; j++)
  246. {
  247. hr = LoadedFinalNoise[i]->LockRect( j, &locked, NULL, 0 );
  248. data = (unsigned short*)locked.pBits;
  249. pitch = (locked.Pitch)/2;
  250. for(v=0; v<pitch; v++){
  251. for(u=0; u<pitch; u++)
  252. {
  253. tempData[v*128 + u] = (tempData[(2*v)*128 + 2*u] + tempData[(2*v)*128 + 2*u + 1] + 
  254.        tempData[(2*v+1)*128 + 2*u] + tempData[(2*v+1)*128 + 2*u + 1])/4;
  255. data[v*pitch+u] = 32768+tempData[v*128 + u];
  256. }
  257. }
  258. LoadedFinalNoise[i]->UnlockRect( j );
  259. }
  260. }
  261. }
  262. // 加载尾迹高度场值到纹理
  263. void CNoiseGenerator::LoadTrailToTexture(CBoatWave *pWave)
  264. {
  265. D3DLOCKED_RECT locked;
  266. unsigned short *data;
  267. float *pTrailHeight = &(pWave->waveHeight[0][0][0]);
  268. int tempData[128*128], offset, levels, pitch;
  269. HRESULT hr;
  270. int i, v, u, j, k;
  271. hr = trailHeightMap->LockRect( 0, &locked, NULL, D3DLOCK_DISCARD );
  272. data = (unsigned short*)locked.pBits;
  273. for(k=0; k<128*128; k++){
  274. tempData[k] = 32768*pTrailHeight[k];
  275. data[k] = 32768+tempData[k];
  276. }
  277. trailHeightMap->UnlockRect( 0 );
  278. // 该纹理采用MIP
  279. levels = trailHeightMap->GetLevelCount();
  280. trailHeightMap->UnlockRect( 1 );
  281. for(j=1; j<levels; j++)
  282. {
  283. hr = trailHeightMap->LockRect( j, &locked, NULL, 0 );
  284. data = (unsigned short*)locked.pBits;
  285. pitch = (locked.Pitch)/2;
  286. for(v=0; v<pitch; v++){
  287. for(u=0; u<pitch; u++)
  288. {
  289. tempData[v*128 + u] = (tempData[(2*v)*128 + 2*u] + tempData[(2*v)*128 + 2*u + 1] + 
  290.        tempData[(2*v+1)*128 + 2*u] + tempData[(2*v+1)*128 + 2*u + 1])/4;
  291. data[v*pitch+u] = 32768+tempData[v*128 + u];
  292. }
  293. }
  294. trailHeightMap->UnlockRect( j );
  295. }
  296. }
  297. // 从噪声场中获取相应点的高度
  298. float CNoiseGenerator::GetHeight(int x, int y)
  299. {
  300. int height=0, x0, y0, x1, y1, a0, a1;
  301. int *pNoise = FinalNoise;
  302. int i;
  303. for(i=0; i<2; i++)
  304. {
  305. x0 = (x/4096)&127, y0 = ((y/4096)&127)*128;
  306. x1 = (x/4096+1)&127, y1 = ((y/4096+1)&127)*128;
  307. a0 = x&4095, a1 = y&4095;
  308. height += ( (4096-a1)*( ((4096-a0)*pNoise[x0+y0] + a0*pNoise[x1+y0])/4096 ) + a1*( ((4096-a0)*pNoise[x0+y1] + a0*pNoise[x1+y1])/4096 ) )/4096;
  309. x = x * 8;
  310. y = y * 8;
  311. pNoise += 128*128;
  312. }
  313. return height*7.0f/(1<<14);
  314. }
  315. // 从噪声场中获取相应点的高度
  316. float CNoiseGenerator::GetHeight(float u, float v)
  317. {
  318. float magnifying = 4096 * 0.38f;
  319. return GetHeight((int)(magnifying*u), (int)(magnifying*v) );
  320. }
  321. // 更新产生法向量场纹理的数据
  322. void CNoiseGenerator::UpdateVerticesNormal(CBoatWave *pWave)
  323. {
  324. HRESULT hr;
  325. LPDIRECT3DSURFACE9 new_target,old_target,old_depthstencil;
  326. // 此处将纹理作为渲染目标,而不是通常所说的后台缓冲区
  327. hr = device->GetRenderTarget(0, &old_target );
  328. hr = device->GetDepthStencilSurface( &old_depthstencil );
  329. hr = heightMap->GetSurfaceLevel( 0,&new_target );
  330. hr = device->SetRenderTarget( 0, new_target );
  331. device->SetDepthStencilSurface( depthstencil );
  332. device->SetRenderState( D3DRS_ZENABLE, D3DZB_FALSE );
  333. // 第一步得到高度场纹理
  334. hr = device->SetFVF(D3DFVF_SEAVERTEX);
  335. hr = hMapEffect->Begin(NULL,NULL);
  336. hMapEffect->Pass(0);
  337. hMapEffect->SetFloat("scale", 0.38);
  338. hMapEffect->SetTexture("noise0",LoadedFinalNoise[0]);
  339. hMapEffect->SetTexture("noise1",LoadedFinalNoise[1]);
  340. hMapEffect->SetVector("trailCorner00", &D3DXVECTOR4(pWave->corner00.x, 0, pWave->corner00.y, 0) );
  341. hMapEffect->SetVector("trailCorner10", &D3DXVECTOR4(pWave->corner10.x, 0, pWave->corner10.y, 0) );
  342. hMapEffect->SetVector("trailCorner01", &D3DXVECTOR4(pWave->corner01.x, 0, pWave->corner01.y, 0) );
  343. hMapEffect->SetVector("trailCorner11", &D3DXVECTOR4(pWave->corner11.x, 0, pWave->corner11.y, 0) );
  344. hMapEffect->SetTexture("trailHeight",trailHeightMap);
  345. device->DrawIndexedPrimitive( D3DPT_TRIANGLELIST, 0, 0, sizeX*sizeY, 0, 2*(sizeX-1)*(sizeY-1) );
  346. hMapEffect->End();
  347. // 第二步由高度场纹理计算得到法向量场纹理
  348. hr = normalMap->GetSurfaceLevel( 0,&new_target );
  349. hr = device->SetRenderTarget( 0, new_target );
  350. hr = nMapEffect->Begin(NULL,NULL);
  351. nMapEffect->Pass(0);
  352. nMapEffect->SetFloat("dsizeX", 1.0f/512);
  353. nMapEffect->SetFloat("dsizeY", 1.0f/1024);
  354. nMapEffect->SetVector("corner00", &corner00 );
  355. nMapEffect->SetVector("corner10", &corner10 );
  356. nMapEffect->SetVector("corner01", &corner01 );
  357. nMapEffect->SetVector("corner11", &corner11 );
  358. nMapEffect->SetFloat("amplitude", 2*7.0f);
  359. nMapEffect->SetTexture("heightmap",heightMap);
  360. device->DrawIndexedPrimitive( D3DPT_TRIANGLELIST, 0, 0, sizeX*sizeY, 0, 2*(sizeX-1)*(sizeY-1) );
  361. nMapEffect->End();
  362. device->SetRenderState( D3DRS_ZENABLE, D3DZB_TRUE );
  363. device->SetRenderTarget( 0, old_target );
  364. device->SetDepthStencilSurface( old_depthstencil );
  365. }