Display 3D graphics on the STM32F407

As you know, older STMs have decent frequencies and RAM volumes. Well, if so, then why not run 3D-graphics on such controllers? Yes, there is nothing easier!

Demo picture

To display 3D graphics, I connected a 320x240 resolution display to the STM32F4Discovery board based on the STM32F407. No, not FSMC - this board has the necessary contacts. However, for our experiments, normal ports are enough.
The display is connected like this:
  • CS -> E12
  • RST -> E2
  • RS -> E15
  • WR -> E14
  • RD -> E13
  • D0 -> E4
  • D1 -> E5
  • D2 -> E6
  • D3 -> E7
  • D4 -> E8
  • D5 -> E9
  • D6 -> E10
  • D7 -> E11


The repository has classes for three different display options (IL9325, SPFD5408, HX8347D).


Appearance

For drawing 3D-graphics, I once very long ago made some kind of fragment of the OpenGL library of the first version. This is the likeness I attached to the STM32. This library requires 6 bytes per pixel (2 per color and 4 per Z-buffer). The memory of the STM32F407 in this version is only enough for 160x120. Well, then we’ll stretch the image twice vertically and horizontally.
This lesson is able to:
1) Texture texture with sizes that are multiples of the power of two;
2) Z-clipping;
3) Interpolation of the color of the vertices inside the face;
4) Lighting calculation for eight sources with attenuation adjustment from distance.

The procedure for working with the library is as follows:
First you need to initialize the library (it will allocate memory for the screen). Then, as with OpenGL, you need to configure the projection matrix and viewport.
 const int32_t WIDTH=160;
 const int32_t HEIGHT=120;
 const float VISIBLE_ANGLE=60;
 const float NEAR_PLANE=1;
 const float FAR_PLANE=1000;	
 float aspect=static_cast<float>(WIDTH)/static_cast<float>(HEIGHT);
 		
 cSGL.Init(WIDTH,HEIGHT);
 cSGL.Perspective(VISIBLE_ANGLE,aspect,NEAR_PLANE,FAR_PLANE);
 cSGL.SetViewport(0,0,WIDTH,HEIGHT);


Actually, now you can draw, almost the same way as in OpenGL (for similar commands).

For example, you can specify a light source:
 cSGL.MatrixMode(CSGL::SGL_MATRIX_MODELVIEW);
 cSGL.LoadIdentity();
 float l0_position[]={0,0,0};
 float l0_ambient[]={0.1,0.1,0.1};
 float l0_diffuse[]={0.7,0.7,0.7};
 float l0_specular[]={1,1,1};
 float l0_shininess[]={1};
 cSGL.Lightfv(CSGL::SGL_LIGHT0,CSGL::SGL_POSITION,l0_position);
 cSGL.Lightfv(CSGL::SGL_LIGHT0,CSGL::SGL_AMBIENT,l0_ambient);
 cSGL.Lightfv(CSGL::SGL_LIGHT0,CSGL::SGL_DIFFUSE,l0_diffuse);
 cSGL.Lightfv(CSGL::SGL_LIGHT0,CSGL::SGL_SPECULAR,l0_specular);
 cSGL.Lightfv(CSGL::SGL_LIGHT0,CSGL::SGL_SHININESS,l0_shininess);


You can specify the material for the surface:
 float m0_ambient[]={0.1,0.1,0.1};
 float m0_diffuse[]={0.5,0.5,0.5};
 float m0_specular[]={0.5,0.5,0.5};
 float m0_emission[]={0.1,0.1,0.1};
 cSGL.Materialfv(CSGL::SGL_AMBIENT,m0_ambient);
 cSGL.Materialfv(CSGL::SGL_DIFFUSE,m0_diffuse);
 cSGL.Materialfv(CSGL::SGL_SPECULAR,m0_specular); 
 cSGL.Materialfv(CSGL::SGL_EMISSION,m0_emission); 


You can enable lighting calculation cSGL.Enable (CSGL :: SGL_LIGHTING); and a specific light source cSGL.Enable (CSGL :: SGL_LIGHT0);
Illumination is equally considered for the front and rear. Moreover, I did not cut off the back edges (I rarely need it). But if you want to make it a couple of trifles.

Creating light sources is not necessary. It is quite possible to set the color of the faces yourself using cSGL.Color3f. Color (and color parameters of the material, too) is specified normalized [0..1];

The texture is connected with the cSGL.BindTexture command. Please note that the library always uses texturing!An array of texture colors is defined as a sequence of four bytes (r, g, b, alpha) and here r, g, b, alpha are numbers from 0 to 255. Strictly speaking, it is precisely these numbers that multiply the intensity of the channels R, G, B specified by glColor3f (or calculated from light sources) when rendering. An array of texture data should be maintained for the entire time the face is displayed.

The conclusion of the face is as follows:
  
  cSGL.Begin();
   cSGL.TexCoordf(0,0);	
   cSGL.Vertex3f(x6,y6,z6);
   cSGL.TexCoordf(0,1);	 
   cSGL.Vertex3f(x4,y4,z4);
   cSGL.TexCoordf(1,0);	 
   cSGL.Vertex3f(x2,y2,z2);
  cSGL.End();


cSGL.Begin enables face drawing, cSGL.End ends this mode. Inside these commands are placed the command to set the point's parameters (normal, normalized texture coordinate, normalized color of the point) and point rendering cSGL.Vertex3f. The number of points inside begin / end can be arbitrary, and as a whole makes up the displayed convex polygon.

Texturing, projection and modeling are controlled, as in OpenGL, by three matrices selected by commands
MatrixMode(SGL_MATRIX_TEXTURE);
MatrixMode(SGL_MATRIX_PROJECTION);
MatrixMode(SGL_MATRIX_MODELVIEW);

Operations with these matrices are performed by commands
LoadIdentity();
cSGL.Rotatef(angle,0,0,1);
cSGL.Translatef(-0.5,-0.5,0);


For drawing, the library uses the CGLScreenColor point class. This affects performance not for the better, but allows you to easily transfer the library between different displays and architectures.
What is FPS now? For a given octahedron without one face (I took it), measurements of the duration, in fact, of drawing procedures give about 150-200 FPS. But transferring buffer ports to the display with doubling the picture significantly reduces FPS, to about 10-15 (yes, I didn’t even think about optimizing it for now).
I draw your attention to the fact that the library was not optimized in almost any place.Her task was simply to make an understandable 3D-drawing tool with the possibility of modernization. I believe that by optimizing it is possible to speed up the output of graphics on STM32 once again by 5-10 (for example, using FSMC, optimizing drawing and transferring data to the display).

Why can such a library be useful? Well, for example, display any indications to the user in a visual form. For example, the orientation of a simple 3D object.

Video work:


Repository for STM32
Repository for Windows.

Good luck in the development of the project! :)

All Articles