Please help me to check what is the problem in my code with glscissor()

I’m studying and building 3D modeling tools with OpenGL and trying to improve overall performance in drawing with glscissor(), however other objects are cleared up as well whenever I try to draw a new object in clipped area by glscissor().
Please help me out to check what can be the problem and how to fix it.

I was only able to see entire objects when I set force redraw flag to true in attached video.
So basically I want to keep the previous objects stay in the screen with no update, and to add new object and make all those to be visible at the same time.

Vertex3D 2021-06-14 15-22-37

I will post major function in my project

void Display_Handle::DisplayOperator(Objects &sourceObject, Textures &sourceTexture, GL_Window *glView, ViewportClipping *vClip, OperationMode CurMode, int viewPort, int cameraIndex) {
	for (int viewPort = 0; viewPort < 4; viewPort++) {
		for (int dataIndex = 0; dataIndex < vClip[i].count; dataIndex++) {
		// Clear background with black
		if (CurMode.operation == OPERATION_RENDERING)
			glClearColor(0.0, 0.0, 0.0, 0.0);

		// Clear background with own color
		else
			glClearColor(glView[viewPort].bgColor.r, glView[viewPort].bgColor.g, glView[viewPort].bgColor.b, glView[viewPort].bgColor.a);

		// Clear color buffer
		glClear(GL_COLOR_BUFFER_BIT);

		// Select Projection Matrix
		glMatrixMode(GL_PROJECTION);

		// Clear depth buffer
		glClear(GL_DEPTH_BUFFER_BIT);

		// Enable scissor
		glEnable(GL_SCISSOR_TEST);

		// Scissor area
		glScissor(vClip[viewPort].data[dataIndex].area.x, vClip[viewPort].data[dataIndex].area.y, vClip[viewPort].data[dataIndex].area.width, vClip[viewPort].data[dataIndex].area.height);

		// Disable scissor
		glDisable(GL_SCISSOR_TEST);

		// Reset Projection Matrix
		glLoadIdentity();

		// Viewport
		glViewport(0, 0, glView[viewPort].init.Width, glView[viewPort].init.Height);

		// Range
		ViewX = (GLdouble)(glView[viewPort].init.Width / 2);
		ViewY = (GLdouble)(glView[viewPort].init.Height / 2);

		// Projection
		glOrtho(ViewX, -ViewX, ViewY, -ViewY, -500.0, 500.0);

		// Select Modelview Matrix
		glMatrixMode(GL_MODELVIEW);

		// Reset Modelview Matrix
		glLoadIdentity();

		// Zoom in, out
		glScaled(glView[viewPort].distance, glView[viewPort].distance, glView[viewPort].distance);

		// Pan
		if (glView[viewPort].viewType == VIEW_TOP || glView[viewPort].viewType == VIEW_BOTTOM)
			glTranslated(glView[viewPort].translate.x, glView[viewPort].translate.z, 0.0);

		else if (glView[viewPort].viewType == VIEW_FRONT || glView[viewPort].viewType == VIEW_BACK)
			glTranslated(glView[viewPort].translate.x, glView[viewPort].translate.y, 0.0);

		else if (glView[viewPort].viewType == VIEW_LEFT || glView[viewPort].viewType == VIEW_RIGHT)
			glTranslated(glView[viewPort].translate.z, glView[viewPort].translate.y, 0.0);

		// View
		gluLookAt(glView[viewPort].eye.x, glView[viewPort].eye.y, glView[viewPort].eye.z, glView[viewPort].center.x, glView[viewPort].center.y, glView[viewPort].center.z, glView[viewPort].up.x, glView[viewPort].up.y, glView[viewPort].up.z);

		// Get viewport axis
		glGetDoublev(GL_MODELVIEW_MATRIX, glView[viewPort].mvMatrix);
		glGetDoublev(GL_PROJECTION_MATRIX, glView[viewPort].prjMatrix);
		glGetIntegerv(GL_VIEWPORT, glView[viewPort].viewport);
				
		// Grid view
		UpdateGridView(viewPort);

		// Draw objects and textures
		DrawObject(sourceObject, sourceTexture, vClip[viewPort].data[dataIndex].objectID, viewPort, CurMode.activeMode, cameraIndex);

		// Swap buffers
		SwapBuffers(glView[viewPort].hDC);
	}
}

This is something that people new to 3D drawing frequently attempt, in a misguided but well-intentioned attempt to improve performance.

You actually shouldn’t do this at all. The optimal code path for your GPU is to actually draw everything every frame; even if some or all of it doesn’t change.

First of all, it lets you clear (via glClear) at the start of each frame, which your GPU can optimize other rendering tasks around, and which just flat-out plays nicer with certain types of GPU.

Secondly, it lets your GPU double-buffer and use SwapBuffers calls more optimally, in particular in relation to how the buffer swap is implemented.

Thirdly, and as you’re starting to discover, a whole lot of code just gets a whole lot simpler as a result.

There’s a reason why every major application does things this way, and that’s because it’s what works.

As mhagain says, you almost certainly shouldn’t try to do this. Just draw everything whenever you need to refresh the view.

As for why it doesn’t work: SwapBuffers leaves the back buffer (the one you’re drawing to) in an indeterminate state. It may remain unchanged, it may be cleared, it may be the previous front buffer, it may be some uninitialised chunk of video memory. After a SwapBuffers call, the next OpenGL command should usually be glClear.

Back when video hardware was really slow, it wasn’t uncommon for CAD software to perform incremental updates (i.e. only drawing what has changed). But this normally used single-buffering, drawing everything to the front buffer. The main problem with that is that is that while the back buffer is destroyed by a SwapBuffers call, the front buffer is destroyed (or damaged) whenever the window system feels like it. So you need to keep track of “damage” events and be able to repaint damaged regions as necessary. And on top of that, single-buffered rendering isn’t particularly efficient (or even reliable) with modern hardware, mainly because no-one does it.

If you really need to update a scene incrementally, the reliable way to do it is to use some form of offscreen surface: either a framebuffer object (requires OpenGL 3.0 or the GL_ARB_framebuffer_object extension) or some platform-specific mechanism such as pbuffers or a GLXPixmap. These retain their contents until explicitly modified.

1 Like

This topic was automatically closed 183 days after the last reply. New replies are no longer allowed.