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