无法让 OpenGL ES2 显示任何内容

Cannot get OpenGL ES2 to display anything

我正在尝试使用 2 个三角形绘制一个红色矩形。我可以清除屏幕,但无法渲染三角形。我做错了什么?

Solid.vert 着色器:

#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 着色器:

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

char *fsSolid  = STRINGIFY(

precision mediump float;

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

}

);

计划:

#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;
} 

问题出在顶点着色器中的 Projection * ModelView 乘数。删除它就可以了。我显然不明白这本书的内容。

更新:我使用的顶点很大。下面的程序有效。我希望它能帮助其他遇到困难的人:

#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;
}