mirror of https://github.com/axmolengine/axmol.git
issue #1506: RenderTextureTest
This commit is contained in:
parent
6b7716770e
commit
39ba6b4618
|
@ -34,10 +34,9 @@ NS_CC_BEGIN
|
|||
|
||||
typedef enum eImageFormat
|
||||
{
|
||||
kCCImageFormatJPG = 0,
|
||||
kCCImageFormatJPEG = 0,
|
||||
kCCImageFormatPNG = 1,
|
||||
kCCImageFormatRawData = 2
|
||||
} tImageFormat;
|
||||
} tCCImageFormat;
|
||||
/**
|
||||
@brief CCRenderTexture is a generic rendering target. To render things into it,
|
||||
simply construct a render target, call begin on it, call visit on any cocos
|
||||
|
@ -86,31 +85,20 @@ public:
|
|||
/** clears the texture with a color */
|
||||
void clear(float r, float g, float b, float a);
|
||||
|
||||
/** saves the texture into a file */
|
||||
// para szFilePath the absolute path to save
|
||||
// para x,y the lower left corner coordinates of the buffer to save
|
||||
// pare nWidth,nHeight the size of the buffer to save
|
||||
// when nWidth = 0 and nHeight = 0, the image size to save equals to buffer texture size
|
||||
bool saveBuffer(const char *szFilePath, int x = 0, int y = 0, int nWidth = 0, int nHeight = 0);
|
||||
/* creates a new CCImage from with the texture's data.
|
||||
Caller is responsible for releasing it by calling delete.
|
||||
*/
|
||||
CCImage* newCCImage();
|
||||
|
||||
/** saves the texture into a file. put format at the first argument, or ti will be overloaded with
|
||||
* saveBuffer(const char *szFilePath, int x = 0, int y = 0, int nWidth = 0, int nHeight = 0) */
|
||||
// para name the file name to save
|
||||
// para format the image format to save, here it supports kCCImageFormatPNG and kCCImageFormatJPG */
|
||||
// para x,y the lower left corner coordinates of the buffer to save
|
||||
// pare nWidth,nHeight the size of the buffer to save
|
||||
// when nWidth = 0 and nHeight = 0, the image size to save equals to buffer texture size
|
||||
bool saveBuffer(int format, const char *name, int x = 0, int y = 0, int nWidth = 0, int nHeight = 0);
|
||||
/** saves the texture into a file using JPEG format. The file will be saved in the Documents folder.
|
||||
Returns YES if the operation is successful.
|
||||
*/
|
||||
bool saveToFile(const char *szFilePath);
|
||||
|
||||
/* get buffer as UIImage, can only save a render buffer which has a RGBA8888 pixel format */
|
||||
CCData *getUIImageAsDataFromBuffer(int format);
|
||||
|
||||
/** save the buffer data to a CCImage */
|
||||
// para pImage the CCImage to save
|
||||
// para x,y the lower left corner coordinates of the buffer to save
|
||||
// pare nWidth,nHeight the size of the buffer to save
|
||||
// when nWidth = 0 and nHeight = 0, the image size to save equals to buffer texture size
|
||||
bool getUIImageFromBuffer(CCImage *pImage, int x = 0, int y = 0, int nWidth = 0, int nHeight = 0);
|
||||
/** saves the texture into a file. The format could be JPG or PNG. The file will be saved in the Documents folder.
|
||||
Returns YES if the operation is successful.
|
||||
*/
|
||||
bool saveToFile(const char *name, tCCImageFormat format);
|
||||
|
||||
protected:
|
||||
GLuint m_uFBO;
|
||||
|
|
|
@ -103,6 +103,8 @@ bool CCRenderTexture::initWithWidthAndHeight(int w, int h, CCTexture2DPixelForma
|
|||
return false;
|
||||
}
|
||||
|
||||
CCAssert(m_ePixelFormat != kCCTexture2DPixelFormat_A8, "only RGB and RGBA formats are valid for a render texture");
|
||||
|
||||
bool bRet = false;
|
||||
do
|
||||
{
|
||||
|
@ -143,13 +145,7 @@ bool CCRenderTexture::initWithWidthAndHeight(int w, int h, CCTexture2DPixelForma
|
|||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_pTexture->getName(), 0);
|
||||
|
||||
// check if it worked (probably worth doing :) )
|
||||
GLuint status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
||||
if (status != GL_FRAMEBUFFER_COMPLETE)
|
||||
{
|
||||
CCAssert(0, "Render Texture : Could not attach texture to framebuffer");
|
||||
CC_SAFE_DELETE(m_pTexture);
|
||||
break;
|
||||
}
|
||||
CCAssert(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE, "Could not attach texture to framebuffer");
|
||||
|
||||
m_pTexture->setAliasTexParameters();
|
||||
|
||||
|
@ -183,11 +179,13 @@ void CCRenderTexture::begin()
|
|||
float heightRatio = size.height / texSize.height;
|
||||
|
||||
// Adjust the orthographic projection and viewport
|
||||
glViewport(0, 0, texSize.width * CC_CONTENT_SCALE_FACTOR(), texSize.height * CC_CONTENT_SCALE_FACTOR() );
|
||||
glViewport(0, 0, (GLsizei)(texSize.width * CC_CONTENT_SCALE_FACTOR()), (GLsizei)(texSize.height * CC_CONTENT_SCALE_FACTOR()));
|
||||
|
||||
// special viewport for 3d projection + retina display
|
||||
if ( director->getProjection() == kCCDirectorProjection3D && CC_CONTENT_SCALE_FACTOR() != 1 )
|
||||
glViewport(-texSize.width/2, -texSize.height/2, texSize.width * CC_CONTENT_SCALE_FACTOR(), texSize.height * CC_CONTENT_SCALE_FACTOR() );
|
||||
{
|
||||
glViewport((GLsizei)(-texSize.width/2), (GLsizei)(-texSize.height/2), (GLsizei)(texSize.width * CC_CONTENT_SCALE_FACTOR()), (GLsizei)(texSize.height * CC_CONTENT_SCALE_FACTOR()));
|
||||
}
|
||||
|
||||
kmMat4 orthoMatrix;
|
||||
kmMat4OrthographicProjection(&orthoMatrix, (float)-1.0 / widthRatio, (float)1.0 / widthRatio,
|
||||
|
@ -223,11 +221,13 @@ void CCRenderTexture::end(bool bIsTOCacheTexture)
|
|||
CCSize size = director->getWinSizeInPixels();
|
||||
|
||||
// restore viewport
|
||||
glViewport(0, 0, size.width * CC_CONTENT_SCALE_FACTOR(), size.height * CC_CONTENT_SCALE_FACTOR() );
|
||||
glViewport(0, 0, GLsizei(size.width * CC_CONTENT_SCALE_FACTOR()), GLsizei(size.height * CC_CONTENT_SCALE_FACTOR()));
|
||||
|
||||
// special viewport for 3d projection + retina display
|
||||
if ( director->getProjection() == kCCDirectorProjection3D && CC_CONTENT_SCALE_FACTOR() != 1 )
|
||||
glViewport(-size.width/2, -size.height/2, size.width * CC_CONTENT_SCALE_FACTOR(), size.height * CC_CONTENT_SCALE_FACTOR() );
|
||||
{
|
||||
glViewport((GLsizei)(-size.width/2), (GLsizei)(-size.height/2), (GLsizei)(size.width * CC_CONTENT_SCALE_FACTOR()), (GLsizei)(size.height * CC_CONTENT_SCALE_FACTOR()));
|
||||
}
|
||||
|
||||
//TODO: Does this line take effect? director->setProjection(director->getProjection());
|
||||
|
||||
|
@ -241,7 +241,7 @@ void CCRenderTexture::end(bool bIsTOCacheTexture)
|
|||
int tx = (int)s.width;
|
||||
int ty = (int)s.height;
|
||||
m_pUITextureImage = new CCImage;
|
||||
if (true == getUIImageFromBuffer(m_pUITextureImage, 0, 0, tx, ty))
|
||||
if (m_pUITextureImage == newCCImage())
|
||||
{
|
||||
VolatileTexture::addDataTexture(m_pTexture, m_pUITextureImage->getData(), kTexture2DPixelFormat_RGBA8888, s);
|
||||
}
|
||||
|
@ -259,31 +259,31 @@ void CCRenderTexture::clear(float r, float g, float b, float a)
|
|||
this->end();
|
||||
}
|
||||
|
||||
bool CCRenderTexture::saveBuffer(const char *szFilePath, int x, int y, int nWidth, int nHeight)
|
||||
bool CCRenderTexture::saveToFile(const char *szFilePath)
|
||||
{
|
||||
bool bRet = false;
|
||||
|
||||
CCImage *pImage = new CCImage();
|
||||
if (pImage != NULL && getUIImageFromBuffer(pImage, x, y, nWidth, nHeight))
|
||||
CCImage *pImage = newCCImage();
|
||||
if (pImage)
|
||||
{
|
||||
bRet = pImage->saveToFile(szFilePath);
|
||||
bRet = pImage->saveToFile(szFilePath, kCCImageFormatJPEG);
|
||||
}
|
||||
|
||||
CC_SAFE_DELETE(pImage);
|
||||
return bRet;
|
||||
}
|
||||
bool CCRenderTexture::saveBuffer(int format, const char *fileName, int x, int y, int nWidth, int nHeight)
|
||||
bool CCRenderTexture::saveToFile(const char *fileName, tCCImageFormat format)
|
||||
{
|
||||
bool bRet = false;
|
||||
CCAssert(format == kCCImageFormatJPG || format == kCCImageFormatPNG,
|
||||
CCAssert(format == kCCImageFormatJPEG || format == kCCImageFormatPNG,
|
||||
"the image can only be saved as JPG or PNG format");
|
||||
|
||||
CCImage *pImage = new CCImage();
|
||||
if (pImage != NULL && getUIImageFromBuffer(pImage, x, y, nWidth, nHeight))
|
||||
CCImage *pImage = newCCImage();
|
||||
if (pImage)
|
||||
{
|
||||
std::string fullpath = CCFileUtils::getWriteablePath() + fileName;
|
||||
|
||||
bRet = pImage->saveToFile(fullpath.c_str());
|
||||
bRet = pImage->saveToFile(fullpath.c_str(), true);
|
||||
}
|
||||
|
||||
CC_SAFE_DELETE(pImage);
|
||||
|
@ -291,75 +291,43 @@ bool CCRenderTexture::saveBuffer(int format, const char *fileName, int x, int y,
|
|||
return bRet;
|
||||
}
|
||||
|
||||
/* get buffer as UIImage */
|
||||
bool CCRenderTexture::getUIImageFromBuffer(CCImage *pImage, int x, int y, int nWidth, int nHeight)
|
||||
/* get buffer as CCImage */
|
||||
CCImage* CCRenderTexture::newCCImage()
|
||||
{
|
||||
if (NULL == pImage || NULL == m_pTexture)
|
||||
CCAssert(m_ePixelFormat == kCCTexture2DPixelFormat_RGBA8888, "only RGBA8888 can be saved as image");
|
||||
|
||||
if (NULL == m_pTexture)
|
||||
{
|
||||
return false;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const CCSize& s = m_pTexture->getContentSizeInPixels();
|
||||
int tx = (int)s.width;
|
||||
int ty = (int)s.height;
|
||||
|
||||
if (x < 0 || x >= tx || y < 0 || y >= ty)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (nWidth < 0
|
||||
|| nHeight < 0
|
||||
|| (0 == nWidth && 0 != nHeight)
|
||||
|| (0 == nHeight && 0 != nWidth))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// to get the image size to save
|
||||
// if the saving image domain exeeds the buffer texture domain,
|
||||
// it should be cut
|
||||
int nSavedBufferWidth = nWidth;
|
||||
int nSavedBufferHeight = nHeight;
|
||||
if (0 == nWidth)
|
||||
{
|
||||
nSavedBufferWidth = tx;
|
||||
}
|
||||
if (0 == nHeight)
|
||||
{
|
||||
nSavedBufferHeight = ty;
|
||||
}
|
||||
nSavedBufferWidth = x + nSavedBufferWidth > tx ? (tx - x): nSavedBufferWidth;
|
||||
nSavedBufferHeight = y + nSavedBufferHeight > ty ? (ty - y): nSavedBufferHeight;
|
||||
int nSavedBufferWidth = (int)s.width;
|
||||
int nSavedBufferHeight = (int)s.height;
|
||||
|
||||
GLubyte *pBuffer = NULL;
|
||||
GLubyte *pTempData = NULL;
|
||||
bool bRet = false;
|
||||
CCImage *pImage = new CCImage();
|
||||
|
||||
do
|
||||
{
|
||||
CCAssert(m_ePixelFormat == kCCTexture2DPixelFormat_RGBA8888, "only RGBA8888 can be saved as image");
|
||||
|
||||
CC_BREAK_IF(! (pBuffer = new GLubyte[nSavedBufferWidth * nSavedBufferHeight * 4]));
|
||||
|
||||
// On some machines, like Samsung i9000, Motorola Defy,
|
||||
// the dimension need to be a power of 2
|
||||
int nReadBufferWidth = 0;
|
||||
int nReadBufferHeight = 0;
|
||||
int nMaxTextureSize = 0;
|
||||
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &nMaxTextureSize);
|
||||
|
||||
nReadBufferWidth = ccNextPOT(tx);
|
||||
nReadBufferHeight = ccNextPOT(ty);
|
||||
|
||||
CC_BREAK_IF(0 == nReadBufferWidth || 0 == nReadBufferHeight);
|
||||
CC_BREAK_IF(nReadBufferWidth > nMaxTextureSize || nReadBufferHeight > nMaxTextureSize);
|
||||
|
||||
CC_BREAK_IF(! (pTempData = new GLubyte[nReadBufferWidth * nReadBufferHeight * 4]));
|
||||
if(! (pTempData = new GLubyte[nSavedBufferWidth * nSavedBufferHeight * 4]))
|
||||
{
|
||||
delete[] pBuffer;
|
||||
pBuffer = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
this->begin();
|
||||
glPixelStorei(GL_PACK_ALIGNMENT, 1);
|
||||
glReadPixels(0,0,nReadBufferWidth,nReadBufferHeight,GL_RGBA,GL_UNSIGNED_BYTE, pTempData);
|
||||
glReadPixels(0,0,nSavedBufferWidth, nSavedBufferHeight,GL_RGBA,GL_UNSIGNED_BYTE, pTempData);
|
||||
this->end(false);
|
||||
|
||||
// to get the actual texture data
|
||||
|
@ -367,105 +335,17 @@ bool CCRenderTexture::getUIImageFromBuffer(CCImage *pImage, int x, int y, int nW
|
|||
for (int i = 0; i < nSavedBufferHeight; ++i)
|
||||
{
|
||||
memcpy(&pBuffer[i * nSavedBufferWidth * 4],
|
||||
&pTempData[(y + nSavedBufferHeight - i - 1) * nReadBufferWidth * 4 + x * 4],
|
||||
&pTempData[(nSavedBufferHeight - i - 1) * nSavedBufferWidth * 4],
|
||||
nSavedBufferWidth * 4);
|
||||
}
|
||||
|
||||
bRet = pImage->initWithImageData(pBuffer, nSavedBufferWidth * nSavedBufferHeight * 4, CCImage::kFmtRawData, nSavedBufferWidth, nSavedBufferHeight, 8);
|
||||
pImage->initWithImageData(pBuffer, nSavedBufferWidth * nSavedBufferHeight * 4, CCImage::kFmtRawData, nSavedBufferWidth, nSavedBufferHeight, 8);
|
||||
} while (0);
|
||||
|
||||
CC_SAFE_DELETE_ARRAY(pBuffer);
|
||||
CC_SAFE_DELETE_ARRAY(pTempData);
|
||||
|
||||
return bRet;
|
||||
}
|
||||
|
||||
|
||||
CCData * CCRenderTexture::getUIImageAsDataFromBuffer(int format)
|
||||
{
|
||||
CC_UNUSED_PARAM(format);
|
||||
CCData * pData = NULL;
|
||||
//@ todo CCRenderTexture::getUIImageAsDataFromBuffer
|
||||
|
||||
// #include "Availability.h"
|
||||
// #include "UIKit.h"
|
||||
|
||||
// GLubyte * pBuffer = NULL;
|
||||
// GLubyte * pPixels = NULL;
|
||||
// do
|
||||
// {
|
||||
// CC_BREAK_IF(! m_pTexture);
|
||||
//
|
||||
// CCAssert(m_ePixelFormat == kCCTexture2DPixelFormat_RGBA8888, "only RGBA8888 can be saved as image");
|
||||
//
|
||||
// const CCSize& s = m_pTexture->getContentSizeInPixels();
|
||||
// int tx = s.width;
|
||||
// int ty = s.height;
|
||||
//
|
||||
// int bitsPerComponent = 8;
|
||||
// int bitsPerPixel = 32;
|
||||
//
|
||||
// int bytesPerRow = (bitsPerPixel / 8) * tx;
|
||||
// int myDataLength = bytesPerRow * ty;
|
||||
//
|
||||
// CC_BREAK_IF(! (pBuffer = new GLubyte[tx * ty * 4]));
|
||||
// CC_BREAK_IF(! (pPixels = new GLubyte[tx * ty * 4]));
|
||||
//
|
||||
// this->begin();
|
||||
// glReadPixels(0,0,tx,ty,GL_RGBA,GL_UNSIGNED_BYTE, pBuffer);
|
||||
// this->end();
|
||||
//
|
||||
// int x,y;
|
||||
//
|
||||
// for(y = 0; y <ty; y++) {
|
||||
// for(x = 0; x <tx * 4; x++) {
|
||||
// pPixels[((ty - 1 - y) * tx * 4 + x)] = pBuffer[(y * 4 * tx + x)];
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if (format == kCCImageFormatRawData)
|
||||
// {
|
||||
// pData = CCData::dataWithBytesNoCopy(pPixels, myDataLength);
|
||||
// break;
|
||||
// }
|
||||
|
||||
//@ todo impliment save to jpg or png
|
||||
/*
|
||||
CGImageCreate(size_t width, size_t height,
|
||||
size_t bitsPerComponent, size_t bitsPerPixel, size_t bytesPerRow,
|
||||
CGColorSpaceRef space, CGBitmapInfo bitmapInfo, CGDataProviderRef provider,
|
||||
const CGFloat decode[], bool shouldInterpolate,
|
||||
CGColorRenderingIntent intent)
|
||||
*/
|
||||
// make data provider with data.
|
||||
// CGBitmapInfo bitmapInfo = kCGImageAlphaPremultipliedLast | kCGBitmapByteOrderDefault;
|
||||
// CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, pixels, myDataLength, NULL);
|
||||
// CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
|
||||
// CGImageRef iref = CGImageCreate(tx, ty,
|
||||
// bitsPerComponent, bitsPerPixel, bytesPerRow,
|
||||
// colorSpaceRef, bitmapInfo, provider,
|
||||
// NULL, false,
|
||||
// kCGRenderingIntentDefault);
|
||||
//
|
||||
// UIImage* image = [[UIImage alloc] initWithCGImage:iref];
|
||||
//
|
||||
// CGImageRelease(iref);
|
||||
// CGColorSpaceRelease(colorSpaceRef);
|
||||
// CGDataProviderRelease(provider);
|
||||
//
|
||||
//
|
||||
//
|
||||
// if (format == kCCImageFormatPNG)
|
||||
// data = UIImagePNGRepresentation(image);
|
||||
// else
|
||||
// data = UIImageJPEGRepresentation(image, 1.0f);
|
||||
//
|
||||
// [image release];
|
||||
// } while (0);
|
||||
//
|
||||
// CC_SAFE_DELETE_ARRAY(pBuffer);
|
||||
// CC_SAFE_DELETE_ARRAY(pPixels);
|
||||
return pData;
|
||||
return pImage;
|
||||
}
|
||||
|
||||
NS_CC_END
|
||||
|
|
|
@ -22,8 +22,8 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __CC_IMAGE_H_YANGWS_20110115__
|
||||
#define __CC_IMAGE_H_YANGWS_20110115__
|
||||
#ifndef __CC_IMAGE_H__
|
||||
#define __CC_IMAGE__
|
||||
|
||||
#include "CCCommon.h"
|
||||
|
||||
|
@ -147,4 +147,4 @@ private:
|
|||
|
||||
NS_CC_END;
|
||||
|
||||
#endif // __CC_IMAGE_H_YANGWS_20110115__
|
||||
#endif // __CC_IMAGE_H__
|
||||
|
|
|
@ -235,7 +235,7 @@ RenderTextureSave::RenderTextureSave()
|
|||
CCSize s = CCDirector::sharedDirector()->getWinSize();
|
||||
|
||||
// create a render texture, this is what we are going to draw into
|
||||
m_pTarget = CCRenderTexture::renderTextureWithWidthAndHeight(s.width, s.height);
|
||||
m_pTarget = CCRenderTexture::renderTextureWithWidthAndHeight(s.width, s.height, kCCTexture2DPixelFormat_RGBA8888);
|
||||
m_pTarget->retain();
|
||||
m_pTarget->setPosition(ccp(s.width / 2, s.height / 2));
|
||||
|
||||
|
@ -246,6 +246,7 @@ RenderTextureSave::RenderTextureSave()
|
|||
// create a brush image to draw into the texture with
|
||||
m_pBrush = CCSprite::spriteWithFile("Images/fire.png");
|
||||
m_pBrush->retain();
|
||||
m_pBrush->setColor(ccRED);
|
||||
m_pBrush->setOpacity(20);
|
||||
this->setIsTouchEnabled(true);
|
||||
|
||||
|
@ -278,10 +279,29 @@ void RenderTextureSave::saveImage(cocos2d::CCObject *pSender)
|
|||
{
|
||||
static int counter = 0;
|
||||
|
||||
char str[20];
|
||||
sprintf(str, "image-%d.png", counter);
|
||||
m_pTarget->saveBuffer(kCCImageFormatPNG, str);
|
||||
CCLOG("Image saved %s", str);
|
||||
char png[20];
|
||||
sprintf(png, "image-%d.png", counter);
|
||||
char jpg[20];
|
||||
sprintf(jpg, "image-%d.jpg", counter);
|
||||
|
||||
m_pTarget->saveToFile(png, kCCImageFormatPNG);
|
||||
m_pTarget->saveToFile(jpg, kCCImageFormatJPEG);
|
||||
|
||||
|
||||
CCImage *pImage = m_pTarget->newCCImage();
|
||||
|
||||
CCTexture2D *tex = CCTextureCache::sharedTextureCache()->addUIImage(pImage, png);
|
||||
|
||||
CC_SAFE_DELETE(pImage);
|
||||
|
||||
CCSprite *sprite = CCSprite::spriteWithTexture(tex);
|
||||
|
||||
sprite->setScale(0.3f);
|
||||
addChild(sprite);
|
||||
sprite->setPosition(ccp(40, 40));
|
||||
sprite->setRotation(counter * 3);
|
||||
|
||||
CCLOG("Image saved %s and %s", png, jpg);
|
||||
|
||||
counter++;
|
||||
}
|
||||
|
@ -359,7 +379,7 @@ RenderTextureIssue937::RenderTextureIssue937()
|
|||
|
||||
|
||||
/* A2 & B2 setup */
|
||||
CCRenderTexture *rend = CCRenderTexture::renderTextureWithWidthAndHeight(32, 64);
|
||||
CCRenderTexture *rend = CCRenderTexture::renderTextureWithWidthAndHeight(32, 64, kCCTexture2DPixelFormat_RGBA4444);
|
||||
|
||||
if (NULL == rend)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue