/////////////////////////////////////////////////////////////////////////// // // Realistic rain real-time simulation program // // Pierre Rousseau // /////////////////////////////////////////////////////////////////////////// // // Particle systems handling // /////////////////////////////////////////////////////////////////////////// #include "windows.h" #include "RainCloseDropsParticles.h" #include using namespace std; extern float startPos[3]; ////////////////////////////////////////////////////////////////////////////////////////////////////////// CloseDropsParticles::CloseDropsParticles(SceneManager *sceneMgr, SceneNode *parentSyst, SceneNode *parentCam) { mSceneMgr = sceneMgr; mParentCam = parentCam; mParentSyst = parentSyst; // CHANGE THE FOLLOWING PARAMETERS TO MODIFY THE SIZES OF THE PARTICLES mRainWidth = 0.2f; // ranging from 0.1 to 0.9 mRainStreaksHeight = 1.0; mActiveParticlesCount = BILLBOARD_POS_TEX_SIZE * BILLBOARD_POS_TEX_SIZE; mParticlesNode = parentSyst->createChildSceneNode(); mRainLightMgr = new RainLightManager(mSceneMgr); createLights(); std::cout << "creating rain system" << std::endl << std::endl; initParticles(); } CloseDropsParticles::~CloseDropsParticles() { mSceneMgr->destroyStaticGeometry(STATIC_GEOMETRY_NAME); cout << "Particles destructed." << endl; } void CloseDropsParticles::createLights() { mSceneMgr->setAmbientLight(ColourValue(1.0, 1.0, 1.0)); mRainLightMgr->addStreetLight(ColourValue::Green, Vector3(startPos[0] + 100 , startPos[1] - HAUTEUR_OBSERVATEUR, startPos[2] + 20), 120); // green light mRainLightMgr->addStreetLight(ColourValue::Red, Vector3(startPos[0] + 130 , startPos[1] - HAUTEUR_OBSERVATEUR, startPos[2] + 60), 120); // red light mRainLightMgr->addStreetLight(ColourValue::Red + ColourValue::Green + ColourValue::Blue, Vector3(startPos[0] + 160 , startPos[1] - HAUTEUR_OBSERVATEUR, startPos[2] + 100), 120); // white light mRainLightMgr->finalizeLights(); } RainLightManager *CloseDropsParticles::getLightManagerPtr() { return mRainLightMgr; } void CloseDropsParticles::updateLights() { mRainLightMgr->updateLights(); } void CloseDropsParticles::createBillboardsPositionRenderTexture(RenderTexture *PSPosTexture, Vector3 nodePos, BillboardSet *bbSet) { //initialize the render to texture related stuff String camName = "camera_for_" + PSPosTexture->getName(); Camera *PSPosCamera = new Ogre::Camera(camName, mSceneMgr); SceneNode *mPSPosCamNode = mSceneMgr->getRootSceneNode()->createChildSceneNode(); mPSPosCamNode->setPosition(nodePos); mPSPosCamNode->attachObject(PSPosCamera); PSPosCamera->setPosition(Vector3(0, 0, 0)); PSPosCamera->setNearClipDistance( 10 ); PSPosCamera->setFarClipDistance( 12 ); PSPosCamera->setFOVy(Ogre::Radian(Ogre::Degree(90))); PSPosCamera->setProjectionType(PT_ORTHOGRAPHIC ); PSPosCamera->setAspectRatio(1.0); mPSPosCamNode->attachObject(bbSet); Billboard *mBillboard = bbSet->createBillboard(Vector3(0, 0, -11)); mBillboard->setDimensions(20, 20); mBillboard->setColour(ColourValue::White); TextureFrameListener *textureLis = new TextureFrameListener(mSceneMgr); PSPosTexture->addListener(textureLis); PSPosTexture->addViewport(PSPosCamera); PSPosTexture->getViewport (0)->setOverlaysEnabled (false); PSPosTexture->getViewport (0)->setClearEveryFrame(true); PSPosTexture->setAutoUpdated(false); } void CloseDropsParticles::createBillboardsPositionTextureMaterial(String inputTextureName) { MaterialPtr posTextureMaterial = MaterialManager::getSingleton().create("rtt_material_using_" + inputTextureName, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); // alpha rejection mustn't be set, to avoid breaking the FBO TextureUnitState *tPosSrcUnit = posTextureMaterial->getTechnique (0)->getPass (0)->createTextureUnitState (); tPosSrcUnit->setTextureName (inputTextureName); tPosSrcUnit->setTextureFiltering (FO_POINT, FO_POINT, FO_NONE ); tPosSrcUnit->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP); // mode clamp for this texture posTextureMaterial->setDepthCheckEnabled (true); posTextureMaterial->setDepthWriteEnabled (true); //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // shader part //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// String progName; // fragment program which will map the generated textures progName = "billboardPosTexUpdater" + inputTextureName; HighLevelGpuProgramPtr fp = HighLevelGpuProgramManager::getSingleton().createProgram(progName, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, "cg", GPT_FRAGMENT_PROGRAM); fp->setSourceFile("billboardPosTexUpdaterFP.cg"); fp->setParameter("profiles", "ps_2_x arbfp1"); fp->setParameter("entry_point", "main"); posTextureMaterial->getTechnique (0)->getPass (0)->setFragmentProgram (progName); posTextureMaterial->compile(); } void CloseDropsParticles::definePosTextureAndBackup() { String tmp; // first : define the "primary" and "secondary" RTT's tmp = String("billboardset_for_") + PARTICLE_POSITION_TEXTURE_NAME; bbSet1 = mSceneMgr->createBillboardSet(tmp); particlePosTexture = Root::getSingleton().getRenderSystem()->createRenderTexture (PARTICLE_POSITION_TEXTURE_NAME, BILLBOARD_POS_TEX_SIZE, BILLBOARD_POS_TEX_SIZE, TEX_TYPE_2D, PF_FLOAT32_RGB); createBillboardsPositionRenderTexture(particlePosTexture, Vector3(0, 10, 0), bbSet1); tmp = String("billboardset_for_") + PARTICLE_POSITION_BACKUP_TEXTURE_NAME; bbSet2 = mSceneMgr->createBillboardSet(tmp); // particlePosTextureBackup was already created and initialized particlePosTextureBackup = Root::getSingleton().getRenderSystem()->createRenderTexture (PARTICLE_POSITION_BACKUP_TEXTURE_NAME, BILLBOARD_POS_TEX_SIZE, BILLBOARD_POS_TEX_SIZE, TEX_TYPE_2D, PF_FLOAT32_RGB); createBillboardsPositionRenderTexture(particlePosTextureBackup, Vector3(100, 10, 0), bbSet2); // initialization createBillboardsPositionTextureMaterial(PARTICLE_POSITION_INIT_TEXTURE_NAME); tmp = String("rtt_material_using_") + PARTICLE_POSITION_INIT_TEXTURE_NAME; bbSet2->setMaterialName(tmp); particlePosTextureBackup->update(); // create and bind the materials used for the billboardSets createBillboardsPositionTextureMaterial(PARTICLE_POSITION_BACKUP_TEXTURE_NAME); tmp = String("rtt_material_using_") + PARTICLE_POSITION_BACKUP_TEXTURE_NAME; bbSet1->setMaterialName(tmp); // now it's initialized, set it to normal rendering createBillboardsPositionTextureMaterial(PARTICLE_POSITION_TEXTURE_NAME); tmp = String("rtt_material_using_") + PARTICLE_POSITION_TEXTURE_NAME; bbSet2->setMaterialName(tmp); } void CloseDropsParticles::initializeBillboardsPositionTexture() { // initialize the texture TexturePtr InitializationBillBoardPositionTexture = TextureManager::getSingleton().createManual( PARTICLE_POSITION_INIT_TEXTURE_NAME, // name ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, TEX_TYPE_2D, // type BILLBOARD_POS_TEX_SIZE, BILLBOARD_POS_TEX_SIZE, // width & height 0, // number of mipmaps PF_FLOAT32_RGB, // pixel format TU_DYNAMIC_WRITE_ONLY_DISCARDABLE); // Get the pixel buffer HardwarePixelBufferSharedPtr pixelBuffer = InitializationBillBoardPositionTexture->getBuffer(); // Lock the pixel buffer and get a pixel box pixelBuffer->lock(HardwareBuffer::HBL_DISCARD); // for best performance use HBL_DISCARD! const PixelBox& pixelBox = pixelBuffer->getCurrentLock(); float* pDest = static_cast(pixelBox.data); ///////////////////////////////////////////////// // (indPart%100) * 10 - 500, 10, (indPart/100) * 10 - 1000 // ((i + j * BILLBOARD_POS_TEX_SIZE )% 100) * 10 - 500, 10, ((i + j * BILLBOARD_POS_TEX_SIZE) / 100) * 10 - 1000 ///////////////////////////////////////////////// // Fill in some pixel data. for (size_t j = 0; j < BILLBOARD_POS_TEX_SIZE; j++) for(size_t i = 0; i < BILLBOARD_POS_TEX_SIZE; i++) { if (i + j * BILLBOARD_POS_TEX_SIZE < mActiveParticlesCount) { // the drops are initially positionned on a regular horizontal grid, with random altitude. *pDest++ = i / float(BILLBOARD_POS_TEX_SIZE); // R -> X *pDest++ = (rand() % 10000) / 10000.0f; // G -> Y *pDest++ = j / float(BILLBOARD_POS_TEX_SIZE); // B -> Z } else { *pDest++ = 0.0; // R -> X *pDest++ = 0.0; // G -> Y *pDest++ = 0.0; // B -> Z } } // Unlock the pixel buffer pixelBuffer->unlock(); InitializationBillBoardPositionTexture->load(); } void CloseDropsParticles::makeControlOverlay() { MaterialPtr posTextureVerifMaterial1 = MaterialManager::getSingleton().create("overlayVerif1", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); posTextureVerifMaterial1->getTechnique (0)->getPass (0)->setAlphaRejectSettings(CMPF_NOT_EQUAL, 0); TextureUnitState *tUnitVerif = posTextureVerifMaterial1->getTechnique (0)->getPass (0)->createTextureUnitState (); //tUnitVerif->setTextureName (REFRACT_RTT_NAME); tUnitVerif->setTextureName (PARTICLE_POSITION_TEXTURE_NAME); tUnitVerif->setTextureFiltering (TFO_NONE ); tUnitVerif->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP); // mode clamp for this texture posTextureVerifMaterial1->compile(); OverlayElement *posTexPanel1 = OverlayManager::getSingleton ().createOverlayElement ("Panel", "PosTexPanel1", false); posTexPanel1->setDimensions(0.15, 0.2); posTexPanel1->setPosition(0.01, 0.01); posTexPanel1->setMaterialName ("overlayVerif1"); MaterialPtr posTextureVerifMaterial2 = posTextureVerifMaterial1->clone("overlayVerif2"); TextureUnitState *tUnitVerif2 = posTextureVerifMaterial2->getTechnique (0)->getPass (0)->getTextureUnitState (0); tUnitVerif2->setTextureName (LIGHT_INFO_TEXTURE_NAME); tUnitVerif2->setTextureFiltering (TFO_NONE ); tUnitVerif2->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP); posTextureVerifMaterial2->compile(); OverlayElement *posTexPanel2 = OverlayManager::getSingleton ().createOverlayElement ("Panel", "PosTexPanel2", false); posTexPanel2->setDimensions(0.15, 0.01); //posTexPanel2->setDimensions(0.15, 0.2); posTexPanel2->setPosition(0.01, 0.22); posTexPanel2->setMaterialName ("overlayVerif2"); Overlay *posTexOverlay = OverlayManager::getSingleton ().create("PositionTextureOverlay"); posTexOverlay->add2D ((OverlayContainer *)posTexPanel1); posTexOverlay->add2D ((OverlayContainer *)posTexPanel2); posTexOverlay->show (); } MeshPtr CloseDropsParticles::createHardwareBillboardMesh(String materialName, String meshName) { MeshPtr msh = MeshManager::getSingleton().createManual(meshName, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, new ManualHardwareBillboardMeshLoader(materialName)); msh->load(); return msh; } void CloseDropsParticles::modifyClonedHardwareBillboardMesh(MeshPtr &msh, int partNumber) { SubMesh* sm = msh->getSubMesh(0); Ogre::VertexData* vertex_data = sm->vertexData; const Ogre::VertexElement* texCoordsElem = vertex_data->vertexDeclaration->findElementBySemantic(Ogre::VES_TEXTURE_COORDINATES); Ogre::HardwareVertexBufferSharedPtr vbuf = vertex_data->vertexBufferBinding->getBuffer(texCoordsElem->getSource()); unsigned char* vertex = static_cast(vbuf->lock(Ogre::HardwareBuffer::HBL_DISCARD)) ; float* pReal; // vertex 0 texCoordsElem->baseVertexPointerToElement(vertex, &pReal); // uv *pReal++ = 1; *pReal++ = 0; // position texture coordinates *pReal++ = float(partNumber % BILLBOARD_POS_TEX_SIZE) / float(BILLBOARD_POS_TEX_SIZE); *pReal++ = float(partNumber / BILLBOARD_POS_TEX_SIZE) / float(BILLBOARD_POS_TEX_SIZE); // vertex 1 vertex += vbuf->getVertexSize(); texCoordsElem->baseVertexPointerToElement(vertex, &pReal); // uv *pReal++ = 0; *pReal++ = 0; // position texture coordinates *pReal++ = float(partNumber % BILLBOARD_POS_TEX_SIZE) / float(BILLBOARD_POS_TEX_SIZE); *pReal++ = float(partNumber / BILLBOARD_POS_TEX_SIZE) / float(BILLBOARD_POS_TEX_SIZE); // vertex 2 vertex += vbuf->getVertexSize(); texCoordsElem->baseVertexPointerToElement(vertex, &pReal); // uv *pReal++ = 0; *pReal++ = 1; // position texture coordinates *pReal++ = float(partNumber % BILLBOARD_POS_TEX_SIZE) / float(BILLBOARD_POS_TEX_SIZE); *pReal++ = float(partNumber / BILLBOARD_POS_TEX_SIZE) / float(BILLBOARD_POS_TEX_SIZE); // vertex 3 vertex += vbuf->getVertexSize(); texCoordsElem->baseVertexPointerToElement(vertex, &pReal); // uv *pReal++ = 1; *pReal++ = 1; // position texture coordinates *pReal++ = float(partNumber % BILLBOARD_POS_TEX_SIZE) / float(BILLBOARD_POS_TEX_SIZE); *pReal++ = float(partNumber / BILLBOARD_POS_TEX_SIZE) / float(BILLBOARD_POS_TEX_SIZE); vbuf->unlock(); msh->load(); } void CloseDropsParticles::initParticles() { StaticGeometry *s; // we create the texture which will be used to update the particles positions. initializeBillboardsPositionTexture(); createMaterial(RAIN_MATERIAL_NAME); // we create the billboards as static geometry in a vertex buffer on the graphics card. The positions will only be modified in a shader s = mSceneMgr->createStaticGeometry(STATIC_GEOMETRY_NAME); // we must set our region parameters so that only one region includes all the geometry s->setOrigin(Vector3(-5000, -500, -5000)); s->setRegionDimensions(Vector3(10000, 1000, 10000)); s->setRenderingDistance(100000); int discreetSize = int(sqrt(BILLBOARD_POS_TEX_SIZE * BILLBOARD_POS_TEX_SIZE / 3.0)); cout << endl << endl << "Loading " << BILLBOARD_POS_TEX_SIZE * BILLBOARD_POS_TEX_SIZE << " particles" << endl; // we should position the particles so that they cover the whole world (to avoid clipping) for (int indPart = 0; indPart < BILLBOARD_POS_TEX_SIZE * BILLBOARD_POS_TEX_SIZE; indPart++) { String meshName = BILLBOARD_MESH_NAME + StringConverter::toString(indPart); // define the billboard (quad) mesh to use modifyClonedHardwareBillboardMesh(createHardwareBillboardMesh(RAIN_MATERIAL_NAME, meshName), indPart); String entName = "simple_quad_for_hardware_bilboard_" + StringConverter::toString(indPart); Entity *e = mSceneMgr->createEntity(entName, meshName); e->setQueryFlags(0x00000002); float indX = float( (indPart / 3) % discreetSize ) / float(discreetSize); float indY = (indPart % 3) / 2.0; // three stories of droplets float indZ = float( (indPart / 3) / discreetSize ) / float(discreetSize); Vector3 pos(PARTICLES_MIN_X + (PARTICLES_MAX_X - PARTICLES_MIN_X) * indX , PARTICLES_MIN_Y + (PARTICLES_MAX_Y - PARTICLES_MIN_Y) * indY , PARTICLES_MIN_Z + (PARTICLES_MAX_Z - PARTICLES_MIN_Z) * indZ); // we give each particle a different position, to avoid clipping s->addEntity(e, pos); // progress bar printf("|"); int discret = 50; int prog = int (discret * indPart / (BILLBOARD_POS_TEX_SIZE * BILLBOARD_POS_TEX_SIZE) ); for (int car=0 ; car <= prog ; car++) printf("#"); for (int car=prog+1 ; car <= discret ; car++) printf(" "); printf("|\r"); } s->build(); cout << endl << endl << "Particles loaded" << endl << endl; } void CloseDropsParticles::updatePositionTexture(bool primary) { if (static_cast(MaterialManager::getSingleton().getByName(RAIN_MATERIAL_NAME))-> getTechnique (0)->getPass (0)->getTextureUnitState (1)->isBlank()) { std::cout << "merde !!!" << std::endl; } if (primary) { particlePosTexture->update(); static_cast(MaterialManager::getSingleton().getByName(RAIN_MATERIAL_NAME))->getTechnique (0)->getPass (0)->getTextureUnitState (1)->setTextureName(PARTICLE_POSITION_TEXTURE_NAME); static_cast(MaterialManager::getSingleton().getByName(RAIN_MATERIAL_NAME))->compile(); } else { particlePosTextureBackup->update(); static_cast(MaterialManager::getSingleton().getByName(RAIN_MATERIAL_NAME))->getTechnique (0)->getPass (0)->getTextureUnitState (1)->setTextureName(PARTICLE_POSITION_BACKUP_TEXTURE_NAME); static_cast(MaterialManager::getSingleton().getByName(RAIN_MATERIAL_NAME))->compile(); } } void CloseDropsParticles::createMaterial(String name) { dropsTexturesMaterial = MaterialManager::getSingleton().create(name, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); #ifndef SNOW mCamera = createDropsCamera(); mParentCam->attachObject(mCamera); dropsTexture = Root::getSingleton().getRenderSystem()->createRenderTexture (REFRACT_RTT_NAME, RTTSIZE, RTTSIZE, TEX_TYPE_2D, PF_R8G8B8); dropsTexture->setAutoUpdated(true); // the main RTT texture will be updated automatically TextureFrameListener *textureLis = new TextureFrameListener(mSceneMgr); // to avoid seeing the drops in the rtt dropsTexture->addListener(textureLis); dropsTexture->addViewport(mCamera); dropsTexture->getViewport (0)->setOverlaysEnabled (false); dropsTexture->getViewport (0)->setClearEveryFrame(true); #endif dropsTexturesMaterial->getTechnique (0)->getPass (0)->setAlphaRejectSettings(CMPF_NOT_EQUAL, 0); // we discard the portions of the texture where alpha = 0 TextureUnitState *createMaterialTUnit1 = dropsTexturesMaterial->getTechnique (0)->getPass (0)->createTextureUnitState (); #ifdef SNOW createMaterialTUnit1->setTextureName ("flocon.png"); dropsTexturesMaterial->getTechnique (0)->getPass (0)->setSceneBlending(SBT_TRANSPARENT_ALPHA); #else createMaterialTUnit1->setTextureName (REFRACT_RTT_NAME); #endif createMaterialTUnit1->setTextureFiltering (FO_POINT, FO_POINT, FO_NONE ); createMaterialTUnit1->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP); // mode wrap for this texture TextureUnitState *createMaterialTUnit2 = dropsTexturesMaterial->getTechnique (0)->getPass (0)->createTextureUnitState (); createMaterialTUnit2->setTextureName (PARTICLE_POSITION_INIT_TEXTURE_NAME); // real position texture isn't yet initialized // THE FOLLOWING LINE IS NECESSARY TO HANDLE VERTEX TEXTURE FETCH IN OGRE. // IT NEEDS OGRE EIHORT // THIS IS THE REASON WHY THE PROGRAM WILL NOT RUN PROPERLY IN DIRECTX // -SHOULD- BE FINE AFTER THE PROGRAM GETS PORTED TO EIHORT (OGRE 1.4) // createMaterialTUnit2->setBindingType(BT_VERTEX); createMaterialTUnit2->setTextureFiltering (FO_POINT, FO_POINT, FO_NONE ); createMaterialTUnit2->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP); // mode clamp for this texture #ifndef SNOW String maskName = "masques/masque_" + StringConverter::toString(mRainWidth * 5.0f) + "_.tga"; TextureUnitState *createMaterialTUnit3 = dropsTexturesMaterial->getTechnique (0)->getPass (0)->createTextureUnitState (); createMaterialTUnit3->setTextureName (maskName); // because we start with billboard width = 0.5 createMaterialTUnit3->setTextureFiltering (FO_POINT, FO_POINT, FO_NONE ); createMaterialTUnit3->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP); // mode clamp for this texture #endif #ifdef STREAKS TextureUnitState *createMaterialTUnit4 = dropsTexturesMaterial->getTechnique (0)->getPass (0)->createTextureUnitState (); createMaterialTUnit4->setTextureName ("shape.tga"); createMaterialTUnit4->setTextureFiltering (FO_POINT, FO_POINT, FO_NONE ); createMaterialTUnit4->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP); // mode clamp for this texture dropsTexturesMaterial->getTechnique (0)->getPass (0)->setSceneBlending(SBT_TRANSPARENT_ALPHA); #endif #ifdef LIGHT_EXTENSION TextureUnitState *createMaterialTUnit5 = dropsTexturesMaterial->getTechnique (0)->getPass (0)->createTextureUnitState (); createMaterialTUnit5->setTextureName (LIGHT_INFO_TEXTURE_NAME); createMaterialTUnit5->setTextureFiltering (FO_POINT, FO_POINT, FO_NONE ); createMaterialTUnit5->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP); // mode clamp for this texture #endif dropsTexturesMaterial->getTechnique (0)->setLodIndex(0); dropsTexturesMaterial->setDepthCheckEnabled (true); // we activate depth test dropsTexturesMaterial->setDepthWriteEnabled (true); GPUmaterial(); dropsTexturesMaterial->compile(); } Camera* CloseDropsParticles::createDropsCamera() { Camera *dropsCamera; String camName; dropsCamera = new Ogre::Camera("refract_drops_camera", mSceneMgr); dropsCamera->setPosition(Vector3(0, 0, 0)); dropsCamera->setNearClipDistance( 1 ); dropsCamera->setFarClipDistance( 10000 ); dropsCamera->setFOVy(Ogre::Radian(FOVyRtt)); // large FOVy, 170 dropsCamera->setAspectRatio(4.0f/3.0f); dropsCamera->setLodBias(0.01); return dropsCamera; } void CloseDropsParticles::updateFragmentProgramParameter(const String &name, float value) { GpuProgramParametersSharedPtr paramsFP = dropsTexturesMaterial->getTechnique (0)->getPass (0)->getFragmentProgramParameters (); paramsFP->setNamedConstant(name, value); } void CloseDropsParticles::updateFragmentProgramParameter(const String &name, Vector3 value) { GpuProgramParametersSharedPtr paramsFP = dropsTexturesMaterial->getTechnique (0)->getPass (0)->getFragmentProgramParameters (); paramsFP->setNamedConstant(name, value); } void CloseDropsParticles::updateFragmentProgramParameter(const String &name, Vector4 value) { GpuProgramParametersSharedPtr paramsFP = dropsTexturesMaterial->getTechnique (0)->getPass (0)->getFragmentProgramParameters (); paramsFP->setNamedConstant(name, value); } void CloseDropsParticles::updateTimeSinceLastFrame(float tslf) { String tmpstr = String("rtt_material_using_") + PARTICLE_POSITION_TEXTURE_NAME; GpuProgramParametersSharedPtr paramsPosFP = static_cast(MaterialManager::getSingleton().getByName(tmpstr))->getTechnique (0)->getPass (0)->getFragmentProgramParameters (); paramsPosFP->setNamedConstant("tslf", tslf); // two distinct materials are used for position update, let's synchronize the second tmpstr = String("rtt_material_using_") + PARTICLE_POSITION_BACKUP_TEXTURE_NAME; paramsPosFP = static_cast(MaterialManager::getSingleton().getByName(tmpstr))->getTechnique (0)->getPass (0)->getFragmentProgramParameters (); paramsPosFP->setNamedConstant("tslf", tslf); } void CloseDropsParticles::updateRainBilboardSideLength(float rainBbSide) { GpuProgramParametersSharedPtr paramsVP = dropsTexturesMaterial->getTechnique (0)->getPass (0)->getVertexProgramParameters (); paramsVP->setNamedConstant("rainBbSide", rainBbSide); } void CloseDropsParticles::updateStreaksHeight(float streaksHeight) { #ifdef STREAKS GpuProgramParametersSharedPtr paramsVP = dropsTexturesMaterial->getTechnique (0)->getPass (0)->getVertexProgramParameters (); paramsVP->setNamedConstant("streaksHeight", streaksHeight); #endif } void CloseDropsParticles::updateLightCount(float nbLights) { #ifdef LIGHT_EXTENSION GpuProgramParametersSharedPtr paramsFP = dropsTexturesMaterial->getTechnique (0)->getPass (0)->getFragmentProgramParameters (); paramsFP->setNamedConstant("nbLights", nbLights); #endif } void CloseDropsParticles::updateViewPos(Vector3 viewPos) { GpuProgramParametersSharedPtr paramsVP = dropsTexturesMaterial->getTechnique (0)->getPass (0)->getVertexProgramParameters (); paramsVP->setNamedConstant("viewPos", viewPos); } void CloseDropsParticles::updateViewDir(Vector3 viewDir) { GpuProgramParametersSharedPtr paramsVP = dropsTexturesMaterial->getTechnique (0)->getPass (0)->getVertexProgramParameters (); paramsVP->setNamedConstant("viewDir", viewDir); } void CloseDropsParticles::updateFallVector(Vector3 fallVect) { String tmpstr = String("rtt_material_using_") + PARTICLE_POSITION_TEXTURE_NAME; GpuProgramParametersSharedPtr paramsPosFP = static_cast(MaterialManager::getSingleton().getByName(tmpstr))->getTechnique (0)->getPass (0)->getFragmentProgramParameters (); paramsPosFP->setNamedConstant("fallVect", fallVect); // two distinct materials are used for position update, let's synchronize the second tmpstr = String("rtt_material_using_") + PARTICLE_POSITION_BACKUP_TEXTURE_NAME; paramsPosFP = static_cast(MaterialManager::getSingleton().getByName(tmpstr))->getTechnique (0)->getPass (0)->getFragmentProgramParameters (); paramsPosFP->setNamedConstant("fallVect", fallVect); #ifdef STREAKS // needed also in the vertex shader, to bend the streaks GpuProgramParametersSharedPtr paramsVP = dropsTexturesMaterial->getTechnique (0)->getPass (0)->getVertexProgramParameters (); paramsVP->setNamedConstant("fallVect", fallVect); #endif } void CloseDropsParticles::updateBoxMin(Vector3 boxMin) { GpuProgramParametersSharedPtr paramsVP = dropsTexturesMaterial->getTechnique (0)->getPass (0)->getVertexProgramParameters (); paramsVP->setNamedConstant("boxMin", boxMin); } void CloseDropsParticles::updateBoxMax(Vector3 boxMax) { GpuProgramParametersSharedPtr paramsVP = dropsTexturesMaterial->getTechnique (0)->getPass (0)->getVertexProgramParameters (); paramsVP->setNamedConstant("boxMax", boxMax); } void CloseDropsParticles::updateLastMove(Vector3 lastMove) { String tmpstr = String("rtt_material_using_") + PARTICLE_POSITION_TEXTURE_NAME; GpuProgramParametersSharedPtr paramsPosFP = static_cast(MaterialManager::getSingleton().getByName(tmpstr))->getTechnique (0)->getPass (0)->getFragmentProgramParameters (); paramsPosFP->setNamedConstant("lastMove", lastMove); // two distinct materials are used for position update, let's synchronize the second tmpstr = String("rtt_material_using_") + PARTICLE_POSITION_BACKUP_TEXTURE_NAME; paramsPosFP = static_cast(MaterialManager::getSingleton().getByName(tmpstr))->getTechnique (0)->getPass (0)->getFragmentProgramParameters (); paramsPosFP->setNamedConstant("lastMove", lastMove); } void CloseDropsParticles::updateRandomMove(Vector3 randomMove) { String tmpstr = String("rtt_material_using_") + PARTICLE_POSITION_TEXTURE_NAME; GpuProgramParametersSharedPtr paramsPosFP = static_cast(MaterialManager::getSingleton().getByName(tmpstr))->getTechnique (0)->getPass (0)->getFragmentProgramParameters (); paramsPosFP->setNamedConstant("randomMove", randomMove); // two distinct materials are used for position update, let's synchronize the second tmpstr = String("rtt_material_using_") + PARTICLE_POSITION_BACKUP_TEXTURE_NAME; paramsPosFP = static_cast(MaterialManager::getSingleton().getByName(tmpstr))->getTechnique (0)->getPass (0)->getFragmentProgramParameters (); paramsPosFP->setNamedConstant("randomMove", randomMove); } void CloseDropsParticles::updateShaderParameters(float tslf, float rainBbSide, float streaksHeight, int nbLights, Vector3 viewPos, Vector3 viewDir, Vector3 fallVect, Vector3 boxMin, Vector3 boxMax, Vector3 lastMove, Vector3 randomMove, int useShader) { // data to update : // floats : // time since last frame (in seconds) // particle count // billboard position texture side length // billboard side length // streaks height // number of lights // vec3 : // viewer position // view direction // fall vector (including wind) // minimum box position // maximum box position // viewer movement to compensate (in box coordinates) // random displacement when respawning the particle // actualizing parameters for the position update shader String tmpstr = String("rtt_material_using_") + PARTICLE_POSITION_TEXTURE_NAME; GpuProgramParametersSharedPtr paramsPosFP = static_cast(MaterialManager::getSingleton().getByName(tmpstr))->getTechnique (0)->getPass (0)->getFragmentProgramParameters (); paramsPosFP->setNamedConstant("tslf", tslf); paramsPosFP->setNamedConstant("randomMove", randomMove); paramsPosFP->setNamedConstant("lastMove", lastMove); paramsPosFP->setNamedConstant("fallVect", fallVect); // two distinct materials are used for position update, let's synchronize the second tmpstr = String("rtt_material_using_") + PARTICLE_POSITION_BACKUP_TEXTURE_NAME; paramsPosFP = static_cast(MaterialManager::getSingleton().getByName(tmpstr))->getTechnique (0)->getPass (0)->getFragmentProgramParameters (); paramsPosFP->setNamedConstant("tslf", tslf); paramsPosFP->setNamedConstant("randomMove", randomMove); paramsPosFP->setNamedConstant("lastMove", lastMove); paramsPosFP->setNamedConstant("fallVect", fallVect); // actualizing vertex program parameters GpuProgramParametersSharedPtr paramsVP = dropsTexturesMaterial->getTechnique (0)->getPass (0)->getVertexProgramParameters (); paramsVP->setNamedConstant("viewPos", viewPos); paramsVP->setNamedConstant("viewDir", viewDir); paramsVP->setNamedConstant("boxMin", boxMin); paramsVP->setNamedConstant("boxMax", boxMax); paramsVP->setNamedConstant("rainBbSide", rainBbSide); #ifdef STREAKS paramsVP->setNamedConstant("streaksHeight", streaksHeight); #endif // actualizing fragment program parameters GpuProgramParametersSharedPtr paramsFP = dropsTexturesMaterial->getTechnique (0)->getPass (0)->getFragmentProgramParameters (); #ifdef LIGHT_EXTENSION paramsFP->setNamedConstant("nbLights", nbLights); #endif } void CloseDropsParticles::GPUmaterial() { // vertex program which will modify texture coordinates HighLevelGpuProgramPtr vp = HighLevelGpuProgramManager::getSingleton().createProgram("gouttesTexCoordsVP", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, "cg", GPT_VERTEX_PROGRAM); vp->setSourceFile("gouttesTexCoordsVP.cg"); vp->setParameter("profiles", "vs_3_0 vp40"); #ifdef STREAKS vp->setParameter("entry_point", "mainStreaks"); #else vp->setParameter("entry_point", "mainNoStreaks"); #endif // vertex program binding dropsTexturesMaterial->getTechnique (0)->getPass (0)->setVertexProgram ("gouttesTexCoordsVP"); // we give it some parameters GpuProgramParametersSharedPtr paramsVP = dropsTexturesMaterial->getTechnique (0)->getPass (0)->getVertexProgramParameters (); paramsVP->setNamedAutoConstant("worldviewproj", GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX); paramsVP->setNamedAutoConstant("worldview", GpuProgramParameters::ACT_WORLDVIEW_MATRIX); // fragment program which will map the generated textures HighLevelGpuProgramPtr fp = HighLevelGpuProgramManager::getSingleton().createProgram("gouttesTexCoordsFP", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, "cg", GPT_FRAGMENT_PROGRAM); fp->setSourceFile("gouttesTexCoordsFP.cg"); fp->setParameter("profiles", "ps_3_0 fp40"); #ifdef SNOW fp->setParameter("entry_point", "main_Snow_noLight"); #else #ifdef STREAKS #ifdef LIGHT_EXTENSION fp->setParameter("entry_point", "main_Streaks_Light"); #else // LIGHT fp->setParameter("entry_point", "main_Streaks_noLight"); #endif // LIGHT #else // STREAKS #ifdef LIGHT_EXTENSION fp->setParameter("entry_point", "main_noStreaks_Light"); #else // LIGHT fp->setParameter("entry_point", "main_noStreaks_noLight"); #endif // LIGHT #endif // STREAKS #endif // SNOW dropsTexturesMaterial->getTechnique (0)->getPass (0)->setFragmentProgram ("gouttesTexCoordsFP"); #ifdef LIGHT_EXTENSION GpuProgramParametersSharedPtr paramsFP = dropsTexturesMaterial->getTechnique (0)->getPass (0)->getFragmentProgramParameters (); paramsFP->setNamedAutoConstant("worldview", GpuProgramParameters::ACT_WORLDVIEW_MATRIX); // lighting paramsFP->setNamedAutoConstant("colAmb", GpuProgramParameters::ACT_AMBIENT_LIGHT_COLOUR); #endif //LIGHT }