Created
December 25, 2018 18:35
-
-
Save andresfelipemendez/6b8328f384c7037b1a0688d982358db0 to your computer and use it in GitHub Desktop.
The Fundamental of C/C++ Game programming Brian Beuken Chapter Three Hello Triangle Using the Target
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <stdio.h> | |
| #include <assert.h> | |
| #include <math.h> | |
| #include <sys/time.h> | |
| #include "bcm_host.h" | |
| #include <EGL/egl.h> | |
| #include <EGL/eglext.h> | |
| #include <GLES2/gl2.h> | |
| #define TRUE 1 | |
| #define FALSE 0 | |
| typedef struct | |
| { | |
| //save a Handle to a program object | |
| GLuint programObject; | |
| } UserData; | |
| typedef struct Target_State | |
| { | |
| uint32_t width; | |
| uint32_t height; | |
| EGLDisplay display; | |
| EGLSurface surface; | |
| EGLContext context; | |
| EGL_DISPMANX_WINDOW_T nativeWindow; | |
| UserData *user_data; | |
| void(*draw_func)(struct Target_State*); | |
| } Target_State; | |
| Target_State state; | |
| Target_State* p_state = &state; | |
| static const EGLint attribute_list[] = | |
| { | |
| EGL_RED_SIZE, 8, | |
| EGL_GREEN_SIZE, 8, | |
| EGL_BLUE_SIZE, 8, | |
| EGL_ALPHA_SIZE, 8, | |
| EGL_SURFACE_TYPE, EGL_WINDOW_BIT, | |
| EGL_NONE | |
| }; | |
| static const EGLint context_attributes[] = | |
| { | |
| EGL_CONTEXT_CLIENT_VERSION, 2, | |
| EGL_NONE | |
| }; | |
| GLuint LoadShader(GLenum type, const char *shaderSrc) | |
| { | |
| GLuint TheShader = glCreateShader(type); | |
| if (TheShader == 0) return 0; | |
| glShaderSource(TheShader, 1, &shaderSrc, NULL); | |
| glCompileShader(TheShader); | |
| GLint IsItCompiled; | |
| glGetShaderiv(TheShader, GL_COMPILE_STATUS, &IsItCompiled); | |
| if (!IsItCompiled) { | |
| GLint Retinfolen = 0; | |
| glGetShaderiv(TheShader, GL_INFO_LOG_LENGTH, &Retinfolen); | |
| if (Retinfolen > 1) | |
| { | |
| char* infoLog = (char*)malloc(sizeof(char)*Retinfolen); | |
| glGetShaderInfoLog(TheShader, Retinfolen, NULL, infoLog); | |
| fprintf(stderr, "Error compiling this shader:\n%s\n", infoLog); | |
| free(infoLog); | |
| } | |
| glDeleteShader(TheShader); | |
| return 0; | |
| } | |
| return TheShader; | |
| } | |
| int Init(Target_State *p_state) | |
| { | |
| p_state->user_data = (UserData *)malloc(sizeof(UserData)); | |
| GLbyte vShaderStr[] = | |
| "attribute vec4 a_position;\n" | |
| "attribute vec2 a_texCoord;\n" | |
| "varying vec2 v_texCoord;\n" | |
| "void main()\n" | |
| "{gl_Position=a_position;\n" | |
| "v_texCoord=a_texCoord;}\n"; | |
| GLbyte fShaderStr[] = | |
| "precision mediump float;\n" | |
| "varying vec2 v_texCoord;\n" | |
| "uniform sampler2D s_texture;\n" | |
| "void main()\n" | |
| "{gl_FragColor=vec4(1.0,0.0,0.0,1.0);}\n"; | |
| GLuint programObject, vertexShader, fragmentShader; | |
| vertexShader = LoadShader(GL_VERTEX_SHADER, (char*)vShaderStr); | |
| fragmentShader = LoadShader(GL_FRAGMENT_SHADER, (char*)fShaderStr); | |
| programObject = glCreateProgram(); | |
| if (programObject == 0) return 0; | |
| glAttachShader(programObject, vertexShader); | |
| glAttachShader(programObject, fragmentShader); | |
| glLinkProgram(programObject); | |
| GLint AreTheyLinked; | |
| glGetProgramiv(programObject, GL_LINK_STATUS, &AreTheyLinked); | |
| if (!AreTheyLinked) | |
| { | |
| GLint RetInfoLen = 0; | |
| glGetProgramiv(programObject, GL_INFO_LOG_LENGTH, &RetInfoLen); | |
| if (RetInfoLen > 1) | |
| { | |
| GLchar* infoLog = (GLchar*)malloc(sizeof(char)*RetInfoLen); | |
| glGetProgramInfoLog(programObject, RetInfoLen, NULL, infoLog); | |
| fprintf(stderr, "Error linking program:\n%s\n", infoLog); | |
| free(infoLog); | |
| } | |
| glDeleteProgram(programObject); | |
| return FALSE; | |
| } | |
| p_state->user_data->programObject = programObject; | |
| glClearColor(0.0f, 0.0f, 0.0f, 1.0f); | |
| return TRUE; | |
| } | |
| void init_ogl(Target_State *state, int width, int height) | |
| { | |
| int32_t success = 0; | |
| EGLBoolean result; | |
| EGLint num_config; | |
| DISPMANX_ELEMENT_HANDLE_T DispmanElementH; | |
| DISPMANX_DISPLAY_HANDLE_T DispmanDisplayH; | |
| DISPMANX_UPDATE_HANDLE_T DispmanUpdateH; | |
| VC_RECT_T dest_rect; | |
| VC_RECT_T src_rect; | |
| EGLConfig config; | |
| state->display = eglGetDisplay(EGL_DEFAULT_DISPLAY); | |
| assert(state->display != EGL_NO_DISPLAY); | |
| result = eglInitialize(state->display, NULL, NULL); | |
| assert(EGL_FALSE != result); | |
| result = eglChooseConfig(state->display, attribute_list, &config, 1, &num_config); | |
| assert(EGL_FALSE != result); | |
| result = eglBindAPI(EGL_OPENGL_ES_API); | |
| assert(EGL_FALSE != result); | |
| state->context = eglCreateContext(state->display, config, EGL_NO_CONTEXT, context_attributes); | |
| assert(state->context != EGL_NO_CONTEXT); | |
| state->width = width; | |
| state->height = height; | |
| dest_rect.x = 0; | |
| dest_rect.y = 0; | |
| dest_rect.width = state->width; | |
| dest_rect.height = state->height; | |
| src_rect.x = 0; | |
| src_rect.y = 0; | |
| DispmanDisplayH = vc_dispmanx_display_open(0); | |
| DispmanUpdateH = vc_dispmanx_update_start(0); | |
| DispmanElementH = vc_dispmanx_element_add( | |
| DispmanUpdateH, | |
| DispmanDisplayH, | |
| 0, | |
| &dest_rect, | |
| 0, | |
| &src_rect, | |
| DISPMANX_PROTECTION_NONE, | |
| 0, | |
| 0, | |
| (DISPMANX_TRANSFORM_T)0); | |
| state->nativeWindow.element = DispmanElementH; | |
| state->nativeWindow.width = state->width; | |
| state->nativeWindow.height = state->height; | |
| vc_dispmanx_update_submit_sync(DispmanUpdateH); | |
| state->surface = eglCreateWindowSurface(state->display, config, &(state->nativeWindow), NULL); | |
| assert(state->surface != EGL_NO_SURFACE); | |
| result = eglMakeCurrent(state->display, state->surface, state->surface, state->context); | |
| assert(EGL_FALSE != result); | |
| } | |
| void Draw(Target_State *p_state) | |
| { | |
| UserData *userData = p_state->user_data; | |
| GLfloat TryVertices[] = | |
| { | |
| 0.0f, 0.5f, 0.0f, | |
| -0.5f, -0.5f, 0.0f, | |
| 0.5f, -0.5f, 0.0f | |
| }; | |
| glViewport(0, 0, p_state->width, p_state->height); | |
| glClear(GL_COLOR_BUFFER_BIT); | |
| glUseProgram(userData->programObject); | |
| glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, TryVertices); | |
| glEnableVertexAttribArray(0); | |
| glDrawArrays(GL_TRIANGLES, 0, 3); | |
| if (glGetError() != GL_NO_ERROR) printf("oh bugger"); | |
| } | |
| void esInitContext(Target_State *p_state) | |
| { | |
| if (p_state != NULL) | |
| { | |
| memset(p_state, 0, sizeof(Target_State)); | |
| } | |
| } | |
| void esRegisteredDrawFunc(Target_State *p_state, void(*draw_func)(Target_State*)) | |
| { | |
| p_state->draw_func = draw_func; | |
| } | |
| void esMainLoop(Target_State *esContext) | |
| { | |
| int Counter = 0; | |
| while (Counter++ < 200) | |
| { | |
| if (esContext->draw_func != NULL) | |
| esContext->draw_func(esContext); | |
| eglSwapBuffers(esContext->display, esContext->surface); | |
| } | |
| } | |
| int main(int argc, char *argv[]) | |
| { | |
| UserData user_data; | |
| bcm_host_init(); | |
| esInitContext(p_state); | |
| init_ogl(p_state, 1024, 720); | |
| p_state->user_data = &user_data; | |
| if (!Init(p_state)) | |
| return 0; | |
| esRegisteredDrawFunc(p_state, Draw); | |
| esMainLoop(p_state); | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Include Directories: /opt/vc/include /opt/vc/include/interface/vcos/pthreads /opt/vc/include/interface/vmcs_host/linux | |
| Library Directories: /opt/vc/lib | |
| Library Names: brcmGLESv2 brcmEGL openmaxil bcm_host vcos vchiq_arm pthread EGL GLESv2 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment