I want to make a very simple OpenGL application (using freeglut) that just puts text on the screen. However, the Text is flipped (x-axis):
static char *string = "Hello World!\nHi";
void draw(void);
int main(int argc, char **argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(WIN_WIDTH, WIN_HEIGHT);
glutInitWindowPosition(100, 100);
glutCreateWindow("hello!");
glClearColor(0.0, 0.0, 0.0, 1.0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0f, WIN_WIDTH, WIN_HEIGHT, 0.0f, 0.0f, 1.0f);
glutDisplayFunc(&draw);
glutMainLoop();
return(0);
}
void draw(void) {
glClear(GL_COLOR_BUFFER_BIT);
glPushMatrix();
for (char* p = string; *p; p++)
glutStrokeCharacter(GLUT_STROKE_MONO_ROMAN, *p);
glPopMatrix();
glFlush();
}
You've mirrored the y axis with the orthographic projection. The standard y-axis points up, not down. One possibility is to change the projection:
glOrtho(0.0f, WIN_WIDTH, WIN_HEIGHT, 0.0f, 0.0f, 1.0f);
glOrtho(0.0f, WIN_WIDTH, 0.0f, WIN_HEIGHT, 0.0f, 1.0f);
Another possibility is to flip the y-coordinates with glScalef and adjust the position with glTranslatef:
void draw(void)
{
glClear(GL_COLOR_BUFFER_BIT);
glPushMatrix();
glTranslatef(0.0f, 100.0f, 0.0f);
glScalef(1.0f, -1.0f, 1.0f);
for (char* p = string; *p; p++)
glutStrokeCharacter(GLUT_STROKE_MONO_ROMAN, *p);
glPopMatrix();
glFlush();
}
Related
I've drawn a square in opengl in 1st window , and when I try to draw some object on second screen .I am getting a blank screen.
here is my code.
#include <GL/glut.h>
void display() {
glClearColor(1.0f, 0.0f, 0.0f, 1.0f); // Set background color to black and opaque
//glClear(GL_COLOR_BUFFER_BIT); // Clear the color buffer (background)
// Draw a Red 1x1 Square centered at origin
glBegin(GL_QUADS); // Each set of 4 vertices form a quad
glColor3f(0.0f, 1.0f, 0.0f); // Red
glVertex2f(-0.5f, -0.5f); // x, y
glVertex2f( 0.5f, -0.5f);
glVertex2f( 0.5f, 0.5f);
glVertex2f(-0.5f, 0.5f);
glEnd();
glFlush(); // Render now
}
void displayc2()
{
glClear(GL_COLOR_BUFFER_BIT); // Clear the color buffer (background)
glClearColor(1.0f, 0.0f, 0.0f, 1.0f); // Set background color to black and opaque
glBegin(GL_QUADS); // Each set of 4 vertices form a quad
glColor3f(0.0f, 1.0f, 0.0f); // green
glVertex2f(-0.5f, -0.5f); // x, y
glVertex2f( 0.5f, -0.5f);
glVertex2f( 0.5f, 0.5f);
glVertex2f(-0.5f, 0.5f);
glEnd();
}
void keycb(unsigned char key,int x , int y)
{
int win2;
if(key=='a') exit(0);
else if(key == 'b')
{
win2 = glutCreateWindow("window 2");
glutInitWindowSize(450, 450); // Set the window's initial width & height
glutInitWindowPosition(50, 50);
glutDisplayFunc(displayc2);
glutMainLoop(); // Enter the event-processing loop
}
}
int main(int argc, char** argv) {
int win1;
glutInit(&argc, argv); // Initialize GLUT
win1 = glutCreateWindow("OpenGL Setup Test"); // Create a window with the given title
glutInitWindowSize(450, 450); // Set the window's initial width & height
glutInitWindowPosition(50, 50); // Position the window's initial top-left corner
glutDisplayFunc(display); // Register display callback handler for window re-paint
glutKeyboardFunc(keycb);
glutMainLoop(); // Enter the event-processing loop
return 0;
}
What I am trying to do is , when I press the character 'b' on my keyboard , it should display a second screen . The first screen and the object are coming successfully But,here I am getting the second screen but i am not getting the object in the second screen.the second screen is blank in this case. tell me whats wrong in this code or is there any other way to acheive this ?
I am doing opengl in ubuntu 18.04 using C programming.
Some remarks to make your problem work:
before using glutDisplayFunc, you must select the window. If you have only one window, the question does not ask, but if you have two, you must call glutSetWindow(...) before.
note too that glutInitWindow... function work for the next window to be created.
glutMainLoop should be called once.
And finally, do not forget to call glFlush() at the end of display functions:
#include <GL/glut.h>
int win1, win2;
void display()
{
glClearColor(1.0f, 0.0f, 0.0f, 1.0f); // Set background color to black and opaque
glBegin(GL_QUADS); // Each set of 4 vertices form a quad
glColor3f(1.0f, 0.0f, 0.0f); // Red
glVertex2f(-0.5f, -0.5f); // x, y
glVertex2f(0.5f, -0.5f);
glVertex2f(0.5f, 0.5f);
glVertex2f(-0.5f, 0.5f);
glEnd();
glFlush(); // Render now
}
void displayc2()
{
glClear(GL_COLOR_BUFFER_BIT); // Clear the color buffer (background)
glClearColor(1.0f, 0.0f, 0.0f, 1.0f); // Set background color to black and opaque
glBegin(GL_QUADS); // Each set of 4 vertices form a quad
glColor3f(0.0f, 1.0f, 0.0f); // green
glVertex2f(-0.5f, -0.5f); // x, y
glVertex2f(0.5f, -0.5f);
glVertex2f(0.5f, 0.5f);
glVertex2f(-0.5f, 0.5f);
glEnd();
glFlush(); // Render now
}
void keycb(unsigned char key, int x, int y)
{
if (key == 'a')
exit(0);
else if (key == 'b'&&win2==0) {
glutInitWindowSize(450, 450);
glutInitWindowPosition(250, 250);
win2 = glutCreateWindow("window 2");
// Select the window for glutDisplayFunc
glutSetWindow(win2);
glutDisplayFunc(displayc2);
}
}
int main(int argc, char **argv)
{
glutInit(&argc, argv); // Initialize GLUT
glutInitWindowSize(450, 450); // Set the window's initial width & height
glutInitWindowPosition(50, 50); // Position the window's initial top-left corner
win1 = glutCreateWindow("OpenGL Setup Test"); // Create a window with the given title
glutDisplayFunc(display); // Register display callback handler for window re-paint
glutKeyboardFunc(keycb);
glutMainLoop(); // Enter the event-processing loop
return 0;
}
I do not understand how this main function works. I have a display function, which uses glDrawArrays, but I do not see it being called. I only see it being used as a parameter for glutDisplayFunction.
Here is my main:
int main(int argc, char** argv){
// Set up the window
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGB);
glutInitWindowSize(800, 600);
glutCreateWindow("Hello Triangle");
// Tell glut where the display function is
glutDisplayFunc(display);
// A call to glewInit() must be done after glut is initialized!
GLenum res = glewInit();
// Check for any errors
if (res != GLEW_OK) {
fprintf(stderr, "Error: '%s'\n", glewGetErrorString(res));
return 1;
}
// Set up your objects and shaders
init();
// Begin infinite event loop
glutMainLoop();
return 0;
}
The problem is, I need to create two different triangles, on the same window, using seperate VAOs and VBOs. I've created the seperate VAO and VBO for my second triangle. However, I do not see how I am meant to generate and link my buffers, draw my arrays, switch to my second buffer, and draw those arrays, when I do not even know when my display function is being called.
My display function looks like this:
void display(){
glClear(GL_COLOR_BUFFER_BIT);
// NB: Make the call to draw the geometry in the currently activated vertex buffer. This is where the GPU starts to work!
glDrawArrays(GL_TRIANGLES, 0, 3);
glutSwapBuffers();
}
All operations could be done in separate function named asyouwant called from main
example:
#include <GL/glut.h>
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE);
glutInitWindowSize(300, 300);
glutInitWindowPosition(100, 100);
glutCreateWindow("Hello world :D");
glutDisplayFunc(displayMe); // = > draw in displayme function
glutMainLoop();
return 0;
}
void displayMe(void)
{
glClear(GL_COLOR_BUFFER_BIT);
glBegin(GL_POLYGON);
glVertex3f(0.0, 0.0, 0.0);
glVertex3f(0.5, 0.0, 0.0);
glVertex3f(0.5, 0.5, 0.0);
glVertex3f(0.0, 0.5, 0.0);
glEnd();
// a second geoform
glBegin(GL_POLYGON);
glVertex3f(0.0, 0.0, 0.0);
glVertex3f(-0.5, 0.0, 0.0);
glVertex3f(-0.5, -0.5, 0.0);
glVertex3f(0.0, -0.5, 0.0);
glEnd();
glFlush();
}
As complement: for VAO and buffer
1- Init (declare VAO , declare buffer of vertices, ...)
GLuint VaoID;
glGenVertexArrays(1, &VaoID);
glBindVertexArray(VaoID);
// An array of 3 vectors which represents 3 vertices
static const GLfloat g_vertex_buffer_data[] = {
-1.0f, -1.0f, 0.0f,
1.0f, -1.0f, 0.0f,
0.0f, 1.0f, 0.0f,
};
Once time only
// This will identify our vertex buffer
GLuint vertexbuffer;
// Generate 1 buffer, put the resulting identifier in vertexbuffer
glGenBuffers(1, &vertexbuffer);
// The following commands will talk about our 'vertexbuffer' buffer
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
// Give our vertices to OpenGL.
glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data, GL_STATIC_DRAW);
2- Use it (bind and draw in display fucntion)
// 1st attribute buffer : vertices
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glVertexAttribPointer(
0, // attribute 0. No particular reason for 0, but must match the layout in the shader.
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
// Draw the triangle !
glDrawArrays(GL_TRIANGLES, 0, 3); // Starting from vertex 0; 3 vertices total -> 1 triangle
glDisableVertexAttribArray(0);
I have small code drawing a square initially but when I maximize the window it changes to rectangle. I know this has do with aspect ratio and when I add glutReshapeFunc(Reshape); call it works perfectly, I mean after maximizing the window, it remains square only. ReshapFunc is called every time display is modified and before the first display as well.
I am not getting just by adding reshapefunc, how it maintains aspect ratio. Please help me understanding this. I am copying my code here:
void display()
{
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(0.5, 0.5, 1.0);
glBegin(GL_POLYGON);
glVertex2f(-0.5, -0.5);
glVertex2f(0.5, -0.5);
glVertex2f(0.5, 0.5);
glVertex2f(-0.5, 0.5);
glEnd();
glutSwapBuffers();
glFlush();
}
void Reshape(int w, int h) {
glutPostRedisplay();
}
void init()
{
glClearColor(1.0, 0.0, 1.0, 0.0);
glColor3f(1.0, 1.0, 1.0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(-1.0, 1.0, -1.0, 1.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
glutInitWindowSize(500, 500);
glutInitWindowPosition(200, 200);
glutCreateWindow("basics");
glutDisplayFunc(display);
// If I comment this, it will become rectangle.
glutReshapeFunc(Reshape);
init();
glutMainLoop();
}
Your problem is related to the use of gluOrtho2D (...). If you want to preserve aspect ratio, your projection matrix needs to be defined based on the dimensions of your window.
I suggest you do this in your reshape function:
GLdouble aspect = (GLdouble)w / (GLdouble)h;
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
gluOrtho2D (-1.0 * aspect, 1.0 * aspect, -1.0, 1.0);
glMatrixMode (GL_MODELVIEW);
glViewport (0, 0, w, h);
Here is a simple opengl program by me. I'm trying to clear the screen before I draw a triangle. I've called glClear() in my init() function, however, it seemed that it failed to clear the screen.
#include <stdio.h>
#include <stdlib.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>
void myIdleFunc()
{
glBegin(GL_TRIANGLES);
{
glColor3f(1.0f, 1.0f, 1.0f);
glVertex2f(0.0f, 1.0f);
glVertex2f(-1.0f, -1.0f);
glVertex2f(1.0f, -1.0f);
}
glEnd();
glFlush();
usleep(1000000);
}
void init()
{
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glFlush();
}
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE);
glutCreateWindow("Hello, World!");
init();
glutIdleFunc(myIdleFunc);
glutMainLoop();
return 1;
}
Here is a screen-shot, the text is from the gnome terminal in the back ground.
Where's your display callback? You shouldn't use the idle function for drawing.
All drawing needs to take place in the appropriate callbacks, the GL context might not be active until glutMainLoop starts running, and with no active context, your commands simply get ignored (without a context, there might not even be a place to store errors for retrieval with glGetError).
NOTE: Usually you want to clear the buffer at the beginning of every frame. You might get away with clearing just once with single-buffering, but double-buffering is better and requires you to somehow render the entire area between each swap.
Your problem is, that you do clear the screen in your initialization code. But you need to clear it every frame, so right at the start of your display (or in your case idle) function.
I don't use GLUT but a really simple way to display something like this is:
while( !done ) { /* Loop until done. Do drawing. */
glClear( GL_COLOR_BUFFER_BIT);
glLoadIdentity();
glBegin(GL_TRIANGLES);
{
glColor3f(1.0f, 1.0f, 1.0f);
glVertex2f(0.0f, 1.0f);
glVertex2f(-1.0f, -1.0f);
glVertex2f(1.0f, -1.0f);
}
glEnd();
glFlush();
SwapBuffers( );
etc... event handling....
}
Run this code and probably you will get the solution.
#include<GL/gl.h>
#include<GL/glut.h>
#include<stdio.h>
double x_0 = -100;
double y_0 = -25;
double x_1 = 100;
double y_1 = -25;
double x_2 = 100;
double y_2 = 25;
double x_3 = -100;
double y_3 = 25;
void
init(void)
{
/*initialize the x-y co-ordinate*/
glClearColor(0,0,0,0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(-320, 319,-240, 239);
glClear(GL_COLOR_BUFFER_BIT);
glFlush();
}
void
drawRectangle()
{
glBegin(GL_LINES);
glVertex2d(x_0, y_0);
glVertex2d(x_1, y_1);
glVertex2d(x_1, y_1);
glVertex2d(x_2, y_2);
glVertex2d(x_2, y_2);
glVertex2d(x_3, y_3);
glVertex2d(x_3, y_3);
glVertex2d(x_0, y_0);
glEnd();
glFlush();
}
int
main(int argc, char *argv[])
{
double x_0, y_0, x_1, y_1;
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(640, 480);
glutInitWindowPosition(400, 400);
glutCreateWindow("Clear Screen");
init();
drawRectangle();
/* clear the screen. You can uncomment following three lines to view the effect of clearing */
// glClearColor(0, 0, 0, 0);
// glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// /* don't forget to flush */
// glFlush();
/***/
glutMainLoop();
}
Compile and run -
gcc file.c -lglut -lGLU -lGL
./a.out
I'm having trouble getting a texture loaded with SOIL to show up properly on this quad. In case it's not clear, I'm just writing up a little 2D sprite engine, and this is the rendering portion (needs a bit of optimization without a doubt). I haven't done any OpenGL in a couple months, and I'm admittedly quite rusty.
#include <OpenGL/OpenGL.h>
#include <GLUT/GLUT.h>
#include "SOIL.h"
#include <stdio.h>
GLuint linktex;
void drawSprite(GLint left, GLint right, GLint bottom, GLint top, GLuint texture){
//Draw clockwise
glColor3f(1.0, 1.0, 1.0);
glBindTexture(GL_TEXTURE_2D, texture);
glBegin(GL_QUADS);
glTexCoord2i(1,1); glVertex2i(right , top);
glTexCoord2i(1,0); glVertex2i(right , bottom);
glTexCoord2i(0,0); glVertex2i(left , bottom);
glTexCoord2i(0,1); glVertex2i(left , top);
glEnd();
}
void display(void){
glClearColor(0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity();
glOrtho(0.0, 240.0, 0.0, 160.0, -1.0, 1.0);
drawSprite(50, 82, 50, 82, linktex);
glFlush();
}
void reshape(int w, int h){
glViewport(0, 0, (GLsizei)w, (GLsizei)h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
}
void init(){
glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glFrontFace(GL_CW);
GLuint linktex = SOIL_load_OGL_texture(
"link.png",
SOIL_LOAD_AUTO,
SOIL_CREATE_NEW_ID,
SOIL_FLAG_INVERT_Y
);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR);
if( 0 == linktex )
{
printf( "SOIL loading error: '%s'\n", SOIL_last_result());
}
}
int main (int argc, char **argv) {
glutInit (&argc, argv);
glutInitDisplayMode (GLUT_SINGLE);
glutInitWindowSize (240, 160);
glutInitWindowPosition (100, 100);
glutCreateWindow ("Test");
glutDisplayFunc (display);
glutReshapeFunc (reshape);
glutMainLoop();
init();
return 0;
}
It looks like when you are loading the texture, you are assigning the id to a local variable linktex instead of the global you declared at the beginning of the file.
When you reference linktex in the void display(void); method, the texture is un-initialized.
Try changing your call to load the texture to :
// comment out the type declaration, to assign to the global instead of a local
/*GLuint*/ linktex = SOIL_load_OGL_texture(
"link.png",
SOIL_LOAD_AUTO,
SOIL_CREATE_NEW_ID,
SOIL_FLAG_INVERT_Y
);