www.pudn.com > packmk2.rar > software_noisemaker.cpp
#include "software_noisemaker.h" #include#include #include "tools.h" #define SSE false // SSE is broken atm #define quadpipe false #define packednoise true software_noisemaker::software_noisemaker(int sX, int sY, parameterhandler *prm, const LPDIRECT3DDEVICE9 dev) { this->device = dev; this->sizeX = sX; this->sizeY = sY; this->prm = prm; time = 0.0; last_time = timeGetTime(); octaves = 0; // don't want to have the noise accessed before it's calculated f_sizeX = (float) sizeX; f_sizeY = (float) sizeY; // reset normals vertices = new SOFTWARESURFACEVERTEX[sizeX*sizeY]; for(int v=0; v init_noise(); #ifndef CPU_NORMALS this->load_effects(); this->init_textures(); #endif } void software_noisemaker::resize(int sX, int sY) { delete vertices; this->sizeX = sX; this->sizeY = sY; f_sizeX = (float) sizeX; f_sizeY = (float) sizeY; // reset normals delete vertices; vertices = new SOFTWARESURFACEVERTEX[sizeX*sizeY]; for(int v=0; v noise[i] = rand()&0x0000FFFF; float temp = (float) rand()/RAND_MAX; tempnoise[i] = 4*(temp - 0.5f); } for(int frame=0; frame noise[frame*n_size_sq + v*n_size + u] = noise_magnitude*temp; } } } } void software_noisemaker::calc_noise() { octaves = min(prm->params[p_iOctaves].iData, max_octaves); // calculate the strength of each octave float sum=0.0f; for(int i=0; i get_float(p_fFalloff),1.0f*i); sum += f_multitable[i]; } { for(int i=0; i get_float( p_fAnimspeed ); lp_itime = 0.99*lp_itime + 0.01 * itime; if ( !prm->get_bool(p_bPaused) ) time += lp_itime; double r_timemulti = 1.0; for(int o=0; o >scale_decimalbits) + ((amount[1] * noise[i + n_size_sq * image[1]])>>scale_decimalbits) + ((amount[2] * noise[i + n_size_sq * image[2]])>>scale_decimalbits)); } } r_timemulti *= prm->get_float( p_fTimemulti ); } if(packednoise) { int octavepack = 0; for(int o=0; o > upsamplepower; int pv = v >> upsamplepower; int fu = u & (magnitude-1); int fv = v & (magnitude-1); int fu_m = magnitude - fu; int fv_m = magnitude - fv; int o = fu_m*fv_m*o_noise[octave*n_size_sq + ((pv)&n_size_m1)*n_size + ((pu)&n_size_m1)] + fu*fv_m*o_noise[octave*n_size_sq + ((pv)&n_size_m1)*n_size + ((pu+1)&n_size_m1)] + fu_m*fv*o_noise[octave*n_size_sq + ((pv+1)&n_size_m1)*n_size + ((pu)&n_size_m1)] + fu*fv*o_noise[octave*n_size_sq + ((pv+1)&n_size_m1)*n_size + ((pu+1)&n_size_m1)]; return o >> (upsamplepower+upsamplepower); } software_noisemaker::~software_noisemaker() { delete [] vertices; } bool software_noisemaker::render_geometry(const D3DXMATRIXA16 *m) { this->calc_noise(); float magnitude = n_dec_magn * prm->get_float(p_fScale); float inv_magnitude_sq = 1.0f/(prm->get_float(p_fScale)*prm->get_float(p_fScale)); D3DXMATRIXA16 m_inv; D3DXMatrixInverse( &m_inv, NULL, m ); D3DXVec3TransformNormal( &e_u, &D3DXVECTOR3(1,0,0), m); D3DXVec3TransformNormal( &e_v, &D3DXVECTOR3(0,1,0), m); D3DXVec3Normalize( &e_u, &e_u ); D3DXVec3Normalize( &e_v, &e_v ); t_corners0 = this->calc_worldpos(D3DXVECTOR2(0.0f,0.0f),m); t_corners1 = this->calc_worldpos(D3DXVECTOR2(+1.0f,0.0f),m); t_corners2 = this->calc_worldpos(D3DXVECTOR2(0.0f,+1.0f),m); t_corners3 = this->calc_worldpos(D3DXVECTOR2(+1.0f,+1.0f),m); D3DXMATRIXA16 surface_to_world; float du = 1.0f/float(sizeX-1), dv = 1.0f/float(sizeY-1), u,v=0.0f; D3DXVECTOR4 result; int i=0; for(int iv=0; iv params[p_bSmooth].bData) { //for(int n=0; n<3; n++) for(int v=1; v<(sizeY-1); v++) { for(int u=1; u<(sizeX-1); u++) { vertices[v*sizeX + u].y = 0.2f * (vertices[v*sizeX + u].y + vertices[v*sizeX + (u+1)].y + vertices[v*sizeX + (u-1)].y + vertices[(v+1)*sizeX + u].y + vertices[(v-1)*sizeX + u].y); } } } if(!prm->params[p_bDisplace].bData) { // reset height to 0 for(int u=0; u<(sizeX*sizeY); u++) { vertices[u].y = 0; } } #ifdef CPU_NORMALS calc_normals(); #else this->upload_noise(); #endif return true; } // check the point of intersection with the plane (0,1,0,0) and return the position in homogenous coordinates D3DXVECTOR4 software_noisemaker::calc_worldpos(D3DXVECTOR2 uv, const D3DXMATRIXA16 *m) { // this is hacky.. this does take care of the homogenous coordinates in a correct way, // but only when the plane lies at y=0 D3DXVECTOR4 origin(uv.x,uv.y,-1,1); D3DXVECTOR4 direction(uv.x,uv.y,1,1); D3DXVec4Transform( &origin, &origin, m ); D3DXVec4Transform( &direction, &direction, m ); direction -= origin; float l = -origin.y / direction.y; // assumes the plane is y=0 D3DXVECTOR4 worldPos = origin + direction*l; return worldPos; } void software_noisemaker::calc_normals() { for(int v=1; v<(sizeY-1); v++) { for(int u=1; u<(sizeX-1); u++) { D3DXVECTOR3 vec1( vertices[v*sizeX + u + 1].x-vertices[v*sizeX + u - 1].x, vertices[v*sizeX + u + 1].y-vertices[v*sizeX + u - 1].y, vertices[v*sizeX + u + 1].z-vertices[v*sizeX + u - 1].z); D3DXVECTOR3 vec2( vertices[(v+1)*sizeX + u].x - vertices[(v-1)*sizeX + u].x, vertices[(v+1)*sizeX + u].y - vertices[(v-1)*sizeX + u].y, vertices[(v+1)*sizeX + u].z - vertices[(v-1)*sizeX + u].z); D3DXVECTOR3 normal; D3DXVec3Cross( &normal, &vec2, &vec1 ); vertices[v*sizeX + u].nx = normal.x; vertices[v*sizeX + u].ny = normal.y; vertices[v*sizeX + u].nz = normal.z; } } } inline int software_noisemaker::readtexel_linear(int u, int v, int offset) { int iu, iup, iv, ivp, fu, fv; iu = (u>>n_dec_bits)&n_size_m1; iv = ((v>>n_dec_bits)&n_size_m1)*n_size; iup = (((u>>n_dec_bits) + 1)&n_size_m1); ivp = (((v>>n_dec_bits) + 1)&n_size_m1)*n_size; fu = u & n_dec_magn_m1; fv = v & n_dec_magn_m1; /*float f_fu = (float) fu / n_dec_magn; float f_fv = (float) fv / n_dec_magn;*/ /*float ut01 = ((n_dec_magn_m1-fu)*o_noise[iv + iu + offset] + fu*o_noise[iv + iup + offset]); float ut23 = ((n_dec_magn_m1-fu)*o_noise[ivp + iu + offset] + fu*o_noise[ivp + iup + offset]);*/ int ut01 = ((n_dec_magn-fu)*o_noise[offset + iv + iu] + fu*o_noise[offset + iv + iup]) >> n_dec_bits; int ut23 = ((n_dec_magn-fu)*o_noise[offset + ivp + iu] + fu*o_noise[offset + ivp + iup]) >> n_dec_bits ; int ut = ((n_dec_magn-fv)*ut01 + fv*ut23) >> n_dec_bits; return ut; } inline float software_noisemaker::get_height_at(int u, int v, int octaves) { int value=0; //r_noise = o_noise; // pointer to the current noise source octave for(int i=0; i params[p_fStrength].fData / noise_magnitude; } float software_noisemaker::get_height_at(float u, float v) { float magnitude = n_dec_magn * prm->get_float(p_fScale); //return get_height_at(magnitude*u, magnitude*v, octaves); return get_height_dual(magnitude*u, magnitude*v); } void software_noisemaker::init_textures() { // the noise textures. currently two of them (= 8 levels) device->CreateTexture(np_size,np_size,0,D3DUSAGE_DYNAMIC, D3DFMT_L16, D3DPOOL_DEFAULT, &(this->packed_noise_texture[0]),NULL); device->CreateTexture(np_size,np_size,0,D3DUSAGE_DYNAMIC, D3DFMT_L16, D3DPOOL_DEFAULT, &(this->packed_noise_texture[1]),NULL); device->CreateTexture(nmapsize_x,nmapsize_y,1,D3DUSAGE_RENDERTARGET, D3DFMT_A16B16G16R16, D3DPOOL_DEFAULT, &(this->heightmap),NULL); device->CreateTexture(nmapsize_x,nmapsize_y,1,D3DUSAGE_AUTOGENMIPMAP|D3DUSAGE_RENDERTARGET, D3DFMT_A16B16G16R16, D3DPOOL_DEFAULT, &(this->normalmap),NULL); /*device->CreateTexture(nmapsize_x,nmapsize_y,1,D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &(this->heightmap),NULL); device->CreateTexture(nmapsize_x,nmapsize_y,1,D3DUSAGE_AUTOGENMIPMAP|D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &(this->normalmap),NULL); */ // create z/stencil-buffer device->CreateDepthStencilSurface( nmapsize_x, nmapsize_y,D3DFMT_D24S8, D3DMULTISAMPLE_NONE, 0, true, &depthstencil, NULL ); } void software_noisemaker::upload_noise() { D3DLOCKED_RECT locked; unsigned short *data; int tempdata[np_size_sq]; for(int t=0; t<2; t++) { int offset = np_size_sq*t; // upload the first level packed_noise_texture[t]->LockRect( 0, &locked, NULL, D3DLOCK_DISCARD ); data = (unsigned short*)locked.pBits; for(int i=0; i UnlockRect( 0 ); int c = packed_noise_texture[t]->GetLevelCount(); // calculate the second level, and upload it HRESULT hr = packed_noise_texture[t]->LockRect( 1, &locked, NULL, 0 ); data = (unsigned short*)locked.pBits; int sz = np_size>>1; for(int v=0; v >2; data[v*sz+u] = 32768+tempdata[v*np_size + u]; } } packed_noise_texture[t]->UnlockRect( 1 ); for(int j=2; j LockRect( j, &locked, NULL, 0 ); data = (unsigned short*)locked.pBits; int pitch = (locked.Pitch)>>1; sz = np_size>>j; for(int v=0; v >2; data[v*pitch+u] = 32768+tempdata[v*np_size + u]; } } packed_noise_texture[t]->UnlockRect( j ); } } } void software_noisemaker::generate_normalmap( ) { #ifndef CPU_NORMALS HRESULT hr; // do the heightmap thingy LPDIRECT3DSURFACE9 target,bb,old_depthstencil; hr = device->GetRenderTarget(0, &bb ); hr = heightmap->GetSurfaceLevel( 0,&target ); device->GetDepthStencilSurface( &old_depthstencil ); //hr = device->SetRenderState( D3DRS_CULLMODE, D3DCULL_CCW ); //device->SetStreamSource( 0, surf_software_vertices, 0, sizeof(SOFTWARESURFACEVERTEX) ); hr = device->SetFVF( D3DFVF_SOFTWARESURFACEVERTEX); //device->SetIndices(surf->surf_indicies); hr = hmap_effect->Begin(NULL,NULL); hmap_effect->Pass(0); hmap_effect->SetFloat("scale", prm->params[p_fScale].fData); hmap_effect->SetTexture("noise0",packed_noise_texture[0]); hmap_effect->SetTexture("noise1",packed_noise_texture[1]); hr = device->SetRenderTarget( 0, target ); device->SetDepthStencilSurface( depthstencil ); //device->Clear( 0, NULL,D3DCLEAR_TARGET, D3DCOLOR_XRGB(255,128,28), 1.0f, 0 ); device->SetRenderState( D3DRS_ZENABLE, D3DZB_FALSE ); device->DrawIndexedPrimitive( D3DPT_TRIANGLELIST, 0, 0, sizeX*sizeY, 0, 2*(sizeX-1)*(sizeY-1) ); hmap_effect->End(); // calculate normalmap hr = normalmap->GetSurfaceLevel( 0,&target ); hr = device->SetRenderTarget( 0, target ); hr = nmap_effect->Begin(NULL,NULL); nmap_effect->Pass(0); nmap_effect->SetFloat("inv_mapsize_x", 1.0f/nmapsize_x); nmap_effect->SetFloat("inv_mapsize_y", 1.0f/nmapsize_y); nmap_effect->SetVector("corner00", &t_corners0 ); nmap_effect->SetVector("corner01", &t_corners1 ); nmap_effect->SetVector("corner10", &t_corners2 ); nmap_effect->SetVector("corner11", &t_corners3 ); nmap_effect->SetFloat("amplitude", 2*prm->params[p_fStrength].fData); nmap_effect->SetTexture("hmap",heightmap); device->DrawIndexedPrimitive( D3DPT_TRIANGLELIST, 0, 0, sizeX*sizeY, 0, 2*(sizeX-1)*(sizeY-1) ); nmap_effect->End(); // restore the device device->SetRenderState( D3DRS_ZENABLE, D3DZB_TRUE ); device->SetRenderTarget( 0, bb ); device->SetDepthStencilSurface( old_depthstencil ); #endif } void software_noisemaker::load_effects() { char *errortext; LPD3DXBUFFER errors; D3DXHANDLE hTechnique; // load effect D3DXCreateEffectFromFile(device, "v2_heightmapgen.fx", NULL, NULL, 0, NULL, &hmap_effect, &errors ); if (errors != NULL){ errortext = (char*) errors->GetBufferPointer(); MessageBox(NULL, errortext, "hmap_effect", MB_OK); } hmap_effect->FindNextValidTechnique(NULL, &hTechnique); hmap_effect->SetTechnique(hTechnique); // load effect D3DXCreateEffectFromFile(device, "v2_normalmapgen.fx", NULL, NULL, 0, NULL, &nmap_effect, &errors ); if (errors != NULL){ errortext = (char*) errors->GetBufferPointer(); MessageBox(NULL, errortext, "nmap_effect", MB_OK); } nmap_effect->FindNextValidTechnique(NULL, &hTechnique); nmap_effect->SetTechnique(hTechnique); }