Portals cannot be generated on the fly as the definition of a portal engine needs a convex “room” with 1 or several portals leading to that room, and finding those combinations is hard and its relatively easy to let the artists specify a few polygons. You can always use the room’s bound as the convex object and display it once one of the room’s portals is in view.
BSPs cannot be generated on the fly as to get maximum usage from them, they need to be balanced and finding that balanced tree takes long hours or even days if you want to push it.
Bounding culling is something of an interest to me. Its simple to create, but difficult to master. The basic idea is to encompass a geometry with a convex hull that can be a sphere, world axis aligned bounding box (AABB), object oriented bounding box (OOBB), or a k-dop. I have listed those in order of increating “tightness” around the object, however, the bad side is they are also listed in order of how slow they are to calculate (sphere being the fastest, k-dop being the slowest). The art of frustum culling is getting the right balance to achieve maximum FPS because you dont want to be spending too much time in the CPU when it would just be faster to render the dam thing.
The way I do frustum culling is rather simple. I initialise the OOBB to contain the vertices in an axis aligned manner, then with every update, rotate the OOBB to comform with the rotation of the geometry its encompassing. Then, before rendering, you traverse the tree, check every bound to the frustum and see which one is outside and which ones are inside and only draw the inside ones. Thats the simple jist of it, but its also the slowest method you can do 
To make frustum culling fly, I use 3 optimisations, i’l list them in order of importance:
Temporal plane coherency
This idea comes from the simple fact that if the bound failed on a plane, then there is a high probability it will fail on the same plane next frame. So simply store the last plane the bound has and check against that first, if that fails, you can immediately say the bound (and hence the geometry) is out of view. If that fails, then you have to find out in which way does it fail? Does it fail completely? meaning are all 8 vertices of the OOBB inside the plane? Or are some of them inside and some are outside (Intersecting the plane)? This leads me on to the next optimisation
Plane bitmasking
If you have a tree, each node should have a bound that encompasses the bound of its children, then simply checking against that 1 bound will eliminate an entire heirarchy (alot of geometry in some cases for a simple calculation). If the node’s bound is intersecting a plane, you can safely say to its children only check against the plane that the node is intersecting. This again saves on the number of plane checking that is required and can save 40 dot products (8 vertices * 5 planes). But if the node is not intersecting, i.e. failing or passing, then this optimisation is useless, which leads me to the next optimisations, when a bound is inside.
Octant test
You divide the frustum into 8 parts, 4 near the camera, 4 far from the camera. This produces a centre point in the frustum which can be calculated using:
Vector3f centre = new Vector3f();
centre.x = camera.location.x + (camera.getLeftPlaneCoefficient() + camera.getRightPlaneCoefficient())/2;
centre.y = camera.location.y + (camera.getUpPlaneCoefficient() + getDownPlaneCoefficient())/2;
centre.z = camera.location.z + (camera.getNearPlaneCoefficient() + getFarPlaneCoefficient())/2;
Then check the bound’s location against the centre point to find out in which octant the bound is in, this will reduce the number of planes to check from 6 to 3, saving you 24 dot produces (8 vertices * 3 planes).
Those three work beautifully with any type of bound, you just have to pick one that does it for you. I chose OOBB’s because they are tight fitting around the object, yet are easy to calculate. But if you use AABB, there is another optimisation you can use, and thats the n-p vertex test:
n-p vertex test
If the box is aligned to the world axis, that means for each bound check you only need to test 2 vertices, the n vertex and the p vertex, because the n vertex is the closest to the plane, the p vertex is the furtherest from the plane, and from those 2 vertices, you can determine if the bound is inside, outside or intersecting. Just another optimisation in the hat…
There are alot more optimisations, some can even be hardware accelerated (such as occlusion queries, which you will need for portal culling), but i’l leave those details to you 
DP