7.01Mirrors

advertisement
95.4002
Comp 4002
Wilf LaLonde ©2009
Implementing “Mirrors”
• Many problems to resolve (we’ll consider each as
we encounter them).
Reflected
O1 is visible
objects
already behind
should not
appear in front
O1
O2
Comp 4002
Reflected O2
should not be visible
Wilf LaLonde ©2009
Example: The Back of the Mirror
Comp 4002
Wilf LaLonde ©2009
Example: The Front of the Mirror
Comp 4002
Wilf LaLonde ©2009
Implementing “Mirrors”
• Strategy: Draw all objects twice.
• Once normally.
• Once reflected and clipped to mirror region.
Use reflection
transformation R
O2 is not visible
O1
O2
Comp 4002
Warning: We Will Find Out That We
Have To Do It In The Other Order
Wilf LaLonde ©2009
Recall: W versus W-1
• Vehicle’s W maps from local to world.
• Vehicle’s W-1 maps back from world to local.
W
Mirror z-axis
points behind
mirror
W-1
Treat mirror like a vehicle…
Comp 4002
Wilf LaLonde ©2009
To “Reflect” an Object About The Mirror
• Replace the object’s local to world transformation
W by WR where
R = WM-1 Sz=-1 WM
WM is the mirror’s local to world transf..
Sz=-1is the transf.. that scales z by -1; i.e.,
scale by x = 1.0, y = 1.0, z = -1.0.
Explanation on next page.
Comp 4002
Wilf LaLonde ©2009
Explaining the “Reflect” Transformation
• Why replacing W by WR mirrors the object.
R = WM-1 Sz=-1 WM
W
WWM-1
WWM-1Sz=-1
WWM-1Sz=-1WM
object in world coordinates.
object in mirror’s local
coordinates
makes front go behind and
vice versa (flips sign of z).
back to world coordinates.
IF WM converts local to world,
THEN WM-1 converts world to local
Comp 4002
Wilf LaLonde ©2009
A Side-Effect of the “Reflect” Transformation
• A front-facing face becomes back facing (and
vice-versa).
2
3
1
1
4
4
2
Will this be a
front or back
face?
3
This must be counteracted.
Comp 4002
Wilf LaLonde ©2009
Solution: Flip Face Visibility
• Two possible solutions:
• Flip which faces must be culled using
glCullFace (GL_BACK); //or GL_FRONT
• Flip polygon vertex ordering; i.e., clockwise
to anti-clockwise (or vice versa)
glFrontFace (GL_CW); //or GL_CCW
Comp 4002
Wilf LaLonde ©2009
Reflected Back Objects Become Visible Too?
• Must eliminate those objects that WERE behind
(after the reflection, they are in front).
Before
behind
Comp 4002
After
in front (not wanted)
Wilf LaLonde ©2009
Solution: Clip Undesired Objects
• Approach:
• Use a clipping plane
Positive side draws
Negative side disappears
glEnable (GL_CLIP_PLANE0);
glClipPlane (GL_CLIP_PLANE0, plane);
• But be careful
PLANES BEHAVE LIKE LIGHTS. They are
transformed from local to camera
coordinates and then stay UNCHANGED
relative to the camera EVEN IF THE
CAMERA IS MOVED.
Comp 4002
Wilf LaLonde ©2009
Let’s Look At A Top View To See Where The
Plane is Relative To The Camera
Where is the plane
NORMAL relative to
the mirror?
negative z
a mirror is
like a vehicle
clipping plane
Mirror with
M and M-1
Camera with
C and C-1
Comp 4002
Where is the plane
relative to the
camera?
pointing toward camera
Wilf LaLonde ©2009
Clipping Plane Details
Plane = [Nx,Ny,Nz,-N.P0]
• Plane at mirror center P0=[0,0,0]
relative to mirror local coordinates
P = {0,0,1,0} ,
-N.P0=0
• Plane in world coordinates
P*M
• Plane as seen by camera
P*MC-1
Mirror z-axis
points behind
mirror
Mirror with
M and M-1
Camera with
C and C-1
Comp 4002
Wilf LaLonde ©2009
Tell Renderer To Clip Undesired Objects
• Solution: Specify plane in local coordinates
• Set up stack to contain MC-1 (M is mirror
transformation, C is camera).
glPushMatrix (); //Assuming C-1 is already on stack
glMultMatrix (mirrorLocalToWorld); //M
Gldouble localPlane = {0.0, 0.0, 1.0, 0.0};
//Normal is -ve z-axis (to keep what mirror sees).
glClipPlane (GL_CLIP_PLANE0, localPlane);
glPopMatrix (); //restore
Clipping plane points in direction that is KEPT..
Comp 4002
Wilf LaLonde ©2009
Another Problem: Won’t Z-Buffering Screw up?
• We need to render objects twice, once normally
and once reflected-and-with-back-objects-clipped.
• What about objects obscured by mirror?
Isn’t O3 closer
than reflected O1?
O2
O1
Reflected O1
Comp 4002
O3
Solution: Draw
INSIDE first and
OUTSIDE last…
Wilf LaLonde ©2009
Partial solution: I Call It Hardening The Mirror
• IN MIRROR ONLY, PASS1: Render all objects
reflected and back clipped (exclude mirror;
reflected O1 drawn but not O2 or O3).
Get just
.
• Render mirror but disable
coloring to harden it
O2
(z-buffer works; everything
in mirror get mirror’s
z-depth).
• PASS2: Render all
O1
O3
objects normally
(exclude mirror; O1, O2 and
O3 will be drawn properly
z-buffered). Get both
(O1+O2) +
Comp 4002
Wilf LaLonde ©2009
Rendering The Mirror
• Disable coloring but permit z-buffering.
glColorMask (0, 0, 0, 0); //Disable coloring; 0 for false.
• Render the mirror as if there were something to
draw.
… render mirror polygon ...
• Enable coloring once again.
glColorMask (1, 1, 1, 1); //Enable coloring; 1 for true.
Comp 4002
Wilf LaLonde ©2009
One Remaining Problem (Drawing only INSIDE)
• How do we draw ONLY inside the mirror. If not
done, reflected O2 will be visible!
O1
O2
Reflected O2 should not be visible
• Solution should handle arbitrary shaped mirrors.
Comp 4002
Wilf LaLonde ©2009
How to Clip To Mirror Interior
• Need to mask area by rendering the mirror first
without coloring or z-buffering (to handle arbitrary
mirror shapes).
• Then need to render reflected objects only inside
the masked area.
should not
be visible
O1
O2
Comp 4002
Wilf LaLonde ©2009
Using Stencil Functions/Operations
• The stencil buffer has available a fixed number of
bits per screen pixel; e.g., 8 bits.
• These bits can all be set to any integer value; e.g.
0 or 255.
• Some of these bits can be ignored with suitable
masks; e.g., 0x0F only looks at the right 4 bits.
Comp 4002
Wilf LaLonde ©2009
Using Stencil Functions/Operations
• How Stencil Buffer is Used (Done in Hardware)
• If stencil test passes, drawing is allowed.
• Stencil buffer changed according to operation.
• glStencilFunc (operation, data, mask)
QUERY: Do masked stencil buffer bits at point
being drawn satisfy “data operation bits”;
i.e., 5 < bits.
ORDER IS BACKWARD
Example: glStencilFunc (GL_LESS, 5, 0x0F);
• glStencilOp (failRule, passZfailRule, passZpassRule)
MODIFICATION: bits := rule (bits)
Example rule: GL_INCR, GL_ZERO.
Comp 4002
Wilf LaLonde ©2009
Sample Stencil Functions/Operations
• glStencilFunc (function, data, mask)
GL_NEVER, GL_ALWAYS, GL_LESS,
GL_LEQUAL, GL_EQUAL, GL_GEQUAL,
GL_GREATER, GL_NOTEQUAL
TEST: Do masked stencil bits satisfy “5 < stencil bits”
Example: glStencilFunc (GL_LESS, 5, 0x0F);
• glStencilOp (iffails, ifpassesButZfails, ifpassesAndZpasses)
GL_KEEP, GL_ZERO, GL_INCR, GL_DECR,
GL_REPLACE (by data), GL_INVERT
MODIFICATION: bits := rule (bits)Except for replace
Comp 4002
Wilf LaLonde ©2009
Sample Stencil Functions/Operations
• glStencilMask (mask)
Controls which bits are changed by glStencilOp.
Default is: all bits; i.e., mask = 0xffffffff
~0
equivalent to
0xffffffff
Not needed here but other applications might.
Comp 4002
Wilf LaLonde ©2009
Creating a Mask (4 steps: first 2)
• Enable the stencil buffer
glEnable (GL_STENCIL_TEST);
glClearStencil (0); //The fill value to use.
glClear (GL_STENCIL_BUFFER_BIT); //Now fill.
• Disable coloring and z-buffering
glColorMask (0, 0, 0, 0); //Disable coloring; 0 for false.
glDisable (GL_DEPTH_TEST);
The stencil buffer can perform masking.
Comp 4002
Wilf LaLonde ©2009
Creating a Mask (4 steps: last 2)
• Ensure that any drawn location replaces stencil
bits (currently 0) by 1.
glStencilFunc (GL_NEVER, 1 “variable”, ~0 “mask”);
//On anything, fail the test (so nothing draws).
glStencilOp (GL_REPLACE, GL_REPLACE,
GL_REPLACE); //ifF, ifPButZfails, ifPAndZpasse
//Always replace bits that fail by 1.
• Render mirror as if it were a normal object
… render mirror ... All mirror bits NOW 1.
Comp 4002
Wilf LaLonde ©2009
Rendering Inside the Mask
• Re-enable coloring and depth buffering.
glColorMask (1, 1, 1, 1); //Enable coloring; 1 for true.
glEnable (GL_DEPTH_TEST);
• Don’t allow stencil bits to change anymore.
glStencilFunc (GL_EQUAL, 1, ~0);
//On 1 pass the test and keep bits unchanged.
glStencilOp (GL_KEEP, GL_KEEP, GL_KEEP);
• Render reflected objects as discussed earlier
… render reflected objects …
Comp 4002
Wilf LaLonde ©2009
Implementing “Mirrors”
• So many steps (perhaps a summary is needed).
Reflected
O1 is visible
objects
already
behind
O1
O2
Comp 4002
Reflected
O2 is not visible
Wilf LaLonde ©2009
Implementing “Mirrors” (Summary)
• Create stencil mask from mirror face
Disable coloring and z-buffering.
Enable stencil buffering to set to 1 when drawing.
Set up mirror and render it to make mirror bits 1.
• In mirror, render reflected world (no mirror)
Enable coloring and z-buffering (stencil still enabled).
Set up stencil buffer to not change bits.
Set up reflection matrix and back clipping plane.
Flip front/back facing test.
Render whole world (mirror excluded).
Disable stencil buffering and clipping plane.
Restore front/back facing test.
Comp 4002
Wilf LaLonde ©2009
Implementing “Mirrors” (Summary)
• Render mirror to “harden it”
Disable coloring but NOT z-buffering.
Set up mirror and render it.
Alternative: use blending and draw mostly transparent
but slightly colored mirror.
• Outside mirror, render world (no mirror)
Enable coloring.
Render whole world (mirror excluded).
Comp 4002
Wilf LaLonde ©2009
95.4002
Comp 4002
Wilf LaLonde ©2009
Clipping Plane Approach
• Advantages: Not all cards support stencil buffers
(today, they probably all do…). Better reason:
stencil buffer also useful for shadows (conflict).
• Disadvantages:
• Can’t handle unusual shapes since number of
clipping planes is limited (currently, 6 is limit
and 1 is needed for clipping out back side
objects; so really only have 5).
• Recursively clipped mirrors can end up with
many more sides than 4… (must approximate
with 5). See next slide…
Comp 4002
Wilf LaLonde ©2009
Recursive Mirrors More Difficult
• When more than 5 planes are needed to
represent sub-mirrors, there are artifacts.
Imagine that PART of the yellow mirror is
visible inside mirror1. 6 planes needed to
bound it (one more than allowed)…
mirror2 seen inside mirror1
has 6 sides AFTER CLIPPING
mirror1
Comp 4002
Wilf LaLonde ©2009
95.4002
Comp 4002
Wilf LaLonde ©2009
Recursive Mirrors
• Main idea
• Use a counter incrementing as you go
deeper/decrementing as you come back.
First mirror at 1, inside ones at 2, inside
those at 3, … alternating front/back facing
order…
• For the stencil buffer approach, make mask
that matches counter.
• For planes approach, compute new planes
pushing old ones onto a stack (activate
only top INNERMOST ones).
Comp 4002
Wilf LaLonde ©2009
Interactions with Visibility
• Consider reflected frustum. visibility camera
position
mirror
Region 1
portal
virtual
(reflected)
camera
Region
4
Region
2
portal
camera
Comp 4002
Region 3
Wilf LaLonde ©2009
Visibility in Recursive Mirrors
• Should adjust the frustum by narrowing onto
mirror (need not be exact… JUST contain).
• Reflect the narrowed frustum.
• When drawing world in mirror, take reflected
frustum visibility into account.
and visibility camera position (a point in
front of mirror; not the camera position
nor the reflected camera position) if you
are computing region visibility.
Why: Because The Region You Are In Must Be
Where The Front of the Mirror is Located
Comp 4002
Wilf LaLonde ©2009
Recursive Mirrors: Reflections
• Camera must be reflected in such a way that
routines that make use of the camera for
drawing special effects do not know it was
done (e.g., coronas, lens flares, sun flares,
sprites, etc make use of camera position)
• When camera is asked for position, it
returns it’s virtual reflected position (not
visibility position).
• Lights on player get reflected; so they must be
recomputed…
Comp 4002
Wilf LaLonde ©2009
95.4002
Comp 4002
Wilf LaLonde ©2009
Much Simpler Than A Mirror
• Switch to the remote camera.
Display
Normal
camera
•
•
•
•
Remote
camera
Render world normally.
Copy what you drew onto a texture.
Switch back to the normal camera.
Draw the mirror’s “face” using the new texture
bits.
Comp 4002
Wilf LaLonde ©2009
Drawing into Restricted Area Of Color Buffer
glPushAttrib (GL_VIEWPORT_BIT); //draw
glEnable (GL_SCISSOR_TEST); //into
glScissor (0, 0, 64, 64); //top-left
glViewport (0, 0, 64, 64); //part
glClearColor (0.0f, 0.0f, 0.0f, 1.0f);
glClear (GL_COLOR_BUFFER_BIT |
GL_DEPTH_BUFFER_BIT);
glPushMatrix();
Setup new camera matrix, etc.
Draw whatever you want to draw.
glPopMatrix();
glDisable (GL_SCISSOR_TEST);
glPopAttrib();
Comp 4002
Wilf LaLonde ©2009
Moving Color Buffer To Your Texture
Select/activate a texture handle to
draw into. Then …
glCopyTexImage2D (GL_TEXTURE_2D, 0,
GL_RGB, 0, 0, 64, 64, 0);
Problem: It’s very slow to copy from a
back buffer to a texture.
Can draw directly into a second back buffer that
is simultaneously a texture
New cards support frame buffers (back buffers
built from textures that can be drawn with).
Comp 4002
Wilf LaLonde ©2009
Download