I am using cygwin SDL 1.2.15 using the latest cygwin
Here is my code using SDL and openGL
#include <SDL/SDL.h>
#include <SDL/SDL_opengl.h>
#include <iostream>
size_t sx=600, sy=600, bpp=32;
void render(void) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity(); // set location in front of camera
//glTranslated(0, 0, -10);
glBegin(GL_QUADS); // draw a square
glColor3d(1, 0, 0);
glVertex3d(-2, 2, 0);
glVertex3d( 2, 2, 0);
glVertex3d( 2, -2, 0);
glVertex3d(-2, -2, 0);
glEnd();
glFlush();
SDL_GL_SwapBuffers();
GLenum e;
while ((e =glGetError()) != GL_NO_ERROR)
std::cout<<"Error "<< e << std::endl;
}
int input(void) {
SDL_Event event;
while (SDL_PollEvent(&event))
if (event.type == SDL_QUIT || (event.type == SDL_KEYUP && event.key.keysym.sym == SDLK_ESCAPE)) return 0;
return 1;
}
and this is my main function
int main(int argc, char *argv[]) {
SDL_Surface *surf;
if (SDL_Init(SDL_INIT_EVERYTHING) != 0) return 0;
if (!(surf = SDL_SetVideoMode(sx, sy, bpp, SDL_OPENGL))) return 0;
glViewport(0, 0, sx, sy);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0, (float)sx / (float)sy, 1.0, 100.0);
glMatrixMode(GL_MODELVIEW);
glClearColor(0, 0, 0, 1);
glClearDepth(1.0);
glEnable(GL_DEPTH_TEST);
GLenum e;
while ((e =glGetError()) != GL_NO_ERROR)
std::cout<<"Error "<< e << std::endl;
for (;;) {
if (!input()) break;
render();
SDL_Delay(10);
}
SDL_FreeSurface(surf);
SDL_Quit();
return 0;
}
it compiles with no error but when I run it only the window shows up and now openGL rectangle..
You have setup a near plane to one :
gluPerspective(45.0, (float)sx / (float)sy, 1.0/*near plane*/, 100.0);
Everything that is closer to the camera is clipped.
Your quad lies in plane z = 0. Try moving it a bit backward.
glBegin(GL_QUADS); // draw a square
glColor3d(1, 0, 0);
glVertex3d(-2, 2, 5);
glVertex3d( 2, 2, 5);
glVertex3d( 2, -2, 5);
glVertex3d(-2, -2, 5);
glEnd();
I don't remember if Z is facing the camera, so you might need negative Z value.
You also need to pay attention to face culling. It might be better to deactivate it to be sure ( glDisable( GL_CULL_FACE ))
Try changing the black color of the SDL window. Some times it renders the drawing with black color...may be this helps!
Related
I'm trying to look at the square from the other side using the gluLookAt() function.
After using the function, nothing changes, although I expected that the corners of the square will change.
I set the camera point to the rightmost part of the world and look at its center, where the square is located.
He had to stretch out to the sides. Why hasn't anything changed?
Code:
#include "includes.h"
using namespace std;
constexpr auto FPS_RATE = 60;
int windowHeight = 600, windowWidth = 600, windowDepth = 600;
void init();
void idleFunction();
void displayFunction();
double getTime();
double getTime()
{
using Duration = std::chrono::duration<double>;
return std::chrono::duration_cast<Duration>(
std::chrono::high_resolution_clock::now().time_since_epoch()
).count();
}
const double frame_delay = 1.0 / FPS_RATE;
double last_render = 0;
void init()
{
glutDisplayFunc(displayFunction);
glutIdleFunc(idleFunction);
glViewport(0, 0, windowWidth, windowHeight);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-windowWidth / 2, windowWidth / 2, -windowHeight / 2, windowHeight / 2, -windowDepth / 2, windowDepth / 2);
glClearColor(0.0, 0.0, 0.0, 0.0);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
}
void idleFunction()
{
const double current_time = getTime();
if ((current_time - last_render) > frame_delay)
{
last_render = current_time;
glutPostRedisplay();
}
}
void displayFunction()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBegin(GL_POLYGON);
gluLookAt(-300, 0, 0,
0, 0, 0,
0, 1, 0);
glColor3f(1, 1, 1);
glVertex3i(-150, 150, 0);
glVertex3i(150, 150, 0);
glVertex3i(150, -150, 0);
glVertex3i(-150, -150, 0);
glEnd();
glutSwapBuffers();
}
int main(int argc, char* argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize(windowWidth, windowHeight);
glutInitWindowPosition((GetSystemMetrics(SM_CXSCREEN) - windowWidth) / 2, (GetSystemMetrics(SM_CYSCREEN) - windowHeight) / 2);
glutCreateWindow("Window");
init();
glutMainLoop();
return 0;
}
The issue is caused because gluLookAt() is call with in a glBegin/glEnd sequence. This is not allowed. You've to call gluLookAt before glBegin.
Once drawing of primitives was started by glBegin it is only allowed to specify vertex coordinates (glVertex) and change attributes (e.g. glColor, glTexCoord ...), till the drawn is ended (glEnd).
All other instruction will be ignored and cause a GL_INVALID_OPERATION error (error code 1282).
Further note, that glLookAt doesn't set a the current matrix. It defines a matrix and multiplies the current matrix by the new matrix. Set the matrix mode (glMatrixMode) and set Identity matrix by glLoadIdentity before gluLookAt.
With the view matrix
gluLookAt(-300, 0, 0, 0, 0, 0, 0, 1, 0);
you want "see" anything, because with that matrix the line of sight is set along the x-axis and you look at the 2 dimensional polygon from the side.
Note, the polygon is a 2D object. The size of the object appears different if you look at it from the front, from the side (then it is a line and not visible) or from an direction in between. The first 3 parameters of gluLookAt define the point of view the next 3 parameters define the point you look at. The vector from the point of view to the point you look at is the line of sight.
Probably yo want look along the z-axis:
void displayFunction()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0, 0, -300, 0, 0, 0, 0, 1, 0);
glBegin(GL_POLYGON);
glColor3f(1, 1, 1);
glVertex3i(-150, 150, 0);
glVertex3i(150, 150, 0);
glVertex3i(150, -150, 0);
glVertex3i(-150, -150, 0);
glEnd();
glutSwapBuffers();
}
You use Orthographic (parallel) projection. If you would use Perspective projection, then the projected size of the object would decrease, when the distance to the point of view increases. Perspective projection can be set by gluPerspective. e.g.:
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(90.0, (double)windowWidth / windowHeight, 0.1, 600.0);
I've got a taks from university and have to make a small example of solar system, the objects have to rotate etc. The problem is that when I do not call GluLookAt() everything looks fine, but I would like to change the view and when I call the function, there occurs that one orbit renders completely strangely.
I do not know if problem is with wrong creation of the first orbit, or with the proper values in gluLookAt parameters. Can anyone help?
Here's how it looks without calling gluLookAt():
Here's how it looks after gluLookAt():
Here's the code:
#include "stdafx.h"
#include <GL\glut.h>
#include <math.h>
GLfloat yRotated=1;
GLfloat movement = 0;
void drawCircle(float r) { // radius
glBegin(GL_LINE_LOOP);
for (int i = 0; i <= 300; i++) {
double angle = 2 * 3.14 * i / 300;
double x = r*cos(angle);
double y = r*sin(angle);
glVertex3d(x, y, -5.5);
}
glEnd();
}
void display(void) {
glMatrixMode(GL_MODELVIEW);
glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity();
//gluLookAt(5, 5, 5, 0, 0, -8, 0, 1, 0); // 3rd coordinate - depth
float radius1 = 6;
float radius2 = 1;
//first orbit
glColor3f(1, 1, 1);
glPushMatrix();
glTranslatef(0, 0, -5.5);
drawCircle(radius1);
glPopMatrix();
//second orbit with rotation
glPushMatrix();
glRotatef(yRotated, 0, 0, 1);
glPushMatrix();
glTranslatef(radius1 / 2, 0, 0);
drawCircle(radius2);
glPopMatrix();
glPopMatrix();
//first czajnik
glColor3f(0.8, 0.2, 0.1);
glPushMatrix();
glTranslatef(0.0, 0.0, -5.5);
// glScalef(1.0, 1.0, 1.0);
glRotatef(yRotated, 0, 0, 1);
glRotatef(90, 1, 0, 0);
glutSolidSphere(1,20,20);
//second czajnik
glPushMatrix();
glColor3f(0, 0, 1);
glTranslatef(radius1/2, 0, 0);
glRotatef(yRotated, 0, 1, 0);
glutSolidSphere(0.5, 20, 20);
//third czajnik
glPushMatrix();
glTranslatef(radius2, 0, 0);
glColor3f(1, 1, 0);
glRotatef(yRotated, 0, 1, 0);
glutSolidSphere(0.2, 20, 20);
glPopMatrix();
//second czajnik pop
glPopMatrix();
//first czajnik pop
glPopMatrix();
glFlush();
}
void idle() {
yRotated += 0.1;
Sleep(2);
display();
}
void myReshape(int w, int h) {
if (w == 0 || h == 0) return;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(70.0, (GLdouble)w / (GLdouble)h, 0.5, 20.0);
glViewport(0, 0, w, h);
}
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(900, 600);
glutCreateWindow("Solar system");
//window with a title
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glClearColor(0, 0, 0, 1.0);
glutDisplayFunc(display);
glutReshapeFunc(myReshape);
glutIdleFunc(idle);
glutMainLoop();
return 0;
}
Some of your objects are at different z values, e.g. 1st orbit at -5.5, second at 0, because you "popped" the matrix.
In general, do not do so many push\pops nested into each other, matrix stack isn't made of rubber.
There is more efficient circle drawing procedure than to calculate sine and cosine for each step, e.g. to get advantage of circle being a figure of rotation:
inline void circle(F32 r, U32 quality)
{
if (r < F_ALMOST_ZERO) return;
F32 th = M_PI /(quality-1);
F32 s = sinf(th);
F32 c = cosf(th);
F32 t;
F32 x = r;
F32 y = 0;
::glBegin (GL_LINE_LOOP);
for(U32 i = 0; i < quality; i++)
{
glVertex2f(x, y);
t = x;
x = c*x + s*y;
y = -s*t + c*y;
}
::glEnd();
}
it can be optimized further by using symmetry, but this one is the basis.
I wrote a simple parser for the ASCII STL format. When I try to render the triangles with the supplied normals, the resulting object is missing many faces:
This is how it should look like:
What I already tried:
explicitly disabled backface culling (though it shouldn't have been active before)
ensured that the depth buffer is enabled
Here is a minimal sample program which reproduces the error:
#include <SDL2/SDL.h>
#include <SDL2/SDL_main.h>
#include <SDL2/SDL_render.h>
#include <SDL2/SDL_opengl.h>
int main(int argc, char **argv) {
SDL_Init(SDL_INIT_VIDEO);
int screen_w=1280,screen_h=720;
SDL_Window * win = SDL_CreateWindow("test", 20, 20, screen_w, screen_h,
SDL_WINDOW_OPENGL);
SDL_GLContext glcontext = SDL_GL_CreateContext(win);
STLParser stlparser;
std::ifstream file(".\\logo.stl");
stlparser.parseAscii(file);
const auto& ndata = stlparser.getNData();
const auto& vdata = stlparser.getVData();
std::cout << "number of facets: " << ndata.size() << std::endl;
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
glMatrixMode(GL_PROJECTION | GL_MODELVIEW);
glLoadIdentity();
glScalef(1.f, -1.f, 1.f);
glOrtho(0, screen_w, 0, screen_h, -screen_w, screen_w);
glClearDepth(1.0f);
glDepthFunc(GL_LEQUAL);
glEnable(GL_DEPTH_TEST);
glDisable(GL_CULL_FACE);
glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);
glNormalPointer(GL_FLOAT, 0, ndata.data());
glVertexPointer(3, GL_FLOAT, 0, vdata.data());
SDL_Event event;
bool quit = false;
while (!quit) {
while (SDL_PollEvent(&event))
switch(event.type) {
case SDL_QUIT: quit = true; break;
}
;
// Drawing
glClearColor(255,255,255,255);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glTranslatef(screen_w/2,0,0);
glRotatef(0.5,0,1,0);
glTranslatef(-screen_w/2,0,0);
glPushMatrix();
glTranslatef(screen_w/2,screen_h/2,0);
glColor3f(0.5,0.5,0);
glDrawArrays(GL_TRIANGLES, 0, vdata.size());
glPopMatrix();
SDL_GL_SwapWindow(win);
SDL_Delay(10);
}
SDL_DestroyWindow(win);
SDL_Quit();
return 0;
}
The STLParser methods getNData() and getVData() have the following signatures:
const std::vector<std::array<float,3>>& getNData() const;
const std::vector<std::array<std::array<float,3>,3>>& getVData() const;
STLParser output should be correct, but I can provide the sources as well if needed.
What am I doing wrong?
You should change
glDrawArrays(GL_TRIANGLES, 0, vdata.size());
to
glDrawArrays(GL_TRIANGLES, 0, 3 * vdata.size());
I.e. count should be vertex count, but not triangle count.
Within my project, I've been having trouble getting an triangle to display within OnRender(), but for some reason, nothing other than the background color (green) is visible.
int main(int argc, char **argv)
{
if (!OnInit())
return -1;
SDL_Event Event;
while (_isRunning)
{
while (SDL_PollEvent(&Event))
OnEvent(&Event);
OnRender();
OnLoop();
SDL_GL_SwapWindow(_screen);
}
OnCleanup();
return 0;
}
void generalSetup()
{
// Initialize SDL2
if (SDL_Init(SDL_INIT_VIDEO) < 0)
sdldie("Failed to initial SDL2.");
else
{
/* Request OpenGL 3.2 */
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
// Create window
_screen = SDL_CreateWindow("Window", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
800, 600, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN);
// Create Context
_mainContext = SDL_GL_CreateContext(_screen);
// Create Surface
_surface = SDL_GetWindowSurface(_screen);
SDL_FillRect(_surface, NULL, SDL_MapRGB(_surface->format, 0xCC, 0x20, 0x20));
SDL_UpdateWindowSurface(_screen);
/* swap synchronized */
SDL_GL_SetSwapInterval(1);
// Initialize GLew 1.10
glewExperimental = GL_TRUE;
GLenum error = glewInit();
if (error != GLEW_OK)
printf("Warning: Unable to set VSync! SDL Error: %s\n", SDL_GetError());
else
std::cout << "GLew Initialized" << std::endl;
glClearColor(0, 1, 0, 0);
glViewport(0, 0, 800, 600);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45, 800 / 600, 1, 1000);
gluLookAt(0, 0, 20, 0, 0, 0, 0, 1, 0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
}
bool OnInit()
{
generalSetup();
return true;
}
void OnEvent(SDL_Event* Event)
{
if (Event->type == SDL_QUIT)
_isRunning = false;
}
void OnLoop()
{
}
void OnRender()
{
glClearColor(1.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glPushMatrix();
glTranslatef(0.f, 0.f, -10.f);
glBegin(GL_TRIANGLES);
glColor3f(0.1, 0.2, 0.3);
glVertex3f(0, 0, 0);
glVertex3f(1, 0, 0);
glVertex3f(0, 1, 0);
glEnd();
glPopMatrix();
}
void OnCleanup()
{
SDL_GL_DeleteContext(_mainContext);
SDL_DestroyWindow(_screen);
SDL_Quit();
}
You requested a Core context. None of your immediate-mode (matrix stack, glBegin(), etc.) code will work.
Drop back to a compatibility context (SDL_GL_CONTEXT_PROFILE_COMPATIBILITY) or supply all the necessary shaders, vertex buffers, etc. that Core requires.
You are trying to render through the immediate mode, but it is not supported by the OpenGL 3.2. Try using the version 2.0 or 2.1, which support both shaders (if you are intending to use them) and the immediate mode.
I'm trying to display an image in openGL using SDL and SOIL but it isn't working.
Globals.h
#include <SDL.h>
#include <SDL_OpenGL.h>
#include <SOIL.h>
#include "player.h"
main.cpp
#include "Globals.h"
int main(int argc, char** argv){
//Begin SDL initialization
SDL_Init(SDL_INIT_EVERYTHING);
SDL_Surface* Screen = SDL_SetVideoMode(800, 600, 32, SDL_SWSURFACE|SDL_OPENGL);
SDL_Event Event;
//End SDL initialization
//Begin OpenGL initialization
glClearColor(1, 1, 1, 1);//Set colour for empty screen
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);//Enable transparency
glEnable(GL_TEXTURE_2D);
glShadeModel(GL_SMOOTH);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glOrtho(-400, 400, -300, 300, -1, 1);//Set grid for display
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
//End OpenGL initialization
Player Player(0, 0, 32, 64, 1, 0, 0, 0.5);
bool gameRunning = true;
while(gameRunning){
while(SDL_PollEvent(&Event)){
if(Event.type == SDL_QUIT)
gameRunning = false;
//If user closed the window in any way stop gameRunning
Player.Events(Event);
}
Player.Update();
glClear(GL_COLOR_BUFFER_BIT);//Clear screen
glPushMatrix();
Player.DisplayWithImage("Brick.png", 32, 64);
glPopMatrix();
SDL_GL_SwapBuffers();//Update screen with new shit
}
SDL_Quit();//Quit SDL
return 0;//End program
}
player.h
#pragma once
class Player{
public:
GLfloat X, Y, W, H, R, G, B, A;
bool movingUp, movingRight, movingDown, movingLeft;
GLuint image;
Player(GLfloat x, GLfloat y, GLfloat w, GLfloat h,
GLfloat r, GLfloat g, GLfloat b, GLfloat a);
void Events(SDL_Event &Event);
void Update();
void Display();
void DisplayWithImage(const char* filename, GLsizei w, GLsizei h);
};
player.cpp
#include "Globals.h"
Player::Player(GLfloat x, GLfloat y, GLfloat w, GLfloat h, GLfloat r, GLfloat g, GLfloat b, GLfloat a){
X = x;
Y = y;
W = w;
H = h;
R = r;
G = g;
B = b;
A = a;
movingUp = false;
movingRight = false;
movingDown = false;
movingLeft = false;
}
void Player::Events(SDL_Event &Event){
if(Event.type == SDL_KEYDOWN){
if(Event.key.keysym.sym == SDLK_w)
movingUp = true;
if(Event.key.keysym.sym == SDLK_d)
movingRight = true;
if(Event.key.keysym.sym == SDLK_s)
movingDown = true;
if(Event.key.keysym.sym == SDLK_a)
movingLeft = true;
}
if(Event.type == SDL_KEYUP){
if(Event.key.keysym.sym == SDLK_w)
movingUp = false;
if(Event.key.keysym.sym == SDLK_d)
movingRight = false;
if(Event.key.keysym.sym == SDLK_s)
movingDown = false;
if(Event.key.keysym.sym == SDLK_a)
movingLeft = false;
}
}
void Player::Update(){
if(movingUp)
Y ++;
if(movingRight)
X ++;
if(movingDown)
Y --;
if(movingLeft)
X --;
}
void Player::Display(){
glBegin(GL_QUADS);
glColor4f(R, G, B, A);
//bottom right
glVertex2f(X+(W/2), Y-(H/2));
//top right
glVertex2f(X+(W/2), Y+(H/2));
//top left
glVertex2f(X-(W/2), Y+(H/2));
//bottom left
glVertex2f(X-(W/2), Y-(H/2));
glEnd();
}
void Player::DisplayWithImage(const char* filename, GLsizei w, GLsizei h){
image = SOIL_load_OGL_texture // load an image file directly as a new OpenGL texture
(
filename,
SOIL_LOAD_AUTO,
SOIL_CREATE_NEW_ID,
SOIL_FLAG_MIPMAPS | SOIL_FLAG_INVERT_Y | SOIL_FLAG_NTSC_SAFE_RGB | SOIL_FLAG_COMPRESS_TO_DXT
);
glBindTexture(GL_TEXTURE_2D, image);
glBegin(GL_QUADS);
//bottom right
glTexCoord2f(0, 0); glVertex2f(X+(W/2), Y-(H/2));
//top right
glTexCoord2f(0, H); glVertex2f(X+(W/2), Y+(H/2));
//top left
glTexCoord2f(W, H); glVertex2f(X-(W/2), Y+(H/2));
//bottom left
glTexCoord2f(W, 0); glVertex2f(X-(W/2), Y-(H/2));
glEnd();
}
You have three problems in your code:
GL_TEXTURE_2D uses normalized texture coordinates (0.0 - 1.0). Unless H and W are 1.0 or less you do not want to use them for your texture coordinates. If you just want to stretch this texture across your quad one time, use 1.0 in-place of W and H.
Most Serious Issue: You are creating a new texture on each frame, you should load the texture one time and then pass the loaded texture handle to DisplayWithImage (...) instead of having that function load a texture each time you call it.
glOrtho (...) creates an orthographic projection matrix, any GL operation that uses the projection matrix in isolation (e.g. not Projection * ModelView) is going to fail to work properly if you use an identity projection matrix and an orthographic projection matrix for your modelview matrix. By the same token, things like vertex lighting will not work properly with a projection matrix serving as your modelview matrix...
You can correct bullet point 3 by re-writing part of your code this way:
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-400, 400, -300, 300, -1, 1);//Set grid for display
~~~~~~~ This should come AFTER you set the matrix mode to projection!