A friend is making an art piece using NoiseInk https://github.com/trentbrooks/Noise-Ink and would like the background to be transparent instead of black. Ideally he would have this Java app running over a video (hence the transparency). So how could he play a video as the background, or at the very least make the background transparent? I have tried everything I could think of!
The catch is your friend is not clearing the screen, but adding a transparent rectangle to get a trails effect in the easyFade() function:
void easyFade()
{
fill(bgColor,overlayAlpha);
noStroke();
rect(0,0,width,height);//fade background
}
The same can be done with images, but slightly different: simply use the tint() function to add transparency to your background video. Just for testing purposes, say you have an image to test this with (test.png), you can try something like this:
PImage bg;
void setup(){
size(240,240);noStroke();
bg = loadImage("test.png");
}
void draw(){
easyFade();
fill(255);
ellipse(mouseX,mouseY,10,10);
}
void easyFade()
{
tint(255,10);
image(bg,0,0);
}
In your case the video will either be a loaded Movie or a live Capture but the above would still work, since both extend PImage (and you render them to screen with the image() call).
UPDATE
One issue with this approach though is the fade will affect the background video as well.
To keep things separated, you can use another 'layer' using PGraphics:
import processing.video.*;
PGraphics gfx;
Capture video;
int w = 640;
int h = 480;
void setup() {
size(w, h);
video = new Capture(this, w, h,30);
video.start();
gfx = createGraphics(w, h);
gfx.beginDraw();
gfx.background(0);
gfx.endDraw();
// println(Capture.list());
}
void draw(){
image(video,0,0);
pushStyle();
tint(255,127);//tint just the rendered graphics as transparent to see the video beneath
image(gfx,0,0);
popStyle();
//draw your awesome optical flow graphics here
gfx.beginDraw();
gfx.fill(0,10);//same as easyFade() draw transparent bg
gfx.rect(0,0,width,height);
gfx.fill(255);
gfx.ellipse(mouseX,mouseY,10,10);
gfx.endDraw();
}
void captureEvent(Capture c) {
c.read();
}
Again, this would display the graphics faded.
A variation of this would be blending the graphics layer, using the blend() function.
Given that normally the graphics background is dark and you want to overlay the bright graphics, you can use a blend mode like ADD or SCREEN which would make 'background'/dark areas transparent:
import processing.video.*;
PGraphics gfx;
Capture video;
int w = 640;
int h = 480;
void setup() {
size(w, h);
video = new Capture(this, w, h,30);
video.start();
gfx = createGraphics(w, h);
gfx.beginDraw();
gfx.background(0);
gfx.endDraw();
// println(Capture.list());
}
void draw(){
image(video,0,0);
blend(gfx,0,0,w,h,0,0,w,h,SCREEN);//blend the rendered graphics on top of the video using SCREEN mode
//draw your awesome optical flow graphics here
gfx.beginDraw();
gfx.fill(0,10);//same as easyFade() draw transparent bg
gfx.rect(0,0,width,height);
gfx.fill(255);
gfx.ellipse(mouseX,mouseY,10,10);
gfx.endDraw();
}
void captureEvent(Capture c) {
c.read();
}
Have fun playing with these! :)
Related
I want to render a cube with three faces visible, each of those faces should have a different texture applied to it, which should be easily interchangable. I managed to get this basic code running, that only works with colors.
import com.jogamp.opengl.*;
import com.jogamp.opengl.awt.GLJPanel;
import javax.swing.*;
import java.awt.*;
import static com.jogamp.opengl.GL.GL_MULTISAMPLE;
public class CubeRenderer extends GLJPanel implements GLEventListener {
public static void main(String[] args) {
JFrame window = new JFrame("JOGL Scene");
GLCapabilities caps = new GLCapabilities(null);
CubeRenderer panel = new CubeRenderer(caps);
window.setContentPane(panel);
window.pack();
window.setLocation(50,50);
window.setResizable(false);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setVisible(true);
panel.requestFocusInWindow();
}
private final float rotateX;
private final float rotateY;
private final float rotateZ; // rotation amounts about axes
private int texture;
// Correct orientation -45.0, 150.0, 90.0
public CubeRenderer(GLCapabilities capabilities) {
super(capabilities);
setPreferredSize( new Dimension(500,500) );
addGLEventListener(this);
rotateX = -45.0f;
rotateY = 150.0f;
rotateZ = 90.0f;
}
private void square(GL2 gl, float r, float g, float b) {
gl.glColor3f(r,g,b); // The color for the square.
gl.glTranslatef(0,0,0.5f); // Move square 0.5 units forward.
gl.glNormal3f(0,0,1); // Normal vector to square (this is actually the default).
gl.glBegin(GL2.GL_TRIANGLE_FAN);
gl.glVertex2f(-0.5f,-0.5f); // Draw the square (before the
gl.glVertex2f(0.5f,-0.5f); // the translation is applied)
gl.glVertex2f(0.5f,0.5f); // on the xy-plane, with its
gl.glVertex2f(-0.5f,0.5f); // at (0,0,0).
gl.glEnd();
}
private void cube(GL2 gl) {
gl.glPushMatrix();
gl.glRotatef(180,0,1,0); // rotate square to back face
square(gl,0,1,1); // back face is cyan
gl.glPopMatrix();
gl.glPushMatrix();
gl.glRotatef(-90,0,1,0); // rotate square to left face
square(gl,0,1,0); // left face is green
gl.glPopMatrix();
gl.glPushMatrix();
gl.glRotatef(-90,1,0,0); // rotate square to top face
square(gl,0,0,1); // top face is blue
gl.glPopMatrix();
}
public void display(GLAutoDrawable drawable) {
// called when the panel needs to be drawn
GL2 gl = drawable.getGL().getGL2();
gl.glClearColor(0,0,0,0);
gl.glClear( GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT );
gl.glMatrixMode(GL2.GL_PROJECTION); // Set up the projection.
gl.glLoadIdentity();
gl.glOrtho(-1,1,-1,1,-2,2);
gl.glMatrixMode(GL2.GL_MODELVIEW);
gl.glLoadIdentity(); // Set up modelview transform.
gl.glRotatef(rotateZ,0,0,1);
gl.glRotatef(rotateY,0,1,0);
gl.glRotatef(rotateX,1,0,0);
cube(gl);
}
public void init(GLAutoDrawable drawable) {
// called when the panel is created
GL2 gl = drawable.getGL().getGL2();
gl.glClearColor(0.8F, 0.8F, 0.8F, 1.0F);
gl.glEnable(GL.GL_DEPTH_TEST);
gl.glEnable(GL2.GL_LIGHTING);
gl.glEnable(GL2.GL_LIGHT0);
gl.glEnable(GL2.GL_COLOR_MATERIAL);
gl.glEnable(GL_MULTISAMPLE);
}
public void dispose(GLAutoDrawable drawable) {
// called when the panel is being disposed
}
public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
// called when user resizes the window
}
}
I however could not figure out how to apply texture instead of colors and how to then render the whole cube into a png, as I could not get any of these tutorials to run, as most of them were quite old.
Either merge the 3 images into a single image, create a single texture, bind it, enable texture target and use your texture as a texture atlas by using appropriate texture coordinates (see glTexCoords) or create 3 textures for your 3 images and perform enable/bind/draw/disable for each texture.
Have a look at TextureIO, AWTTextureIO, glBindTexture, glEnable, glDisable and glTexCoord2f.
Please note that my answer assumes that you use the fixed pipeline but using the programmable pipeline would be preferable on the long term. You should use the retained mode (VAOs, VBOs, ...) even though you use the fixed pipeline instead of the immediate mode (glBegin, glEnd, glVertex, ...) in my humble opinion.
I have a 540x720 background image.
I need to show it in full screen regardless of screen size and resolution (My game will run on desktop and on Android) and regardless of portrait/landscape mode.
I want to keep the aspect ratio of the image, if necessary by cropping the image.
I have already tried ScreenViewport and ExtendViewport but when resizing the window, the background is no longer full screen (for example if the window becomes horizontal) and letter-boxing occurs (showing white side bars).
public class MainMenuScreen implements Screen, InputProcessor {
final MyGame game;
TextureRegionDrawable textureRegionDrawableBackground = new TextureRegionDrawable(new TextureRegion(new Texture(game.backgroundFileName)));
Stage stageBackground = new Stage(new ScreenViewport());
// Stage stageBackground = new Stage(new ExtendViewport(Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), new OrthographicCamera(Gdx.graphics.getWidth(), Gdx.graphics.getHeight())));
Image image = new Image(textureRegionDrawableBackground);
image.setPosition(0, 0);
image.setHeight(Gdx.graphics.getHeight());
// makes the background as tall as the screen while maintaining its aspect ratio
image.setWidth(Gdx.graphics.getHeight() * textureRegionDrawableBackground.getRegion().getRegionWidth() / textureRegionDrawableBackground.getRegion().getRegionHeight());
stageBackground.addActor(image);
}
public void render(float delta) {
stageBackground.getViewport().apply();
stageBackground.draw();
}
public void resize(int width, int height) {
stageBackground.getViewport().update(width, height, true);
}
How to achieve that?
Thanks
Use FillViewport which will maintain aspect ratio and be full screen by cropping part of the image.
See here
https://gamefromscratch.com/libgdx-tutorial-part-17-viewports/
so recently I decided to try and make some form of sprite-esque game, similar to the older Final Fantasy games. I'm mostly doing this as a code learning process rather than using things like RPGMaker to actually create an idea.
The biggest part I'm concerned about are how to properly paint multiple layers of images (such as static Sprites, background images, etc) in a simple way. While I would normally just test a bunch of things to see rather than asking, I realize there are many (possibly easy) methods of ways to implement any one thing in coding.
What are some ways (or Classes) to implement this? Preferably a way that is easy to change what layers are where (layer A in front of B... oh wait no B in front of A! at any time)
I do hope that's not too broad of a question.. .
Thanks.
The most basic approach is the painter's algorithm, simply paint layers in reverse order of the distance to the screen (first background, then characters, then foreground for instance).
You have each layer represented by a simple class, something like:
public class Layer
{
List<Sprite> sprites;
public void draw(Graphics g)
{
for (Sprite sprite : sprites)
sprite.draw(g);
}
}
where a sprite would be:
public class Sprite
{
BufferedImage image;
float x, y, w, h;
public void draw(Graphics g)
{
g.drawImage(image, (int)x, (int)y, (int)(x+w), (int)(y+h), 0, 0, image.getWidth(), image.getHeight(), null);
}
}
Here, the background would be a layer with a single sprite that is the size of the screen. You can subclass the background layer to achieve effects like parallax.
Finally, your layers would be part of a scene:
public class Scene
{
List<Layer> layers;
public void draw(Graphics g)
{
for (Layer layer : layers)
layer.draw(g);
}
}
Changing the order of rendering is as simple as changing the order in the 'layers' list in a scene.
Are you looking to put foreground images into a background image? If yes, then the following code will help:
public class Image {
public static void main(String args[]) throws IOException {
BufferedImage bgImage = ImageIO.read(new File("1.jpg"));
BufferedImage fgImage =ImageIO.read(new File("2.jpg"));
BufferedImage overlayedImage = overlay(bgImage, fgImage);
if (overlayedImage != null) {
File outputfile = new File("3.jpg");
ImageIO.write(overlayedImage, "jpg", outputfile);
} else {}
}
public static BufferedImage overlay(BufferedImage bgImage,
BufferedImage fgImage) {
Graphics2D g = bgImage.createGraphics();
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g.drawImage(bgImage, 0, 0, null);
g.drawImage(fgImage, 0, 0, null);
g.dispose();
return bgImage;
}
}
I was surprised to find that View.onDraw() wipes the canvas before drawing. This isn't what I want. What's a good way to retain the previous drawings so that I only need to draw the changes on top of the previous drawings during each call?
There are couple of APIs to define dirty rect for view to invalidate:
public void invalidate(Rect dirty)
public void invalidate(int l, int t, int r, int b)
However more likely the View is redrawn all the way, when for example you swipe it, or another View above it in Z order get's invalidated.
You can try to use setDrawingCacheEnabled and if you are doing the drawing yourself, be sure to cache Bitmaps you are drawing.
I implemented a SurfaceView. Then in I created my own bitmap and canvas that I draw into, to draw to the screen I draw the bitmap to the screen.
For example:
private Canvas myCanvas = null;
private Bitmap myCanvasBitmap = null;
private Matrix identityMatrix;
public mySurfaceCreated(canvasWidth, canvasHeight){
myCanvasBitmap = Bitmap.createBitmap(canvasWidth, canvasHeight, Bitmap.Config.ARGB_8888);
myCanvas = new Canvas();
myCanvas.setBitmap(myCanvasBitmap);
identityMatrix = new Matrix();
}
public void myDraw(Canvas canvas) {
// Draw stuff onto myCanvas, NOT the canvas given by the android OS.
drawStuff(myCanvas);
// Draw onto the canvas given by the android OS.
canvas.drawBitmap(myCanvasBitmap, identityMatrix, null);
}
This way I do not need to draw the entire canvas each time, but instead only the needed changes. Note that the canvas created by the OS is still completely redrawn each time.
I'm new in libdgx developement and also in game developement. I am reading the book "Learning Libgdx Game Development" from Andreas Oehlke and I am trying to develop my own game in parallel.
I have a problem when I try to add the background. In the book, he uses a color, so it's very simple. But I want to add an image from a texture atlas. The image is to small to recover all the screen, so I want to repeat it. I can't use regBackground.setWrap(TextureWrap.Repeat, TextureWrap.Repeat) because regBackground is not a texture. How i can resolve my problem properly?
public class Background extends AbstractGameObject {
private TextureRegion regBackground;
public Background () {
init();
}
private void init () {
dimension.set(1f, 1f);
regBackground = Assets.instance.levelDecoration.background;
}
public void render (SpriteBatch batch) {
TextureRegion reg = null;
reg = regBackground;
batch.draw(reg.getTexture(),
position.x, position.y,
origin.x, origin.y,
dimension.x, dimension.y,
scale.x, scale.y,
rotation,
reg.getRegionX(), reg.getRegionY(),
reg.getRegionWidth(), reg.getRegionHeight(),
false, false);
}
}
In my Assets class, I have this code to find the region in the texture atlas :
public class AssetLevelDecoration {
public final AtlasRegion background;
public AssetLevelDecoration (TextureAtlas atlas) {
background = atlas.findRegion("background");
}
}
I progressed in solving my problem. I use the setWrap method to repeat my texture :
public class Background extends AbstractGameObject {
private TextureRegion regBackground;
public Background (int width, int heigth) {
init(width, heigth);
}
private void init (int width, int heigth) {
dimension.set(width, heigth);
regBackground = Assets.instance.levelDecoration.background;
origin.x = -dimension.x/2;
origin.y = -dimension.y/2;
}
public void render (SpriteBatch batch) {
TextureRegion reg = null;
reg = regBackground;
Texture test = reg.getTexture();
test.setWrap(TextureWrap.Repeat, TextureWrap.Repeat);
batch.draw(test,
position.x + origin.x, position.y + origin.y,
test.getWidth(), test.getHeight(),
reg.getRegionX(), reg.getRegionY(),
reg.getRegionWidth(), reg.getRegionHeight()
);
}
}
Now, I obtain this, but I just want to repeat my background image (wood square).
http://s24.postimg.org/c1m92ffwx/Capture_du_2013_11_12_15_49_03.jpg
The problem is that the getTexture() recover the all image and not only my background. How can I fix this?
I would just add a comment but I don't have the rep.
To solve the issue of the repeating of the whole texture instead of only the wooden square you have 2 choices. A) separate the textureregion onto a separate texture. B) loop over the to repeat the draw, which should be negligible in terms of performance.
http://badlogicgames.com/forum/viewtopic.php?f=11&t=8883
a simpler approach will be
batch.draw(imageReference,startX,startY,widthOfScreen,heightOfScreen);
batch.draw() is an overloaded method so use only those parameter u need
the syntax is just a pseudo code
MOst importantlu This may give image stretching(depending on image).
I have created an introduction to images including repeating texture here: https://libgdx.info/basic_image/
I hope it helps
This creates an image along this line: