I though so, I’m newbie in shaders Here’s what I’ve found:
antialias.fsh:
#ifdef GL_ES
#extension GL_OES_standard_derivatives : enable
varying mediump vec4 v_color;
varying mediump vec2 v_texcoord;
#else
varying vec4 v_color;
varying vec2 v_texcoord;
#endif
void main()
{
#if defined GL_OES_standard_derivatives
gl_FragColor = v_color*smoothstep(0.0, length(fwidth(v_texcoord)), 1.0 - length(v_texcoord));
#else
gl_FragColor = v_color*step(0.0, 1.0 - length(v_texcoord));
#endif
}
And here’s what I’ve created (based on my old code, where it was used to add effect on sprite):
AntialiasedRenderTexture.h:
#ifndef __AntialiasedRenderTexture__
#define __AntialiasedRenderTexture__
#include "cocos2d.h"
#include "AntialiasEffect.h"
USING_NS_CC;
class AntialiasEffect;
class AntialiasedRenderTexture : public RenderTexture
{
public:
static AntialiasedRenderTexture* create(int w, int h, Texture2D::PixelFormat format, GLuint depthStencilFormat);
static AntialiasedRenderTexture* create(int w, int h, Texture2D::PixelFormat format);
static AntialiasedRenderTexture* create(int w, int h);
void draw(Renderer *renderer, const Mat4 &transform, uint32_t flags) override;
protected:
AntialiasEffect* effect;
~AntialiasedRenderTexture();
};
#endif /* defined(__AntialiasedRenderTexture__) */
AntialiasedRenderTexture.cpp:
#include "AntialiasedRenderTexture.h"
AntialiasedRenderTexture* AntialiasedRenderTexture::create(int w, int h, Texture2D::PixelFormat eFormat){
AntialiasedRenderTexture *ret = new (std::nothrow) AntialiasedRenderTexture();
if(ret && ret->initWithWidthAndHeight(w, h, eFormat))
{
ret->autorelease();
ret->effect = AntialiasEffect::create();
return ret;
}
CC_SAFE_DELETE(ret);
return nullptr;
}
AntialiasedRenderTexture* AntialiasedRenderTexture::create(int w, int h, Texture2D::PixelFormat eFormat, GLuint uDepthStencilFormat)
{
AntialiasedRenderTexture *ret = new (std::nothrow) AntialiasedRenderTexture();
if(ret && ret->initWithWidthAndHeight(w, h, eFormat, uDepthStencilFormat))
{
ret->autorelease();
ret->effect = AntialiasEffect::create();
return ret;
}
CC_SAFE_DELETE(ret);
return nullptr;
}
AntialiasedRenderTexture* AntialiasedRenderTexture::create(int w, int h)
{
AntialiasedRenderTexture *ret = new (std::nothrow) AntialiasedRenderTexture();
if(ret && ret->initWithWidthAndHeight(w, h, Texture2D::PixelFormat::RGBA8888, 0))
{
ret->autorelease();
ret->effect = AntialiasEffect::create();
return ret;
}
CC_SAFE_DELETE(ret);
return nullptr;
}
void AntialiasedRenderTexture::draw(Renderer *renderer, const Mat4 &transform, uint32_t flags)
{
if (_autoDraw)
{
//Begin will create a render group using new render target
begin();
//clear screen
_clearCommand.init(_globalZOrder);
_clearCommand.func = CC_CALLBACK_0(AntialiasedRenderTexture::onClear, this);
renderer->addCommand(&_clearCommand);
QuadCommand q = QuadCommand();
auto blendFunc = BlendFunc::ALPHA_PREMULTIPLIED;
q.init(_globalZOrder, _texture->getName(), effect->getGLProgramState(), blendFunc, &_quad, 1, transform, flags); //<-- stuck here, what should I do with _quad parameter
renderer->addCommand(&q);
//! make sure all children are drawn
sortAllChildren();
for(const auto &child: _children)
{
if (child != _sprite)
child->visit(renderer, transform, flags);
}
//End will pop the current render group
end();
}
}
AntialiasedRenderTexture::~AntialiasedRenderTexture() {
CC_SAFE_RELEASE(effect);
}
AntialiasEffect.h:
#ifndef __AntialiasEffect__
#define __AntialiasEffect__
#include "cocos2d.h"
#include "AntialiasedRenderTexture.h"
USING_NS_CC;
class AntialiasedRenderTexture;
class AntialiasEffect : public Ref
{
public:
CREATE_FUNC(AntialiasEffect);
GLProgramState* getGLProgramState() const { return _glprogramstate; }
virtual void setTarget(AntialiasedRenderTexture *t){}
protected:
bool init();
bool initGLProgramState(const std::string &fragmentFilename);
AntialiasEffect();
virtual ~AntialiasEffect();
GLProgramState *_glprogramstate;
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_WP8 || CC_TARGET_PLATFORM == CC_PLATFORM_WINRT)
std::string _fragSource;
EventListenerCustom* _backgroundListener;
#endif
};
#endif /* defined(__AntialiasEffect__) */
AntialiasEffect.cpp:
#include "AntialiasEffect.h"
bool AntialiasEffect::init() {
return initGLProgramState("Shaders/antialias.fsh");
}
bool AntialiasEffect::initGLProgramState(const std::string &fragmentFilename)
{
auto fileUtiles = FileUtils::getInstance();
auto fragmentFullPath = fileUtiles->fullPathForFilename(fragmentFilename);
auto fragSource = fileUtiles->getStringFromFile(fragmentFullPath);
auto glprogram = GLProgram::createWithByteArrays(ccPositionTextureColor_noMVP_vert, fragSource.c_str());
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_WP8 || CC_TARGET_PLATFORM == CC_PLATFORM_WINRT)
_fragSource = fragSource;
#endif
_glprogramstate = GLProgramState::getOrCreateWithGLProgram(glprogram);
_glprogramstate->retain();
return _glprogramstate != nullptr;
}
AntialiasEffect::AntialiasEffect()
: _glprogramstate(nullptr)
{
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_WP8 || CC_TARGET_PLATFORM == CC_PLATFORM_WINRT)
_backgroundListener = EventListenerCustom::create(EVENT_RENDERER_RECREATED,
[this](EventCustom*)
{
auto glProgram = _glprogramstate->getGLProgram();
glProgram->reset();
glProgram->initWithByteArrays(ccPositionTextureColor_noMVP_vert, _fragSource.c_str());
glProgram->link();
glProgram->updateUniforms();
}
);
Director::getInstance()->getEventDispatcher()->addEventListenerWithFixedPriority(_backgroundListener, -1);
#endif
}
AntialiasEffect::~AntialiasEffect()
{
CC_SAFE_RELEASE_NULL(_glprogramstate);
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_WP8 || CC_TARGET_PLATFORM == CC_PLATFORM_WINRT)
Director::getInstance()->getEventDispatcher()->removeEventListener(_backgroundListener);
#endif
}
I’m stuck in class AntialiasedRenderTexture.cpp on line:
q.init(_globalZOrder, _texture->getName(), effect->getGLProgramState(), blendFunc, &_quad, 1, transform, flags); //<-- what should I do with _quad parameter