So I'm trying to render a basic overlay onto my 3D scene, and currently I can either have the 3D scene or the 2D overlay, I cant work out how to get both
In my main method, where render is called, I moved specific render functions to manager classes, so in the main render I call :
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
glEnable(GL_COLOR_MATERIAL);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-aspect, aspect, -1, 1, -10, 10);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
material.setColour(new Vector3f(1,1,1));
sLight.getPointLight().setPosition(camera.getPosition());
sLight.setDirection(camera.getForward());
DayCycle.getInstance().update(Time.getDelta());
shader.updateUniforms(transform.getTransformation(), transform.getProjectedTransformation(), material);
//material is a wrapper class for textures and specular value etc
//transform is a matrix wrapper for getting projected transformations, taking the camera position when its created
WorldManager.renderAll(true); //true denotes yes to wireframe mode
InterfaceManager.renderAll();
glfwSwapBuffers(window);
glfwPollEvents();
If i comment out WorldManager.renderAll(), I get the little 2d square in the right part of the screen, If i dont comment it, I get the world render but no little square
WorldManager.renderAll()
public static void renderAll(boolean wireframeMode)
{
RendererUtils.setWireframeMode(wireframeMode);
for (String s : chunks.keySet())
{
Chunk actingChunk = chunks.get(s);
Transform transform = new Transform();
Shader shader = PhongShader.getInstance();
transform.setTranslation(new Vector3f(actingChunk.getLocation().getX() * (Chunk.ChunkSize),0.0f, actingChunk.getLocation().getY() * (Chunk.ChunkSize)));
transform.setScale(1.0f, 50f, 1.0f);
shader.updateUniforms(transform.getTransformation(), transform.getProjectedTransformation(), actingChunk.getMaterial());
shader.bind();
actingChunk.getMesh().draw();
//transform.setRotation(new Vector3f(0,0,0));
}
}
InterfaceManager.renderAll()
public static void renderAll()
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, width, 0, height, -10, 10);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glDisable(GL_CULL_FACE);
glDisable(GL_DEPTH_TEST);
RendererUtils.setWireframeMode(false);
for (Interface i : interfaces)
{
Transform transform = new Transform();
transform.setTranslation(new Vector3f(0,0,0));
InterfaceShader.getInstance().updateUniforms(transform.getProjectedTransformation());
InterfaceShader.getInstance().bind();
i.getMesh().draw();
}
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
}
When I have WorldManager.renderAll() uncommented, i get a nice sea of triangles (as its meant to look) but no 2D square
With it commented, I get a nice little square where its meant to be and nothing else
Shaders are here : https://pastebin.com/xWaWhQHy because I felt this post was getting too long to have them inlined
What's my problem? I cant figure out where it is
Edit : If i've missed any pertinent code, tell me and i'll upload it to a pastebin
Edit 2 : updated my code here to reflect that i'd removed a shader in interfaceManager to actually get a square to draw at all : https://pastebin.com/pHHDsCvF for the shader code
Edit 3 : Ive determined it's something to do with my interface shaders, If i use PhongShader instead of InterfaceShader then it works exactly how I wanted it to
I can suggest you to modify the code this way:
WorldManager.renderAll(true); //true denotes yes to wireframe mode
glClear(GL_DEPTH_BUFFER_BIT);
InterfaceManager.renderAll();
This way you will clear depth buffer before rendering 2d interface.
The problem was that I was still applying transformations to the vertices after passing them to the shader.
By editing out the transformation (and later scrapping the entire vertex shader) in the InterfaceShader instance, the little squares were appearing in the right place
Related
I have a tile engine using orthographic projection in immediate mode and I'm just trying to draw a 3d cube on top of my tile scene, in hopes that I can eventually incorporate 3d models into my engine instead of just sprites / textured quads. I would also like to make the tiles 3d for that slight bit of extra eye candy.. Hopefully I can eventually convert this to use modern OpenGL so I can take advantage of those extra features. Not on the top of my priority list at the moment. So on to the question.
I'm initializing OpenGL with this:
void initGL()
{
glDisable(GL_DEPTH_TEST);
glViewport( 0,0,SCREEN_WIDTH,SCREEN_HEIGHT);
//Initialize Projection Matrix
glMatrixMode( GL_PROJECTION );
glPushMatrix();
glLoadIdentity();
//Initialize Modelview Matrix
glMatrixMode( GL_MODELVIEW );
glPushMatrix();
glLoadIdentity();
glOrtho(0,SCREEN_WIDTH,SCREEN_HEIGHT,0,0,1);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
//...setting some various other attributes, omitted for brevity...
glEnable(GL_TEXTURE_2D);
glClearColor( 0, 0, 0, 0 );
}
I have a function for drawing a cube that works.
void draw_cube()
{
/* position object */
glRotatef(30.0F, 1.0F, 0.0F, 0.0F);
glRotatef(30.0F, 0.0F, 1.0F, 0.0F);
/* draw six faces of a cube */
glBegin(GL_QUADS);
...vertices... (removed for brevity)
glEnd();
}
I made 2 functions for setting the 2d and 3d projection modes.
void set3d()
{
glEnable(GL_DEPTH_TEST);
glClear(GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(0,SCREEN_WIDTH,0,SCREEN_HEIGHT, 0,1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void set2d()
{
glClear(GL_COLOR_BUFFER_BIT);
glDisable(GL_DEPTH_TEST);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0,SCREEN_WIDTH,SCREEN_HEIGHT,0,0,1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
For the sake of completeness, some pseudocode of my textured quad drawing..
pushmatrix();
translate();
rotate();
-translate();
glbegin();
...vertices
glend();
popmatrix();
So far I have managed to get the cube to draw on top of the tiles, but it disappears after approximately 1 second to never be seen again until I run the program again.
Basically what I'm doing in the main loop is this:
move objects around, process collisions, etc.
set2d();
draw textured quads, lines, text, etc. in 2d mode.
set3d();
draw_cube();
My question is: Why is the cube disappearing, and are there any errors in my set2d() and set3d() functions?
You have quite a few problems in this code, too many to list in comments in fact.
Your projection matrices are changing the handedness of your post-projected coordinate space, which will affect polygon winding.
Stick to a single handedness, unless you want to reverse the direction used for front- / back-facing polygon facets (glFrontFace (...)) - it is CCW by default, but you will have to change it to CW when you use set3d (...) to maintain consistent behavior.
This problem arises because you have the Y-axis going different directions
The behavior your are describing, where the object appears briefly and then disappears is indicative of an issue with your matrix stack.
Are you calling initGL (...) more than once in your software? You will run into a stack overflow if you do this enough times since you needlessly push the current matrix onto the stack and never pop it off.
You cannot use 0.0 for zNear with a perspective projection matrix, this will result in wonky math during the perspective divide step that comes after transformation to clip-space; the depth buffer will not work correctly.
In fact, glFrustum (...) will generate a GL_INVALID_VALUE error and do exactly nothing if you pass a value ≤ 0.0 for zNear. On a related note, gluPerspective (...) will not do this since it is not actually part of OpenGL, but it is equally invalid behavior to pass such a value to gluPerspective (...).
I have a 3D scene with an object and I would like to save a view of that object that is different from the one of the current screen I look at.
So I thought I'd just have to do something like this (pseudo code):
PushMatrix()
LoadIdentity()
TranslateAndRotate()
gluperspective()
setViewport()
DrawScene()
saveScreenshot()
PopMatrix()
But I only get a picture of the current view of my camera, not the one I specified.
Did I forget something?
EDIT:
Because of the answer below, I tried the following code:
void ScenePhotograph(GLubyte* Target, float *Translation, float RotationAroundY)
{
glMatrixMode(GL_PROJECTION);
gluPerspective(54.0f, (GLfloat)openGLControl1->Width / (GLfloat)openGLControl1->Height, 1.0f, 3000.0f);
glViewport(0,0,openGLControl1->Width, openGLControl1->Height);
glMatrixMode(GL_MODELVIEW);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glTranslatef(Translation[0],Translation[1],Translation[2]);
glRotatef(RotationAroundY, 0,1,0);
openGLControl1_OnDrawGL(NULL,System::EventArgs::Empty);
openGLControl1->Refresh();
glReadPixels(0, 0, openGLControl1->Width, openGLControl1->Height, GL_RGB, GL_UNSIGNED_BYTE, Target);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
cam->SetView();
openGLControl1_OnDrawGL(NULL,System::EventArgs::Empty);
openGLControl1->Refresh();
glutSwapBuffers();
}
That is giving me an access violation at glutSwapBuffers();
Any Ideas?
First, make sure you are not mixing diferent matrix in your code. To get a screenshot, you will need to position your camera exactly as you normally do to view it on your sccreen, but, before you swap the buffers, you read the pixels from the current framebuffer and store it as an image.
So, what you need is something like this:
glMatrixMode(GL_PROJECTION);
gluPerspective();
glMatrixMode(GL_MODELVIEW);
glClear(); // clear buffers here
loadIdendity();
setCameraPosition();
TranslateRotate();
DrawScene();
screenShot();
// do again to set your camera to correct position
glClear(); // clear buffers here
loadIdendity();
setCameraPosition();
TranslateRotate();
DrawScene();
swapBuffers();
as you can see, screenShot take care of reading the pixels from your current framebuffer and save it as an image. So do everything again to position your camera to the correct place
I just started working with OpenGL, but I ran into a problem after implementing a Font system.
My plan is to simply visualize several Pathfinding Algorithms.
Currently OpenGL gets set up like this (OnSize gets called once on window creation manually):
void GLWindow::OnSize(GLsizei width, GLsizei height)
{
// set size
glViewport(0,0,width,height);
// orthographic projection
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0,width,height,0.0,-1.0,1.0);
glMatrixMode(GL_MODELVIEW);
m_uiWidth = width;
m_uiHeight = height;
}
void GLWindow::InitGL()
{
// enable 2D texturing
glEnable(GL_TEXTURE_2D);
// choose a smooth shading model
glShadeModel(GL_SMOOTH);
// set the clear color to black
glClearColor(0.0, 0.0, 0.0, 0.0);
glEnable(GL_ALPHA_TEST);
glAlphaFunc(GL_GREATER, 0.0f);
}
In theory I don't need blending, because I will only use untextured Quads to visualize obstacles and line etc to draw paths... So everything will be untextured, except the fonts...
The Font Class has a push and pop function, that look like this (if I remember right my Font system is based on a NeHe Tutorial that I was following quite a while ago):
inline void GLFont::pushScreenMatrix()
{
glPushAttrib(GL_TRANSFORM_BIT);
GLint viewport[4];
glGetIntegerv(GL_VIEWPORT, viewport);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glOrtho(viewport[0],viewport[2],viewport[1],viewport[3], -1.0, 1.0);
glPopAttrib();
}
inline void GLFont::popProjectionMatrix()
{
glPushAttrib(GL_TRANSFORM_BIT);
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glPopAttrib();
}
So the Problem:
If I don't draw a Text I can see the Quads I want to draw, but they are quite dark, so there must be something wrong with my general OpenGL Matrix Properties.
If I draw Text (so the font related push and pop functions get called) I can't see any Quads.
The question:
How do I solve this problem and some background information why this happened would also be nice, because I am still a beginner/student, who just started.
If your quads are untextured, you will run into undefined behaviour. What will probably happen is that any previous texture will be used, and the colour at point (0,0) will be used, which could be what is causing them to be invisible.
Really, you need to disable texturing before trying to draw untextured quads using glDisable(GL_TEXTURE_2D). Again, if you don't, it'll just use the previous texture and texture co-ordinates, which without seeing your draw() loop, I'm assuming to be undefined.
I know how to speed up rendering in 3d by simply rendering the nearest planes first.
But how do i get advantage of this type of method in 2d mode? I cant use depth testing because they are all in the same z-level.
So i was thinking if it could be speed up when i dont need to render the invisible parts of the layers "below". Is this possible?
Note that i am rendering in 3d mode, there may be 3d objects and 2d objects at the same time. So i cant switch to 2d render only, i always use 3d coordinates for everything. And i may rotate the camera as i wish, so camera-specific tricks arent acceptable.
Edit: i tried the method Ville suggested:
( http://img815.imageshack.us/img815/7857/zfighting.png )
but as you see, it will result in z-fighting.
The code i used for rendering that is here:
glDepthFunc(GL_LESS);
glEnable(GL_DEPTH_TEST);
glDisable(GL_TEXTURE_2D);
glDisable(GL_ALPHA_TEST);
glDisable(GL_POLYGON_OFFSET_FILL);
glColor4f(1,0,0,1);
DrawQuad(0, 0, 10, 10);
glColor4f(0,0,1,1);
DrawQuad(5, 5, 15, 15);
glDepthFunc(GL_LEQUAL);
It sounds like you are rendering all your "2D" objects on the same plane. You could render your 2D parts into an off-screen framebuffer with an orthographic projection and give them different Z values as datenwolf suggested. Then render the framebuffer texture into your main 3D scene.
What do you understand by 2D mode? Do you mean orthographic projection? Then I have good news: Depth testing works there perfectly as well. gluOrtho2D is basically the same like glOrtho(..., -1, 1); i.e. you have the Z range -1 ... 1 to spend.
EDIT due to comment:
It is perfectly possible to combine rendering several projections in one single frame:
void render_perspective_scene(void);
void render_ortho_scene(void);
void render_HUD();
void display()
{
float const aspect = (float)win_width/(float)win_height;
glViewport(0,0,win_width,win_height);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-aspect*near/lens, aspect*near/lens, -near/lens, near/lens, near, far);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
render_perspective_scene();
// just clear the depth buffer, so that everything that's
// drawn next will overlay the previously rendered scene.
glClear(GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-aspect*scale, aspect*scale, -scale, scale, 0, 1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
render_ortho_scene();
// Same for the HUD, only that we render
// that one in pixel coordinates.
glClear(GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, win_width, 0, win_height, 0, 1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
render_HUD();
}
Of course if you've fallen for those bad tutorials that place the projection matrix setup in the reshape handler you're of course mind blocked, to see that obvious solution.
Hi I got 4 viewports and one large that I can switch between now I got an object namely the camera and the cameras target position that I show with rendering a sphere at those locations. I want to show the cameras position in 3 of my viewports but not in the last which is the camera display but at the moment I got an all or nothing scenario.
void display(int what)
{
if(what==5){
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
camControll();}
if(what==1){
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(75,15,-5,0,5,-5,0,1,0);}
if(what==2){
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0,110,0,0,0,0,1,0,0);}
if(what==3){
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f, float(320) / float(240), 0.1f, 100.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
camControll();}
if(what==4){
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(185,75,25,0,28,0,0,1,0);}
//glMatrixMode(GL_MODELVIEW);
//glLoadIdentity();
////gluLookAt(cos(shared.time) * shared.distance, 10, sin(shared.time) * shared.distance, 0, 0, 0, 0, 1, 0);
////ca.orbitYaw(0.05);
//ca.lookAt();
glClearColor(0, 0, 0, 1);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
drawScene(); // scene that all views should render
drawCamera(); / camera position that only certain views should render
glutSwapBuffers();
}
I'm thinking that perhaps I could do one sweep for first the 3 viewports and then call glutSwapBuffers() and then do the other viewport without the camera position but some stuttering I previously had was traced to glutSwapBuffers() being called for each viewport so I guess there has to be another way only that I cant figure it out.
You have to render everything before swapping buffers.
As you do it - it is not going to work. Actually, it will work, but not you want.
EDIT
To render to a texture take a look into one of the links here.
After changing a view, render the image for the specific view to a texture. Then for the final image, set the final view and render all 3 textures. Only when the final image is rendered, swap buffers.
On the 2nd thought, it would be much better if you could set the vertices of all objects to render and render whole image in one pass.