libgdx shader in actor - libgdx

I have custom group, which consist of some actors, and also uses custom shader in its draw()
It looks like:
override fun draw(batch: Batch, parentAlpha: Float) {
super.draw(batch, parentAlpha)
Gdx.gl.glDepthMask(false)
Gdx.gl.glEnable(GL20.GL_BLEND)
Gdx.gl.glBlendFunc(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA)
val sh = stage.batch.shader // Save current shader
stage.batch.shader = shader // Set custom shader
shader.begin()
shader.setUniformMatrix("u_projTrans", stage.camera.combined)
shader.setUniformf("u_color", color)
shader.setUniformf("u_scale", scale)
shader.setUniformf("u_radius", radius)
shader.setUniformf("u_pos_center", v)
mesh.render(shader, GL20.GL_TRIANGLES, 0, 6)
shader.end()
stage.batch.shader = sh // Restore default shader
}
All the actors in the group are drawn, but not custom shader.
Not sure I do it correctly. Where I'm wrong?

Don't make those direct OpenGL calls because those are GL parameters that SpriteBatch manages for itself so you could be messing up its defaults for other actors it draws later. You can set blend functions and enable blending on the batch directly. SpriteBatch already disables depth testing and masking by default.
If you want to draw the children of this group with that shader, move super.draw to after you've set the shader parameters. Do not call shader.begin() or end(), as these are handled for you by the batch.
But if you are just drawing that custom mesh, then it doesn't make sense for you to be messing with the batch's shader at all. Instead, you should call batch.end at the beginning of this method (maybe after calling super.draw), and call batch.begin at the end of this method. Without seeing your custom shader or how you set up your mesh, it's not possible to determine if there are additional issues preventing you from seeing your mesh.

Related

Actionscript 3: Drawing lines and bitmaps the right way

I'm just getting started with Flash/ActionScript and it seems to be the general consensus to create Sprites, Bitmaps, MovieClips, etc for various objects in order to represent pictures and other graphics.
However, the way I'm used to writing games and whatnot in other languages is to just loop repeatedly and each frame use something similar to the Graphics object to redraw the scene on the main Sprite. Is this how it's also done in Flash, and is it good practice? I can do it this way, but I'm wondering if there's some Flash ecosystem standard instead.
Here's an example of the way I'm used to:
public class MyApp extends Sprite
{
public function MyApp()
{
var t:Timer = new Timer(20);
t.addEventListener(TimerEvent.TIMER, update);
t.start();
}
public function update(e:TimerEvent)
{
this.graphics.clear();
//Rendering code and updating of objects.
}
}
Is this acceptable?
Well, it depends.
In Flash, you have the option of relying on the Flash Player's vector rasterizer and rendering system, which will figure out all the redrawing for you. For instance, you can draw once to a Sprite then simply apply transforms to the sprite (set x, y, width, height, rotation, scaleX, scaleY, transform.matrix, transform.colorTransform, etc). Any of these objects could be a vector shape or a bitmap, and you can also use cacheAsBitmap and cacheAsBitmapMatrix for even more redraw optimization. The Flash Player will only redraw areas that change, on the frame that they change. I would consider this the traditional "Flash way".
Using the Graphics API is just a programmatic way to create vector shape data. Think of it as a code alternative to drawing in the Flash IDE. You could draw using Graphics once when the object is created, or if you needed to change the actual shape (ie not just the transform) you are correct that you would clear() and redraw it. However, ideally you would not be doing that a lot. If you find yourself redrawing the shape a lot, you might want to move to a pre-rendered sprite-sheet approach. In that case you use BitmapData to more quickly copy pre-drawn pixel data to a Bitmap object. This is generally faster than relying on the vector rasterizer to render your Graphics commands, as long as you use the fast pixel methods like copyPixels(). This is probably closer to the sort of rendering systems you are used to in other platforms that don't have a vector rasterizer built in.
Lastly, it's worth noting that the newest (and fastest) way to render objects in Flash is completely different than all that. It's called Stage3D and it uses a completely different rendering pipeline than the vector rasterizer. It's powered by GPU rendering APIs, so it's blazing fast (great for games) but has no vector rasterizing abilities. It can be used for both 3D and 2D. It's a bit more involved to work with, but there are some useful frameworks to make it easier, most notably the Starling 2D framework.
Hope that helps.
The "Flash way" is to use EnterFrame event instead of using timer to draw. You must make your calculation whenever you want but let flash draw you scene.
It works the same way in actionscript.
public class App extends Sprite // adding "my" to identifier names doesn't add any information, so there's no real point in doing it
{
public function App()
{
addEventListener(Event.ENTER_FRAME, update); // "each frame"
}
private function update(e:Event):void //not just parameters of functions have a type, but also their return value
{
graphics.clear(); // no need for "this" here
//Rendering code and updating of objects.
}
}
Keep in mind that the Graphics API is vector based and as such will only draw so many things before dropping performance.
Sprite is a general purpose container, not to be confused with what the term "sprite" stands for in a sprite sheet.
What you are probably referring to when saying "main Sprite" is some rectangular region of pixels that you can manipulate.In this case, a BitmapData is what you want, which is displayed with a Bitmap object.
BitmapData does not offer a graphics property. Essentially, drawing vectors and manipulating pixels are treated separately in As3. If you want to draw a line in a BitmapData object, you'd have to first draw the line as a vector into a Sprite (or better Shape, if all you want to do is draw on it) using its graphics property, then use draw() of BitmapData to set its pixels according to the drawn line.

How to animate textures in a 3d model?

I wish to have a animated 3d texture in my LibGDX code but I am struggling to find out how to do it.
I assume how this "should" be done is either;
a) Directly accessing and modifying the texture on the model. (via a pixmap? ByteBuffer?)
or
b) Prerendering a big image containing all the frames (say, 20) and then moving the UV co-ordinates to create the illusion of the animation. (akin to ImageStrips in 2d/webdesign).
I did work out how I could completely replace the material eachtime, but that seems a much worse way of doing it. So if anyone could show the commands I need to do either a) or b) (or a similar optimal method) I would be great-fall.
Maths I am fine with. The intricacies of OpenGLES or GDX I am not :)
(The solution should at least work HTML/Android compiles, ideally everything)
Since the latest release it is very easy to play a 2d animation on a 3d surface. First make sure to get familiar with the 2d animation concept, as explained over here: https://github.com/libgdx/libgdx/wiki/2D-Animation. Then, instead of using a spritebatch, you can use the TextureRegion (which Animation#getKeyFrame returns) to set the material of the surface, as shown here: https://github.com/libgdx/libgdx/blob/master/tests/gdx-tests/src/com/badlogic/gdx/tests/g3d/TextureRegion3DTest.java. So basically you would get in your render method:
attribute.set(animation.getKeyFrame(stateTime, true));
Or if you want a more generic approach:
instance.getMaterial("<name of material>").get(TextureAttribute.class, TextureAttribute.Diffuse).set(animation.getKeyFrame(stateTime, true));
Or, if there's only one material in the ModelInstance:
instance.materials.get(0).get(TextureAttribute.class, TextureAttribute.Diffuse).set(animation.getKeyFrame(stateTime, true));
If you have the memory for it I would definetly choose b), it is easier on the processor. Also, you would only change a uniform's value. However, due to preprocessing it might take some time to open the application.
Get you uniform variable, where you compile your shaders, animationPos should be global.
Gluint animationPos = glGetUniformLocation(shaderProgram, "nameoftheuniform");
Your main loop should pass animationPos value to the shader:
Gluniform1i ( animationPos, curentAnimationIndex);
Add this your fragment shader variables:
uniform int animationPos;
Fragment shader main:
float texCoordY = texCoord.y; //texture coordinates should be passed from vertex shader
float texCoordX = texCoord.x/20.0f; //we are dividing it with 20 since it is the amount of textures that we have and if we use it directly it would try to use all the texture. Whereas the texture stores at 20 different textures.
float textureIndex = 1.0f*animationPos/20.0f; //Pointer to the start of the animation texture.
gl_fragColor = texture2D ( yourTexture, vec2( textureIndex + texCoordX, texCoordY));
Above code assumes that you expanded your textures in the x direction, you can also try to expand it like a matrix, then you need to change the texCoord calculation part. Also that we are using 20 textures.
The option a) is more heavy on the processor and you will be changing the texture every time so it will use pci a bit more, but easier on memory. The question is more like a design decision, but I guess 20 images can be handled so go with option b).
Edit: Added code.

libGDX: same texture with shaders, different textures without

my name ist Tom (Ger) and i am developing a small 3D game with libGDX.
when i am using a Model, ModelInstance with a ModelBatch and the Environment, i can render different ModelInstances (with different Models) with there right textures.
But i need to use a shader for some wobble effects.
But when i use a shader everything works finde, except for the textures. there are the same for every ModelInscance i want to render.
i guess there is a texture binding problem. I load my Models this way:
assets = new AssetManager();
assets.load("blob.g3db", Model.class);
and fetch them with a simple:
public static Model getModel(String name) {
return assets.get(name + ".g3db", Model.class);
}
So i guess the assetsManager is loading the textures as well (cause it works without the shader).
My Question is:
How can i render differend 3D Objects with a Shader with there correct Textures?
Thanks in Advance...
Tom
The Models and the ModelInstances have a Material, where you can set a Texture, Color and other things to it.
So if 2 ModelInstances share the same Model you can set different Materials to their ModelInstances. By doing this you have different Textures. The DefaultShader implementation takes care about them. If you create your own Shader you need to take care about them.
Important: It does not work without Shader, cause you always render with Shader. You don't set the Shader manually, but libgdx uses DefaultShader by default.
I suggest you read some of Xoppas tutorials.

AS3 Stage3D: how to render all triangles with an overall alpha?

I am working on a 2D AS3 project, where the different layers are rendered via Stage3D, in a single drawTriangles() call, as a single mesh.
(if you are familiar with the BunnyMark GPUSprite mini render engine, that will give you an idea: http://www.bytearray.org/?p=4074)
What I would like is to draw one of these entire 'render layers', with an overall alpha transparency value, that would apply to ALL triangles drawn, adding to their own alpha values.
IE I am not looking to change the alpha by using textures with alpha transparency or via having to go through setting each triangle separately to have the same alpha: I want a master switch that would affect the alpha value of everything that is drawn? ( something computationally cheap)
Is this possible? Perhaps via a Shader, or a setProgramConstantsFromVector command?
Well you could render your layer to a texture, then you could put this texture on the stage with the alpha you want, this way your whole layer would have the same alpha!
You can do this in two ways, the first way is to render it to a texture, and display that texture with Stage3D and create a shader that adjusts the alpha.
The second way is rendering it to a bitmapData, and displaying it on the normal stage. I'll give an example for this way:
var bmd:BitmapData = new BitmapData(renderWidth, renderHeight, true, 0);
var bit:Bitmap = new Bitmap(bmd);
bit.alpha = 0.5;
addChild(bit);
//In your render loop at the beginning
context3D.renderToBitmapData(bmd);

Getting Graphics-Object or Bitmap from BrowserField on Blackberry

I would like to get the Bitmap of the content of a webpage as it is displayed in the BrowserField. Therefore I'd need the Graphic-object of the browser field. But the paint-method is protected unfortunately.
Is there a way to get this?
Thank's
Normally, if you want to do some custom drawing with a field ie. draw into the field's graphics context, you'd subclass Field and override the paint method. However, when it comes to BrowserField, you can't do that because it's declared final.
There is a workaround for this, though. You can subclass a Manager and add your BrowserField to an instance of that manager. So, for example, if you want to add your BrowserField instance to a VerticalFieldManager, you can use the following code to get access to the Graphics object the browser will be drawn into. In this sample code, you'll see that I use the graphics object and manager's superclass implementation to draw into a bitmap. Then, that bitmap is drawn to the screen.
VerticalFieldManager vfm = new VerticalFieldManager() {
// Override to gain access to Field's drawing surface
//
protected void paint(Graphics graphics) {
// Create a bitmap to draw into
//
Bitmap b = new Bitmap(vfm.getVirtualWidth(), vfm.getVirtualHeight());
// Create a graphics context to draw into the bitmap
//
Graphics g = Graphics.create(b);
// Give this graphics context to the superclass implementation
// so it will draw into the bitmap instead of the screen
//
super.paint(g);
// Now, draw the bitmap
//
graphics.drawBitmap(0,
0,
vfm.getVirtualWidth(),
vfm.getVirtualHeight(),
b,
0,
0);
}
};
And, there you have a Bitmap containing the contents of the manager. Should note, though, that this has the potential to consume a lot of memory.