You can grant access to views and stored procedures without granting direct access to the underlying tables (see https://stackoverflow.com/questions/4134740/grant-select-permission-on-a-view-but-not-on-underlying-objects amongst similar questions for some detail). This will certainly work for reading from views, though I'm not sure about writing to them (it would be difficult for it to know if they should be writing specific things, so you may have to manage this with INSTEAD OF triggers instead of it being done for you).
With the permissions correctly set the users can only access what the procedures/views expose to them, so you can control their access by giving different users different procs/views that each have different filtering clauses. You can even give the different views/procs the same name if you give each user (or class of user) its own schema, so you don't need different code/configuration elsewhere for User1, User2, ..., UserN as they can all run SELECT <something> FROM FilteredView and get results (User1 might see results from the view u1.FilterdeView, User2 and User3 might have reports as their default schema so they get results from reports.FilteredView instead, and so forth).
My knowledge of this is MSSQL specific, but I'm pretty sure other major DMBSs (such as Oracle or postgres) have very similar access granularity controls.