I tried to write an "Engine" to render shapes using OpenGL.
The idea is that you can write "renderers" which are just functions that render shapes and add them to a list for the Engine class to display.
So I added a cube and a pyramid (the code for which I just copied from the internet) - and I made them rotate.
As you can see in the images at the bottom of the question - the shapes acted weird - you could see the back of the shape from the front, etc.
Now, I understand that OpenGL just renders stuff in the order I tell it to render them - causing things that are written first to be rendered first - but I used the glDepthFunc which should make it such that stuff renders by "depth" and not order of writing.
#include <GL/glut.h>
#include <iostream>
#include <list>
namespace Graphics
{
class Engine
{
public:
static void Init();
static void Display();
static void Reshape(GLsizei width, GLsizei height);
static void Timer(int value);
static bool Run(int argc, char** argv);
// A renderer is just a method that does stuff and return a boolean
using renderer_t = bool(*)();
static void AddRenderer(renderer_t renderer);
private:
static std::list<renderer_t> renderers;
};
}
namespace Graphics
{
std::list<Engine::renderer_t> Engine::renderers;
void Engine::Init()
{
glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Set background color to black and opaque
glClearDepth(1.0f); // Set background depth to farthest
glEnable(GL_DEPTH_TEST); // Enable depth testing for z-culling
glDepthFunc(GL_LEQUAL); // Set the type of depth-test
glShadeModel(GL_SMOOTH); // Enable smooth shading
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Nice perspective corrections
}
void Engine::Display()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear color and depth buffers
glMatrixMode(GL_MODELVIEW); // To operate on model-view matrix
for (auto renderer : Engine::renderers)
{
if (!renderer())
{
std::cout << "A renderer has failed rendering something... :(" << std::endl;
}
}
glutSwapBuffers(); // Swap the front and back frame buffers (double buffering)
}
void Engine::Reshape(GLsizei width, GLsizei height)
{ // GLsizei for non-negative integer
// Compute aspect ratio of the new window
if (height == 0) height = 1; // To prevent divide by 0
GLfloat aspect = (GLfloat)width / (GLfloat)height;
// Set the viewport to cover the new window
glViewport(0, 0, width, height);
// Set the aspect ratio of the clipping volume to match the viewport
glMatrixMode(GL_PROJECTION); // To operate on the Projection matrix
glLoadIdentity(); // Reset
// Enable perspective projection with fovy, aspect, zNear and zFar
gluPerspective(45.0f, aspect, 0.1f, 100.0f);
}
void Engine::Timer(int value)
{
glutPostRedisplay(); // Post re-paint request to activate display()
glutTimerFunc(15, Engine::Timer, 0); // next timer call milliseconds later
}
bool Engine::Run(int argc, char** argv)
{
glutInit(&argc, argv); // Initialize GLUT
glutInitDisplayMode(GLUT_DOUBLE); // Enable double buffered mode
glutInitWindowSize(640, 480); // Set the window's initial width & height
glutInitWindowPosition(50, 50); // Position the window's initial top-left corner
glutCreateWindow("FML"); // Create window with the given title
glutDisplayFunc(Engine::Display); // Register callback handler for window re-paint event
glutReshapeFunc(Engine::Reshape); // Register callback handler for window re-size event
Engine::Init(); // Our own OpenGL initialization
glutTimerFunc(0, Engine::Timer, 0); // Call the next display immediately
glutMainLoop(); // Enter the infinite event-processing loop
return true;
}
void Engine::AddRenderer(renderer_t renderer)
{
Engine::renderers.push_back(renderer);
}
}
using namespace Graphics;
static bool RenderCube()
{
static auto angleCube = 0.0f;
// Render a color-cube consisting of 6 quads with different colors
glLoadIdentity(); // Reset the model-view matrix
glTranslatef(1.5f, 0.0f, -7.0f); // Move right and into the screen
glRotatef(angleCube, 1.0f, 1.0f, 1.0f);
glBegin(GL_QUADS); // Begin drawing the color cube with 6 quads
// Top face (y = 1.0f)
// Define vertices in counter-clockwise (CCW) order with normal pointing out
glColor3f(0.0f, 1.0f, 0.0f); // Green
glVertex3f( 1.0f, 1.0f, -1.0f);
glVertex3f(-1.0f, 1.0f, -1.0f);
glVertex3f(-1.0f, 1.0f, 1.0f);
glVertex3f( 1.0f, 1.0f, 1.0f);
// Bottom face (y = -1.0f)
glColor3f(1.0f, 0.5f, 0.0f); // Orange
glVertex3f( 1.0f, -1.0f, 1.0f);
glVertex3f(-1.0f, -1.0f, 1.0f);
glVertex3f(-1.0f, -1.0f, -1.0f);
glVertex3f( 1.0f, -1.0f, -1.0f);
// Front face (z = 1.0f)
glColor3f(1.0f, 0.0f, 0.0f); // Red
glVertex3f( 1.0f, 1.0f, 1.0f);
glVertex3f(-1.0f, 1.0f, 1.0f);
glVertex3f(-1.0f, -1.0f, 1.0f);
glVertex3f( 1.0f, -1.0f, 1.0f);
// Back face (z = -1.0f)
glColor3f(1.0f, 1.0f, 0.0f); // Yellow
glVertex3f( 1.0f, -1.0f, -1.0f);
glVertex3f(-1.0f, -1.0f, -1.0f);
glVertex3f(-1.0f, 1.0f, -1.0f);
glVertex3f( 1.0f, 1.0f, -1.0f);
// Left face (x = -1.0f)
glColor3f(0.0f, 0.0f, 1.0f); // Blue
glVertex3f(-1.0f, 1.0f, 1.0f);
glVertex3f(-1.0f, 1.0f, -1.0f);
glVertex3f(-1.0f, -1.0f, -1.0f);
glVertex3f(-1.0f, -1.0f, 1.0f);
// Right face (x = 1.0f)
glColor3f(1.0f, 0.0f, 1.0f); // Magenta
glVertex3f(1.0f, 1.0f, -1.0f);
glVertex3f(1.0f, 1.0f, 1.0f);
glVertex3f(1.0f, -1.0f, 1.0f);
glVertex3f(1.0f, -1.0f, -1.0f);
glEnd();
angleCube += 0.2f;
return true;
}
static bool RenderPyramid()
{
static auto anglePyramid = 0.0f;
// Render a pyramid consists of 4 triangles
glLoadIdentity(); // Reset the model-view matrix
glTranslatef(-1.5f, 0.0f, -6.0f); // Move left and into the screen
glRotatef(anglePyramid, 1.0f, 1.0f, 1.0f);
glBegin(GL_TRIANGLES); // Begin drawing the pyramid with 4 triangles
// Front
glColor3f(1.0f, 0.0f, 0.0f); // Red
glVertex3f( 0.0f, 1.0f, 0.0f);
glColor3f(0.0f, 1.0f, 0.0f); // Green
glVertex3f(-1.0f, -1.0f, 1.0f);
glColor3f(0.0f, 0.0f, 1.0f); // Blue
glVertex3f(1.0f, -1.0f, 1.0f);
// Right
glColor3f(1.0f, 0.0f, 0.0f); // Red
glVertex3f(0.0f, 1.0f, 0.0f);
glColor3f(0.0f, 0.0f, 1.0f); // Blue
glVertex3f(1.0f, -1.0f, 1.0f);
glColor3f(0.0f, 1.0f, 0.0f); // Green
glVertex3f(1.0f, -1.0f, -1.0f);
// Back
glColor3f(1.0f, 0.0f, 0.0f); // Red
glVertex3f(0.0f, 1.0f, 0.0f);
glColor3f(0.0f, 1.0f, 0.0f); // Green
glVertex3f(1.0f, -1.0f, -1.0f);
glColor3f(0.0f, 0.0f, 1.0f); // Blue
glVertex3f(-1.0f, -1.0f, -1.0f);
// Left
glColor3f(1.0f,0.0f,0.0f); // Red
glVertex3f( 0.0f, 1.0f, 0.0f);
glColor3f(0.0f,0.0f,1.0f); // Blue
glVertex3f(-1.0f,-1.0f,-1.0f);
glColor3f(0.0f,1.0f,0.0f); // Green
glVertex3f(-1.0f,-1.0f, 1.0f);
glEnd(); // Done drawing the pyramid
anglePyramid += 0.25f;
return true;
}
int main(int argc, char** argv)
{
Engine::AddRenderer(RenderCube);
Engine::AddRenderer(RenderPyramid);
return Engine::Run(argc, argv);
}
Images of the resulting shapes rotating
As you can see the shapes are acting weird - you can see the back of them even though I used the glDepthFunc.
The OS/driver is under no obligation to give you any depth buffer bits unless you specifically request them; zero bits, no depth buffering.
As #BDL pointed out, for GLUT that means ORing in GLUT_DEPTH to your glutInitDisplayMode() parameter.
Related
I am currently rendering a solar system of planets in my 3d space but every single planet is black even when light hits the sphere. The spheres are rendered last in my render function. Had the colors working when the spheres were being rendered on their own but now i've added my sky box and other quads all the spheres refuse to be colored.
#include "Scene.h"
float rotation;
float rotation2;
int direction;
int speed;
Scene::Scene(Input *in)
{
// Initialise variables
rotation = 20;
rotation2 = 0;
direction = 1;
speed = 5;
myTexture = 0;
skyBox = 0;
// Store pointer for input class
input = in;
// OpenGL settings
glShadeModel(GL_SMOOTH); // Enable Smooth Shading
glClearColor(0.39f, 0.58f, 93.0f, 1.0f); // Cornflour Blue Background
glClearDepth(1.0f); // Depth Buffer Setup
glClearStencil(0); // Clear stencil buffer
glEnable(GL_DEPTH_TEST); // Enables Depth Testing
glEnable(GL_LIGHTING); // Enables Lighting
glDepthFunc(GL_LEQUAL); // The Type Of Depth Testing To Do
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Really Nice Perspective Calculations
// Other OpenGL / render setting should be applied here.
myTexture = SOIL_load_OGL_texture
(
"gfx/neongrid.png",
SOIL_LOAD_AUTO,
SOIL_CREATE_NEW_ID,
SOIL_FLAG_MIPMAPS | SOIL_FLAG_NTSC_SAFE_RGB | SOIL_FLAG_COMPRESS_TO_DXT
);
skyBox = SOIL_load_OGL_texture
(
"gfx/starField.png",
SOIL_LOAD_AUTO,
SOIL_CREATE_NEW_ID,
SOIL_FLAG_MIPMAPS | SOIL_FLAG_NTSC_SAFE_RGB | SOIL_FLAG_COMPRESS_TO_DXT
);
glEnable(GL_TEXTURE_2D);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
GL_NEAREST);
camera = new Camera();
}
void Scene::update(float dt)
{
// Update camera position
camera->update(input, dt);
// Handle user input
if (input->isKeyDown(43))
{
direction = 1;
input->SetKeyUp(43);
}
else if (input->isKeyDown(45))
{
direction = -1;
input->SetKeyUp(45);
}
// Update scene related variables
rotation += speed * dt;
rotation2 += (speed *2) * dt;
if (input->isKeyDown('p') && WF == false)
{
WF = true;
input->SetKeyUp('p');
glPolygonMode(GL_FRONT, GL_LINE);
}
if (input->isKeyDown('p') && WF == true)
{
WF = false;
input->SetKeyUp('p');
glPolygonMode(GL_FRONT, GL_FILL);
}
// Calculate FPS for output
calculateFPS();
}
void Scene::render() {
// Clear Color and Depth Buffers
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Reset transformations
glLoadIdentity();
// Set the camera
gluLookAt(camera->getPosition().x, camera->getPosition().y, camera->getPosition().z,
camera->getLookAt().x, camera->getLookAt().y, camera->getLookAt().z,
camera->getUp().x, camera->getUp().y, camera->getUp().z);
glutWarpPointer(400, 300);
glutSetCursor(GLUT_CURSOR_FULL_CROSSHAIR);
// Lighting
GLfloat Light_Ambient[] = { 0.2f, 0.2f, 0.2f, 1.0f };
GLfloat Light_Diffuse[] = { 9.0f, 9.0f, 9.0f, 1.0f };
GLfloat Light_Position[] = { 2.0f, 2.0f, 2.0f, 1.0f };
glLightfv(GL_LIGHT0, GL_AMBIENT, Light_Ambient);
glLightfv(GL_LIGHT0, GL_DIFFUSE, Light_Diffuse);
glLightfv(GL_LIGHT0, GL_POSITION, Light_Position);
glEnable(GL_LIGHT0);
glDisable(GL_DEPTH_TEST);
#pragma region skybox
glPushMatrix();
glTranslatef(camera->getPosition().x, camera->getPosition().y, camera->getPosition().z);
glBindTexture(GL_TEXTURE_2D, skyBox);
glBegin(GL_QUADS);
//Back
glNormal3f(0.0f, 0.0f, 1.0f);
glTexCoord2f(0.0f, 1.0f);
glVertex3f(-1.0f, -1.0f, 1.0f);
glNormal3f(0.0f, 0.0f, 1.0f);
glTexCoord2f(1.0f, 1.0f);
glVertex3f(1.0f, -1.0f, 1.0f);
glNormal3f(0.0f, 0.0f, 1.0f);
glTexCoord2f(1.0f, 0.0f);
glVertex3f(1.0f, 1.0f, 1.0f);
glNormal3f(0.0f, 0.0f, 1.0f);
glTexCoord2f(0.0f, 0.0f);
glVertex3f(-1.0f, 1.0f, 1.0f);
//Right
glNormal3f(1.0f, 0.0f, 0.0f);
glTexCoord2f(0.0f, 1.0f);
glVertex3f(1.0f, -1.0f, -1.0f);
glNormal3f(1.0f, 0.0f, 0.0f);
glTexCoord2f(1.0f, 1.0f);
glVertex3f(1.0f, 1.0f, -1.0f);
glNormal3f(1.0f, 0.0f, 0.0f);
glTexCoord2f(1.0f, 0.0f);
glVertex3f(1.0f, 1.0f, 1.0f);
glNormal3f(1.0f, 0.0f, 0.0f);
glTexCoord2f(0.0f, 0.0f);
glVertex3f(1.0f, -1.0f, 1.0f);
//front
glNormal3f(0.0f, 0.0f, -1.0f);
glTexCoord2f(1.0f, 1.0f);
glVertex3f(1.0f, -1.0f, -1.0f);
glNormal3f(0.0f, 0.0f, -1.0f);
glTexCoord2f(0.0f, 1.0f);
glVertex3f(-1.0f, -1.0f, -1.0f);
glNormal3f(0.0f, 0.0f, -1.0f);
glTexCoord2f(0.0f, 0.0f);
glVertex3f(-1.0f, 1.0f, -1.0f);
glNormal3f(0.0f, 0.0f, -1.0f);
glTexCoord2f(1.0f, 0.0f);
glVertex3f(1.0f, 1.0f, -1.0f);
//left
glNormal3f(-1.0f, 0.0f, 0.0f);
glTexCoord2f(0.0f, 1.0f);
glVertex3f(-1.0f, -1.0f, -1.0f);
glNormal3f(-1.0f, 0.0f, 0.0f);
glTexCoord2f(1.0f, 1.0f);
glVertex3f(-1.0f, -1.0f, 1.0f);
glNormal3f(-1.0f, 0.0f, 0.0f);
glTexCoord2f(1.0f, 0.0f);
glVertex3f(-1.0f, 1.0f, 1.0f);
glNormal3f(-1.0f, 0.0f, 0.0f);
glTexCoord2f(0.0f, 0.0f);
glVertex3f(-1.0f, 1.0f, -1.0f);
//top
glNormal3f(0.0f, 1.0f, 0.0f);
glTexCoord2f(0.0f, 1.0f);
glVertex3f(-1.0f, 1.0f, 1.0f);
glNormal3f(0.0f, 1.0f, 0.0f);
glTexCoord2f(1.0f, 1.0f);
glVertex3f(1.0f, 1.0f, 1.0f);
glNormal3f(0.0f, 1.0f, 0.0f);
glTexCoord2f(1.0f, 0.0f);
glVertex3f(1.0f, 1.0f, -1.0f);
glNormal3f(0.0f, 1.0f, 0.0f);
glTexCoord2f(0.0f, 0.0f);
glVertex3f(-1.0f, 1.0f, -1.0f);
//bottom
glNormal3f(0.0f, -1.0f, 0.0f);
glTexCoord2f(0.0f, 0.0f);
glVertex3f(-1.0f, -1.0f, -1.0f);
glNormal3f(0.0f, -1.0f, 0.0f);
glTexCoord2f(1.0f, 0.0f);
glVertex3f(1.0f, -1.0f, -1.0f);
glNormal3f(0.0f, -1.0f, 0.0f);
glTexCoord2f(1.0f, 1.0f);
glVertex3f(1.0f, -1.0f, 1.0f);
glNormal3f(0.0f, -1.0f, 0.0f);
glTexCoord2f(0.0f, 1.0f);
glVertex3f(-1.0f, -1.0f, 1.0f);
glEnd();
#pragma endregion
glEnable(GL_DEPTH_TEST);
glPopMatrix();
glPushMatrix();
#pragma region wall
glBindTexture(GL_TEXTURE_2D, myTexture);
glTranslatef(0.0, 0.0, 0.0);
glScalef(5.0f, 5.0f, 5.0f);
glBegin(GL_QUADS);
// first face
glNormal3f(1.0f, 0.0f, 0.0f);
glTexCoord2f(0.0f, 0.0f);
glVertex3f(0.0f, 1.0f, 0.0f);
// second face
glNormal3f(1.0f, 0.0f, 0.0f);
glTexCoord2f(1.0f, 0.0f);
glVertex3f(1.0f, 1.0f, 0.0f);
// third face
glNormal3f(1.0f, 0.0f, 0.0f);
glTexCoord2f(1.0f, 1.0f);
glVertex3f(1.0f, 0.0f, 0.0f);
// fourth face
glNormal3f(1.0f, 0.0f, 0.0f);
glTexCoord2f(0.0f, 1.0f);
glVertex3f(0.0f, 0.0f, 0.0f);
glEnd();
glPopMatrix();
glPushMatrix();
glBindTexture(GL_TEXTURE_2D, myTexture);
glScalef(5.0f, 5.0f, 5.0f);
glBegin(GL_QUADS);
// first face
glNormal3f(1.0f, 0.0f, 0.0f);
glTexCoord2f(0.0f, 0.0f);
glVertex3f(0.0f, 0.0f, 0.0f);
// second face
glNormal3f(1.0f, 0.0f, 0.0f);
glTexCoord2f(1.0f, 0.0f);
glVertex3f(1.0f, 0.0f, 0.0f);
// third face
glNormal3f(1.0f, 0.0f, 0.0f);
glTexCoord2f(1.0f, 1.0f);
glVertex3f(1.0f, 0.0f, -1.0f);
// fourth face
glNormal3f(1.0f, 0.0f, 0.0f);
glTexCoord2f(0.0f, 1.0f);
glVertex3f(0.0f, 0.0f, -1.0f);
glEnd();
#pragma endregion
glPopMatrix();
glPushMatrix();
// Render sun
glEnable(GL_TEXTURE_2D);
glColor3f(1.0f, 1.0f, 1.0f);
glBindTexture(GL_TEXTURE_2D, NULL);
glTranslatef(0.5, 0.5, -0.5);
glColor3f(1.0f, 0.0f, 0.0f);
gluSphere(gluNewQuadric(), 0.20, 20, 20);
glPushMatrix(); // Push for default matrix
// Render Planet 1
glRotatef(rotation, 0.5, 0.5, 0);
glTranslatef(0, 0, 1);
glScalef(1, 1, 1);
glColor3f(0.0f, 2.0f, 0.0f);
gluSphere(gluNewQuadric(), 0.20, 10, 10);
glPopMatrix(); // Pop off stack back to sun matrix
glPushMatrix(); // Push for default matrix
// Render Planet 2
glRotatef(rotation2, 0, 1, 0);
glTranslatef(2, 0, 0);
glScalef(0.5, 0.5, 0.5);
glColor3f(0.0f, 0.0f, 1.0f);
gluSphere(gluNewQuadric(), 0.20, 5, 5);
glPushMatrix(); // Pop back to sun
// Render a moon around Planet 2
glRotatef((rotation*2.0), 0, 1, 0);
glTranslatef(1.5, 0, 0);
glScalef(0.3, 0.3, 0.3);
glColor3f(0.0f, 0.0f, 1.0f);
gluSphere(gluNewQuadric(), 0.20, 20, 20);
glPopMatrix(); // Pop to planet 2
glPushMatrix(); // Push for default matrix
// Render a SECOND moon around Planet 2
glRotatef((rotation * 2), 0, 0, 1);
glTranslatef(1.5, 0, 0);
glScalef(0.3, 0.3, 0.3);
glColor3f(0.0f, 0.0f, 1.0f);
gluSphere(gluNewQuadric(), 0.20, 20, 20);
glPopMatrix();
//glPopMatrix();
glPopMatrix(); // Go back to sun!
glPushMatrix();
glTranslatef(2, 2, 2);
glColor3f(1, 0, 0);
gluSphere(gluNewQuadric(), 0.5, 20, 20);
glPopMatrix();
// End render geometry --------------------------------------
// Render text, should be last object rendered.
renderTextOutput();
// Swap buffers, after all objects are rendered.
glutSwapBuffers();
}
// Handles the resize of the window. If the window changes size the perspective matrix requires re-calculation to match new window size.
void Scene::resize(int w, int h)
{
width = w;
height = h;
// Prevent a divide by zero, when window is too short
// (you cant make a window of zero width).
if (h == 0)
h = 1;
float ratio = (float)w / (float)h;
fov = 45.0f;
nearPlane = 0.1f;
farPlane = 100.0f;
// Use the Projection Matrix
glMatrixMode(GL_PROJECTION);
// Reset Matrix
glLoadIdentity();
// Set the viewport to be the entire window
glViewport(0, 0, w, h);
// Set the correct perspective.
gluPerspective(fov, ratio, nearPlane, farPlane);
// Get Back to the Modelview
glMatrixMode(GL_MODELVIEW);
}
// Calculates FPS
void Scene::calculateFPS()
{
frame++;
time = glutGet(GLUT_ELAPSED_TIME);
if (time - timebase > 1000) {
sprintf_s(fps, "FPS: %4.2f", frame*1000.0 / (time - timebase));
timebase = time;
frame = 0;
}
}
// Compiles standard output text including FPS and current mouse position.
void Scene::renderTextOutput()
{
// Render current mouse position and frames per second.
sprintf_s(mouseText, "Mouse: %i, %i", input->getMouseX(), input->getMouseY());
displayText(-1.f, 0.96f, 1.f, 0.f, 0.f, mouseText);
displayText(-1.f, 0.90f, 1.f, 0.f, 0.f, fps);
}
// Renders text to screen. Must be called last in render function (before swap buffers)
void Scene::displayText(float x, float y, float r, float g, float b, char* string) {
// Get Lenth of string
int j = strlen(string);
// Swap to 2D rendering
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-1.0, 1.0, -1.0, 1.0, 5, 100);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// Orthographic lookAt (along the z-axis).
gluLookAt(0.0f, 0.0f, 10.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f);
// Set text colour and position.
glColor3f(r, g, b);
glRasterPos2f(x, y);
// Render text.
for (int i = 0; i < j; i++) {
glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, string[i]);
}
// Reset colour to white.
glColor3f(1.f, 1.f, 1.f);
// Swap back to 3D rendering.
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(fov, ((float)width/(float)height), nearPlane, farPlane);
glMatrixMode(GL_MODELVIEW);
}
Updated sun code :
// Render sun
glTranslatef(0.5, 0.5, -0.5);
glColor3f(1.0f, 0.0f, 0.0f);
gluSphere(gluNewQuadric(), 0.20, 20, 20);
glPushMatrix(); // Push for default matrix
// Render Planet 1
glRotatef(rotation, 0.5, 0.5, 0);
glTranslatef(0, 0, 1);
glScalef(1, 1, 1);
glColor3f(0.0f, 2.0f, 0.0f);
gluSphere(gluNewQuadric(), 0.20, 10, 10);
glPopMatrix(); // Pop off stack back to sun matrix
glPushMatrix(); // Push for default matrix
Found out i was missing a OpenGL setting
glEnable(GL_COLOR_MATERIAL);
Inserted at the start of Scene
Try to end glEnable(GL_TEXTURE_2D); with glDisable(GL_TEXTURE_2D); after you render sun.
If problem appeared after you added skybox. Check if vertices are in right order.
I need to draw a cube to indicate coordinate in OpenGL 3.3 core profile.It works fine without glutInitContextVersion (3, 3); but it becomes totally black when glutInitContextVersion (3, 3); applied.
Here is the drawing code.
void display() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear color and depth buffers
glMatrixMode(GL_MODELVIEW); // To operate on model-view matrix
// Render a color-cube consisting of 6 quads with different colors
glLoadIdentity(); // Reset the model-view matrix
glTranslatef(1.5f, 0.0f, -7.0f); // Move right and into the screen
glBegin(GL_QUADS); // Begin drawing the color cube with 6 quads
// Top face (y = 1.0f)
// Define vertices in counter-clockwise (CCW) order with normal pointing out
glColor3f(0.0f, 1.0f, 0.0f); // Green
glVertex3f( 1.0f, 1.0f, -1.0f);
glVertex3f(-1.0f, 1.0f, -1.0f);
glVertex3f(-1.0f, 1.0f, 1.0f);
glVertex3f( 1.0f, 1.0f, 1.0f);
// Bottom face (y = -1.0f)
glColor3f(1.0f, 0.5f, 0.0f); // Orange
glVertex3f( 1.0f, -1.0f, 1.0f);
glVertex3f(-1.0f, -1.0f, 1.0f);
glVertex3f(-1.0f, -1.0f, -1.0f);
glVertex3f( 1.0f, -1.0f, -1.0f);
// Front face (z = 1.0f)
glColor3f(1.0f, 0.0f, 0.0f); // Red
glVertex3f( 1.0f, 1.0f, 1.0f);
glVertex3f(-1.0f, 1.0f, 1.0f);
glVertex3f(-1.0f, -1.0f, 1.0f);
glVertex3f( 1.0f, -1.0f, 1.0f);
// Back face (z = -1.0f)
glColor3f(1.0f, 1.0f, 0.0f); // Yellow
glVertex3f( 1.0f, -1.0f, -1.0f);
glVertex3f(-1.0f, -1.0f, -1.0f);
glVertex3f(-1.0f, 1.0f, -1.0f);
glVertex3f( 1.0f, 1.0f, -1.0f);
// Left face (x = -1.0f)
glColor3f(0.0f, 0.0f, 1.0f); // Blue
glVertex3f(-1.0f, 1.0f, 1.0f);
glVertex3f(-1.0f, 1.0f, -1.0f);
glVertex3f(-1.0f, -1.0f, -1.0f);
glVertex3f(-1.0f, -1.0f, 1.0f);
// Right face (x = 1.0f)
glColor3f(1.0f, 0.0f, 1.0f); // Magenta
glVertex3f(1.0f, 1.0f, -1.0f);
glVertex3f(1.0f, 1.0f, 1.0f);
glVertex3f(1.0f, -1.0f, 1.0f);
glVertex3f(1.0f, -1.0f, -1.0f);
glEnd(); // End of drawing color-cube
glutSwapBuffers(); // Swap the front and back frame buffers (double buffering)
}
Here is the code in main function:
int main(int argc, char** argv) {
glutInit(&argc, argv); // Initialize GLUT
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA); // Enable double buffered mode
glutInitContextVersion (3, 3);
glutInitWindowSize(640, 480); // Set the window's initial width & height
glutInitWindowPosition(50, 50); // Position the window's initial top-left corner
glutCreateWindow(title); // Create window with the given title
glutDisplayFunc(display); // Register callback handler for window re-paint event
glutReshapeFunc(reshape); // Register callback handler for window re-size event
initGL(); // Our own OpenGL initialization
glutMainLoop(); // Enter the infinite event-processing loop
return 0;
}
How to draw a cube in OpenGL 3.3 core profile?
glBegin and friends are deprecated and removed from the newer versions (3.2 onward).
Instead you need to upload the vertex data to Vertex Buffer Objects. Then use glVertexAttribPointer to tell openGL how the data is laid out.
Besides that you need to write shaders.
Fixed function pipeline (glVertex, glBegin etc.) does not exist in Core Profile.
I'm pretty sure this is due to my lack of understanding of how the GL_MODELVIEW matrix works. Here is a screen recording of what's happening: http://youtu.be/3F7FLkVI7kA
As you can see, the bottom-most triangle is the first triangle being drawn, and moves as I expect the other 2 triangles to move. The second triangle is moved and rotated relative to the first, and the third is moved and rotated relative to that combination.
What I want is for all three triangles to be stationary in 3D space, but spinning (like the first triangle).
Source:
// Main loop
do {
// Clear Screen
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Update camera
glfwGetCursorPos(window, &cursorX, &cursorY);
cam.update(0.001f, (int)cursorX, (int)cursorY);
// Reset Matrix
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// move camera
glRotatef(cam.rotation.x, 1.0f, 0.0f, 0.0f);
glRotatef(cam.rotation.y, 0.0f, 1.0f, 0.0f);
// translate modelview matrix to position of the camera - everything should now draw relative to camera position
glTranslatef(-cam.position.x, cam.position.y, -cam.position.z);
// Draw ground
drawGroundGrid(-25.0f);
drawSpinningTriangle(0.0f, 0.0f, -5.0f);
drawSpinningTriangle(3.14f, 3.0f, -6.0f);
drawSpinningTriangle(-6.0f, 12.0f, -5.0f);
// Swap buffers - back buffer is now front buffer to be rendered to next frame
glfwSwapBuffers(window);
glfwPollEvents();
calcFPS();
} while (!glfwGetKey(window, GLFW_KEY_ESCAPE) && !glfwWindowShouldClose(window));// Main Loop End
[...]
void drawSpinningTriangle(float x, float y, float z) {
glMatrixMode(GL_MODELVIEW);
glTranslatef(x, y, z);
glRotatef(glfwGetTime() * 50.0f, 0.0f, 1.0f, 0.0f);
glBegin(GL_TRIANGLES);
{
// Red vertex
glColor3f(1.0f, 0.0f, 0.0f);
glVertex3f(0.0f, 1.0f, 0.0f);
// Yellow vertex
glColor3f(1.0f, 1.0f, 0.0f);
glVertex3f(-1.0f, -1.0f, 0.0f);
// White vertex
glColor3f(1.0f, 1.0f, 1.0f);
glVertex3f(1.0f, -1.0f, 0.0f);
}
glEnd();
}
First using the matrix stack is deprecated. It's much better to manage your own matrices
Second you should pushMatrix and popMatrix before the transformations and after drawing:
void drawSpinningTriangle(float x, float y, float z) {
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glTranslatef(x, y, z);
glRotatef(glfwGetTime() * 50.0f, 0.0f, 1.0f, 0.0f);
glBegin(GL_TRIANGLES);
{
// Red vertex
glColor3f(1.0f, 0.0f, 0.0f);
glVertex3f(0.0f, 1.0f, 0.0f);
// Yellow vertex
glColor3f(1.0f, 1.0f, 0.0f);
glVertex3f(-1.0f, -1.0f, 0.0f);
// White vertex
glColor3f(1.0f, 1.0f, 1.0f);
glVertex3f(1.0f, -1.0f, 0.0f);
}
glEnd();
glPopMatrix();
}
This will save and restore the top most matrix so any changes between the 2 calls are removed.
I'm a complete beginner with OpenGL, just trying to learn (starting with freeglut for the moment). So far I have the following code that should draw some basic 3D objects. The problem is that whatever I put in the render function (although it does execute), it only displays a blank window.
#include "stdafx.h"
#include <iostream>
#include "dependente\glew\glew.h"
#include "dependente\freeglut\glut.h"
void render()
{
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glEnable(GL_DEPTH_TEST);
glTranslatef(-1.5f, 1.0f, -6.0f); // Translate back and to the left
glPushMatrix(); // Push the current modelview matrix on the matrix // Rotate on all 3 axis
glBegin(GL_TRIANGLES); // Draw a pyramid
glColor3f(1.0f, 0.0f, 0.0f); // Red
glVertex3f(0.0f, 1.0f, 0.0f); // Top of front face
glColor3f(0.0f, 1.0f, 0.0f); // Green
glVertex3f(-1.0f, -1.0f, 1.0f); // Left of front face
glColor3f(0.0f, 0.0f, 1.0f); // Blue
glVertex3f(1.0f, -1.0f, 1.0f); // Right of front face
glColor3f(1.0f, 0.0f, 0.0f); // Red
glVertex3f(0.0f, 1.0f, 0.0f); // Top of right face
glColor3f(0.0f, 0.0f, 1.0f); // Blue
glVertex3f(1.0f, -1.0f, 1.0f); // Left of right face
glColor3f(0.0f, 1.0f, 0.0f); // Green
glVertex3f(1.0f, -1.0f, -1.0f); // Right of right face
glColor3f(1.0f, 0.0f, 0.0f); // Red
glVertex3f(0.0f, 1.0f, 0.0f); // Top of back face
glColor3f(0.0f, 1.0f, 0.0f); // Green
glVertex3f(1.0f, -1.0f, -1.0f); // Left of back face
glColor3f(0.0f, 0.0f, 1.0f); // Blue
glVertex3f(-1.0f, -1.0f, -1.0f); // Right of back face
glColor3f(1.0f, 0.0f, 0.0f); // Red
glVertex3f(0.0f, 1.0f, 0.0f); // Top of left face
glColor3f(0.0f, 0.0f, 1.0f); // Blue
glVertex3f(-1.0f, -1.0f, -1.0f); // Left of left face
glColor3f(0.0f, 1.0f, 0.0f); // Green
glVertex3f(-1.0f, -1.0f, 1.0f); // Right of left face
glEnd();
// Render a quad for the bottom of our pyramid
glBegin(GL_QUADS);
glColor3f(0.0f, 1.0f, 0.0f); // Green
glVertex3f(-1.0f, -1.0f, 1.0f); // Left/right of front/left face
glColor3f(0.0f, 0.0f, 1.0f); // Blue
glVertex3f(1.0f, -1.0f, 1.0f); // Right/left of front/right face
glColor3f(0.0f, 1.0f, 0.0f); // Green
glVertex3f(1.0f, -1.0f, -1.0f); // Right/left of right/back face
glColor3f(0.0f, 0.0f, 1.0f); // Blue
glVertex3f(-1.0f, -1.0f, -1.0f); // Left/right of right/back face
glEnd();
glPopMatrix();
glTranslatef(3.0f, 0.0f, 0.0f); // Translate right
glPushMatrix(); // Push the current modelview matrix on the matrix stack // Rotate the primitive on all 3 axis
glBegin(GL_QUADS);
// Top face
glColor3f(0.0f, 1.0f, 0.0f); // Green
glVertex3f(1.0f, 1.0f, -1.0f); // Top-right of top face
glVertex3f(-1.0f, 1.0f, -1.0f); // Top-left of top face
glVertex3f(-1.0f, 1.0f, 1.0f); // Bottom-left of top face
glVertex3f(1.0f, 1.0f, 1.0f); // Bottom-right of top face
// Bottom face
glColor3f(1.0f, 0.5f, 0.0f); // Orange
glVertex3f(1.0f, -1.0f, -1.0f); // Top-right of bottom face
glVertex3f(-1.0f, -1.0f, -1.0f); // Top-left of bottom face
glVertex3f(-1.0f, -1.0f, 1.0f); // Bottom-left of bottom face
glVertex3f(1.0f, -1.0f, 1.0f); // Bottom-right of bottom face
// Front face
glColor3f(1.0f, 0.0f, 0.0f); // Red
glVertex3f(1.0f, 1.0f, 1.0f); // Top-Right of front face
glVertex3f(-1.0f, 1.0f, 1.0f); // Top-left of front face
glVertex3f(-1.0f, -1.0f, 1.0f); // Bottom-left of front face
glVertex3f(1.0f, -1.0f, 1.0f); // Bottom-right of front face
// Back face
glColor3f(1.0f, 1.0f, 0.0f); // Yellow
glVertex3f(1.0f, -1.0f, -1.0f); // Bottom-Left of back face
glVertex3f(-1.0f, -1.0f, -1.0f); // Bottom-Right of back face
glVertex3f(-1.0f, 1.0f, -1.0f); // Top-Right of back face
glVertex3f(1.0f, 1.0f, -1.0f); // Top-Left of back face
// Left face
glColor3f(0.0f, 0.0f, 1.0f); // Blue
glVertex3f(-1.0f, 1.0f, 1.0f); // Top-Right of left face
glVertex3f(-1.0f, 1.0f, -1.0f); // Top-Left of left face
glVertex3f(-1.0f, -1.0f, -1.0f); // Bottom-Left of left face
glVertex3f(-1.0f, -1.0f, 1.0f); // Bottom-Right of left face
// Right face
glColor3f(1.0f, 0.0f, 1.0f); // Violet
glVertex3f(1.0f, 1.0f, 1.0f); // Top-Right of left face
glVertex3f(1.0f, 1.0f, -1.0f); // Top-Left of left face
glVertex3f(1.0f, -1.0f, -1.0f); // Bottom-Left of left face
glVertex3f(1.0f, -1.0f, 1.0f); // Bottom-Right of left face
glEnd();
glPopMatrix();
glTranslatef(-1.5f, -3.0f, 0.0f); // Back to center and lower screen
glPushMatrix();
glColor3f(1.0f, 1.0f, 0.0f); // Yellow
glutSolidSphere(1.0f, 16, 16); // Use GLUT to draw a solid sphere
glScalef(1.01f, 1.01f, 1.01f);
glColor3f(1.0f, 0.0f, 0.0f); // Red
glutWireSphere(1.0f, 16, 16); // Use GLUT to draw a wireframe sphere
glPopMatrix();
}
void initGlut(int argc, char* argv[]) {
std::cout << "Initialise OpenGL..." << std::endl;
glutInit(&argc, argv);
int iScreenWidth = glutGet(GLUT_SCREEN_WIDTH);
int iScreenHeight = glutGet(GLUT_SCREEN_HEIGHT);
glutInitDisplayMode(GLUT_RGBA | GLUT_ALPHA | GLUT_DOUBLE | GLUT_DEPTH);
glutInitWindowPosition(120, 120);
glutInitWindowSize(600, 600);
glutCreateWindow("OpenGL");
// Register GLUT callbacks
glutDisplayFunc(render);
// Setup initial GL State
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
glClearDepth(1.0f);
glShadeModel(GL_SMOOTH);
glutMainLoop();
std::cout << "Initialise OpenGL: Success!" << std::endl;
}
int _tmain(int argc, char* argv[])
{
initGlut(argc, argv);
return 0;
}
Hopefully someone with more experience will let me know what obvious thing I'm missing.
Here's how I go about debugging the problem "OpenGL isn't drawing anything":
Add this code to the start of my render() function: glClearColor (1, 1, 0, 1); glClear (GL_COLOR_BUFFER_BIT); If the output turns yellow, it's calling your render() function and clearing the output properly. You can then remove that code or comment it out. If the output doesn't turn yellow, then either your render() function isn't getting called or it is, but your OpenGL state is set up not to draw to the screen. (Perhaps the wrong context is current at the time, or the color attachment for the current FBO isn't what you think it is.)
Attempt to draw a single white triangle, with no textures or shaders, centered at the origin. If it shows up, then the other geometry you're trying to draw could be wrong. If it doesn't show up, the problem could be your matrix calculations (projection or modelview matrix). (Are you pointing the "camera" where you think you are? Are your objects being drawn where you think?) It could also be lighting, blending, or depth testing. I turn all of those off for this sort of test just to be sure. (See glEnable()/glDisable() for how to turn them on and off.)
If that stuff works, I start turning on the things that I turned off above: texturing, shaders, lighting, blending, depth testing. I turn them on one at a time until something goes wrong.
If nothing goes wrong, then probably the geometry for my objects is wrong.
I use SFML to create the window.
In this screenshot the cube should be behind the pyramid but it just doesn't work.
Here is the minimal code I used:
#include <OpenGL/gl.h>
#include <OpenGL/glu.h>
#include <SFML/Graphics.hpp>
#include "ResourcePath.hpp"
void resize();
void drawScene();
void initGL();
float rtri = 0;
float rquad = 0;
float z = -10.0f;
int main (int argc, const char * argv[])
{
// Create the main window
sf::RenderWindow *window = new sf::RenderWindow();
window->Create( sf::VideoMode( 800, 600, 32 ), "Collision Detection", sf::Style::Close );
sf::Event event;
bool run = true;
initGL();
resize();
while( run ) {
window->PollEvent( event );
if( event.Type == sf::Event::Closed ) {
run = false;
}
drawScene();
window->Display();
// z+= 0.001f;
}
return EXIT_SUCCESS;
}
void resize() {
glViewport(0,0, 800,600);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
// Calculate The Aspect Ratio Of The Window
gluPerspective(45.0f,800/600,0.1f,100.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void drawScene() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear Screen And Depth Buffer
glLoadIdentity(); // Reset The Current Modelview Matrix
glTranslatef(0.0f,0.0f,-6.0f); // Move Left 1.5 Units And Into The Screen 6.0
glRotatef(rtri,0.0f,1.0f,0.0f); // Rotate The Triangle On The Y axis ( NEW )
glBegin(GL_TRIANGLES);
glColor3f(1.0f,0.0f,0.0f);
glVertex3f( 0.0f, 1.0f, 0.0f);
glColor3f(0.0f,1.0f,0.0f);
glVertex3f(-1.0f,-1.0f, 1.0f);
glColor3f(0.0f,0.0f,1.0f);
glVertex3f( 1.0f,-1.0f, 1.0f);
glColor3f(1.0f,0.0f,0.0f);
glVertex3f( 0.0f, 1.0f, 0.0f);
glColor3f(0.0f,0.0f,1.0f);
glVertex3f( 1.0f,-1.0f, 1.0f);
glColor3f(0.0f,1.0f,0.0f);
glVertex3f( 1.0f,-1.0f, -1.0f);
glColor3f(1.0f,0.0f,0.0f);
glVertex3f( 0.0f, 1.0f, 0.0f);
glColor3f(0.0f,1.0f,0.0f);
glVertex3f( 1.0f,-1.0f, -1.0f);
glColor3f(0.0f,0.0f,1.0f);
glVertex3f(-1.0f,-1.0f, -1.0f);
glColor3f(1.0f,0.0f,0.0f);
glVertex3f( 0.0f, 1.0f, 0.0f);
glColor3f(0.0f,0.0f,1.0f);
glVertex3f(-1.0f,-1.0f,-1.0f);
glColor3f(0.0f,1.0f,0.0f);
glVertex3f(-1.0f,-1.0f, 1.0f);
glEnd();
glLoadIdentity(); // Reset The Current Modelview Matrix
glTranslatef(0.0f,0.0f,z); // Move Right 1.5 Units And Into The Screen 7.0
glRotatef(rquad,1.0f,1.0f,z); // Rotate The Quad On The X axis ( NEW )
glBegin(GL_QUADS);
glColor3f(0.0f,1.0f,0.0f);
glVertex3f( 1.0f, 1.0f,-1.0f);
glVertex3f(-1.0f, 1.0f,-1.0f);
glVertex3f(-1.0f, 1.0f, 1.0f);
glVertex3f( 1.0f, 1.0f, 1.0f);
glColor3f(1.0f,0.5f,0.0f);
glVertex3f( 1.0f,-1.0f, 1.0f);
glVertex3f(-1.0f,-1.0f, 1.0f);
glVertex3f(-1.0f,-1.0f,-1.0f);
glVertex3f( 1.0f,-1.0f,-1.0f);
glColor3f(1.0f,0.0f,0.0f);
glVertex3f( 1.0f, 1.0f, 1.0f);
glVertex3f(-1.0f, 1.0f, 1.0f);
glVertex3f(-1.0f,-1.0f, 1.0f);
glVertex3f( 1.0f,-1.0f, 1.0f);
glColor3f(1.0f,1.0f,0.0f);
glVertex3f( 1.0f,-1.0f,-1.0f);
glVertex3f(-1.0f,-1.0f,-1.0f);
glVertex3f(-1.0f, 1.0f,-1.0f);
glVertex3f( 1.0f, 1.0f,-1.0f);
glColor3f(0.0f,0.0f,1.0f);
glVertex3f(-1.0f, 1.0f, 1.0f);
glVertex3f(-1.0f, 1.0f,-1.0f);
glVertex3f(-1.0f,-1.0f,-1.0f);
glVertex3f(-1.0f,-1.0f, 1.0f);
glColor3f(1.0f,0.0f,1.0f);
glVertex3f( 1.0f, 1.0f,-1.0f);
glVertex3f( 1.0f, 1.0f, 1.0f);
glVertex3f( 1.0f,-1.0f, 1.0f);
glVertex3f( 1.0f,-1.0f,-1.0f);
glEnd(); // Done Drawing The Quad
rtri+=0.2f; // Increase The Rotation Variable For The Triangle ( NEW )
rquad-=0.15f;
z-=0.01;
}
void initGL() {
glShadeModel(GL_SMOOTH); // Enable Smooth Shading
glClearColor(0.0f, 0.0f, 0.0f, 0.5f); // Black Background
glClearDepth(1.0f); // Depth Buffer Setup
glEnable(GL_DEPTH_TEST); // Enables Depth Testing
glDepthFunc(GL_LEQUAL); // The Type Of Depth Testing To Do
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
glEnable( GL_CULL_FACE );
/* Position the camera */
glTranslatef(0, 0, -5);
}
I've tried different depth functions, GL_LESS, GL_EQUAL, I've tried them all. Also enabling and disabling depth testing on different places, nothing seems to work.
I'm running Mac OS X 10.7 ( Lion ), not sure if that is important, though I didn't seem to have any trouble with these kind of things before upgrading.
Your code looks okay. I suspect that your window simply does not have a depth buffer. You're using sf::RenderWindow, whose documentation says (emphasis mine):
Simple wrapper for sf::Window that allows easy 2D rendering.
I don't know SFML, but this tutorial suggests to create your window like this:
sf::WindowSettings Settings;
Settings.DepthBits = 24; // Request a 24 bits depth buffer
Settings.StencilBits = 8; // Request a 8 bits stencil buffer
Settings.AntialiasingLevel = 2; // Request 2 levels of antialiasing
sf::Window App(sf::VideoMode(800, 600, 32), "SFML OpenGL", sf::Style::Close, Settings);
You could set StencilBits and AntialiasingLevel to 0 since this example doesn't need them.
In latest version of SFML WindowSettings replaced by ContextSettings. Depth settings can be configured as.
//Configuring SFML window
sf::ContextSettings window_settings;
window_settings.depthBits = 24; // Request a 24-bit depth buffer
window_settings.stencilBits = 8; // Request a 8 bits stencil buffer
window_settings.antialiasingLevel = 2; // Request 2 levels of antialiasing
// Opening SFML window
sf::Window window(sf::VideoMode(800, 600), "Title", sf::Style::Resize | sf::Style::Close, window_settings);
glewExperimental = GL_TRUE;
// Initializing glew and openGL
glewInit();
glViewport(0, 0, 800, 600);
// Enabling Depth
glEnable(GL_DEPTH_TEST);