Rendering a *stuffed* translucent cube in OpenGL
Dunno how to express my confusion but here is how it goes in my mind: A cube with transparent(or translucent) sides is not a solid (filled, stuffed) cube. It's more like an empty glass cube. Now what I 开发者_开发百科want is a solid, stuffed glass cube. Just like a crystal ball but in cube shape. Things behind them appear differently.How do I tell OpenGL that my geometry is stuffed ? How do i achieve the effect of looking at some scene from behind a very thick layer of , say, glass ?
The proper term is "solid". And your problem is a nontrivial one and there's no easy, in-situ way to solve it. The best thing for a simple fake refraction is rendering a cubemap with the origin at the objects bounding volume's center, and use that cubemap in with the objects normals scaled as texture coordinates. If you want it to look more accurate you need to know about light-matter interactions. The only perfectly accurate way to recreate the effects of light-matter interaction is by raytracing (if differential ray elements are used, one may call this photon mapping).
Using OpenGL one can get coarse approximations if the results are to be rendered in realtime.
Rendering translucent solids needs to somehow resemble the optical effects of
- refraction
- reflection
- absorbtion - as the light passes through the solid it will be filtered out
- flourescence – for example if sunlight, or just violet light passes through a piece of uranium glass, the ultraviolet part will cause green flourescence. The blue part of the light gets absorbed, but you get a green part emitting from the glass.
- scattering - small particles in the glass, impurities, small air bubbles, etc. scatter the light out. This is what fog does.
In most cases it's sufficient to fake refraction and absorbtion. Glass can be rendered that way quite effectively. There are 3 important variables to rendering a refractive, absorbtive solid:
- the angle of entry of the incoming ray (this implicitly determines the ray within the solid)
- the thinkness of the material
- the angle of exit of the ray
There are several ways to obtain those:
- You can precompute them, store them as a set of spherical harmonics coefficients used as an additional sampler input in a shader.
- You can use depth peeling to slice the object in question into layers of surfaces. Odd numbered layers are entry, even numbered are exit. You go from near to far. Near surface hit refracts the ray, you follow that ray until it hits the exit surface and refract it there again. The length of the ray is used as parameter into, e.g. a Beer-Lambert law absorbtion equation.
So how do you implement this in OpenGL. I'm afraid an answer on Stackoverflow will not be able to cover it, unless it grew into a fully fledged paper. Thus I refer you to Chapter 19 of GPU Gems 2, which covers the basics http://http.developer.nvidia.com/GPUGems2/gpugems2_chapter19.html
You are trying to achieve a refraction effect. This isn't a trivial problem in the general case, and there is a substantial body of techniques available in books and online.
For a cube, specifically, you can compute the refraction analytically and apply a suitable transform while rendering each facet (you must subdivide each front-facing facet according to the one or more rear-facing facets that project through it; you then have to figure out how the scene behind the cube will refract through each subdivision). This is a poor explanation, but a proper explanation would be quite involved, I'm afraid. Sorry I can't help more, but I hope this is enough to set you on the right track.
A simple way to achieve what you want would be to render the cube's front side as transparent faces with an alpha value getting the bigger the thicker the cube is. This will only work acceptably for pixels the vector from the viewer to which passes through the front side and the front side's opposite side of the cube. If the pixel is seen through adjacent cube sides, you would need to do some shader math to compute the proper opacity.
You could try drawing many transparent squares between the top/bottom, left/right, and front/back faces. This way, thing obscured by more of the cube would be behind more transparent layers and thus be less visible.
精彩评论