I'm working on a scroll-box in minecraft.
The scroll-box has one problem, some controls will render outside of the box, so i decided to look up if it's possible to prevent that.
I found stencils, but it doesn't work out, maybe i did something wrong?
GL11.glEnable(GL11.GL_BLEND);
GL11.glEnable(GL11.GL_STENCIL_TEST);
GL11.glEnable(GL11.GL_TEXTURE_2D);
GL11.glDisable(GL11.GL_DEPTH_TEST);
GL11.glClearStencil(0);
GL11.glClear(GL11.GL_STENCIL_BUFFER_BIT);
GL11.glStencilFunc(GL11.GL_ALWAYS, 1, 1);
GL11.glStencilOp(GL11.GL_KEEP, GL11.GL_KEEP, GL11.GL_REPLACE);
and this is the line of rendering the scroll-box background:
Vector4d color = new Vector4d(140, 140, 140, 255);
RenderHelper2D.drawGradientRect(1, 1, this.width-1, this.height-1, color, color);
http://i.imgur.com/Ycg7AKo.png (It's the black outlined gray pattern)
GL11.glBlendFunc(GL11.GL_ONE_MINUS_DST_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
GL11.glStencilFunc(GL11.GL_EQUAL, 1, 1);
GL11.glStencilOp(GL11.GL_KEEP, GL11.GL_KEEP, GL11.GL_KEEP );
render all objectives inside the scroll-box (the buttons). Which shouldn't be shown outside of the box.
gui.drawForeground(renderer);
and reset everything
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
GL11.glColorMask(true, true, true, true);
GL11.glDisable(GL11.GL_STENCIL_TEST);
I think you are looking for glScissor
It lets you basically assign a rectangular cropping window on your screen, and whatever you draw, nothing will ever be drawn outside of this rectangle.
Don't forget to call glEnable(GL_SCISSOR_TEST) before and glDisable(GL_SCISSOR_TEST) after you draw your scroll box. It won't work without the enable, and it won't stop without the disable ;)
Keep in mind that the values supplied to glScissor are integers for the origin and the width and height of the desired cropping window, the origin being defined as the lower left. Thus,
glEnable(GL_SCISSOR_TEST)
glScissor(0,0,100,100)
:: DRAW YOUR CONTROLS HERE ::
glDisable(GL_SCISSOR_TEST)
will create a 100x100 cropping window in the lower left corner of your screen.
You can use stencilbuffers if you want, but those are for more complicated tasks. Since UI usually works with rectangles, glScissor is perfect for it.
Related
I have a quad drawn on the screen, positioned at the top of the screen and centred. As I resize the screen so it is not as high, the quad appears to move in the opposite direction from what it should, IE, up at the same rate it should be going down on my monitor.
It is constantly being set to be at the top of the screen and centred each loop, before rendering.
this.location[0] = (Display.getWidth()/2)-(this.size[0]/2);
this.location[1] = 0;
Then I render the quad and print out its Y location. this consistently returns 0, no matter what I resize the window to. By printing out the mouse coordinates I can confirm that the top of the screen is 0 when it is resized. Why is it then, that even though I am setting the quad to be at 0, then rendering it exactly after, it still isn't drawn at 0?
Is there some Opengl or LWJGL concept I don't understand?
Here's the Opengl Setup code.
GL11.glEnable(GL_TEXTURE_2D);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0,Display.getWidth(),Display.getHeight(),0 ,1, -1);
glMatrixMode(GL_MODELVIEW);
Since nobody has answered this, and I have found a solution, inefficient as it may be, here's an answer.
I Changed the line
glOrtho(0,Display.getWidth(),Display.getHeight(), 0 ,1, -1);
to
glOrtho(0,Display.getWidth(), 0,Display.getHeight(),1, -1);
Which means instead of the top being the top, the top is now the bottom of the screen. I then had to create another variable inside my box class, called realY which is the actual y coordinate of the box/quad's left hand corner.
Then with some simple math (this.realY = (Display.getHeight() - this.location[1])-this.size[1];) I convert the input Y into the upside down version of itself, so 0 becomes the height of the screen, and vise versa
To me, this seems like a inefficient solution, and more of a workaround. If anyone has a better answer, please post it.
So i have a created a background which is 1920 x 1080 in size.
And i have a window that is 1280 x 720 (will not always be this size)
Now when i render the sprite using this code:
#Override
public void render(float delta)
{
Gdx.gl20.glClearColor(0.2F, 0.5F, 1F, 1F);
Gdx.gl20.glClear(GL20.GL_COLOR_BUFFER_BIT);
sb.begin();
sb.draw(Assets.splash_spr_bg, 0, 0);
sb.end();
}
The sprite appears in the window but not the whole sprite, just like 1/2 of it.
Now here's my question:
·How can i make the sprite fill the whole screen no matter what size the screen is?
Thanks for any help! :)
I recommend using Viewports for this: https://github.com/libgdx/libgdx/wiki/Viewports
Its a great way to handel screen sizes.
To make it fill the whole screen u probably have to try something like:
Picture1.setX(stage.getWidth() / 2 - Picture1.getWidth() / 2);
Picture1.setY(stage.gethight() - Picture1.getHeight() /)
In this example i use a stage, but it will work without just remember that u get the screen width and height instead or set them to 0,0 and place it under in the corner. Also notice that i cut the width in half, this is because it will otherwise always render outside your screen. Then u could try and use something like:
Picture1.setSize(stage.getWidth() / 2, stage.getHeight()):
the other way u could do it is by setting your viewport zoomed in on the picture (so the same size) that way it will also give you a full screen view even tho i dislike that idea, but thats a personal preference. Also this later one wont make your background look all stretched and pixelated because it isn't being resized, but if u take a picture thats big enough you also wont notice it in the first option.
Just mess around a little with it, its pretty easy.
Example of how to implement Viewport: http://pastebin.com/3SrWKcEg
I am using scene2d for a board game. I want the board to be zoomable and movable inside its assigned rectangular part of the screen, while the rest of the screen stays the same.
I have tried to use a separate stage for the board, but haven't found a way to initialise viewports and cameras that does this correctly.
I tried the following code in Screen.resize(int width, int height) as a test, but the boardStage becomes stretched vertically, and when zoomed in (like here), it fills the whole screen.
hudStage.setViewport(8, 12, true, 0, 12, width, height);
boardStage.setViewport(8, 8, true, 0, 10, width, width);
OrthographicCamera cam = (OrthographicCamera) boardStage.getCamera();
cam.zoom =.5f;
What is the correct way to do this?
We have implemented a similar zoom for our board game.
https://play.google.com/store/apps/details?id=net.peakgames.mobile.rummi.android
We are using a second camera which is zoomed:
A scissorStack is used to clip the second camera rendering area.
Second camera is enabled only when there is a touch/drag on the board.
we are changing the camera position as the user drags on the board.
hope this helps..
I think you want to use a scene2d ScrollPane instead of a new Stage. I'm not entirely sure how you'd do the zooming with this, but I think the scaling stuff should work.
I was trying to follow example codes to simply display a rectangle on a black background, but it didn't seem to be displaying. What I did was
private static void initGL(){
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0,Display.getWidth(),0,Display.getHeight(),-1,1);
glMatrixMode(GL_MODELVIEW);
glDisable(GL_DEPTH_TEST); //2D mode
glColor3f(0.5f, 0.0f, 1.0f);
glBegin(GL_QUADS);
glVertex2f(-0.75, 0.75);
glVertex2f(-0.75, -0.75);
glVertex2f(0.75, -0.75);
glVertex2f(0.75, 0.75);
glEnd();
}
It doesn't display anything on the screen except for a black background. Does anyone know what I might have done wrong? I'm using lwjgl in eclipse.
First things first: You only have to run the whole
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0,Display.getWidth(),0,Display.getHeight(),-1,1);
glMatrixMode(GL_MODELVIEW);
thing once during your program, probably shortly after you run Display.create().
Also, you're tessellating using the wrong vertices. You wrote
glVertex2f(-0.75, 0.75);
glVertex2f(-0.75, -0.75);
glVertex2f(0.75, -0.75);
glVertex2f(0.75, 0.75);
which means draw a rectangle from (-0.75, -0.75) pixels to (0.75, 0.75) pixels. This is too small to be noticed. My guess is you assumed glVertex2f deals with fractions of the display width. It does not. glVertex2f deals with actual coordinates, it just allows fractional pixels, unlike glVertex2i (this is useful believe it or not, it helps with smoother animations). Something like
glVertex2f(100F, 100F);
places a vertex at (100, 100), and is effectively equivalent to
glVertex2i(100, 100);
Also, remember that negative pixels will be rendered off the screen, because OpenGL's origin of the coordinate system, (0, 0), is in the lower left and behaves like the first quadrant from the coordinate system in math class, not like the traditional computer coordinate system with (0, 0) in the upper left.
As for the the black background, LWJGL's Display has a black background by default, so it's recommended to draw a quad with your background color that covers the entire display width and height. One quad won't really affect your performance.
glVertex2f uses same size units as your glOrtho so unless your display width and height are in units of ones, like 10 or less, you may not see anything!
In the two attached pictures, the desktop screenshot of libgdx functions as expected. The screenshot from my Galaxy Nexus is unfortunately not as expected. I am attempting to create a simple motion blur or trail effect.
Rendering as I expected on my desktop.
Not rendering as I expected on my Galaxy nexus.
The circle textures are drawn in a for loop during rendering and the effect is achieved with a pixmap using the RGBA of 0, 0, 0, 0.1f that is drawn before the circles.
screenClearSprite creation
Pixmap screenClearPixmap = new Pixmap(256, 256, Format.RGBA8888);
screenClearPixmap.setColor(Color.rgba8888(0, 0, 0, 0.1f));
screenClearPixmap.fillRectangle(0, 0, 256, 256);
screenClearTexture = new Texture(screenClearPixmap);
screenClearSprite = new Sprite(screenClearTexture);
screenClearSprite.setSize(screenWidth, screenHeight);
screenClearPixmap.dispose();
Render
batch.begin();
font.draw(batch, "fps:" + Gdx.graphics.getFramesPerSecond(), 0, 20);
screenClearSprite.draw(batch);
for (int i = 0; i < circleBodies.size(); i++) {
tempPos = circleBodies.get(i).getPosition();
batch.draw(circleTexture, (tempPos.x * SCALE) + screenWidthHalf
- circleSizeHalf, (tempPos.y * SCALE) + screenHeightHalf
- circleSizeHalf);
}
batch.end();
So, what did I do wrong? Perhaps there is a better way to get the 'motion blur' effect of movement?
Here is a different approach, where you clear your screen each time with solid color and no alpha.
This means that you will have to modify your code some. The good thing about this, is that the way you are doing it has some flaws: It will blur everything in motion, not just the balls. And can quickly produce ugly results/artefacts unless you are careful.
Do the same as you are doing now, but instead of drawing the balls to the batch, draw them onto a texture/bitmap/whatever. Then each frame add an alpha-blended image over the balls-image, and then draw the balls in their current position on top of that. Then add that image to your screen. Very much like you are doing now, except you draw to something else and keep it. This way you don't have to rely on the viewport you are drawing onto, and can keep everything separated.
This method is similar to drawing to an accumulation buffer.
Instead of doing it the way you are doing, you can keep track of the n latest positions of each ball. And then draw all of them each frame, with different alpha. This is very easy to implement. Can result in many drawing calls if you have many balls or a large n, but if it's not too much it shouldn't limit your fps and gives nice control.
Perhaps there is a better way to get the 'motion blur' effect of
movement?
in order to make motion blur in my game i use another approch "The particle effect" it works realy fine with me and i didn't have Android/Desktop problems or with different android devices
all you have to do is to use "Particle Effect Editor" of Libgdx and make your effect then load it in your project finally draw it at the same position you draw your object (and alos draw your object)
Tips to make the right effect file with Paticle Editor :
set (use) the same image of the object that you want to blur it motion in the particle effect
try to limit the count : the max number of particle allowed
Disable the "velocity" and "Angle"
parameter
Particle effect help to do motion effect
Hope this will help someone !