| // |
| // 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_KD.c |
| // |
| // This is a simple example that draws a single triangle with |
| // a minimal vertex/fragment shader using OpenKODE. |
| // |
| #include <KD/kd.h> |
| #include <EGL/egl.h> |
| #include <GLES2/gl2.h> |
| |
| typedef struct |
| { |
| // Handle to a program object |
| GLuint programObject; |
| |
| // EGL handles |
| EGLDisplay eglDisplay; |
| EGLContext eglContext; |
| EGLSurface eglSurface; |
| |
| } 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 ); |
| |
| if ( shader == 0 ) |
| return 0; |
| |
| // Load the shader source |
| glShaderSource ( shader, 1, &shaderSrc, NULL ); |
| |
| // Compile the shader |
| glCompileShader ( shader ); |
| |
| // 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 = kdMalloc (sizeof(char) * infoLen ); |
| |
| glGetShaderInfoLog ( shader, infoLen, NULL, infoLog ); |
| kdLogMessage ( infoLog ); |
| |
| kdFree ( infoLog ); |
| } |
| |
| glDeleteShader ( shader ); |
| return 0; |
| } |
| |
| return shader; |
| |
| } |
| |
| /// |
| // Initialize the shader and program object |
| // |
| int Init ( UserData *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" ); |
| |
| // 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 = kdMalloc (sizeof(char) * infoLen ); |
| |
| glGetProgramInfoLog ( programObject, infoLen, NULL, infoLog ); |
| kdLogMessage ( infoLog ); |
| |
| kdFree ( 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 ( UserData *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, 320, 240 ); |
| |
| // Clear the color buffer |
| glClear ( GL_COLOR_BUFFER_BIT ); |
| |
| // Use the program object |
| glUseProgram ( userData->programObject ); |
| |
| // Load the vertex data |
| glVertexAttribPointer ( 0, 3, GL_FLOAT, GL_FALSE, 0, vVertices ); |
| glEnableVertexAttribArray ( 0 ); |
| |
| glDrawArrays ( GL_TRIANGLES, 0, 3 ); |
| |
| eglSwapBuffers ( userData->eglDisplay, userData->eglSurface ); |
| } |
| |
| |
| /// |
| // InitEGLContext() |
| // |
| // Initialize an EGL rendering context and all associated elements |
| // |
| EGLBoolean InitEGLContext ( UserData *userData, |
| KDWindow *window, |
| EGLConfig config ) |
| { |
| EGLContext context; |
| EGLSurface surface; |
| EGLint contextAttribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE, EGL_NONE }; |
| |
| // Get native window handle |
| EGLNativeWindowType hWnd; |
| if(kdRealizeWindow(window, &hWnd) != 0) |
| { |
| return EGL_FALSE; |
| } |
| surface = eglCreateWindowSurface(userData->eglDisplay, config, hWnd, NULL); |
| if ( surface == EGL_NO_SURFACE ) |
| { |
| return EGL_FALSE; |
| } |
| |
| // Create a GL context |
| context = eglCreateContext(userData->eglDisplay, config, EGL_NO_CONTEXT, contextAttribs ); |
| if ( context == EGL_NO_CONTEXT ) |
| { |
| return EGL_FALSE; |
| } |
| |
| // Make the context current |
| if ( !eglMakeCurrent(userData->eglDisplay, surface, surface, context) ) |
| { |
| return EGL_FALSE; |
| } |
| |
| userData->eglContext = context; |
| userData->eglSurface = surface; |
| |
| return EGL_TRUE; |
| } |
| |
| /// |
| // kdMain() |
| // |
| // Main function for OpenKODE application |
| // |
| KDint kdMain ( KDint argc, const KDchar *const *argv ) |
| { |
| EGLint attribList[] = |
| { |
| EGL_RED_SIZE, 8, |
| EGL_GREEN_SIZE, 8, |
| EGL_BLUE_SIZE, 8, |
| EGL_ALPHA_SIZE, EGL_DONT_CARE, |
| EGL_DEPTH_SIZE, EGL_DONT_CARE, |
| EGL_STENCIL_SIZE, EGL_DONT_CARE, |
| EGL_NONE |
| }; |
| EGLint majorVersion, |
| minorVersion; |
| UserData userData; |
| EGLint numConfigs; |
| EGLConfig config; |
| KDWindow *window = KD_NULL; |
| |
| userData.eglDisplay = eglGetDisplay( EGL_DEFAULT_DISPLAY ); |
| |
| // Initialize EGL |
| if ( !eglInitialize(userData.eglDisplay, &majorVersion, &minorVersion) ) |
| { |
| return EGL_FALSE; |
| } |
| |
| // Get configs |
| if ( !eglGetConfigs(userData.eglDisplay, NULL, 0, &numConfigs) ) |
| { |
| return EGL_FALSE; |
| } |
| |
| // Choose config |
| if ( !eglChooseConfig(userData.eglDisplay, attribList, &config, 1, &numConfigs) ) |
| { |
| return EGL_FALSE; |
| } |
| |
| |
| // Use OpenKODE to create a Window |
| window = kdCreateWindow ( userData.eglDisplay, config, KD_NULL ); |
| if( !window ) |
| kdExit ( 0 ); |
| |
| if ( !InitEGLContext ( &userData, window, config ) ) |
| kdExit ( 0 ); |
| |
| if ( !Init ( &userData ) ) |
| kdExit ( 0 ); |
| |
| // Main Loop |
| while ( 1 ) |
| { |
| // Wait for an event |
| const KDEvent *evt = kdWaitEvent ( 0 ); |
| if ( evt ) |
| { |
| // Exit app |
| if ( evt->type == KD_EVENT_WINDOW_CLOSE) |
| break; |
| } |
| |
| // Draw frame |
| Draw ( &userData ); |
| } |
| |
| // EGL clean up |
| eglMakeCurrent ( 0, 0, 0, 0 ); |
| eglDestroySurface ( userData.eglDisplay, userData.eglSurface ); |
| eglDestroyContext ( userData.eglDisplay, userData.eglContext ); |
| |
| // Destroy the window |
| kdDestroyWindow(window); |
| |
| return 0; |
| } |