Bugzilla – Attachment 57 Details for
Bug 163
Extend Render-to-Texture functionality to include Render-to-Depth-Texture
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
Log In
[x]
|
Forgot Password
Login:
[x]
Framebuffer object implementation of the desired functionality.
RenderToTextureFBO.java (text/plain), 18.25 KB, created by
Sven Gothel
on 2006-02-07 14:27:00 CET
(
hide
)
Description:
Framebuffer object implementation of the desired functionality.
Filename:
MIME Type:
Creator:
Sven Gothel
Created:
2006-02-07 14:27:00 CET
Size:
18.25 KB
patch
obsolete
>package demos.renderToTexture; > >import java.awt.event.WindowAdapter; >import java.awt.event.WindowEvent; > >import javax.media.opengl.DebugGL; >import javax.media.opengl.GL; >import javax.media.opengl.GLAutoDrawable; >import javax.media.opengl.GLCanvas; >import javax.media.opengl.GLEventListener; >import javax.media.opengl.GLException; >import javax.swing.JFrame; > >import com.sun.opengl.utils.GLUT; > >public class RenderToTextureFBO implements GLEventListener >{ > private static GLUT glut = new GLUT(); > > public static void main(String[] args) > { > RenderToTextureFBO renderer = new RenderToTextureFBO(); > > GLCanvas canvas = new GLCanvas(); > > canvas.addGLEventListener(renderer); > > JFrame frame = new JFrame("Render To Texture Demo"); > > frame.addWindowListener(new WindowAdapter() > { > public void windowClosing(WindowEvent evt) > { > System.exit(0); > } > }); > > frame.getContentPane().add(canvas); > canvas.setSize(300, 300); > > frame.pack(); > frame.setVisible(true); > } > > private static float[] lightPosition = new float[] > { > 1, 0, 10, 1 > }; > > private FramebufferObjectRenderer framebufferRenderer; > > private boolean isFramebufferRendererCreated = false; > > public void init(GLAutoDrawable drawable) > { > drawable.setGL(new DebugGL(drawable.getGL())); > > GL gl = drawable.getGL(); > > gl.glEnable(GL.GL_DEPTH_TEST); > gl.glEnable(GL.GL_NORMALIZE); > gl.glEnable(GL.GL_LIGHTING); > > gl.glClearColor(0.5f, 0.5f, 0.5f, 0); > > // Place the camera > gl.glMatrixMode(GL.GL_PROJECTION); > gl.glLoadIdentity(); > gl.glFrustum(-2.0 / 10, 2.0 / 10, -2.0 / 10, 2.0 / 10, 1, 11); > > gl.glMatrixMode(GL.GL_MODELVIEW); > gl.glLoadIdentity(); > gl.glTranslated(0, 0, -10); > > // Configure the light > gl.glEnable(GL.GL_LIGHT0); > gl.glLightfv(GL.GL_LIGHT0, GL.GL_POSITION, lightPosition, 0); > > if (!isFramebufferRendererCreated) > { > framebufferRenderer = new FramebufferObjectRenderer(256); > framebufferRenderer.init(drawable); > isFramebufferRendererCreated = true; > } > } > > public void display(GLAutoDrawable drawable) > { > GL gl = drawable.getGL(); > > gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); > > framebufferRenderer.renderToFrameBuffer(drawable); > > // Draw the teapot casting a shadow on a repeated picture of the > // offscreen colour buffer. > // We'll use multi-texture unit 1 for the shadowing... > framebufferRenderer.prepareForShadowedRendering(drawable, > GL.GL_TEXTURE1); > // ... and multi-texture unit 0 for the picture > framebufferRenderer.prepareForColouredRendering(drawable, > GL.GL_TEXTURE0); > drawSquare(drawable); > framebufferRenderer.stopColouredRendering(drawable); > drawFloatingTeapot(drawable); > framebufferRenderer.stopShadowedRendering(drawable, GL.GL_TEXTURE1); > } > > private static void drawFloatingTeapot(GLAutoDrawable drawable) > { > GL gl = drawable.getGL(); > > gl.glPushAttrib(GL.GL_TRANSFORM_BIT); > { > gl.glMatrixMode(GL.GL_MODELVIEW); > gl.glPushMatrix(); > { > gl.glTranslated(0.5, 0, 3); > glut.glutSolidTeapot(0.25, true); > } > gl.glPopMatrix(); > } > gl.glPopAttrib(); > } > > private static void drawSquare(GLAutoDrawable drawable) > { > GL gl = drawable.getGL(); > > gl.glBegin(GL.GL_QUADS); > { > gl.glNormal3d(0, 0, 1); > gl.glMultiTexCoord2d(GL.GL_TEXTURE0, 0, 0); > gl.glVertex3d(-1, -1, 0); > gl.glMultiTexCoord2d(GL.GL_TEXTURE0, 2, 0); > gl.glVertex3d(1, -1, 0); > gl.glMultiTexCoord2d(GL.GL_TEXTURE0, 2, 2); > gl.glVertex3d(1, 1, 0); > gl.glMultiTexCoord2d(GL.GL_TEXTURE0, 0, 2); > gl.glVertex3d(-1, 1, 0); > } > gl.glEnd(); > } > > public void displayChanged(GLAutoDrawable drawable, > boolean modeChanged, > boolean deviceChanged) > { > // Nothing to do > } > > public void reshape(GLAutoDrawable drawable, > int x, > int y, > int width, > int height) > { > // Nothing to do > } > > private static class FramebufferObjectRenderer > { > private int textureDimension; > > private int frameBufferID; > private int colourTextureID; > private int depthTextureID; > > public FramebufferObjectRenderer(int textureDimension) > { > super(); > > this.textureDimension = textureDimension; > } > > public void init(GLAutoDrawable drawable) > { > GL gl = drawable.getGL(); > > // Allocate the framebuffer object > int[] result = new int[1]; > gl.glGenFramebuffersEXT(1, result, 0); > frameBufferID = result[0]; > gl.glBindFramebufferEXT(GL.GL_FRAMEBUFFER_EXT, frameBufferID); > > // Allocate the colour texture > gl.glGenTextures(1, result, 0); > colourTextureID = result[0]; > gl.glBindTexture(GL.GL_TEXTURE_2D, colourTextureID); > gl.glTexParameteri(GL.GL_TEXTURE_2D, > GL.GL_TEXTURE_MIN_FILTER, > GL.GL_NEAREST); > gl.glTexParameteri(GL.GL_TEXTURE_2D, > GL.GL_TEXTURE_MAG_FILTER, > GL.GL_NEAREST); > gl.glTexParameteri(GL.GL_TEXTURE_2D, > GL.GL_TEXTURE_WRAP_S, > GL.GL_CLAMP_TO_EDGE); > gl.glTexParameteri(GL.GL_TEXTURE_2D, > GL.GL_TEXTURE_WRAP_T, > GL.GL_CLAMP_TO_EDGE); > gl.glTexImage2D(GL.GL_TEXTURE_2D, > 0, > GL.GL_RGBA8, > textureDimension, > textureDimension, > 0, > GL.GL_RGBA, > GL.GL_UNSIGNED_BYTE, > null); > > // Allocate the depth texture > gl.glGenTextures(1, result, 0); > depthTextureID = result[0]; > gl.glBindTexture(GL.GL_TEXTURE_2D, depthTextureID); > gl.glTexParameteri(GL.GL_TEXTURE_2D, > GL.GL_TEXTURE_MIN_FILTER, > GL.GL_NEAREST); > gl.glTexParameteri(GL.GL_TEXTURE_2D, > GL.GL_TEXTURE_MAG_FILTER, > GL.GL_NEAREST); > gl.glTexParameteri(GL.GL_TEXTURE_2D, > GL.GL_TEXTURE_WRAP_S, > GL.GL_CLAMP_TO_EDGE); > gl.glTexParameteri(GL.GL_TEXTURE_2D, > GL.GL_TEXTURE_WRAP_T, > GL.GL_CLAMP_TO_EDGE); > gl.glGetIntegerv(GL.GL_DEPTH_BITS, result, 0); > int depthFormat; > switch (result[0]) > { > case 16: > depthFormat = GL.GL_DEPTH_COMPONENT16; > break; > case 24: > depthFormat = GL.GL_DEPTH_COMPONENT24; > break; > case 32: > depthFormat = GL.GL_DEPTH_COMPONENT32; > break; > default: > throw new GLException("Unexpected number of depth bits: " > + result[0]); > } > gl.glTexImage2D(GL.GL_TEXTURE_2D, > 0, > depthFormat, > textureDimension, > textureDimension, > 0, > GL.GL_DEPTH_COMPONENT, > GL.GL_UNSIGNED_INT, > null); > > // Attach the textures to the framebuffer > gl.glFramebufferTexture2DEXT(GL.GL_FRAMEBUFFER_EXT, > GL.GL_COLOR_ATTACHMENT0_EXT, > GL.GL_TEXTURE_2D, > colourTextureID, > 0); > gl.glFramebufferTexture2DEXT(GL.GL_FRAMEBUFFER_EXT, > GL.GL_DEPTH_ATTACHMENT_EXT, > GL.GL_TEXTURE_2D, > depthTextureID, > 0); > > gl.glBindFramebufferEXT(GL.GL_FRAMEBUFFER_EXT, 0); > } > > private int counter = 0; > > public void renderToFrameBuffer(GLAutoDrawable drawable) > { > GL gl = drawable.getGL(); > > gl.glPushAttrib(GL.GL_TRANSFORM_BIT | GL.GL_ENABLE_BIT > | GL.GL_COLOR_BUFFER_BIT); > > gl.glBindFramebufferEXT(GL.GL_FRAMEBUFFER_EXT, frameBufferID); > > gl.glEnable(GL.GL_DEPTH_TEST); > gl.glEnable(GL.GL_NORMALIZE); > gl.glDisable(GL.GL_LIGHTING); > > gl.glClearColor(0, 0, 1, 0); > > // Place the offscreen camera at the light position > gl.glMatrixMode(GL.GL_PROJECTION); > gl.glPushMatrix(); > gl.glLoadIdentity(); > applyLightFrustum(gl); > > gl.glMatrixMode(GL.GL_MODELVIEW); > gl.glPushMatrix(); > gl.glLoadIdentity(); > applyLightTransformation(gl); > > gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); > > // Draw the teapot as a red silhouette > if (counter++ % 2 == 0) > { > gl.glColor3d(1, 0, 0); > } > else > { > gl.glColor3d(0, 1, 0); > } > drawFloatingTeapot(drawable); > // Don't draw the square (because we don't want it to cast a shadow) > > // Unbind the framebuffer > gl.glBindFramebufferEXT(GL.GL_FRAMEBUFFER_EXT, 0); > > gl.glMatrixMode(GL.GL_PROJECTION); > gl.glPopMatrix(); > gl.glMatrixMode(GL.GL_MODELVIEW); > gl.glPopMatrix(); > gl.glPopAttrib(); > } > > private void applyLightFrustum(GL gl) > { > // Set up the viewing frustum so that the light only sees the > // volume between itself and the unit X-Y square at the origin > // (because that is the only volume in which we will be casting > // shadows). > gl.glFrustum(-2.0 / 10, 0, -1.0 / 10, 1.0 / 10, 1, 10); > } > > private void applyLightTransformation(GL gl) > { > gl.glTranslated(-lightPosition[0], > -lightPosition[1], > -lightPosition[2]); > } > > public void prepareForShadowedRendering(GLAutoDrawable targetDrawable, > int textureUnitID) > { > GL gl = targetDrawable.getGL(); > > // The state modified by this preparation will be restored by a call > // to finishShadowedRendering() > gl.glPushAttrib(GL.GL_TEXTURE_BIT); > > gl.glActiveTexture(textureUnitID); > gl.glBindTexture(GL.GL_TEXTURE_2D, depthTextureID); > gl.glPushAttrib(GL.GL_TEXTURE_BIT); > // Generate texture coordinates - an object-linear texture > // generation that sets the texture coordinates to be the > // object-space vertex coordinates (we will use the texture matrix > // to transform from object-space to light-space) > gl.glEnable(GL.GL_TEXTURE_GEN_S); > gl.glEnable(GL.GL_TEXTURE_GEN_T); > gl.glEnable(GL.GL_TEXTURE_GEN_R); > gl.glEnable(GL.GL_TEXTURE_GEN_Q); > gl.glTexGeni(GL.GL_S, GL.GL_TEXTURE_GEN_MODE, GL.GL_OBJECT_LINEAR); > gl.glTexGeni(GL.GL_T, GL.GL_TEXTURE_GEN_MODE, GL.GL_OBJECT_LINEAR); > gl.glTexGeni(GL.GL_R, GL.GL_TEXTURE_GEN_MODE, GL.GL_OBJECT_LINEAR); > gl.glTexGeni(GL.GL_Q, GL.GL_TEXTURE_GEN_MODE, GL.GL_OBJECT_LINEAR); > gl.glPushAttrib(GL.GL_TRANSFORM_BIT); > { > gl.glMatrixMode(GL.GL_MODELVIEW); > gl.glPushMatrix(); > { > gl.glLoadIdentity(); > float[] objectPlane = new float[] > { > 1, 0, 0, 0 > }; > gl.glTexGenfv(GL.GL_S, GL.GL_OBJECT_PLANE, objectPlane, 0); > objectPlane[0] = 0; > objectPlane[1] = 1; > gl.glTexGenfv(GL.GL_T, GL.GL_OBJECT_PLANE, objectPlane, 0); > objectPlane[1] = 0; > objectPlane[2] = 1; > gl.glTexGenfv(GL.GL_R, GL.GL_OBJECT_PLANE, objectPlane, 0); > objectPlane[2] = 0; > objectPlane[3] = 1; > gl.glTexGenfv(GL.GL_Q, GL.GL_OBJECT_PLANE, objectPlane, 0); > } > gl.glPopMatrix(); > > // Modify texture matrix - the texture matrix will transform > // from object-space coordinates to light-space (i.e. the same > // transformation that was applied when rendering the shadow > // texture) > gl.glMatrixMode(GL.GL_TEXTURE); > // The texture matrix will be restored by > // stopShadowedRendering() > gl.glPushMatrix(); > gl.glLoadIdentity(); > // Go from the unit square to the upper quadrant (because > // texture coords run from 0 to 1) > gl.glScalef(0.5f, 0.5f, 0.5f); > gl.glTranslatef(1, 1, 1); > // Apply the transformation to light-space > applyLightFrustum(gl); > applyLightTransformation(gl); > } > gl.glPopAttrib(); > > // Set the texture up to be used as a depth comparison > int textureTarget = GL.GL_TEXTURE_2D; > gl.glEnable(textureTarget); > gl.glTexEnvi(GL.GL_TEXTURE_ENV, > GL.GL_TEXTURE_ENV_MODE, > GL.GL_MODULATE); > gl.glTexParameteri(textureTarget, > GL.GL_TEXTURE_MIN_FILTER, > GL.GL_LINEAR); > gl.glTexParameteri(textureTarget, > GL.GL_TEXTURE_MAG_FILTER, > GL.GL_LINEAR); > gl.glTexParameteri(textureTarget, > GL.GL_TEXTURE_WRAP_S, > GL.GL_CLAMP_TO_EDGE); > gl.glTexParameteri(textureTarget, > GL.GL_TEXTURE_WRAP_T, > GL.GL_CLAMP_TO_EDGE); > gl.glTexParameteri(textureTarget, > GL.GL_TEXTURE_COMPARE_MODE, > GL.GL_COMPARE_R_TO_TEXTURE); > gl.glTexParameteri(textureTarget, > GL.GL_TEXTURE_COMPARE_FUNC, > GL.GL_LEQUAL); > gl.glTexParameteri(textureTarget, > GL.GL_DEPTH_TEXTURE_MODE, > GL.GL_LUMINANCE); > } > > public void stopShadowedRendering(GLAutoDrawable targetDrawable, > int textureUnitID) > { > GL gl = targetDrawable.getGL(); > gl.glActiveTexture(textureUnitID); > gl.glPushAttrib(GL.GL_TRANSFORM_BIT); > { > gl.glMatrixMode(GL.GL_TEXTURE); > gl.glPopMatrix(); > } > gl.glPopAttrib(); > > // Restore the texture attributes for the textureUnith texture > gl.glPopAttrib(); > > // Unbind the depth texture > gl.glBindTexture(GL.GL_TEXTURE_2D, 0); > > // Restore the active texture > gl.glPopAttrib(); > } > > public void prepareForColouredRendering(GLAutoDrawable targetDrawable, > int textureUnitID) > { > GL gl = targetDrawable.getGL(); > > // The state modified by this preparation will be restored by a call > // to finishShadowedRendering() > gl.glPushAttrib(GL.GL_TEXTURE_BIT); > > gl.glActiveTexture(textureUnitID); > gl.glBindTexture(GL.GL_TEXTURE_2D, colourTextureID); > > // Set the texture up to be used for painting a surface > int textureTarget = GL.GL_TEXTURE_2D; > gl.glEnable(textureTarget); > gl.glTexEnvi(GL.GL_TEXTURE_ENV, > GL.GL_TEXTURE_ENV_MODE, > GL.GL_MODULATE); > gl.glTexParameteri(textureTarget, > GL.GL_TEXTURE_MIN_FILTER, > GL.GL_LINEAR); > gl.glTexParameteri(textureTarget, > GL.GL_TEXTURE_MAG_FILTER, > GL.GL_LINEAR); > gl.glTexParameteri(textureTarget, > GL.GL_TEXTURE_WRAP_S, > GL.GL_REPEAT); > gl.glTexParameteri(textureTarget, > GL.GL_TEXTURE_WRAP_T, > GL.GL_REPEAT); > } > > public void stopColouredRendering(GLAutoDrawable targetDrawable) > { > GL gl = targetDrawable.getGL(); > > gl.glBindTexture(GL.GL_TEXTURE_2D, 0); > > // Restore the active texture > gl.glPopAttrib(); > } > > } > >}
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Actions:
View
Attachments on
bug 163
: 57