Search code examples
opengl-esopengl-es-2.0sdl-2fragment-shadervertex-shader

Cannot get OpenGL ES2 to display anything


I'm trying to draw a red rectangle using 2 triangles. I can clear the screen but I cannot get my triangles to render. What am I doing wrong?

Solid.vert shader:

#ifndef STRINGIFY
#define STRINGIFY(a) #a
#endif

char *vsSolid  = STRINGIFY(

uniform   mat4 Projection;
uniform   mat4 ModelView;

attribute vec4 vPosition;

void main()
{
  gl_Position = Projection * ModelView * vPosition;
}

);

Solid.frag shader:

#ifndef STRINGIFY
#define STRINGIFY(a) #a
#endif

char *fsSolid  = STRINGIFY(

precision mediump float;

void main()
{
  gl_FragColor = vec4( 1.0, 0, 0, 1 );

}

);

Program:

#import <Foundation/Foundation.h>
#include "SDL.h"
#include <time.h>

#include "SDL_opengles.h"
#include "SDL_opengles2.h"

#define FALSE 0
#define TRUE  1

#ifndef BOOL
#define BOOL int
#endif

#define min(a,b)    ((a) < (b) ? (a) : (b))
#define max(a,b)    ((a) > (b) ? (a) : (b))

#define SCREEN_WIDTH  320
#define SCREEN_HEIGHT 480

#include "Solid.vert"
#include "Solid.frag"

GLuint g_SolidProgram = 0;

BOOL          g_Running      = TRUE;

SDL_Window    *g_SDLWindow   = NULL;
SDL_Surface   *g_SDLSurface  = NULL;
SDL_Renderer  *g_SDLRenderer = NULL;
SDL_Texture   *g_SDLTexture  = NULL;
int g_ScreenHeight = SCREEN_HEIGHT;
int g_ScreenWidth  = SCREEN_WIDTH;


//--------------------------------------------------------------------------------------------
// BuildShader()
//--------------------------------------------------------------------------------------------
GLuint BuildShader( char *pszSource, GLenum shaderType )
{
  GLuint hShader = glCreateShader( shaderType );
  glShaderSource(hShader, 1, &pszSource, 0 );
  glCompileShader( hShader );

  GLint compileSuccess;

  if( compileSuccess == GL_FALSE )
  {
    GLchar message[ 256 ];
    glGetShaderInfoLog( hShader, sizeof( message ), 0, &message[ 0 ] );
    printf( "%s\n", message );
    exit( 1 );
  }

  return hShader;
}

//--------------------------------------------------------------------------------------------
// BuildProgram()
//--------------------------------------------------------------------------------------------
GLuint BuildProgram( char *pszVertexShaderSource, char *pszFragmentShaderSource )
{
  GLuint vShader = BuildShader( pszVertexShaderSource,   GL_VERTEX_SHADER );
  GLuint fShader = BuildShader( pszFragmentShaderSource, GL_FRAGMENT_SHADER );

  GLuint hProgram = glCreateProgram();
  glAttachShader( hProgram, vShader );
  glAttachShader( hProgram, fShader );
  glLinkProgram( hProgram );

  GLint linkSuccess;

  glGetProgramiv( hProgram, GL_LINK_STATUS, &linkSuccess );

  if( linkSuccess == GL_FALSE )
  {
    GLchar message[ 256 ];
    glGetProgramInfoLog( hProgram, sizeof( message ), 0, &message[ 0 ] );
    printf( "%s\n", message );
    exit( 1 );
  }

  return hProgram;
}

//--------------------------------------------------------------------------------------------
// ApplyOrtho()
//--------------------------------------------------------------------------------------------
void ApplyOrtho( float maxX, float maxY )
{
  float a = 1.0f / maxX;
  float b = 1.0f / maxY;

  float ortho[ 16 ] =
  {
    a, 0, 0, 0,
    0, b, 0, 0,
    0, 0, -1, 0,
    0, 0, 0, 1
  };

  GLint uProjection = glGetUniformLocation( g_SolidProgram, "Projection" );
  glUniformMatrix4fv( uProjection, 1, 0, &ortho[ 0 ] );
}

//--------------------------------------------------------------------------------------------
// ApplyRotation()
//--------------------------------------------------------------------------------------------
void ApplyRotation( float degrees )
{
  float radians = degrees * 3.14159f / 180.0f;
  float s = sinf( radians );
  float c = cosf( radians );

  float zRotation[ 16 ] =
  {
    c, s, 0, 0,
    -s, c, 0, 0,
    0, 0, 1, 0,
    0, 0, 0, 1
  };

  GLint uModelView = glGetUniformLocation( g_SolidProgram, "ModelView" );
  glUniformMatrix4fv( uModelView, 1, 0, &zRotation[ 0 ] );
}

//--------------------------------------------------------------------------------------------
// InitSDL()
//--------------------------------------------------------------------------------------------
void InitSDL( void )
{
  if( SDL_Init( SDL_INIT_VIDEO ) < 0 )
    exit( -1 );

  atexit( SDL_Quit );

  SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); // *new*

  SDL_DisplayMode currentDisplay;

  SDL_GetCurrentDisplayMode( 0, &currentDisplay );

  g_ScreenWidth  = max( currentDisplay.w, currentDisplay.h );
  g_ScreenHeight = min( currentDisplay.w, currentDisplay.h );

  SDL_DisplayMode displayMode;
  SDL_GetDesktopDisplayMode( 0, &displayMode );

  SDL_GL_SetAttribute( SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES );

  SDL_GL_SetAttribute( SDL_GL_CONTEXT_MAJOR_VERSION, 2 );
  SDL_GL_SetAttribute( SDL_GL_CONTEXT_MINOR_VERSION, 0 );

  SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
  SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 24 );

  g_SDLWindow = SDL_CreateWindow( "Test",
                                 SDL_WINDOWPOS_UNDEFINED,
                                 SDL_WINDOWPOS_UNDEFINED,
                                 g_ScreenWidth,
                                 g_ScreenHeight,
                                 /* SDL_WINDOW_FULLSCFREEN | */ SDL_WINDOW_OPENGL );
  if( g_SDLWindow == NULL )
    exit( -1 );

  SDL_GL_CreateContext( g_SDLWindow );

  glViewport( 0, 0, g_ScreenWidth, g_ScreenHeight );                    // Reset The Current Viewport
  glClearColor( 0.9f, 0.9f, 0.9f, 1.0f );

  g_SolidProgram = BuildProgram( vsSolid, fsSolid );
  glUseProgram( g_SolidProgram );

  ApplyOrtho( 2, 3 );
  ApplyRotation( 0 );

}

// We have to create the vertices of our triangle.
float vertices[] =
{
   10.0f, 200.0f, 0.0f,
   10.0f, 100.0f, 0.0f,
  100.0f, 100.0f, 0.0f,
  100.0f, 200.0f, 0.0f,
};

short indices[] =
{
  0, 1, 2,
  0, 2, 3

}; // The order of vertex rendering.


//--------------------------------------------------------------------------------------------
// Draw()
//--------------------------------------------------------------------------------------------
void Draw( int x, int y )
{
  glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

  GLuint hPosition = glGetAttribLocation( g_SolidProgram, "vPosition" );

  glEnableVertexAttribArray( hPosition );

  // Prepare the triangle coordinate data
  glVertexAttribPointer( hPosition, 3, GL_FLOAT, FALSE, 0, vertices );

  // Draw the triangle
  glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices );

  // Disable vertex array
  glDisableVertexAttribArray( hPosition );
}


//--------------------------------------------------------------------------------------------
// main()
//--------------------------------------------------------------------------------------------
int main( int argc, char* argv[] )
{
  InitSDL();

  SDL_Event     event;

  while( g_Running )
  {
    while( SDL_PollEvent( &event ) )
    {
      switch( event.type )
      {
        case SDL_QUIT:
          g_Running = false;
          break;
      }
    }

    Draw( 100, 100 );

    SDL_GL_SwapWindow( g_SDLWindow );
  }

  SDL_Quit();

  return EXIT_SUCCESS;
} 

Solution

  • The problem is the Projection * ModelView multiplier in the vertex shader. Remove that and it works.. I obviously don't understand the book content that this is derived from.

    UPDATE: The vertices I was using were huge. The program below works. I hope it helps anybody else who's stuck:

    #import <Foundation/Foundation.h>
    #include "SDL.h"
    #include <time.h>
    
    #include "SDL_opengles.h"
    #include "SDL_opengles2.h"
    
    
    #define FALSE 0
    #define TRUE  1
    
    #ifndef BOOL
    #define BOOL int
    #endif
    
    #define min(a,b)    ((a) < (b) ? (a) : (b))
    #define max(a,b)    ((a) > (b) ? (a) : (b))
    
    #define SCREEN_WIDTH  320
    #define SCREEN_HEIGHT 480
    
    #include "Solid.vert"
    #include "Solid.frag"
    
    void Draw( int x, int y );
    
    GLuint g_SolidProgram = 0;
    
    BOOL          g_Running      = TRUE;
    
    SDL_Window    *g_SDLWindow   = NULL;
    SDL_Surface   *g_SDLSurface  = NULL;
    SDL_Renderer  *g_SDLRenderer = NULL;
    SDL_Texture   *g_SDLTexture  = NULL;
    int g_ScreenHeight = SCREEN_HEIGHT;
    int g_ScreenWidth  = SCREEN_WIDTH;
    
    
    //--------------------------------------------------------------------------------------------
    // BuildShader()
    //--------------------------------------------------------------------------------------------
    GLuint BuildShader( char *pszSource, GLenum shaderType )
    {
      GLuint hShader = glCreateShader( shaderType );
      glShaderSource(hShader, 1, &pszSource, 0 );
      glCompileShader( hShader );
    
      GLint compileSuccess;
    
      if( compileSuccess == GL_FALSE )
      {
        GLchar message[ 256 ];
        glGetShaderInfoLog( hShader, sizeof( message ), 0, &message[ 0 ] );
        printf( "%s\n", message );
        exit( 1 );
      }
    
      return hShader;
    }
    
    //--------------------------------------------------------------------------------------------
    // BuildProgram()
    //--------------------------------------------------------------------------------------------
    GLuint BuildProgram( char *pszVertexShaderSource, char *pszFragmentShaderSource )
    {
      GLuint vShader = BuildShader( pszVertexShaderSource,   GL_VERTEX_SHADER );
      GLuint fShader = BuildShader( pszFragmentShaderSource, GL_FRAGMENT_SHADER );
    
      GLuint hProgram = glCreateProgram();
      glAttachShader( hProgram, vShader );
      glAttachShader( hProgram, fShader );
      glLinkProgram( hProgram );
    
      GLint linkSuccess;
    
      glGetProgramiv( hProgram, GL_LINK_STATUS, &linkSuccess );
    
      if( linkSuccess == GL_FALSE )
      {
        GLchar message[ 256 ];
        glGetProgramInfoLog( hProgram, sizeof( message ), 0, &message[ 0 ] );
        printf( "%s\n", message );
        exit( 1 );
      }
    
      return hProgram;
    }
    
    //--------------------------------------------------------------------------------------------
    // ApplyOrtho()
    //--------------------------------------------------------------------------------------------
    void ApplyOrtho( float maxX, float maxY )
    {
      float a = 1.0f / maxX;
      float b = 1.0f / maxY;
    
      float ortho[ 16 ] =
      {
        a, 0, 0, 0,
        0, b, 0, 0,
        0, 0, -1, 0,
        0, 0, 0, 1
      };
    
      GLint uProjection = glGetUniformLocation( g_SolidProgram, "Projection" );
      glUniformMatrix4fv( uProjection, 1, 0, &ortho[ 0 ] );
    }
    
    //--------------------------------------------------------------------------------------------
    // ApplyRotation()
    //--------------------------------------------------------------------------------------------
    void ApplyRotation( float degrees )
    {
      float radians = degrees * 3.14159f / 180.0f;
      float s = sinf( radians );
      float c = cosf( radians );
    
      float zRotation[ 16 ] =
      {
        c, s, 0, 0,
        -s, c, 0, 0,
        0, 0, 1, 0,
        0, 0, 0, 1
      };
    
      GLint uModelView = glGetUniformLocation( g_SolidProgram, "ModelView" );
      glUniformMatrix4fv( uModelView, 1, 0, &zRotation[ 0 ] );
    }
    
    //--------------------------------------------------------------------------------------------
    // InitSDL()
    //--------------------------------------------------------------------------------------------
    void InitSDL( void )
    {
      if( SDL_Init( SDL_INIT_VIDEO ) < 0 )
        exit( -1 );
    
      atexit( SDL_Quit );
    
      SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
      SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
      SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
      SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
      SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1);
      SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
      SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
      SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
      SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
      SDL_GL_SetAttribute(SDL_GL_BUFFER_SIZE, 32);
      SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
    
      SDL_DisplayMode currentDisplay;
    
      SDL_GetCurrentDisplayMode( 0, &currentDisplay );
    
      g_ScreenWidth  = max( currentDisplay.w, currentDisplay.h );
      g_ScreenHeight = min( currentDisplay.w, currentDisplay.h );
    
      SDL_DisplayMode displayMode;
      SDL_GetDesktopDisplayMode( 0, &displayMode );
    
      g_SDLWindow = SDL_CreateWindow( "Test",
                                     SDL_WINDOWPOS_UNDEFINED,
                                     SDL_WINDOWPOS_UNDEFINED,
                                     g_ScreenWidth,
                                     g_ScreenHeight,
                                     /* SDL_WINDOW_FULLSCFREEN | */ SDL_WINDOW_OPENGL );
      if( g_SDLWindow == NULL )
        exit( -1 );
    
      SDL_GL_CreateContext( g_SDLWindow );
    
      g_SolidProgram = BuildProgram( vsSolid, fsSolid );
    
      glUseProgram( g_SolidProgram );
    
      ApplyOrtho( 4, 3 );
      ApplyRotation( 0 );
    }
    
    // We have to create the vertices of our triangle.
    float vertices[] =
    {
      -0.25, -0.25, 0.0f,
      -0.25,  0.25, 0,
       0.25,  0.25, 0,
       0.25, -0.25, 0,
    };
    
    short indices[] =
    {
      0, 1, 2,
      0, 2, 3
    
    }; // The order of vertex rendering.
    
    
    //--------------------------------------------------------------------------------------------
    // Draw()
    //--------------------------------------------------------------------------------------------
    void Draw( int x, int y )
    {
      glViewport( 0, 0, g_ScreenWidth, g_ScreenHeight );                    // Reset The Current Viewport
      glClearColor( 0.9f, 0.9f, 0.9f, 1.0f );
    
      glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
    
      GLuint hPosition = glGetAttribLocation( g_SolidProgram, "vPosition" );
    
      glEnableVertexAttribArray( hPosition );
    
      // Prepare the triangle coordinate data
      glVertexAttribPointer( hPosition, 3, GL_FLOAT, FALSE, 0, vertices );
    
      // Draw the triangle
      glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices );
    
      // Disable vertex array
      glDisableVertexAttribArray( hPosition );
    }
    
    //--------------------------------------------------------------------------------------------
    // main()
    //--------------------------------------------------------------------------------------------
    int main( int argc, char* argv[] )
    {
      InitSDL();
    
      SDL_Event     event;
    
      while( g_Running )
      {
        while( SDL_PollEvent( &event ) )
        {
          switch( event.type )
          {
            case SDL_QUIT:
              g_Running = false;
              break;
          }
        }
    
        Draw( 100, 100 );
    
        SDL_GL_SwapWindow( g_SDLWindow );
      }
    
      SDL_Quit();
    
      return EXIT_SUCCESS;
    }