only 1 render function?

Started by
14 comments, last by Lord_Evil 17 years, 1 month ago
Hi guys I have got a beginner question about a serious problem while developing with openGL. As far as i know, there is only 1 function where you can render to a surface, which normally runs in a while-loop, something like: while (!complete) { processEvents(); glBegin(GL_dunnoWhat); glVertex3d(0,0,0,0); glEnd(); if (somethingstrue) { glBegin(whatever); glEnd(); } } It is very inelegant to write rendering code in this one function directly with a lot of IFs and elses. Is there any possibility to add rendering code in another function? Or how do you fellas handle this problem? I personally cannot understand how big game developers solve their complex code in one loop in the same function... I know there are rendering context but I dont know if that's the right point to do. Can you give me some suggestions? thanks, echnaton P.S.: When i try to call a function inside an IF condition, and add rendering code inside that function, it doesn't work (no surprise)
Advertisement
You should be able to make OpenGL rendering calls from any function! Post your code and the exact problems, and someone here will probably be able to help you with that.
OK, actually i tried it with 2 different methods: SDL and freeGLUT, both didnt work.

Heres the code snippet for freeGLUT:

void DrawGLScene() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glColor3f(1.0, 1.0, 1.0);
glTranslatef(scrollX, scrollY, 0.0);
glBegin(GL_LINES);
glVertex2f(0.0, 0.0);
glVertex2f(1.0, 1.0);
glEnd();
glutSwapBuffers();
}


It is called by the glut display function in the main function:
glutDisplayFunc(&DrawGLScene);



And heres the SDL snippet (only the important code):

int main(int argc, char *argv[]) {

SDL_Init( SDL_INIT_VIDEO );
SDL_Surface *pSDLSurface = SDL_SetVideoMode( windowWidth, windowHeight, 32, nFlags );
while(!isDone) {
SDL_PollEvent(&event);
render();
}
SDL_Quit();
}

void render(void) {
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glLoadIdentity();
//here comes everything that will be drawn
SDL_GL_SwapBuffers();
}




I do apologize for this bad display of the code, but somehow whitespaces and tabs are ignored in this forum.

the question is: how do i add code from a function like:

void filleWithBlack() {
glClear(0,0,0,0);
}

and call it from the while loop in the 'main' function (eg. mouse press or something)?
If you're doing it that way you still have to be between glBegin() / glEnd() calls, are you doing that?

Basically like this:

void function1()
{
glBegin();
function2();
glEnd()
}

void function2()
{
// gl draw calls here ...
}

throw table_exception("(? ???)? ? ???");

One way to solve the complex IF / ELSE cases is to use std::stack to hold different game-states.

For example, create a structure like so...
// Function pointer typedefstypedef bool (*UPDATE_FUNCTION)();  // Pointer to a bool functiontypedef void (*RENDER_FUNCTION)();  // Pointer to a void functionstruct GameState{  UPDATE_FUNCTION Update;  RENDER_FUNCTION Render;};


Then, say you have an update and a render routine for a START game-state, say START_Update() and START_Render()...
#include <stack>// Used to hold game-statesstd::stack<GameState> StateStack;// Your functionsbool START_Update() { return(true); }void START_Render() { /* Your rendering code here */ }// Create new game stateGameState NewState;NewState.Update = START_Update;NewState.Render = START_Render;// Add new game-state to stackStateStack.push(NewState);


Then, in your main game loop, you do something like this...
while(GameRunning){  if(!StateStack.top().Update()) { GameRunning = false; }  StateStack.top().Render();}


This probably goes WAY beyond what you were asking, but it eliminates the messy game loop and it is one way for developers to handle their "complex code". And, as Simian Man already said, you can use OpenGL calls in any function (even in your update routines, but that's just bad practice - you should keep your update and render code separate).

NOTE - If there are any errors in the code I provided, please point them out.
EDIT - It would seem my post had barely anything to do with your question. Still, something to look at after you solve your other problems.
yes that is pretty close to what i want to do:

void defaultRenderFunction()
{
glBegin();
myOwnFunction();
glEnd()
}

void myOwnFunction() {
glBegin();
//whatever comes here shouldn't matter
glEnd();
}



first - this does NOT work! i don't get any error but the code i have written inside 'myOwnFunction' won't be visible (it will when i add it to my 'defaultRenderFunction' (which was called by glut or sdl).

later i want to "display" code from another function which will be called/triggered by an event, like a mousebutton.

an example:

i want to display a square when i press the left mousebutton.

one way would be over the If-Way:

void defaultRenderFunction()
{
if (mouseButtonPressed) {
glBegin();
//display the square here
glEnd()
}
}


but that is inelegant because bigger projects won't be concise!

so i like to do something like:

void defaultRenderFunction()
{

switch (keys) { //alredy implemented
case leftmousebutton: //alredy implemented
drawANiceSquare();
break;
}
}

void drawANiceSquare() {
glBegin();
// draw it here by calling glVertex3f();
glEnd();
}

Do you guys understand me?
@TheShadow344:

Thanks, i appreciate your code and will further implement it :D
I'm no pro and don't know tricks like the stack way...

But unfortunately thats not the point i'm looking for.

the precise question is the example i posted above this post.
Quote:Original post by echnaton
yes that is pretty close to what i want to do:

void defaultRenderFunction()
{
glBegin();
myOwnFunction();
glEnd()
}

void myOwnFunction() {
glBegin();
//whatever comes here shouldn't matter
glEnd();
}



first - this does NOT work! i don't get any error but the code i have written inside 'myOwnFunction' won't be visible (it will when i add it to my 'defaultRenderFunction' (which was called by glut or sdl).

The reason you don't get any errors is because you aren't checking for them. I imagine if you added some glGetError( ) calls, you'd see something along the lines of GL_INVALID_OPERATION, since, according to the documentation,
Quote:[A GL_INVALID_OPERATION error is generated if] ... glBegin was called within a glBegin/glEnd sequence.


This isn't your actual code, is it:
Quote:void defaultRenderFunction()
{

switch (keys) { //alredy implemented
case leftmousebutton: //alredy implemented
drawANiceSquare();
break;
}
}

void drawANiceSquare() {
glBegin();
// draw it here by calling glVertex3f();
glEnd();
}

If what I pointed out above doesn't solve the problem, can you post your actual code? It's hard to see what's wrong when we don't see what's actually going on.

-jouley
this is my program:

http://www.file-upload.net/download-214287/test.zip.html


execute it with 'make'


the important section is in the 'keyPressed'-function in the file doctorTest.cpp

quote of the function:

// SAMPLE CODE:
glColor3f(1.0, 1.0, 1.0);
glBegin(GL_LINES);
glVertex2f(0.5, 0.0);
glVertex2f(1.0, 0.1);
glEnd();



this will NOT be displayed but it should...

i will check for errors tomorrow

The render function is simply the entry point into your rendering logic. You can call as many functions as you want, and they can call as many as they want (stack prohibiting, of course), etc...

The code snippet you showed SHOULD work if it is actually representative of your code.

EDIT: I see others have mentioned it, but you can't call glBegin() then call a function that in turn calls glBegin() again. Just call glBegin when you are ready to ACTUALLY send geometry to the pipeline.

This topic is closed to new replies.

Advertisement