Commit 738b571e authored by hybrid's avatar hybrid

Change screenshot function to allow reading from other render targets as well....

Change screenshot function to allow reading from other render targets as well. This is not yet fully implemented, just an API preparation for further features. Most drivers don't support the extra targets anyway. But it will be also possible to ask for different color formats, which should be possible on all drivers. Passing ECF_UNKNOWN will choose an optimal color format without the need of pixel value adaptions.

git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@3744 dfc29bdd-3216-0410-991c-e03cc46cb475
parent 73414257
...@@ -1357,7 +1357,7 @@ namespace video ...@@ -1357,7 +1357,7 @@ namespace video
//! Make a screenshot of the last rendered frame. //! Make a screenshot of the last rendered frame.
/** \return An image created from the last rendered frame. */ /** \return An image created from the last rendered frame. */
virtual IImage* createScreenShot() =0; virtual IImage* createScreenShot(video::ECOLOR_FORMAT format=video::ECF_UNKNOWN, video::E_RENDER_TARGET target=video::ERT_FRAME_BUFFER) =0;
//! Check if the image is already loaded. //! Check if the image is already loaded.
/** Works similar to getTexture(), but does not load the texture /** Works similar to getTexture(), but does not load the texture
......
...@@ -2238,7 +2238,7 @@ void CD3D8Driver::clearZBuffer() ...@@ -2238,7 +2238,7 @@ void CD3D8Driver::clearZBuffer()
//! Returns an image created from the last rendered frame. //! Returns an image created from the last rendered frame.
IImage* CD3D8Driver::createScreenShot() IImage* CD3D8Driver::createScreenShot(video::ECOLOR_FORMAT format, video::E_RENDER_TARGET target)
{ {
#if defined( _IRR_XBOX_PLATFORM_) #if defined( _IRR_XBOX_PLATFORM_)
return 0; return 0;
......
...@@ -199,7 +199,7 @@ namespace video ...@@ -199,7 +199,7 @@ namespace video
virtual void clearZBuffer(); virtual void clearZBuffer();
//! Returns an image created from the last rendered frame. //! Returns an image created from the last rendered frame.
virtual IImage* createScreenShot(); virtual IImage* createScreenShot(video::ECOLOR_FORMAT format=video::ECF_UNKNOWN, video::E_RENDER_TARGET target=video::ERT_FRAME_BUFFER);
//! Set/unset a clipping plane. //! Set/unset a clipping plane.
//! There are at least 6 clipping planes available for the user to set at will. //! There are at least 6 clipping planes available for the user to set at will.
......
...@@ -3160,7 +3160,7 @@ void CD3D9Driver::clearZBuffer() ...@@ -3160,7 +3160,7 @@ void CD3D9Driver::clearZBuffer()
//! Returns an image created from the last rendered frame. //! Returns an image created from the last rendered frame.
IImage* CD3D9Driver::createScreenShot() IImage* CD3D9Driver::createScreenShot(video::ECOLOR_FORMAT format, video::E_RENDER_TARGET target)
{ {
HRESULT hr; HRESULT hr;
......
...@@ -278,7 +278,7 @@ namespace video ...@@ -278,7 +278,7 @@ namespace video
virtual void clearZBuffer(); virtual void clearZBuffer();
//! Returns an image created from the last rendered frame. //! Returns an image created from the last rendered frame.
virtual IImage* createScreenShot(); virtual IImage* createScreenShot(video::ECOLOR_FORMAT format=video::ECF_UNKNOWN, video::E_RENDER_TARGET target=video::ERT_FRAME_BUFFER);
//! Set/unset a clipping plane. //! Set/unset a clipping plane.
virtual bool setClipPlane(u32 index, const core::plane3df& plane, bool enable=false); virtual bool setClipPlane(u32 index, const core::plane3df& plane, bool enable=false);
......
...@@ -2306,7 +2306,7 @@ scene::IMeshManipulator* CNullDriver::getMeshManipulator() ...@@ -2306,7 +2306,7 @@ scene::IMeshManipulator* CNullDriver::getMeshManipulator()
//! Returns an image created from the last rendered frame. //! Returns an image created from the last rendered frame.
IImage* CNullDriver::createScreenShot() IImage* CNullDriver::createScreenShot(video::ECOLOR_FORMAT format, video::E_RENDER_TARGET target)
{ {
return 0; return 0;
} }
......
...@@ -580,7 +580,7 @@ namespace video ...@@ -580,7 +580,7 @@ namespace video
virtual void clearZBuffer(); virtual void clearZBuffer();
//! Returns an image created from the last rendered frame. //! Returns an image created from the last rendered frame.
virtual IImage* createScreenShot(); virtual IImage* createScreenShot(video::ECOLOR_FORMAT format=video::ECF_UNKNOWN, video::E_RENDER_TARGET target=video::ERT_FRAME_BUFFER);
//! Writes the provided image to disk file //! Writes the provided image to disk file
virtual bool writeImageToFile(IImage* image, const io::path& filename, u32 param = 0); virtual bool writeImageToFile(IImage* image, const io::path& filename, u32 param = 0);
......
...@@ -3528,7 +3528,7 @@ void COpenGLDriver::drawStencilShadowVolume(const core::vector3df* triangles, s3 ...@@ -3528,7 +3528,7 @@ void COpenGLDriver::drawStencilShadowVolume(const core::vector3df* triangles, s3
glVertexPointer(3,GL_FLOAT,sizeof(core::vector3df),&triangles[0]); glVertexPointer(3,GL_FLOAT,sizeof(core::vector3df),&triangles[0]);
glStencilMask(~0); glStencilMask(~0);
glStencilFunc(GL_ALWAYS, 0, ~0); glStencilFunc(GL_ALWAYS, 0, ~0);
glPolygonOffset(1.f,1.f); glPolygonOffset(-1.f,-1.f);
glEnable(GL_POLYGON_OFFSET_FILL); glEnable(GL_POLYGON_OFFSET_FILL);
GLenum incr = GL_INCR; GLenum incr = GL_INCR;
...@@ -4259,16 +4259,10 @@ void COpenGLDriver::clearZBuffer() ...@@ -4259,16 +4259,10 @@ void COpenGLDriver::clearZBuffer()
//! Returns an image created from the last rendered frame. //! Returns an image created from the last rendered frame.
IImage* COpenGLDriver::createScreenShot() IImage* COpenGLDriver::createScreenShot(video::ECOLOR_FORMAT format, video::E_RENDER_TARGET target)
{ {
IImage* newImage = new CImage(ECF_R8G8B8, ScreenSize); if (target==video::ERT_MULTI_RENDER_TEXTURES || target==video::ERT_RENDER_TEXTURE || target==video::ERT_STEREO_BOTH_BUFFERS)
u8* pixels = static_cast<u8*>(newImage->lock());
if (!pixels)
{
newImage->drop();
return 0; return 0;
}
// allows to read pixels in top-to-bottom order // allows to read pixels in top-to-bottom order
#ifdef GL_MESA_pack_invert #ifdef GL_MESA_pack_invert
...@@ -4276,16 +4270,42 @@ IImage* COpenGLDriver::createScreenShot() ...@@ -4276,16 +4270,42 @@ IImage* COpenGLDriver::createScreenShot()
glPixelStorei(GL_PACK_INVERT_MESA, GL_TRUE); glPixelStorei(GL_PACK_INVERT_MESA, GL_TRUE);
#endif #endif
if (format==video::ECF_UNKNOWN)
format=video::ECF_A8R8G8B8;
IImage* newImage = new CImage(format, ScreenSize);
u8* pixels = static_cast<u8*>(newImage->lock());
if (pixels)
{
GLenum tgt=GL_FRONT;
switch (target)
{
case video::ERT_FRAME_BUFFER:
break;
case video::ERT_STEREO_LEFT_BUFFER:
tgt=GL_FRONT_LEFT;
break;
case video::ERT_STEREO_RIGHT_BUFFER:
tgt=GL_FRONT_RIGHT;
break;
default:
tgt=GL_AUX0+(target-video::ERT_AUX_BUFFER0);
break;
}
GLenum fmt = (format==video::ECF_A8R8G8B8 || format==video::ECF_A1R5G5B5)?GL_RGBA:GL_RGB;
// We want to read the front buffer to get the latest render finished. // We want to read the front buffer to get the latest render finished.
glReadBuffer(GL_FRONT); glReadBuffer(tgt);
glReadPixels(0, 0, ScreenSize.Width, ScreenSize.Height, GL_RGB, GL_UNSIGNED_BYTE, pixels); glReadPixels(0, 0, ScreenSize.Width, ScreenSize.Height, fmt, GL_UNSIGNED_BYTE, pixels);
glReadBuffer(GL_BACK); glReadBuffer(GL_BACK);
}
#ifdef GL_MESA_pack_invert #ifdef GL_MESA_pack_invert
if (FeatureAvailable[IRR_MESA_pack_invert]) if (FeatureAvailable[IRR_MESA_pack_invert])
glPixelStorei(GL_PACK_INVERT_MESA, GL_FALSE); glPixelStorei(GL_PACK_INVERT_MESA, GL_FALSE);
else else
#endif #endif
if (pixels)
{ {
// opengl images are horizontally flipped, so we have to fix that here. // opengl images are horizontally flipped, so we have to fix that here.
const s32 pitch=newImage->getPitch(); const s32 pitch=newImage->getPitch();
...@@ -4294,7 +4314,15 @@ IImage* COpenGLDriver::createScreenShot() ...@@ -4294,7 +4314,15 @@ IImage* COpenGLDriver::createScreenShot()
for (u32 i=0; i < ScreenSize.Height; i += 2) for (u32 i=0; i < ScreenSize.Height; i += 2)
{ {
memcpy(tmpBuffer, pixels, pitch); memcpy(tmpBuffer, pixels, pitch);
// for (u32 j=0; j<pitch; ++j)
// {
// pixels[j]=(u8)(p2[j]*255.f);
// }
memcpy(pixels, p2, pitch); memcpy(pixels, p2, pitch);
// for (u32 j=0; j<pitch; ++j)
// {
// p2[j]=(u8)(tmpBuffer[j]*255.f);
// }
memcpy(p2, tmpBuffer, pitch); memcpy(p2, tmpBuffer, pitch);
pixels += pitch; pixels += pitch;
p2 -= pitch; p2 -= pitch;
...@@ -4304,7 +4332,7 @@ IImage* COpenGLDriver::createScreenShot() ...@@ -4304,7 +4332,7 @@ IImage* COpenGLDriver::createScreenShot()
newImage->unlock(); newImage->unlock();
if (testGLError()) if (testGLError() || !pixels)
{ {
newImage->drop(); newImage->drop();
return 0; return 0;
......
...@@ -345,7 +345,7 @@ namespace video ...@@ -345,7 +345,7 @@ namespace video
virtual void clearZBuffer(); virtual void clearZBuffer();
//! Returns an image created from the last rendered frame. //! Returns an image created from the last rendered frame.
virtual IImage* createScreenShot(); virtual IImage* createScreenShot(video::ECOLOR_FORMAT format=video::ECF_UNKNOWN, video::E_RENDER_TARGET target=video::ERT_FRAME_BUFFER);
//! checks if an OpenGL error has happend and prints it //! checks if an OpenGL error has happend and prints it
//! for performance reasons only available in debug mode //! for performance reasons only available in debug mode
......
...@@ -921,7 +921,7 @@ void CSoftwareDriver::clearZBuffer() ...@@ -921,7 +921,7 @@ void CSoftwareDriver::clearZBuffer()
//! Returns an image created from the last rendered frame. //! Returns an image created from the last rendered frame.
IImage* CSoftwareDriver::createScreenShot() IImage* CSoftwareDriver::createScreenShot(video::ECOLOR_FORMAT format, video::E_RENDER_TARGET target)
{ {
if (BackBuffer) if (BackBuffer)
{ {
......
...@@ -111,7 +111,7 @@ namespace video ...@@ -111,7 +111,7 @@ namespace video
virtual void clearZBuffer(); virtual void clearZBuffer();
//! Returns an image created from the last rendered frame. //! Returns an image created from the last rendered frame.
virtual IImage* createScreenShot(); virtual IImage* createScreenShot(video::ECOLOR_FORMAT format=video::ECF_UNKNOWN, video::E_RENDER_TARGET target=video::ERT_FRAME_BUFFER);
//! Returns the maximum amount of primitives (mostly vertices) which //! Returns the maximum amount of primitives (mostly vertices) which
//! the device is able to render with one drawIndexedTriangleList //! the device is able to render with one drawIndexedTriangleList
......
...@@ -2584,7 +2584,7 @@ void CBurningVideoDriver::clearZBuffer() ...@@ -2584,7 +2584,7 @@ void CBurningVideoDriver::clearZBuffer()
//! Returns an image created from the last rendered frame. //! Returns an image created from the last rendered frame.
IImage* CBurningVideoDriver::createScreenShot() IImage* CBurningVideoDriver::createScreenShot(video::ECOLOR_FORMAT format, video::E_RENDER_TARGET target)
{ {
if (BackBuffer) if (BackBuffer)
{ {
......
...@@ -136,7 +136,7 @@ namespace video ...@@ -136,7 +136,7 @@ namespace video
virtual void clearZBuffer(); virtual void clearZBuffer();
//! Returns an image created from the last rendered frame. //! Returns an image created from the last rendered frame.
virtual IImage* createScreenShot(); virtual IImage* createScreenShot(video::ECOLOR_FORMAT format=video::ECF_UNKNOWN, video::E_RENDER_TARGET target=video::ERT_FRAME_BUFFER);
//! Returns the maximum amount of primitives (mostly vertices) which //! Returns the maximum amount of primitives (mostly vertices) which
//! the device is able to render with one drawIndexedTriangleList //! the device is able to render with one drawIndexedTriangleList
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment