TexturePtr DrawContext::disc(u16 radius) { TexturePtr result; string path = discPath(radius); if(!Application::instance()->resourceManager->hasTexture(path)) { BitmapPtr bitmap(new Bitmap(2*radius, 2*radius, GL_RGBA)); bitmap->disc(radius-.5, radius-.5, radius+.5); bitmap->premultiplyAlpha(); result.reset(new Texture(bitmap)); Application::instance()->resourceManager->texture(path, result); } else { result = Application::instance()->resourceManager->texture(path); } return result; }
void setupScene() { m_window->getViewports().front()->setRenderQueueIdMask(~RenderQueueId_OffscreenTransparentObjects); LightPtr light(new Light); light->setDirection(glm::normalize(glm::vec3(1.5, -1, -0.5))); light->setPosition(glm::vec3(0, 0.5, 0) + light->getDirection() * -10.0f); m_visSystem->addLight(light); // Volume std::vector<std::string> gridNames; gridNames.push_back(m_config.densityGridName); if (!m_config.temperatureGridName.empty()) { gridNames.push_back(m_config.temperatureGridName); } std::vector<openvdb::GridBase::Ptr> baseGrids = loadGridsFromFile(m_config.vdbVilename, gridNames); openvdb::FloatGrid::Ptr densityGrid = openvdb::gridPtrCast<openvdb::FloatGrid>(baseGrids[0]); openvdb::FloatGrid::Ptr temperatureGrid; if (!m_config.temperatureGridName.empty()) { temperatureGrid = openvdb::gridPtrCast<openvdb::FloatGrid>(baseGrids[1]); // Rescale temperature field to between 0 and 1 { float minValue = 99999999999999; float maxValue = -99999999999999; for (openvdb::FloatGrid::ValueOnCIter iter = temperatureGrid->cbeginValueOn(); iter.test(); ++iter) { float value = *iter; minValue = std::min(minValue, value); maxValue = std::max(maxValue, value); } float scale = 1.0 / (maxValue - minValue); for (openvdb::FloatGrid::ValueOnIter iter = temperatureGrid->beginValueOn(); iter.test(); ++iter) { float value = *iter; value = (value - minValue) * scale; iter.setValue(value); } } // Ensure both grids have the same hierarchy { openvdb::FloatGrid::Ptr resultGrid = openvdb::FloatGrid::create(); resultGrid->tree().combine2(densityGrid->tree(), temperatureGrid->tree(), CopyBIntoA()); temperatureGrid->tree().combine(densityGrid->tree(), CopyBIntoA()); densityGrid = resultGrid; } } std::vector<GridPtr> grids; GridTextureRolesMap gridTextureRoles; grids.push_back(GridPtr(new VdbGrid<openvdb::FloatGrid>(densityGrid, 1))); gridTextureRoles[GridTextureRole_Diffuse] = grids.back(); if (m_config.generateNormals) { Vec3UByteGrid::Ptr normalGrid = createNormalGrid(*densityGrid); grids.push_back(GridPtr(new VdbGrid<Vec3UByteGrid>(normalGrid, 3))); gridTextureRoles[GridTextureRole_Normal] = grids.back(); } if (temperatureGrid) { grids.push_back(GridPtr(new VdbGrid<openvdb::FloatGrid>(temperatureGrid, 1))); gridTextureRoles[GridTextureRole_Temperature] = grids.back(); } openvdb::CoordBBox bbox; densityGrid->constTree().evalLeafBoundingBox(bbox); float scale = 1.0f / (float)bbox.extents().asVec3s().length(); glm::vec3 center = toVec3(bbox.getCenter() * scale); std::ostringstream ss; ss << "Grid extents: " << bbox.extents().x() << ", " << bbox.extents().y() << ", " << bbox.extents().z(); defaultLogger()->logLine(ss.str()); int renderQueueId; if (m_config.renderToLowResTarget) { renderQueueId = RenderQueueId_OffscreenTransparentObjects; } else { renderQueueId = getDefaultRenderQueueId(); } RenderableVolumeConfig config; config.grids = grids; config.materialFactory.reset(new SparseVolumeMaterialFactoryI(gridTextureRoles, m_config.transparent, m_config.opacityMultiplier)); config.scale = scale; config.batchBoxes = !m_config.transparent; // don't batch if we have transparency so we can sort RenderableVolumePtr volume = RenderableVolumeFactory::createRenderableVolume(config); BOOST_FOREACH(const GVis::RenderableNodePtr& node, volume->nodes) { node->translate(-center); m_visSystem->addRenderableNode(node, renderQueueId); } if (m_config.transparent) { RenderQueuePtr renderQueue = m_visSystem->getRenderQueue(renderQueueId); if (renderQueue) renderQueue->setSortingMode(RenderSortingMode_BackToFront); } if (m_config.renderToLowResTarget) { int volumeTargetWidth = m_window->getWidth() / 2; int volumeTargetHeight = m_window->getHeight() / 2; TexturePtr offscreenTransparentObjectsTexture; // Create offscreen transparent objects target { ImageTextureConfig config = ImageTextureConfig::createDefault(); config.width = volumeTargetWidth; config.height = volumeTargetHeight; config.textureAddressMode = TextureAddressMode_Clamp; offscreenTransparentObjectsTexture.reset(new Texture(config)); { RenderTextureTargetConfig config; config.texture = offscreenTransparentObjectsTexture; config.attachment = FrameBufferAttachment_Color; RenderTextureTargetPtr target(new RenderTextureTarget(config)); { ViewportPtr viewport = target->addDefaultViewport(m_camera); viewport->setRenderQueueIdMask(RenderQueueId_OffscreenTransparentObjects); viewport->setBackgroundColor(glm::vec4(0,0,0,0)); } m_window->addRenderTarget(target); } } // Composite offscreen particles { TextureUnit textureUnit(offscreenTransparentObjectsTexture, "albedoSampler"); ShaderProgramPtr shader = ShaderProgram::createShaderProgram(ShaderProgramConfig("Shaders/Common/ScreenQuad.vert", "Shaders/Common/SimpleTextured.frag")); TechniquePtr technique(new Technique(shader)); technique->addTextureUnit(textureUnit); technique->setAlphaBlendingMode(AlphaBlendingMode_PreMultiplied); MaterialPtr material(new Material); material->setTechnique(technique); { RectangleConfig config = RectangleConfig::defaultWithSize(glm::vec2(2, 2)); MeshPtr mesh = RectangleMeshFactory::createMesh(config); GeoPtr geo(new Geo(mesh, material)); RenderableNodePtr renderableNode = RenderableNode::createWithSingleGeo(geo); m_visSystem->addRenderableNode(renderableNode, RenderQueueId_CompositeOffscreenTransparentObjects); } } } if (m_config.orbitCam) { centerNode.reset(new SceneNode); centerNode->addChild(m_camera); m_cameraInputEnabled = false; } m_camera->setPosition_parentSpace(glm::vec3(0,0,1.4)); }
MeshContainer* XFileLoader::CreateMeshContainer() { HRESULT hr; MeshContainer* meshContainer = NULL; Graphics* graphics = Graphics::GetInstance(); IDirect3DDevice9Ptr pD3DDevice = graphics->GetDirect3DDevice(); if( !(m_pD3DMesh->GetFVF() & D3DFVF_NORMAL) ) { LPD3DXMESH tmpMesh = NULL; // 柔軟な頂点フォーマット (FVF) コードを使ってメッシュのコピーを作成する hr = m_pD3DMesh->CloneMeshFVF( m_pD3DMesh->GetOptions(), m_pD3DMesh->GetFVF() | D3DFVF_NORMAL, pD3DDevice, &tmpMesh); // ←ここにコピー if(FAILED(hr)) { goto exit; } // メッシュに含まれる各頂点の法線を計算して、設定する //D3DXComputeNormals( tmpMesh, reinterpret_cast<DWORD*>(pAdjacencyBuf->GetBufferPointer()) ); D3DXComputeNormals( tmpMesh, NULL ); m_pD3DMesh->Release(); m_pD3DMesh = tmpMesh; } D3DVERTEXELEMENT9 pDecl[MAX_FVF_DECL_SIZE]; hr = m_pD3DMesh->GetDeclaration(pDecl); if( FAILED(hr) ) { goto exit; } DWORD vertexNum = m_pD3DMesh->GetNumVertices(); DWORD faceNum = m_pD3DMesh->GetNumFaces(); DWORD attrNum = 0; m_pD3DMesh->GetAttributeTable(NULL, &attrNum); DWORD size = m_pD3DMesh->GetNumBytesPerVertex(); BYTE* pD3DVertice = NULL; m_pD3DMesh->LockVertexBuffer( 0,(LPVOID*)&pD3DVertice ); sVertex* vertices = new sVertex[vertexNum]; for( DWORD vertIdx = 0;vertIdx<vertexNum;vertIdx++ ) { sVertex* vertex = &vertices[vertIdx]; vertex->uv = D3DXVECTOR2(0.0f,0.0f); vertex->color = 0xFFFFFFFF; for( DWORD i=0;i<MAX_FVF_DECL_SIZE;i++ ) { D3DVERTEXELEMENT9& decl = pDecl[i]; if( decl.Stream==0xFF ) { break; } switch( decl.Usage ) { case D3DDECLUSAGE_POSITION: vertex->position = *(D3DXVECTOR3*)(pD3DVertice+vertIdx*size+decl.Offset); vertex->position = vertex->position * m_scale; break; case D3DDECLUSAGE_NORMAL: vertex->normal = *(D3DXVECTOR3*)(pD3DVertice+vertIdx*size+decl.Offset); break; case D3DDECLUSAGE_TEXCOORD: vertex->uv = *(D3DXVECTOR2*)(pD3DVertice+vertIdx*size+decl.Offset); break; case D3DDECLUSAGE_COLOR: vertex->color = *(DWORD*)(pD3DVertice+vertIdx*size+decl.Offset); break; } } } m_pD3DMesh->UnlockVertexBuffer(); LPDIRECT3DINDEXBUFFER9 pIndexBuffer = NULL; m_pD3DMesh->GetIndexBuffer( &pIndexBuffer ); D3DINDEXBUFFER_DESC desc; pIndexBuffer->GetDesc( &desc ); pIndexBuffer->Release(); DWORD* indices = new DWORD[faceNum*3]; if( desc.Format==D3DFMT_INDEX16 ) { WORD* pD3DIndices = NULL; m_pD3DMesh->LockIndexBuffer(0,(LPVOID*)&pD3DIndices ); for( DWORD i=0;i<faceNum*3;i++ ) { indices[i] = pD3DIndices[i]; } m_pD3DMesh->UnlockIndexBuffer(); } else { DWORD* pD3DIndices =NULL; m_pD3DMesh->LockIndexBuffer(0,(LPVOID*)&pD3DIndices ); memcpy( indices,pD3DIndices,sizeof(DWORD)*faceNum*3 ); m_pD3DMesh->UnlockIndexBuffer(); } D3DXATTRIBUTERANGE *attrList = new D3DXATTRIBUTERANGE[attrNum]; m_pD3DMesh->GetAttributeTable(attrList, &attrNum); meshContainer = new MeshContainer; meshContainer->pMesh = new Mesh; meshContainer->pMesh->Create( vertexNum,faceNum,attrNum ); meshContainer->pMesh->SetVertices( vertices ); meshContainer->pMesh->SetIndices( indices ); meshContainer->pMesh->SetAttributeRanges( attrList ); delete[] vertices; delete[] indices; delete[] attrList; meshContainer->materialNum = m_Materials; meshContainer->pMaterials = new sMaterial[m_Materials]; D3DXMATERIAL* pD3DMaterials = (D3DXMATERIAL*)m_pMaterialBuf->GetBufferPointer(); for( DWORD i=0;i<m_Materials;i++ ) { sMaterial* pMaterial = &meshContainer->pMaterials[i]; D3DXMATERIAL* pD3DMaterial = &pD3DMaterials[i]; pMaterial->colorDiffuse = pD3DMaterial->MatD3D.Diffuse; pMaterial->colorSpecular.r = pD3DMaterial->MatD3D.Specular.r; pMaterial->colorSpecular.g = pD3DMaterial->MatD3D.Specular.g; pMaterial->colorSpecular.b = pD3DMaterial->MatD3D.Specular.b; pMaterial->colorSpecular.a = 0.0f; pMaterial->colorAmbient.r = pD3DMaterial->MatD3D.Diffuse.r; pMaterial->colorAmbient.g = pD3DMaterial->MatD3D.Diffuse.g; pMaterial->colorAmbient.b = pD3DMaterial->MatD3D.Diffuse.b; pMaterial->colorAmbient.a = 0.0f; pMaterial->colorEmissive.r = pD3DMaterial->MatD3D.Emissive.r; pMaterial->colorEmissive.g = pD3DMaterial->MatD3D.Emissive.g; pMaterial->colorEmissive.b = pD3DMaterial->MatD3D.Emissive.b; pMaterial->colorEmissive.a = 0.0f; pMaterial->specularPower = pD3DMaterial->MatD3D.Power; TCHAR path[MAX_PATH]; _tcscpy_s( path,m_path.c_str() ); tstring texFileName; tstring sphereFileName; if( pD3DMaterial->pTextureFilename && strlen(pD3DMaterial->pTextureFilename)>0 ) { tstring filename = to_tstring(pD3DMaterial->pTextureFilename); tstring::size_type index = filename.find( _T("*") ); if( index != tstring::npos ) { sphereFileName = filename.substr( index+1 ); PathAppend( path,sphereFileName.c_str() ); sphereFileName = path; PathRemoveFileSpec( path ); texFileName = filename.erase( index ); PathAppend( path,texFileName.c_str() ); texFileName = path; PathRemoveFileSpec( path ); } else { texFileName = filename; PathAppend( path,texFileName.c_str() ); texFileName = path; PathRemoveFileSpec( path ); } tstring ext = PathFindExtension( texFileName.c_str() ); if( ext == _T(".sph" ) || ext == _T(".spa") ) { sphereFileName = texFileName; texFileName = _T(""); } } if( !texFileName.empty() ) { TexturePtr pTex = ResourceManager::GetInstance().GetResource<Texture>( texFileName ); if( !pTex ) { pTex = TexturePtr(new Texture); if( pTex->CreateFromFile( texFileName ) ) { ResourceManager::GetInstance().AddResource( texFileName,pTex ); } else { pTex.reset(); } } if( pTex ) { pMaterial->textureDiffuse = pTex; } } if( !sphereFileName.empty() ) { TexturePtr pTex = ResourceManager::GetInstance().GetResource<Texture>( sphereFileName ); if( !pTex ) { pTex = TexturePtr(new Texture); if( pTex->CreateFromFile( sphereFileName ) ) { ResourceManager::GetInstance().AddResource( sphereFileName,pTex ); } else { pTex.reset(); } } if( pTex ) { pMaterial->textureSphere = pTex; } tstring ext = PathFindExtension( sphereFileName.c_str() ); if( ext == _T(".sph" ) ) { pMaterial->spheremap = eSPHEREMAP_MUL; } else if( ext == _T(".spa") ) { pMaterial->spheremap = eSPHEREMAP_ADD; } } } exit: if( m_pMaterialBuf ) { m_pMaterialBuf->Release(); m_pMaterialBuf = NULL; } if( m_pEffectInstancesBuf ) { m_pEffectInstancesBuf->Release(); m_pEffectInstancesBuf = NULL; } if( m_pAdjacencyBuf ) { m_pAdjacencyBuf->Release(); m_pAdjacencyBuf = NULL; } if( m_pD3DMesh ) { m_pD3DMesh->Release(); m_pD3DMesh = NULL; } return meshContainer; }
PMDModelPtr PMDFileLoader::Open( const tstring& filePath ) { m_fileName = filePath; TCHAR path[MAX_PATH]; _tcscpy_s( path,MAX_PATH,filePath.c_str() ); PathRemoveFileSpec( path ); PathAddBackslash( path ); m_path = path; FILE* fp=NULL; if( _tfopen_s(&fp,m_fileName.c_str(),_T("rb"))!=0 ) { return PMDModelPtr(); } fpos_t fsize = 0; fseek(fp,0,SEEK_END); fgetpos(fp,&fsize); fseek(fp,0,SEEK_SET); size_t sz=(size_t)fsize; unsigned char* buffer=new unsigned char[sz]; fread(buffer,1,sz,fp); fclose(fp); sPMD* pmd = new sPMD; bool ret = PMDLoad(buffer,sz,pmd); delete[] buffer; if( !ret ) { delete pmd; return PMDModelPtr(); } sPMD_Skin* skinBase = NULL; for( DWORD skinIdx=0;skinIdx<pmd->skin_list.skin_count;skinIdx++ ) { sPMD_Skin* skin = &pmd->skin_list.skin[skinIdx]; if( skin->skin_type == ePMD_SkinType_Base ) { skinBase = skin; for( DWORD vertIdx = 0; vertIdx < skin->skin_vert_count ; vertIdx++ ) { DWORD targetIndex = skin->skin_vert[vertIdx].index; memcpy( pmd->vertex_list.vertex[ targetIndex ].pos, skin->skin_vert[vertIdx].pos,sizeof(float)*3 ); } break; } } for( DWORD skinIdx=0;skinIdx<pmd->skin_list.skin_count;skinIdx++ ) { sPMD_Skin* skin = &pmd->skin_list.skin[skinIdx]; if( skin->skin_type != ePMD_SkinType_Base ) { for( DWORD vertIdx = 0; vertIdx < skin->skin_vert_count ; vertIdx++ ) { DWORD targetIndex = skin->skin_vert[vertIdx].index; skin->skin_vert[vertIdx].index = skinBase->skin_vert[ targetIndex ].index; } } } Graphics* graphics = Graphics::GetInstance(); sMaterial* pMaterials = new sMaterial[pmd->material_list.material_count]; for( DWORD i=0;i<pmd->material_list.material_count;i++ ) { sPMD_Material* pmdMat = &pmd->material_list.material[i]; sMaterial* pMaterial = &pMaterials[i]; pMaterial->colorDiffuse.r = 0.0f; pMaterial->colorDiffuse.g = 0.0f; pMaterial->colorDiffuse.b = 0.0f; pMaterial->colorDiffuse.a = pmdMat->alpha; pMaterial->colorAmbient.r = pmdMat->diffuse_color[0]; pMaterial->colorAmbient.g = pmdMat->diffuse_color[1]; pMaterial->colorAmbient.b = pmdMat->diffuse_color[2]; pMaterial->colorAmbient.a = 0.0f; pMaterial->colorSpecular.r = pmdMat->specular_color[0]; pMaterial->colorSpecular.g = pmdMat->specular_color[1]; pMaterial->colorSpecular.b = pmdMat->specular_color[2]; pMaterial->colorSpecular.a = 0.0f; pMaterial->colorEmissive.r = pmdMat->ambient_color[0]; pMaterial->colorEmissive.g = pmdMat->ambient_color[1]; pMaterial->colorEmissive.b = pmdMat->ambient_color[2]; pMaterial->colorEmissive.a = 0.0f; pMaterial->specularPower = pmdMat->specularity; pMaterial->spheremap = eSPHEREMAP_MUL; pMaterial->edge = pmdMat->edge_flag!=0; TCHAR path[MAX_PATH]; _tcscpy_s( path,m_path.c_str() ); tstring texFileName; tstring sphereFileName; if( strlen(pmdMat->texture_file_name)>0 ) { tstring filename = to_tstring(pmdMat->texture_file_name); tstring::size_type index = filename.find( _T("*") ); if( index != tstring::npos ) { sphereFileName = filename.substr( index+1 ); PathAppend( path,sphereFileName.c_str() ); sphereFileName = path; PathRemoveFileSpec( path ); texFileName = filename.erase( index ); PathAppend( path,texFileName.c_str() ); texFileName = path; PathRemoveFileSpec( path ); } else { texFileName = filename; PathAppend( path,texFileName.c_str() ); texFileName = path; PathRemoveFileSpec( path ); } tstring ext = PathFindExtension( texFileName.c_str() ); if( ext == _T(".sph" ) || ext == _T(".spa") ) { sphereFileName = texFileName; texFileName = _T(""); } } if( !texFileName.empty() ) { TexturePtr pTex = ResourceManager::GetInstance().GetResource<Texture>( texFileName ); if( !pTex ) { pTex = TexturePtr(new Texture); pTex->CreateFromFile( texFileName ); ResourceManager::GetInstance().AddResource( texFileName,pTex ); } pMaterial->textureDiffuse = pTex; } if( !sphereFileName.empty() ) { TexturePtr pTex = ResourceManager::GetInstance().GetResource<Texture>( sphereFileName ); if( !pTex ) { pTex = TexturePtr(new Texture); pTex->CreateFromFile( sphereFileName ); ResourceManager::GetInstance().AddResource( sphereFileName,pTex ); } pMaterial->textureSphere = pTex; tstring ext = PathFindExtension( sphereFileName.c_str() ); if( ext == _T(".sph" ) ) { pMaterial->spheremap = eSPHEREMAP_MUL; } else if( ext == _T(".spa") ) { pMaterial->spheremap = eSPHEREMAP_ADD; } } pMaterial->colorToon = D3DXCOLOR( 1.0f,1.0f,1.0f,1.0f ); tstring toonTexName = _T(""); tstring toonTexPath = _T(""); if( 0<=pmdMat->toon_index && pmdMat->toon_index<10 ) { // TODO:デフォルトのtoonファイルは固定パスか・・・ toonTexName = to_tstring( pmd->toon_list.toon_file_name[pmdMat->toon_index] ); } TexturePtr pTex; if( !toonTexName.empty() ) { PathAppend( path,toonTexName.c_str() ); toonTexPath = path; PathRemoveFileSpec( path ); pTex = ResourceManager::GetInstance().GetResource<Texture>( toonTexPath ); if( !pTex ) { pTex = TexturePtr(new Texture); if( !pTex->CreateFromFile( toonTexPath ) ) { pTex.reset(); } } } if( !pTex ) { pTex = graphics->GetDefaultToonTexture( pmdMat->toon_index ); if( !pTex ) { toonTexPath = _T("<FFFFFFFF>"); pTex = ResourceManager::GetInstance().GetResource<Texture>( toonTexPath ); if( !pTex ) { pTex = TexturePtr(new Texture); if( !pTex->CreateDotColor( 0xFFFFFFFF ) ) { pTex.reset(); } } } } if( pTex ) { pMaterial->textureToon = pTex; ResourceManager::GetInstance().AddResource( toonTexPath,pTex ); IDirect3DTexture9Ptr pD3DTexture = pTex->GetTexture(); D3DSURFACE_DESC desc; pD3DTexture->GetLevelDesc( 0,&desc ); D3DLOCKED_RECT lockRect; pD3DTexture->LockRect(0, &lockRect, NULL, 0); int x = 0; int y = desc.Height-1; DWORD color; memcpy(&color,(BYTE*)lockRect.pBits + lockRect.Pitch*y + 4*x, sizeof(DWORD) ); pD3DTexture->UnlockRect(0); pMaterial->colorToon = D3DXCOLOR( color ); } } return PMDModelPtr( new PMDModel(pmd,pmd->material_list.material_count,pMaterials) ); }
void setupScene() { // Must create ClSystem before OpenGL textures. FIXME: this constraint should be more explicit m_clSystem.reset(new ClSystem); m_window->getViewports().front()->setRenderQueueIdMask(~RenderQueueId_OffscreenTransparentObjects); LightPtr light(new Light); light->setDirection(glm::normalize(glm::vec3(1.5, -1, -0.5))); light->setPosition(glm::vec3(0, 1.0, 0) + light->getDirection() * -10.0f); m_visSystem->addLight(light); { ShadowProjectorConfig config = ShadowProjectorConfig::createDefault(); config.sceneHeight = config.sceneWidth = 2; config.shadowFormat = ShadowFormat_RGB32F; m_shadowProjector.reset(new ShadowProjector(config)); m_shadowProjector->setLight(light); m_window->addRenderTarget(m_shadowProjector->getRenderTextureTarget()); } RenderTextureTargetPtr sceneDepthTarget = createDepthTarget(m_camera, m_window->getWidth(), m_window->getHeight()); sceneDepthTarget->getViewports().front()->setRenderQueueIdMask(~RenderQueueId_OffscreenTransparentObjects); TexturePtr sceneDepthTexture = sceneDepthTarget->getTexture(); // Volume { int width = 64; int height = 128; int depth = 128; int size = width * height * depth * 4; m_imageData.reset(new unsigned char[size]); memset(m_imageData.get(), 0, size); // Density texture m_textureConfig = ImageTextureConfig::createDefault(); m_textureConfig.width = width; m_textureConfig.height = height; m_textureConfig.depth = depth; m_textureConfig.is3d = true; m_textureConfig.format = PixelFormat_RGBA8; m_textureConfig.textureAddressMode = TextureAddressMode_Clamp; m_textureConfig.data = m_imageData.get(); m_fluidStateTexture.reset(new Texture(m_textureConfig)); // Normal texture { ImageTextureConfig normalTextureConfig = m_textureConfig; normalTextureConfig.width /= 2; normalTextureConfig.height /= 2; normalTextureConfig.depth /= 2; normalTextureConfig.data = 0; m_normalTexture.reset(new Texture(normalTextureConfig)); } glm::vec3 boxSize(0.5, 1, 1); glm::vec3 volumeTextureSize(m_textureConfig.width, m_textureConfig.height, m_textureConfig.depth); MaterialPtr material(new Material); // Main technique { ShaderProgramPtr shader = ShaderProgram::createShaderProgram(ShaderProgramConfig("Shaders/Volume/RaymarchedVolume.vert", "Shaders/Volume/VolumetricSmoke.frag")); TechniquePtr technique(new Technique(shader)); { Vec3ShaderParameterPtr boxModelSizeParameter(new Vec3ShaderParameter("volumeSize_modelSpace", boxSize)); technique->addCustomShaderParameter(boxModelSizeParameter); Vec3ShaderParameterPtr oneOnVolumeTextureSizeParameter(new Vec3ShaderParameter("oneOnVolumeTextureSize", 1.0f / volumeTextureSize)); technique->addCustomShaderParameter(oneOnVolumeTextureSizeParameter); technique->addCustomShaderParameter(ShaderParameterPtr(new FloatShaderParameter("opacityMultiplier", 30.0))); technique->setAlphaBlendingMode(AlphaBlendingMode_PreMultiplied); { TextureUnit unit(m_fluidStateTexture, "albedoSampler"); technique->addTextureUnit(unit); } { TextureUnit unit(sceneDepthTexture, "sceneDepthSampler"); technique->addTextureUnit(unit); } { TextureUnit unit(m_shadowProjector->getShadowTexture(), "shadowSampler"); technique->addTextureUnit(unit); } { TextureUnit unit(m_normalTexture, "normalSampler"); technique->addTextureUnit(unit); } } material->setTechnique(technique); } // Deep shadow caster technique { ShaderProgramPtr shader = ShaderProgram::createShaderProgram(ShaderProgramConfig("Shaders/Volume/RaymarchedVolume.vert", "Shaders/Volume/VolumeShadowCaster.frag")); TechniquePtr technique(new Technique(shader)); { Vec3ShaderParameterPtr boxModelSizeParameter(new Vec3ShaderParameter("volumeSize_modelSpace", boxSize)); technique->addCustomShaderParameter(boxModelSizeParameter); Vec3ShaderParameterPtr oneOnVolumeTextureSizeParameter(new Vec3ShaderParameter("oneOnVolumeTextureSize", 1.0f / volumeTextureSize)); technique->addCustomShaderParameter(oneOnVolumeTextureSizeParameter); technique->addCustomShaderParameter(ShaderParameterPtr(new FloatShaderParameter("opacityMultiplier", 0.8))); { TextureUnit unit(m_fluidStateTexture, "albedoSampler"); technique->addTextureUnit(unit); } } material->setTechnique(technique, TechniqueCategory_DepthRtt); } { BoxConfig config; config.size = boxSize; MeshPtr mesh = BoxMeshFactory::createMesh(config); GeoPtr geo(new Geo(mesh, material)); RenderableNodePtr renderableNode(new RenderableNode); renderableNode->addRenderable(geo); renderableNode->setPosition(glm::vec3(0, 0.5, 0)); m_visSystem->addRenderableNode(renderableNode, RenderQueueId_OffscreenTransparentObjects); } } // Scene geo { ShadowedMaterialFactory materialFactory(m_shadowProjector->getShadowTexture()); // Ground plane { RectangleConfig config = RectangleConfig::defaultWithSize(glm::vec2(5, 5)); config.orientation = glm::angleAxis(halfPi(), glm::vec3(-1, 0, 0)); MeshPtr mesh = RectangleMeshFactory::createMesh(config); GeoPtr geo(new Geo(mesh, materialFactory.createMaterial(TextureRoles()))); RenderableNodePtr renderableNode = RenderableNode::createWithSingleGeo(geo); m_visSystem->addRenderableNode(renderableNode); } } int volumeTargetWidth = m_window->getWidth() / 2; int volumeTargetHeight = m_window->getHeight() / 2; TexturePtr offscreenTransparentObjectsTexture; // Create offscreen transparent objects target { ImageTextureConfig config = ImageTextureConfig::createDefault(); config.width = volumeTargetWidth; config.height = volumeTargetHeight; config.textureAddressMode = TextureAddressMode_Clamp; offscreenTransparentObjectsTexture.reset(new Texture(config)); { RenderTextureTargetConfig config; config.texture = offscreenTransparentObjectsTexture; config.attachment = FrameBufferAttachment_Color; RenderTextureTargetPtr target(new RenderTextureTarget(config)); { ViewportPtr viewport = target->addDefaultViewport(m_camera); viewport->setRenderQueueIdMask(RenderQueueId_OffscreenTransparentObjects); viewport->setBackgroundColor(glm::vec4(0,0,0,0)); } m_window->addRenderTarget(target); } } // Composite offscreen particles { TextureUnit textureUnit(offscreenTransparentObjectsTexture, "albedoSampler"); ShaderProgramPtr shader = ShaderProgram::createShaderProgram(ShaderProgramConfig("Shaders/Common/ScreenQuad.vert", "Shaders/Common/SimpleTextured.frag")); TechniquePtr technique(new Technique(shader)); technique->addTextureUnit(textureUnit); technique->setAlphaBlendingMode(AlphaBlendingMode_PreMultiplied); MaterialPtr material(new Material); material->setTechnique(technique); { RectangleConfig config = RectangleConfig::defaultWithSize(glm::vec2(2, 2)); MeshPtr mesh = RectangleMeshFactory::createMesh(config); GeoPtr geo(new Geo(mesh, material)); RenderableNodePtr renderableNode(new RenderableNode); renderableNode->addRenderable(geo); m_visSystem->addRenderableNode(renderableNode, RenderQueueId_CompositeOffscreenTransparentObjects); } } int tempBufferElementCount = m_textureConfig.width * m_textureConfig.height * m_textureConfig.depth; std::string fluidKernelsDir = "Kernels/Fluid"; TempBufferPoolPtr tempBufferPool(new TempBufferPool(*m_clSystem, tempBufferElementCount)); m_solver = createFluidSolver(*m_clSystem, getGlTexture(m_fluidStateTexture), tempBufferPool, fluidKernelsDir); FluidSolverParamsPtr params = m_solver->getParams(); params->temperatureBuoyancy = 15; params->densityWeight = 2.0; params->drag = 0.05; m_isosurfaceNormalCalculator = createIsosurfaceNormalCalculator(*m_clSystem, getGlTexture(m_normalTexture), m_solver, tempBufferPool, fluidKernelsDir); m_camera->setPosition(glm::vec3(2.2, 0.5, 0.7)); m_cameraController->rotate(1.2, -0.05); }
void setupScene() { LightPtr light(new Light); light->setDirection(glm::normalize(glm::vec3(2, -1, -1))); m_visSystem->addLight(light); m_camera->getProjection()->setNearClipDistance(0.05); m_camera->getProjection()->setFarClipDistance(1000); // Create heightmap TexturePtr texture; { ImageTextureConfig config = ImageTextureConfig::createDefault(); config.format = PixelFormat_R16; config.width = config.height = 512; boost::scoped_array<char16_t> buffer(new char16_t[config.width * config.height]); for (int y = 0; y < config.height; ++y) { for (int x = 0; x < config.width; ++x) { // interesting ripple pattern glm::vec2 r = glm::vec2((float)x / (float)config.width, (float)y / (float)config.height) * 2.0f - 1.0f; buffer[x + config.width * y] = 32768 + 32767 * std::sin(glm::length(r) * 30.0f); } } config.data = (unsigned char*)buffer.get(); texture.reset(new Texture(config)); texture->setTextureAddressMode(TextureAddressMode_Clamp); } // Create tessellated plane { ShaderProgramConfig config("c:\\projects\\Graphtane\\Shaders\\TessDisplacement\\TessDisplacement.vert", "c:\\projects\\Graphtane\\Shaders\\Common\\SimpleTextured.frag"); config.shaderFilepaths[ShaderType_TessellationControl] = "c:\\projects\\Graphtane\\Shaders\\TessDisplacement\\TessDisplacement.tctrl"; config.shaderFilepaths[ShaderType_TessellationEvaluation] = "c:\\projects\\Graphtane\\Shaders\\TessDisplacement\\TessDisplacement.teval"; ShaderProgramPtr shader = ShaderProgram::createShaderProgram(config); TechniquePtr technique(new Technique(shader)); technique->addTextureUnit(TextureUnit(texture, "heightSampler")); technique->addTextureUnit(TextureUnit(texture, "albedoSampler")); technique->addCustomShaderParameter(ShaderParameterPtr(new FloatShaderParameter("heightScale", 0.2f))); MaterialPtr material(new Material); material->setTechnique(technique); { RectangleConfig config = RectangleConfig::defaultWithSize(glm::vec2(10, 10)); config.quads = true; config.segmentCountX = 32; config.segmentCountY = 32; config.orientation = glm::angleAxis(halfPi(), glm::vec3(-1, 0, 0)); config.flipV = true; MeshPtr mesh = RectangleMeshFactory::createMesh(config); GeoPtr geo(new Geo(mesh, material)); RenderableNodePtr node = RenderableNode::createWithSingleGeo(geo); node->setWireframeModeEnabled(true); m_visSystem->addRenderableNode(node); } } m_camera->setPosition(glm::vec3(0, 4, 6)); m_cameraController->rotate(0, -0.3); }