[3.0beta2] tranparent background Scene

I tried to make a Scene with transparent background

class PlayState: public cocos2d::LayerColor
{
}

cocos2d::Scene* PlayState::createScene()
{
	// 'scene' is an autorelease object
	auto scene = Scene::create();

	// 'layer' is an autorelease object
	auto layer = PlayState::create();

	// add layer as a child to scene
	scene->addChild(layer);

	// return the scene
	return scene;
}

bool PlayState::init()
{
	if(LayerColor::initWithColor(Color4B(0,0,0,0))==false)
	{
		return false;
	}
	return true;
}

then I push the scene

auto scene = PlayState::createScene();
Director::getInstance()->pushScene(scene);

But it’s not working, the background is still opaque black. Is there a way to make transparent background Layer / Scene?

ps : The scene becomes red if I change the Color4B to opaque red
Color4B(255,0,0,255)

bump… is there solution for this?

The original state of a window is black. The scene is already transparent.

@zhangxm
Thanks for your response
I pushed a new scene from a running game scene which has lots of sprites( which is not black and not original state window ).

I still can’t get this new scene I pushed to be half opaque ( alpha = 0.5 ).

I’m using class derived from LayerColor for my scene (instead of usual Layer), and does the init with initWithColor(0,0,0,128);

Still not working ( screen is opaque black ), am I doing it wrong? or there is no way to make a scene tranparent? Cause I’m looking to TransitionFade code and it can make a scene transparent, but all of the children are also transparent which is the purpose of TransitionFade of course.

I tried deriving my scene class from Node still black screen showed

class MyScene: public Node
{
        CREATE_FUNC(MyScene);
        static cocos2d::Scene* createScene();
        bool init();
}

bool MyScene::init()
{
        Node::init();
}

cocos2d::Scene* MyScene::createScene()
{
	// 'scene' is an autorelease object
	auto scene = Scene::create();

	// 'layer' is an autorelease object
	auto layer = MyScene::create();

	// add layer as a child to scene
	scene->addChild(layer);

	// return the scene
	return scene;
}


Director::getInstance()->pushScene(MyScene::createScene());

any clues?

Is it maybe the background scene is not getting rendered if I push a new scene, so even though the new scene is transparent, but it doesn’t render anything from the scene behind it?

Yes, I think a scene is not rendered when there is another scene on top of the stack. I tried adding a Layer on top of a scene with addChild(). And it support alpha transparent.

Only one scene can be rendered at the same time.

@zhangxm
Thanks, that clears it out.
So, there is no way to push a pause screen on top of game screen with pushScene(), instead we have to add a Layer on top of scene and manually clear the event handlers on game screen?

May be you need Director::replaceScene().

No, I don’t want to replace the scene, but I want a pause screen which I can still see the game screen. It’s like the pause screen is floating on top of game screen.

“The original state of a window is black. The scene is already transparent.”

I can confirm that this statement IS NOT CORRECT. The original state of the window is not always black and is an incorrect assumption, one that comes back to bite anyone trying to do an augmented reality app.

If you, for instance, place a transparent EAGLView onto a UIImagePickerController view (camera stream) and place a scene with a transparent layer onto that, you do NOT get a fully transparent layer/scene as you would expect…you get a black box i the middle of your camera view.

It seems that the alpha channel calculations on the layer take into account the color and alpha of the underlying scene…so if you accept the underlying scene’s original black color, and say, put a white layer over top, and try to turn down the white layer’s alpha it will go from white opaque, to grey translucent, back to black opaque (as the white layer become transparent exposing fully the black opaque scene). Interestingly, the underlying black opaque scene is influenced by the layer above it, that is, it does become translucent (and expose the underlying camera view) at points as you turn down the alpha of the white layer overtop of it…but as the alpha of the white layer becomes negligible in the calculations as it trends to zero the black scene goes back to being opaque and instead of a see through augmented reality app you get an ugly black scene box…to test this, simply make your CCEAGLView slightly smaller than the window and make it a child of a camera overlay view…you can watch it go translucent then back to opaque because of that underlying assumption that the default underlying UIView will always be black.

So, the answer…in Cocos2dx v3.1.1, if you wish for a fully transparent scene/ColorLayer as is needed for augmented reality apps (or indeed any cocos2d-x app that wishes to be transparent overtop of native views…video players etc), you need to ensure that your scene and your layer are the SAME COLOR…i use a white LayerColor (with alpha 0) and a white scene.

I have confirmed this behaviour only for iOS so far…will write more when I get to Android/Windows in my app dev cycle if I remember.

I didn’t fully understand your statement, but I think you might be wrong. The only thing you have to do for creating such an app, is to ensure that your view supports transparency:

iOS:

pixelFormat: kEAGLColorFormatRGBA8
eaglView.opaque = NO

Android:

mGLSurfaceView.setEGLConfigChooser(8, 8, 8, 8, 16, 8);
mGLSurfaceView.getHolder().setFormat(PixelFormat.TRANSLUCENT);

This works since 2.x and it definitely works in 3.x because I’m using it in my latest game (in both Android and iOS). No black square or using the same color or anything strange.

Here is a link to my game in Google Play: https://play.google.com/store/apps/details?id=com.itiox.wtf

And here is a screenshot of my game with this very same post:

Please, could you elaborate on this?? I have the same problem right now. I got it to work on iOS, but on Android I can’t get it right.

I added the lines you posted on Cocos2dxActivity.java , on the init method, but it doesn’t seem to change anything :confused:

Thanks!

The basic idea is to create a FrameLayout where you add the cocos2dx GLSurfaceView and your other view (e.g. a camera view).

The GLSurfaceView should be configured to support transparency with the lines I posted before. And it should be in the top (e.g. mGLSurfaceView.setZOrderOnTop(true); )

And the background of the GLSurfaceView might need to be cleared. You can do it overriding or modifying the Cocos2dxRenderer in the onSurfaceCreate method adding something like: pGL10.glClearColor(0,0,0,0);

However, I have to admit some devices (i.e. most Sony Xperia’s) need some additional work.

1 Like

Ok, I got it to work. I was missing the ZOrderOnTop. I’m still getting some weird behaviors, but I think these are just deriving from some early attempt that I didn’t clean properly.

Thanks!

Okay. It’s working, more or less. But to me, there is a deal breaker.

To make the layer transparent, I have to use the setZOrderOnTop(true). But if I do this, the GLSurfaceView goes on top of everything-everything. Including a WebView that I have created from cocos. It seems that the webview it’s created on a different independent view.

I could live with the interface drawn on top of the WebView. But it also means that it loses the touches capability, rendering the webview useless T_T

Is there any way of making the surfaceview transparent without the zorderontop? I’ve seen references to using setZOrderMediaOverlay, but I haven’t had success in placing anything behind it.

I suppose I will have to remove the webviews from the app. Right now they are use to render some information (formatted text, tittles and some images), not to do any actual browsing, so I suppose we can manage without them :confused:

If both, the surface view and the web view, are full screen, the one above is going to try to swallow the touches.

However, you can try to override this behavior. For example, you can override or modify the Cocos2dxGLSurfaceView class, and return false in the onTouchEvent method.

I think, but I haven’t tested it, that this way both of them will get the touches.

Good luck!

hello sir, i’m new to cocos2d-x, i need help in making camera and cocos2d-x glview work in android. any reply will be appreciated. thanks

Thank you again, we managed to get our game working nicely!

We have found some problems with particular devices, namely a Samsung Galaxy S3 i9300. We can guess that it’s the same problem you found with the Sony Xperia, so it would be really nice if you could point us in the right direction to fix it.

Thanks!