NoiseGenerator.cpp
上传用户:henghua
上传日期:2007-11-14
资源大小:7655k
文件大小:14k
- #include "NoiseGenerator.h"
- #include <xmmintrin.h>
- #include <math.h>
- #include "tools.h"
- CNoiseGenerator::CNoiseGenerator(int sX, int sY, CConfiguration *cfg, const LPDIRECT3DDEVICE9 dev)
- {
- // 初始化参数
- device = dev;
- sizeX = sX, sizeY = sY;
- config = cfg;
- time = 0.0;
- lastTime = timeGetTime();
- A= 0.3f;
- InitializeVertices(); // 初始化顶点场数组
- InitializeOriginalNoise(); // 生成原始的噪声场
- LoadEffects(); // 加载效果
- InitializeTextures(); // 初始化创建纹理
- }
- // 初始化顶点场数组
- void CNoiseGenerator::InitializeVertices()
- {
- // 先给创建的顶点场数组赋予法向量和纹理坐标
- noiseVertices = new SEAVERTEX[sizeX*sizeY];
- int v, u;
- for(v=0; v<sizeY; v++)
- for(u=0; u<sizeX; u++)
- {
- noiseVertices[v*sizeX + u].nx = 0.0f;
- noiseVertices[v*sizeX + u].ny = 1.0f;
- noiseVertices[v*sizeX + u].nz = 0.0f;
- noiseVertices[v*sizeX + u].tu = (float)u/(sizeX-1);
- noiseVertices[v*sizeX + u].tv = (float)v/(sizeY-1);
- }
- }
- // 生成原始的噪声场--16*16*256的三维场
- void CNoiseGenerator::InitializeOriginalNoise()
- {
- float tempNoise[256*256], temp;
- int i;
- for(int i=0; i<(256*256); i++)
- {
- temp = (float) rand()/RAND_MAX;
- tempNoise[i] = 4*(temp - 0.5f); // 生成[-2,2]区间内的随机数
- }
- int frame, v, u;
- int v0, v1, v2, u0, u1, u2, f;
- for(frame=0; frame<256; frame++)
- {
- for(v=0; v<16; v++)
- {
- for(u=0; u<16; u++)
- {
- 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;
- temp = (1.0f/14.0f) * ( tempNoise[f + v0 + u0] + tempNoise[f + v0 + u1] + tempNoise[f + v0 + u2] + // 进行一次滤波平滑
- tempNoise[f + v1 + u0] + 6.0f*tempNoise[f + v1 + u1] + tempNoise[f + v1 + u2] +
- tempNoise[f + v2 + u0] + tempNoise[f + v2 + u1] + tempNoise[f + v2 + u2]);
-
- OriginalNoise[frame*256 + v*16 + u] = (1<<14)*temp;
- }
- }
- }
- }
- // 加载效果
- void CNoiseGenerator::LoadEffects()
- {
- char *errortext;
- LPD3DXBUFFER errors;
- D3DXHANDLE hTechnique;
- D3DXCreateEffectFromFile(device, "fx\HeightShader.fx",
- NULL, NULL, 0, NULL, &hMapEffect, &errors );
- if (errors != NULL){
- errortext = (char*) errors->GetBufferPointer();
- MessageBox(NULL, errortext, "hMapEffect", MB_OK);
- }
- hMapEffect->FindNextValidTechnique(NULL, &hTechnique);
- hMapEffect->SetTechnique(hTechnique);
- D3DXCreateEffectFromFile(device, "fx\NormalShader.fx",
- NULL, NULL, 0, NULL, &nMapEffect, &errors );
- if (errors != NULL){
- errortext = (char*) errors->GetBufferPointer();
- MessageBox(NULL, errortext, "nMapEffect", MB_OK);
- }
- nMapEffect->FindNextValidTechnique(NULL, &hTechnique);
- nMapEffect->SetTechnique(hTechnique);
- }
- // 初始化创建纹理
- void CNoiseGenerator::InitializeTextures()
- {
- device->CreateTexture(128,128,0,D3DUSAGE_DYNAMIC, D3DFMT_L16, D3DPOOL_DEFAULT, &(LoadedFinalNoise[0]),NULL);
- device->CreateTexture(128,128,0,D3DUSAGE_DYNAMIC, D3DFMT_L16, D3DPOOL_DEFAULT, &(LoadedFinalNoise[1]),NULL);
- device->CreateTexture(128,128,0,D3DUSAGE_DYNAMIC, D3DFMT_L16, D3DPOOL_DEFAULT, &(trailHeightMap),NULL);
- device->CreateTexture(512,1024,1,D3DUSAGE_RENDERTARGET, D3DFMT_A16B16G16R16, D3DPOOL_DEFAULT, &(heightMap),NULL);
- device->CreateTexture(512,1024,1,D3DUSAGE_AUTOGENMIPMAP|D3DUSAGE_RENDERTARGET, D3DFMT_A16B16G16R16, D3DPOOL_DEFAULT, &(normalMap),NULL);
- device->CreateDepthStencilSurface( 512, 1024, D3DFMT_D24S8, D3DMULTISAMPLE_NONE, 0, true, &depthstencil, NULL );
- }
- CNoiseGenerator::~CNoiseGenerator()
- {
- delete [] noiseVertices;
- }
- bool CNoiseGenerator::UpdateNoise(const D3DXMATRIXA16 *extension, CBoatWave *pWave)
- {
- TimeGoing(); // 控制时间轴的进度
- UpdateTransitionalNoise(); // 更新产生过渡噪声场
- UpdateFinalNoise(); // 更新产生最终噪声场
- UpdateVerticesCoordinate(extension, pWave); // 更新产生顶点场的坐标, 填满初始化时创建的顶点数组
- LoadNoiseToTextures();
- LoadTrailToTexture(pWave);
- return true;
- }
- // 控制时间轴的进度
- void CNoiseGenerator::TimeGoing()
- {
- DWORD thisTime = timeGetTime();
- double interval = thisTime - lastTime;
- static double INTERVAL=0.0;
- interval *= 0.0014;
- INTERVAL = 0.99*INTERVAL + 0.01 * interval; // 这样控制时间进度可以有效避免因桢间时间差带来的不稳定
- lastTime = thisTime;
- time += INTERVAL;
- }
- // 更新产生过渡噪声场--16*16*8的三维场
- void CNoiseGenerator::UpdateTransitionalNoise()
- {
- int i, j, k;
- float varyScales[8];
- for(i=0; i<8; i++)
- {
- varyScales[i] = A*powf(0.51f,1.0f*i); // 0.3和0.51的意义,在于总体幅度控制与各幅度尺度层级的控制
- }
- unsigned int patch[3];
- float scope[3];
- for(i=0; i<8; i++)
- {
- double integer, fraction;
- fraction = modf(time*pow(1.31, i),&integer); // 1.31的意义,在于各时间尺度层级的控制
- int itg = (int)integer;
- scope[0] = varyScales[i]*(pow(sin((fraction+2)*D3DX_PI/3),2));
- scope[1] = varyScales[i]*(pow(sin((fraction+1)*D3DX_PI/3),2));
- scope[2] = varyScales[i]*(pow(sin((fraction)*D3DX_PI/3),2));
- patch[0] = (itg) & 255;
- patch[1] = (itg+1) & 255;
- patch[2] = (itg+2) & 255;
- for(j=0; j<256; j++)
- {
- TransitionalNoise[ j + 256 * i ] = ( ((scope[0] * OriginalNoise[j + 256 * patch[0]])) +
- ((scope[1] * OriginalNoise[j + 256 * patch[1]])) +
- ((scope[2] * OriginalNoise[j + 256 * patch[2]])) ) / 3;
- }
- }
- }
- // 更新产生最终噪声场--128*128*2的三维场,即2个片场,其中这两个片的幅度层级一大一小
- void CNoiseGenerator::UpdateFinalNoise()
- {
- int i, j, k, t;
- int sampleScale, scales[3]={8, 4, 2}, ik, ij, a, b, pitch;
- for(i=0; i<2; i++)
- {
- for(j=0; j<128; j++)
- for(k=0; k<128; k++)
- {
- FinalNoise[j*128+k+i*128*128] = TransitionalNoise[(2*i+3)*256 + (j&15)*16 + (k&15)];
- for(t=0; t<3; t++)
- {
- sampleScale = scales[t];
- ik = k/sampleScale, ij = j/sampleScale, a = k&(sampleScale-1), b = j&(sampleScale-1), pitch = 2*i+t;
- FinalNoise[j*128+k+i*128*128] += ((sampleScale-a)*(sampleScale-b)*TransitionalNoise[pitch*256 + ((ij)&15)*16 + ((ik)&15)] +
- a *(sampleScale-b)*TransitionalNoise[pitch*256 + ((ij)&15)*16 + ((ik+1)&15)] +
- (sampleScale-a)* b *TransitionalNoise[pitch*256 + ((ij+1)&15)*16 + ((ik)&15)] +
- a * b *TransitionalNoise[pitch*256 + ((ij+1)&15)*16 + ((ik+1)&15)]) / (sampleScale*sampleScale);
- };
- }
- }
- }
- // 更新产生顶点场的坐标, 填满初始化时创建的顶点数组
- void CNoiseGenerator::UpdateVerticesCoordinate(const D3DXMATRIXA16 *extension, CBoatWave *pWave)
- {
- // 这个四个顶角约束了绘制的范围而不使人感觉的差异, 从而大大的提高了渲染效率
- corner00 = CalculateWorldPosition(D3DXVECTOR2(0.0f,0.0f),extension);
- corner10 = CalculateWorldPosition(D3DXVECTOR2(+1.0f,0.0f),extension);
- corner01 = CalculateWorldPosition(D3DXVECTOR2(0.0f,+1.0f),extension);
- corner11 = CalculateWorldPosition(D3DXVECTOR2(+1.0f,+1.0f),extension);
- float magnifying = 4096 * 0.38 ; // 0.38的意义控制有显著差异的波峰谷距,即噪声场对可见海面的描述细节的尺度
- D3DXVECTOR4 coordinate;
- int i, j, k;
- float u, v;
- k = 0;
- for(i=0; i<sizeY; i++)
- {
- v = i / float(sizeY-1);
- for(j=0; j<sizeX; j++)
- {
- u = j / float(sizeX-1);
- // 对每个顶点需由四个顶角插值求出各个x,z坐标
- coordinate = (1.0f-v)*( (1.0f-u)*corner00 + u*corner10 ) + v*( (1.0f-u)*corner01 + u*corner11 );
- coordinate /= coordinate.w;
- noiseVertices[k].x = coordinate.x;
- noiseVertices[k].z = coordinate.z;
- // 由求得的x,z坐标得到相应点的高度值
- noiseVertices[k].y = GetHeight((int)(magnifying*coordinate.x), (int)(magnifying*coordinate.z) )
- + pWave->GetHeight(magnifying*coordinate.x, magnifying*coordinate.z) * 0.1 ;
- k++;
- }
- }
-
- // 再次使平滑
- for(i=1; i<(sizeY-1); i++)
- for(j=1; j<(sizeX-1); j++)
- {
- noiseVertices[i*sizeX + j].y = 0.2f * (noiseVertices[i*sizeX + j].y + noiseVertices[i*sizeX + (j+1)].y +
- noiseVertices[i*sizeX + (j-1)].y + noiseVertices[(i+1)*sizeX + j].y + noiseVertices[(i-1)*sizeX + j].y);
- }
- }
- // 由屏幕坐标计算得到世界坐标
- D3DXVECTOR4 CNoiseGenerator::CalculateWorldPosition(D3DXVECTOR2 screenPos, const D3DXMATRIXA16 *extension)
- {
- D3DXVECTOR4 origin(screenPos.x,screenPos.y,0,1);
- D3DXVECTOR4 direction(screenPos.x,screenPos.y,1,1);
- D3DXVec4Transform( &origin, &origin, extension );
- D3DXVec4Transform( &direction, &direction, extension );
-
- direction -= origin;
- float l = - origin.y / direction.y;
- D3DXVECTOR4 worldPos = origin + direction * l;
- return worldPos;
- }
- // 加载噪声场值到纹理
- void CNoiseGenerator::LoadNoiseToTextures()
- {
- D3DLOCKED_RECT locked;
- unsigned short *data;
- int tempData[128*128], offset, levels, pitch;
- HRESULT hr;
- int i, v, u, j, k;
- for(i=0; i<2; i++)
- {
- offset = 128*128*i;
- hr = LoadedFinalNoise[i]->LockRect( 0, &locked, NULL, D3DLOCK_DISCARD );
- data = (unsigned short*)locked.pBits;
- for(k=0; k<128*128; k++){
- tempData[k] = FinalNoise[k+offset];
- data[k] = 32768+tempData[k];
- }
- LoadedFinalNoise[i]->UnlockRect( 0 );
- // 该纹理采用MIP
- levels = LoadedFinalNoise[i]->GetLevelCount();
- LoadedFinalNoise[i]->UnlockRect( 1 );
- for(j=1; j<levels; j++)
- {
- hr = LoadedFinalNoise[i]->LockRect( j, &locked, NULL, 0 );
- data = (unsigned short*)locked.pBits;
- pitch = (locked.Pitch)/2;
- for(v=0; v<pitch; v++){
- for(u=0; u<pitch; u++)
- {
- tempData[v*128 + u] = (tempData[(2*v)*128 + 2*u] + tempData[(2*v)*128 + 2*u + 1] +
- tempData[(2*v+1)*128 + 2*u] + tempData[(2*v+1)*128 + 2*u + 1])/4;
- data[v*pitch+u] = 32768+tempData[v*128 + u];
- }
- }
- LoadedFinalNoise[i]->UnlockRect( j );
- }
- }
- }
- // 加载尾迹高度场值到纹理
- void CNoiseGenerator::LoadTrailToTexture(CBoatWave *pWave)
- {
- D3DLOCKED_RECT locked;
- unsigned short *data;
- float *pTrailHeight = &(pWave->waveHeight[0][0][0]);
- int tempData[128*128], offset, levels, pitch;
- HRESULT hr;
- int i, v, u, j, k;
- hr = trailHeightMap->LockRect( 0, &locked, NULL, D3DLOCK_DISCARD );
- data = (unsigned short*)locked.pBits;
- for(k=0; k<128*128; k++){
- tempData[k] = 32768*pTrailHeight[k];
- data[k] = 32768+tempData[k];
- }
- trailHeightMap->UnlockRect( 0 );
- // 该纹理采用MIP
- levels = trailHeightMap->GetLevelCount();
- trailHeightMap->UnlockRect( 1 );
- for(j=1; j<levels; j++)
- {
- hr = trailHeightMap->LockRect( j, &locked, NULL, 0 );
- data = (unsigned short*)locked.pBits;
- pitch = (locked.Pitch)/2;
- for(v=0; v<pitch; v++){
- for(u=0; u<pitch; u++)
- {
- tempData[v*128 + u] = (tempData[(2*v)*128 + 2*u] + tempData[(2*v)*128 + 2*u + 1] +
- tempData[(2*v+1)*128 + 2*u] + tempData[(2*v+1)*128 + 2*u + 1])/4;
- data[v*pitch+u] = 32768+tempData[v*128 + u];
- }
- }
- trailHeightMap->UnlockRect( j );
- }
- }
- // 从噪声场中获取相应点的高度
- float CNoiseGenerator::GetHeight(int x, int y)
- {
- int height=0, x0, y0, x1, y1, a0, a1;
- int *pNoise = FinalNoise;
- int i;
- for(i=0; i<2; i++)
- {
- x0 = (x/4096)&127, y0 = ((y/4096)&127)*128;
- x1 = (x/4096+1)&127, y1 = ((y/4096+1)&127)*128;
- a0 = x&4095, a1 = y&4095;
- 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;
- x = x * 8;
- y = y * 8;
- pNoise += 128*128;
- }
- return height*7.0f/(1<<14);
- }
- // 从噪声场中获取相应点的高度
- float CNoiseGenerator::GetHeight(float u, float v)
- {
- float magnifying = 4096 * 0.38f;
- return GetHeight((int)(magnifying*u), (int)(magnifying*v) );
- }
- // 更新产生法向量场纹理的数据
- void CNoiseGenerator::UpdateVerticesNormal(CBoatWave *pWave)
- {
- HRESULT hr;
- LPDIRECT3DSURFACE9 new_target,old_target,old_depthstencil;
- // 此处将纹理作为渲染目标,而不是通常所说的后台缓冲区
- hr = device->GetRenderTarget(0, &old_target );
- hr = device->GetDepthStencilSurface( &old_depthstencil );
- hr = heightMap->GetSurfaceLevel( 0,&new_target );
- hr = device->SetRenderTarget( 0, new_target );
- device->SetDepthStencilSurface( depthstencil );
- device->SetRenderState( D3DRS_ZENABLE, D3DZB_FALSE );
- // 第一步得到高度场纹理
- hr = device->SetFVF(D3DFVF_SEAVERTEX);
- hr = hMapEffect->Begin(NULL,NULL);
- hMapEffect->Pass(0);
- hMapEffect->SetFloat("scale", 0.38);
- hMapEffect->SetTexture("noise0",LoadedFinalNoise[0]);
- hMapEffect->SetTexture("noise1",LoadedFinalNoise[1]);
- hMapEffect->SetVector("trailCorner00", &D3DXVECTOR4(pWave->corner00.x, 0, pWave->corner00.y, 0) );
- hMapEffect->SetVector("trailCorner10", &D3DXVECTOR4(pWave->corner10.x, 0, pWave->corner10.y, 0) );
- hMapEffect->SetVector("trailCorner01", &D3DXVECTOR4(pWave->corner01.x, 0, pWave->corner01.y, 0) );
- hMapEffect->SetVector("trailCorner11", &D3DXVECTOR4(pWave->corner11.x, 0, pWave->corner11.y, 0) );
- hMapEffect->SetTexture("trailHeight",trailHeightMap);
- device->DrawIndexedPrimitive( D3DPT_TRIANGLELIST, 0, 0, sizeX*sizeY, 0, 2*(sizeX-1)*(sizeY-1) );
- hMapEffect->End();
-
- // 第二步由高度场纹理计算得到法向量场纹理
- hr = normalMap->GetSurfaceLevel( 0,&new_target );
- hr = device->SetRenderTarget( 0, new_target );
- hr = nMapEffect->Begin(NULL,NULL);
- nMapEffect->Pass(0);
- nMapEffect->SetFloat("dsizeX", 1.0f/512);
- nMapEffect->SetFloat("dsizeY", 1.0f/1024);
- nMapEffect->SetVector("corner00", &corner00 );
- nMapEffect->SetVector("corner10", &corner10 );
- nMapEffect->SetVector("corner01", &corner01 );
- nMapEffect->SetVector("corner11", &corner11 );
- nMapEffect->SetFloat("amplitude", 2*7.0f);
- nMapEffect->SetTexture("heightmap",heightMap);
- device->DrawIndexedPrimitive( D3DPT_TRIANGLELIST, 0, 0, sizeX*sizeY, 0, 2*(sizeX-1)*(sizeY-1) );
- nMapEffect->End();
- device->SetRenderState( D3DRS_ZENABLE, D3DZB_TRUE );
- device->SetRenderTarget( 0, old_target );
- device->SetDepthStencilSurface( old_depthstencil );
- }