I am using OpenGL Shading language along with SDL. I have a static scene with moving objects and the general structure of program is as follows:
initialize(){
//init meshes
}
display(){
//draw commands for static scene
//draw commands for moving objects
}
main()
{
initialize()
while(repeat)
{
display();
//swap buffers or flush drawing commands
}
}
I need to draw static 'scene' but drawing it only once can be sufficient unlike moving objects. Is there a way to redraw only what needs to be redrawn?
If you're making 3D game, you can put entire static scene into single VBO and then draw it with single function call.
If you're making 2D game, you can draw it to texture and then draw a fullscreen quad with this texture.
Related
I've experienced a problem when trying to declare an identifier. The main part is textureBackground.loadFromFile("graphics/background.png");
where textureBackground is the one being underlined
I've tried adding parentheses, changing uppercases, lower cases, check file locations, etc.
int main()
{
//Create a video mode object
VideoMode vm(1920, 1080);
// Create and open a window for game
RenderWindow window(vm, "Scarful!!!", Style::Fullscreen);
while (window.isOpen())
// Texture for graphic on cpu
Texture textureBackground;
// Load graphic into texture
textureBackground.loadFromFile("graphics/background.png");
// Make Sprite
Sprite spriteBackground;
// Attach texture to sprite
spriteBackground.setTexture(textureBackground);
// Set spritebackground to cover screen
spriteBackground.setPosition(0, 0);
{
/* Handle player input */
if (Keyboard::isKeyPressed(Keyboard::Escape))
{
window.close();
}
//Update Scene
//Draw Scene
window.clear();
//Draw Game Scene
window.draw(spriteBackground);
//Show everything we drew
window.display();
}
return 0;
}
Here,
while (window.isOpen())
// Texture for graphic on cpu
Texture textureBackground;
// Load graphic into texture
textureBackground.loadFromFile("graphics/background.png");
You are trying to do this:
while (window.isOpen()) {
// Variable goes out of scope outside of the loop...
Texture textureBackground;
}
textureBackground.loadFromFile("graphics/background.png");
// ^^^^^^^^^^^^^^^^^ is not available anymore...
And since textureBackground is out-of-scope you cannot modify it anymore... I suggest you wanted...
// Texture for graphic on cpu
Texture textureBackground;
// Load graphic into texture
textureBackground.loadFromFile("graphics/background.png");
// Make Sprite
Sprite spriteBackground;
// Attach texture to sprite
spriteBackground.setTexture(textureBackground);
// Set spritebackground to cover screen
spriteBackground.setPosition(0, 0);
while (window.isOpen()) {
// Other code goes here...
}
I've been developing a 2D Engine using SFML + ImGui.
The editor is rendered using ImGui and the scene window is a sf::RenderTexture where I draw the GameObjects and then is converted to ImGui::Image to render it in the editor.
Now I need to create a 3D Engine during this year in my Bachelor Degree but using SDL2 + ImGui and I want to recreate what I did with the 2D Engine.
I've managed to render the editor like I did in the 2D Engine using this Example that comes with ImGui.
But I don't know how to create an equivalent of sf::RenderTexture in SDL2, so I can draw the 3D scene there and convert it to ImGui::Image to show it in the editor.
If you can provide code will be better. And if you want me to provide any specific code tell me.
Here's my solution.
SDL2window::SDL2window()
{
SDL_Init(SDL_INIT_VIDEO);
window = SDL_CreateWindow(...);
renderer = SDL_CreateRenderer(window,...);
texture = SDL_CreateTexture(renderer,..., width, height);
// create another texture for your imgui window here
ImTexture = SDL_CreateTexture(renderer,..., tex_width, tex_height);
...
}
void SDL2window::update(Uint32 *framebuffer)
{
...
// update your main window is necessary
SDL_RenderCopyEx(renderer, texture, NULL, NULL, 0, 0, SDL_FLIP_VERTICAL);
// be care of the size of framebuffer
SDL_UpdateTexture(ImTexture, NULL, framebuffer, tex_width * sizeof(Uint32));
ImGui::Render();
ImGui_ImplSDLRenderer_RenderDrawData(ImGui::GetDrawData());
SDL_RenderPresent(renderer);
}
void SDL2window::MyImgui()
{
...
ImGui::Begin("My Texture");
ImGui::Image(ImTexture, ImVec2(tex_width, tex_height));
ImGui::End();
}
Then run MyImgui() in your main loop, it will work.
ImTexture Window
P.S. I like your SFML 2D engine's UI, it looks great.
Think you're looking for something like this:
// Create a render texture
SDL_Texture *target = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, width, height);
// Activate the render texture
SDL_SetRenderTarget(renderer, target);
// (Do your rendering here)
// Disable the render texture
SDL_SetRenderTarget(renderer, NULL);
// (Use the render texture)
I currently have two viewports in my game. One is for the information in the top (health, gold, magic, etc) and the other viewport shows the map area. I created my own custom mouse cursor using an image and I'm displaying that image just like any other and update the position based on my mouse cursor position. My only problem is that I can only draw that image on a viewport. I have it set the show up on the map area, and when I move my mouse to the top; it won't display on the information area. It just leaves the window. So the first thing I did (I knew it wouldn't work, but tested it anyways) was to draw the mouse on both viewports. But that shows two mouse cursors when moving to the top of the screen (LOL). My question is how can I get the mouse image to draw on the screen using screen (or window) coordinates, outside of the viewport. Does that make sense? I want to be able to move the mouse anywhere on the screen so I can click on items in the map viewport as well as the information viewport.
My viewport class is very simple:
Viewport.h
#pragma once
#include <SDL.h>
class Viewport
{
public:
Viewport(int x, int y, int width, int height);
~Viewport();
SDL_Rect GetViewport();
private:
SDL_Rect viewport;
};
Viewport.cpp
#include "Viewport.h"
Viewport::Viewport(int x, int y, int width, int height)
{
viewport.x = x;
viewport.y = y;
viewport.w = width;
viewport.h = height;
}
Viewport::~Viewport()
{
}
SDL_Rect Viewport::GetViewport()
{
return viewport;
}
In my Game class I initialize two variables for each Viewport
Viewport hud;
Viewport arena;
In the constructor I initialize them to the appropriate sizes. Then In my game drawing function I set the viewports accordingly and draw in the appropriate viewport.
// gfx is my Graphics class. Everything that has to do with drawing is inside that class; including setting the viewport for the render.
gfx.SetViewport(hud.GetViewport());
// This is where I would draw stuff on the hud viewport
gfx.SetViewport(arena.GetViewport());
// Where I draw the map, enemies, etc.
my SetViewport function is setup like this:
void Graphics::SetViewport(SDL_Rect viewport)
{
SDL_RenderSetViewport(renderer, &viewport);
}
How can I get my mouse image to be drawn (with the viewport not relavant). Below are some images of what I'm talking about.
Only displaying on the arena and won't show on the hud.
Displays the mouse on both if I draw the mouse on both viewports
Edit: I made a workaround which will work for this game
I'm just worried that it won't be good for performance on a bigger and larger game
I created another viewport that is as large as the screen (window) and I'm drawing the mouse to that viewport.
Super late answer but here it is. Calling SDL_RenderSetViewport(renderer, NULL) will reset the viewport to the entire window.
You should do this before you call SDL_PollEvent as well because if you poll mouse events when a viewport is active the mouse motion event coordinates will be relative to the viewport and not the main window.
My task is to render a set of 50 RGB frames using openGL's glut library.
I tried: In 3D cube rotation, i have a set of vertices using which i render it to the window. However, in case of rendering the RGB frames what should be done? Below is the code using which i render my 3d cube:
#include <glut.h>
GLfloat vertices[24]={-1.0,-1.0,-1.0,1.0,-1.0,-1.0,1.0,1.0,-1.0,-1.0,1.0,-1.0,-1.0,-1.0,1.0,1.0,-1.0,1.0,1.0,1.0,1.0,-1.0,1.0,1.0};
GLfloat colors[24]={-1.0,-1.0,-1.0,1.0,-1.0,-1.0,1.0,1.0,-1.0,-1.0,1.0,-1.0,-1.0,-1.0,1.0,1.0,-1.0,1.0,1.0,1.0,1.0,-1.0,1.0,1.0};
GLubyte cubeIndices[24]={0,3,2,1,2,3,7,6,0,4,7,3,1,2,6,5,4,5,6,7,0,1,5,4};
static GLfloat theta[3]={0,0,0};
static GLint axis=2;
void display()
{
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glRotatef(theta[0],1.0,0.0,0.0);
glRotatef(theta[1],0.0,1.0,0.0);
glRotatef(theta[2],0.0,0.0,1.0);
glDrawElements(GL_QUADS,24,GL_UNSIGNED_BYTE,cubeIndices);
glutSwapBuffers();
glFlush();
}
void spinCude()
{
theta[axis]+=2.0;
if(theta[axis]>360.0)
theta[axis]-=360.0;
display();
}
void init()
{
glMatrixMode(GL_PROJECTION);
glOrtho(-2.0,2.0,-2.0,2.0,-10.0,10.0);
glMatrixMode(GL_MODELVIEW);
}
void mouse(int btn,int state, int x,int y)
{
if(btn==GLUT_LEFT_BUTTON&& state==GLUT_DOWN) axis=0;
if(btn==GLUT_MIDDLE_BUTTON&& state==GLUT_DOWN) axis=1;
if(btn==GLUT_RIGHT_BUTTON&& state==GLUT_DOWN) axis=2;
}
void main(int argc, char **argv)
{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGB|GLUT_DEPTH);
glutInitWindowSize(500,500);
glutCreateWindow("Simple YUV Player");
init();
glutDisplayFunc(display);
glutIdleFunc(spinCude);
glutMouseFunc(mouse);
glEnable(GL_DEPTH_TEST);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3,GL_FLOAT,0,vertices);
//glEnableClientState(GL_COLOR_ARRAY);
glVertexPointer(3,GL_FLOAT,0,colors);
glutMainLoop();
}
Can anyone suggest me some example or tutorial such that i can modify above code to display RGB frames.
Once you have your RGB-Frame as raw-data in memory things are pretty straight-forward. Create a texture using glGenTextures, bind it using glBindTexture and upload the data via glTexImage2D or glTexSubImage2D. Then render a fullscreen quad or whatever you like with that texture. The benefit of that is that you could render multiple 'virtual' TVs in your scene just by rendering multiple quads with that same texture, imagine a TV-Store where the same video runs on dozen of TVs.
glDrawPixels might also work but it is much less versatile.
I don't know if uploading via texture is the way to go (hardware accelerated movie playback programs like VLC are most likely doing something far more advanced), but it should be a good start.
As Marius already suggested, implement texture mapping first. It's rather straigth forward any texture mapping tutorial will do.
Rendering frames are not the best with OpenGL you should try to avoid them as much as you can since it may involve a client -> host memory copy which is really costy ( takes too much time ) or simply it just takes up too much memory. Anyways if you really have to do it just generate as much textures as you need with glGenTextures load them up with the textures by glTexImage2D and then flip over the frames with a simple loop in each frame.
P.S. Judging by your application's name "YUV Player" you may also need to convert the input data since OpenGL mostly uses RGB not YUV.
I have stumbled upon a problem here while writing a program in which I am animating shapes using openGL.
Currently in the program, I am creating some shapes, with the following snippet
for(int i=50;i<=150;i=i+50){
for(int j=50;j<=750;j=j+200){
//Draw rectangle shape at position(j,i); //shape has additional capability for animations }
}
which gives me this output:
Now, I have to resize these rectangles and move them all to another position. I have the final target Point for the first rectangle rectangle at position[0][0] where it should be moved. However, when I animate the size of these rectangles with something like
rectangle.resize(newWidth, newHeight, animationTime);
the rectangle for obvious reasons do not stick together, and I get something like:
I am looking for something like Grouping which can bind these shapes together, so that even when different animations like resize (and motion etc.) are applied, the vertices or the boundaries should be touching together.
Note that Grouping is the main thing here. I might have a requirement in the future in which I would have to group the two rectangles in the last column, where independent animations (like rotations) already happening on them. So, I picture this something like a plane/container having these two rectangle and that plane/container itself can be animated for position etc. I am fine with algorithm/concept and not the code.
Instead of animating the geometry on the CPU, animate scale/position matrices on the CPU and leave the transformation of the geometry to the vertex shader via the MVP matrix. Use one and the same scale matrix for all the rectangles. (Or two matrices, if your scale factor is different in X and Y).
PS. Here's an example:
float sc = 0;
void init()
{
glMatrixMode (GL_MODELVIEW);
glLoadIdentity ();
}
void on_each_frame()
{
// do other things
// draw pulsating rectangles
sc += 0.02;
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glScalef((float)sin(sc) + 1.5f);
// draw rectangles as usual, **without** scaling them
glPopMatrix();
// do other things
}
Think about implementing a 'DrawableAnimatableObject' which is a high level 3D object that is able to animate and draw itself, and contains your polygons (multiple rectangles in your case) as internal data. See the following incomplete code to give you an idea:
class DrawableAnimatableObject {
private:
Mesh *mesh;
Vector3 position;
Quaternion orientation;
Vector3 scale;
Matrix transform;
public:
DrawableAnimatableObject();
~DrawableAnimatableObject();
//update the object properties for the next frame.
//it updates the scale, position or orientation of your
//object to suit your animation.
void update();
//Draw the object.
//This function converts scale, orientation and position
//information into proper OpenGL matrices and passes them
//to the shaders prior to drawing the polygons,
//therefore no need to resize the polygons individually.
void draw();
//Standard set-get;
void setPosition(Vector3 p);
Vector3 getPosition();
void setOrientation(Quaternion q);
Quaternion getOrientation();
void setScale(float f);
Vector3 getScale();
};
In this code, Mesh is a data structure that contains your polygons. Simply put, it can be a vertex-face list, or a more complicated structure like half-edge. The DrawableAnimatableObject::draw() function should look something like this:
DrawableAnimatableObject::draw() {
transform = Matrix::CreateTranslation(position) * Matrix::CreateFromQuaternion(orientation) * Matrix::CreateScale(scale);
// in modern openGL this matrix should be passed to shaders.
// in legacy OpenGL you will apply this matrix with:
glPushMatrix();
glMultMatrixf(transform);
glBegin(GL_QUADS);
//...
// Draw your rectangles here.
//...
glEnd();
glPopMatrix();
}