Need for glOrtho()

2020-06-19 open gl question glOrtho
I have created an application on a Linux machine that uses Qt and Open Gl to display a frequency spectrum. The code was copied from a strip chart display. There are no rotations, translations, or any type of moves. This is a 2D display with nothing but lines and sometimes points.
Making this short the discovery was that the call to glOrtho() must be done after the glLoadIdentity(), and on every iteration. So far, the values to glOrtho() do not change. In the strip chart they constantly changed as the chart moved through time. If it does not change, why is the reload required?
Someone with more experience with Open GL, and that is not a high hurdle, suggested some changes that led to the solution. It worked, then I commented out some lines to discover the minimum required set. That was followed by some searches and some reading. Am I incorrect and should any of them be re-enabled?
Thank you for your time.

void C_GL_Widget::update_widget_display( )
   const QString MY_NAME = "C_GL_Widget::update_widget_display";
   md_update_widget_display_count ++;
   glClear( GL_COLOR_BUFFER_BIT );
   glMatrixMode( GL_MODELVIEW );
//   glPushMatrix();

   glOrtho( m_ortho_left_clip,   // This is the key.  It must be after load identity.
            m_ortho_right_clip,  // I don't understand why.
            m_ortho_far_clip );
   glColor3ub(  0, 255, 0);
   glLineWidth( 2.5  );
   glBegin( GL_LINE_STRIP ); 
   double y;
   double x;
   for(  int i = 0; i <= m_frequency_bin_count; i ++ )
       x = m_display_buffer[ i ].p[ PX ];
       y = m_display_buffer[ i ].p[ PY ];
       glVertex2d( x,y );
   display_amplitude_markers( );
   display_frequency_markers( );
//   glFlush();
//   glMatrixMode( GL_PROJECTION );  // project does not belong here
//   glLoadIdentity();     //Why load an identify matrix after drawing points?
//   glPopMatrix();

   update( );
} // end of:  update_widget_display ( )

All matrices are initially the identity matrix. So if you want an identity matrix you don’t need to set it explicitly. Once set, matrices retain their value until explicitly changed. However, all matrix functions other than those beginning with glLoad operate by concatenating a relative transformation with the existing value. So if you want to set a matrix to a specific value, ignoring any current value, you need to first use one of the glLoad* functions (typically glLoadIdentity) to reset the matrix to a known state.

Beyond that, explicitly setting the matrices at the start of the redraw function helps to avoid surprises as the program evolves. Relying upon state being preserved is fine until it isn’t; explicitly setting it is more robust. And it’s not as if these functions are computationally expensive.

Having said that, the glPushMatrix and glPopMatrix calls aren’t needed. And are incorrect in light of the glMatrixMode call; if retained, they would push onto the model-view matrix stack but pop from the projection matrix stack.

Thanks for your time. Your reply helps build my confidence.
Why is the glOrtho() call required after the glLoadIdentity()?
That makes me think that the glOrtho settings are localized within Open GL, not global. If so, what are the limits, or the confines of the glOrtho settings?

glOrtho is equivalent to calling glMultMatrix with the matrix shown here.

A sequence of glLoadIdentity followed by glMultMatrix is equivalent to glLoadMatrix. glLoadIdentity, glLoadMatrix and (in 1.3+) glLoadTransposeMatrix simply replace the current matrix. All other matrix operations compose (multiply) the current matrix with some other matrix: C=C*M. So you use glLoadIdentity if you want to “start from scratch”.

All matrix operations affect the topmost matrix on the matrix stack selected by glMatrixMode. Rendering operations use the topmost matrix on each stack. glPushMatrix duplicates the top-most matrix (i.e. pushes a copy of the top-most matrix onto the stack), glPopMatrix removes the top-most matrix; these functions exist so that you can save and then restore the current matrix, which is useful for hierarchical models.