2010年3月27日土曜日

OpenGL ES サンプルソース[Hello_Triangle.c]

OpenGL ES2.0プログラミングガイドに記述されているソース

【実行】



【Hello_Triangle.c】
//
// Book:      OpenGL(R) ES 2.0 Programming Guide
// Authors:   Aaftab Munshi, Dan Ginsburg, Dave Shreiner
// ISBN-10:   0321502795
// ISBN-13:   9780321502797
// Publisher: Addison-Wesley Professional
// URLs:      http://safari.informit.com/9780321563835
//            http://www.opengles-book.com
//

// Hello_Triangle.c
//
//    This is a simple example that draws a single triangle with
//    a minimal vertex/fragment shader.  The purpose of this
//    example is to demonstrate the basic concepts of
//    OpenGL ES 2.0 rendering.
#include <stdlib.h>
#include "esUtil.h"

typedef struct
{
   // Handle to a program object
   GLuint programObject;

} UserData;

///
// Create a shader object, load the shader source, and
// compile the shader.
//
GLuint LoadShader ( GLenum type, const char *shaderSrc )
{
   GLuint shader;
   GLint compiled;
 
   // Create the shader object
   shader = glCreateShader ( type );    // シェーダオブジェクトの作成を行う
                                        // typeには、GL_VERTEX_SHADERかGL_FRAGMENT_SHADERのいずれかを指定する
                                        // GL_VERTEX_SHADERの場合、頂点シェーダが作成される。
                                        // GL_FRAGMENT_SHADERの場合、フラグメントシェーダが作成される。
   if ( shader == 0 )
       return 0;

   // Load the shader source
   glShaderSource (                        // シェーダソースコードをロードする。
       shader,                            // シェーダオブジェクトへのハンドル
       1,                                // シェーダのソース文字列数
       &shaderSrc,                        // シェーダのソース
       NULL                                // それぞれ対応するシェーダソース文字列のサイズを指定する。NULL指定の場合、各文字列はNULLで終了していると仮定する。
    );      
 
   // Compile the shader
   glCompileShader ( shader );            // シェーダのコンパイルを行う。(実装されているOpenGL ESがコンパイル機能がある場合)
                                        // ※バイナリーフォーマットは完全にベンダーに一任されている

   // Check the compile status
   glGetShaderiv ( shader, GL_COMPILE_STATUS, &compiled );        // 正常にコンパイルされたかの情報を取得する

   if ( !compiled )
   {
      GLint infoLen = 0;

      glGetShaderiv ( shader, GL_INFO_LOG_LENGTH, &infoLen );        //
    
      if ( infoLen > 1 )
      {
         char* infoLog = malloc (sizeof(char) * infoLen );

         glGetShaderInfoLog ( shader, infoLen, NULL, infoLog );            // infoログを取り出す
         esLogMessage ( "Error compiling shader:\n%s\n", infoLog );          
       
         free ( infoLog );
      }

      glDeleteShader ( shader );        // シェーダオブジェクトを削除を行う
                                        // すぐに削除されるわけではなく、どのプログラムオブジェクトにも
                                        // アタッチされなくなった時に使用しているメモリが解放される。



      return 0;
   }

   return shader;

}

///
// Initialize the shader and program object
//
int Init ( ESContext *esContext )
{
   UserData *userData = esContext->userData;
   GLbyte vShaderStr[] =                        // 頂点シェーダ
      "attribute vec4 vPosition;    \n"
      "void main()                          \n"
      "{                                        \n"
      "   gl_Position = vPosition;  \n"
      "}                                    \n";
 
   GLbyte fShaderStr[] =                        // フラグメントシェーダ
      "precision mediump float;\n"\
      "void main()                                  \n"
      "{                                            \n"
      "  gl_FragColor = vec4 ( 1.0, 0.0, 0.0, 1.0 );\n"
      "}                                            \n";

   GLuint vertexShader;
   GLuint fragmentShader;
   GLuint programObject;
   GLint linked;

   // Load the vertex/fragment shaders
   vertexShader = LoadShader ( GL_VERTEX_SHADER, vShaderStr );
   fragmentShader = LoadShader ( GL_FRAGMENT_SHADER, fShaderStr );

   // Create the program object
   programObject = glCreateProgram ( );                    // プログラムオブジェクトを作成する
 
   if ( programObject == 0 )
      return 0;

   glAttachShader ( programObject, vertexShader );        // シェーダオブジェクト(頂点シェーダ)をアタッチする
   glAttachShader ( programObject, fragmentShader );    // シェーダオブジェクト(フラグメントシェーダ)をアタッチする

   // Bind vPosition to attribute 0 
   glBindAttribLocation (
       programObject,    // プログラムオブジェクトの名前
       0,                // 頂点属性のインデックス
       "vPosition"        // attribute変数の名前
    );

   // Link the program
   glLinkProgram ( programObject );                                // リンクする。(ハードウェア命令が生成される。)

   // Check the link status
   glGetProgramiv ( programObject, GL_LINK_STATUS, &linked );    // 正常にリンクされたかの情報を取得する

   if ( !linked )
   {
      GLint infoLen = 0;

      glGetProgramiv ( programObject, GL_INFO_LOG_LENGTH, &infoLen );
    
      if ( infoLen > 1 )
      {
         char* infoLog = malloc (sizeof(char) * infoLen );

         glGetProgramInfoLog ( programObject, infoLen, NULL, infoLog );
         esLogMessage ( "Error linking program:\n%s\n", infoLog );          
       
         free ( infoLog );
      }

      glDeleteProgram ( programObject );                        // プログラムオブジェクトを削除する
      return FALSE;
   }

   // Store the program object
   userData->programObject = programObject;

   glClearColor ( 0.0f, 0.0f, 0.0f, 0.0f );
   return TRUE;
}

///
// Draw a triangle using the shader pair created in Init()
//
void Draw ( ESContext *esContext )
{
   UserData *userData = esContext->userData;
   GLfloat vVertices[] = {  0.0f,  0.5f, 0.0f,
                           -0.5f, -0.5f, 0.0f,
                            0.5f, -0.5f, 0.0f };
    
   // Set the viewport
   glViewport ( 0, 0, esContext->width, esContext->height );
 
   // Clear the color buffer
   glClear ( GL_COLOR_BUFFER_BIT );

   // Use the program object
   glUseProgram ( userData->programObject );

   // Load the vertex data
   glVertexAttribPointer (    // 頂点データをロードする
            0,                // 頂点属性のインデックス(0~最大の頂点属性数-1まで)
            3,                // 頂点配列内で指定される成分の数。1~4でなければならない。
            GL_FLOAT,        // データフォーマット
            GL_FALSE,        // 浮動少数点データ型以外のものが、浮動少数点に変換された時に、正規化するかどうかを指定する
            0,                // strideが0の場合、すべての頂点の属性データは連続して格納されます。
            vVertices        // 頂点属性データを保持するバッファへのポインタ
    );

   glEnableVertexAttribArray ( 0 );

   glDrawArrays ( GL_TRIANGLES, 0, 3 );

   eglSwapBuffers ( esContext->eglDisplay, esContext->eglSurface );
}


int main ( int argc, char *argv[] )
{
   ESContext esContext;
   UserData  userData;

   esInitContext ( &esContext );
   esContext.userData = &userData;

   esCreateWindow ( &esContext, "Hello Triangle", 320, 240, ES_WINDOW_RGB );
 
   if ( !Init ( &esContext ) )
      return 0;

   esRegisterDrawFunc ( &esContext, Draw );
 
   esMainLoop ( &esContext );
}

0 件のコメント:

コメントを投稿