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
master
hybrid 2011-05-24 07:15:26 +00:00
parent 73414257b5
commit 738b571e40
13 changed files with 54 additions and 26 deletions

View File

@ -1357,7 +1357,7 @@ namespace video
//! Make a screenshot of 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.
/** Works similar to getTexture(), but does not load the texture

View File

@ -2238,7 +2238,7 @@ void CD3D8Driver::clearZBuffer()
//! 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_)
return 0;

View File

@ -199,7 +199,7 @@ namespace video
virtual void clearZBuffer();
//! 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.
//! There are at least 6 clipping planes available for the user to set at will.

View File

@ -3160,7 +3160,7 @@ void CD3D9Driver::clearZBuffer()
//! 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;

View File

@ -278,7 +278,7 @@ namespace video
virtual void clearZBuffer();
//! 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.
virtual bool setClipPlane(u32 index, const core::plane3df& plane, bool enable=false);

View File

@ -2306,7 +2306,7 @@ scene::IMeshManipulator* CNullDriver::getMeshManipulator()
//! 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;
}

View File

@ -580,7 +580,7 @@ namespace video
virtual void clearZBuffer();
//! 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
virtual bool writeImageToFile(IImage* image, const io::path& filename, u32 param = 0);

View File

@ -3528,7 +3528,7 @@ void COpenGLDriver::drawStencilShadowVolume(const core::vector3df* triangles, s3
glVertexPointer(3,GL_FLOAT,sizeof(core::vector3df),&triangles[0]);
glStencilMask(~0);
glStencilFunc(GL_ALWAYS, 0, ~0);
glPolygonOffset(1.f,1.f);
glPolygonOffset(-1.f,-1.f);
glEnable(GL_POLYGON_OFFSET_FILL);
GLenum incr = GL_INCR;
@ -4259,16 +4259,10 @@ void COpenGLDriver::clearZBuffer()
//! 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);
u8* pixels = static_cast<u8*>(newImage->lock());
if (!pixels)
{
newImage->drop();
if (target==video::ERT_MULTI_RENDER_TEXTURES || target==video::ERT_RENDER_TEXTURE || target==video::ERT_STEREO_BOTH_BUFFERS)
return 0;
}
// allows to read pixels in top-to-bottom order
#ifdef GL_MESA_pack_invert
@ -4276,16 +4270,42 @@ IImage* COpenGLDriver::createScreenShot()
glPixelStorei(GL_PACK_INVERT_MESA, GL_TRUE);
#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.
glReadBuffer(GL_FRONT);
glReadPixels(0, 0, ScreenSize.Width, ScreenSize.Height, GL_RGB, GL_UNSIGNED_BYTE, pixels);
glReadBuffer(tgt);
glReadPixels(0, 0, ScreenSize.Width, ScreenSize.Height, fmt, GL_UNSIGNED_BYTE, pixels);
glReadBuffer(GL_BACK);
}
#ifdef GL_MESA_pack_invert
if (FeatureAvailable[IRR_MESA_pack_invert])
glPixelStorei(GL_PACK_INVERT_MESA, GL_FALSE);
else
#endif
if (pixels)
{
// opengl images are horizontally flipped, so we have to fix that here.
const s32 pitch=newImage->getPitch();
@ -4294,7 +4314,15 @@ IImage* COpenGLDriver::createScreenShot()
for (u32 i=0; i < ScreenSize.Height; i += 2)
{
memcpy(tmpBuffer, pixels, pitch);
// for (u32 j=0; j<pitch; ++j)
// {
// pixels[j]=(u8)(p2[j]*255.f);
// }
memcpy(pixels, p2, pitch);
// for (u32 j=0; j<pitch; ++j)
// {
// p2[j]=(u8)(tmpBuffer[j]*255.f);
// }
memcpy(p2, tmpBuffer, pitch);
pixels += pitch;
p2 -= pitch;
@ -4304,7 +4332,7 @@ IImage* COpenGLDriver::createScreenShot()
newImage->unlock();
if (testGLError())
if (testGLError() || !pixels)
{
newImage->drop();
return 0;

View File

@ -345,7 +345,7 @@ namespace video
virtual void clearZBuffer();
//! 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
//! for performance reasons only available in debug mode

View File

@ -921,7 +921,7 @@ void CSoftwareDriver::clearZBuffer()
//! 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)
{

View File

@ -111,7 +111,7 @@ namespace video
virtual void clearZBuffer();
//! 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
//! the device is able to render with one drawIndexedTriangleList

View File

@ -2584,7 +2584,7 @@ void CBurningVideoDriver::clearZBuffer()
//! 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)
{

View File

@ -136,7 +136,7 @@ namespace video
virtual void clearZBuffer();
//! 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
//! the device is able to render with one drawIndexedTriangleList