├── .gitattributes ├── LICENSE.md ├── README.md ├── chapter-1 ├── chapter.1.1.c ├── chapter.1.2.c ├── chapter.1.3.c └── compatibility │ ├── chapter.1.1.c │ ├── chapter.1.2.c │ └── chapter.1.3.c ├── chapter-2 ├── chapter.2.1.c ├── chapter.2.2.c ├── chapter.2.3.c ├── chapter.2.4.c └── compatibility │ ├── chapter.2.1.c │ ├── chapter.2.2.c │ ├── chapter.2.3.c │ └── chapter.2.4.c ├── chapter-3 ├── chapter.3.0.1.c ├── chapter.3.0.2.c ├── chapter.3.1.c ├── chapter.3.2.c └── compatibility │ ├── chapter.3.0.1.c │ ├── chapter.3.0.2.c │ ├── chapter.3.1.c │ └── chapter.3.2.c └── chapter-4 ├── SimpleShader.fragment.glsl ├── SimpleShader.vertex.glsl ├── Utils.c ├── Utils.h ├── chapter.4.1.c └── compatibility ├── SimpleShader.fragment.3.3.glsl ├── SimpleShader.vertex.3.3.glsl └── chapter.4.1.c /.gitattributes: -------------------------------------------------------------------------------- 1 | * text eol=lf 2 | 3 | *.c text 4 | *.h text 5 | *.glsl text -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (C) 2014 by OpenGLBook.com contributors 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | openglbook-samples 2 | ================== 3 | 4 | This repository contains the source code in C for the chapters at 5 | [openglbook.com](http://openglbook.com/). Please consult your compiler's 6 | documentation on how to compile these files. 7 | 8 | Dependencies are not included, please download and install 9 | [GLEW](http://glew.sourceforge.net/) and 10 | [FreeGLUT](http://freeglut.sourceforge.net/) before compiling. 11 | -------------------------------------------------------------------------------- /chapter-1/chapter.1.1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #define WINDOW_TITLE_PREFIX "Chapter 1" 6 | 7 | int CurrentWidth = 800, 8 | CurrentHeight = 600, 9 | WindowHandle = 0; 10 | 11 | void Initialize(int, char*[]); 12 | void InitWindow(int, char*[]); 13 | void ResizeFunction(int, int); 14 | void RenderFunction(void); 15 | 16 | int main(int argc, char* argv[]) 17 | { 18 | Initialize(argc, argv); 19 | 20 | glutMainLoop(); 21 | 22 | exit(EXIT_SUCCESS); 23 | } 24 | 25 | void Initialize(int argc, char* argv[]) 26 | { 27 | InitWindow(argc, argv); 28 | 29 | fprintf( 30 | stdout, 31 | "INFO: OpenGL Version: %s\n", 32 | glGetString(GL_VERSION) 33 | ); 34 | 35 | glClearColor(0.0f, 0.0f, 0.0f, 0.0f); 36 | } 37 | 38 | void InitWindow(int argc, char* argv[]) 39 | { 40 | glutInit(&argc, argv); 41 | 42 | glutInitContextVersion(4, 0); 43 | glutInitContextFlags(GLUT_FORWARD_COMPATIBLE); 44 | glutInitContextProfile(GLUT_CORE_PROFILE); 45 | 46 | glutSetOption( 47 | GLUT_ACTION_ON_WINDOW_CLOSE, 48 | GLUT_ACTION_GLUTMAINLOOP_RETURNS 49 | ); 50 | 51 | glutInitWindowSize(CurrentWidth, CurrentHeight); 52 | 53 | glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA); 54 | 55 | WindowHandle = glutCreateWindow(WINDOW_TITLE_PREFIX); 56 | 57 | if(WindowHandle < 1) { 58 | fprintf( 59 | stderr, 60 | "ERROR: Could not create a new rendering window.\n" 61 | ); 62 | exit(EXIT_FAILURE); 63 | } 64 | 65 | glutReshapeFunc(ResizeFunction); 66 | glutDisplayFunc(RenderFunction); 67 | } 68 | 69 | void ResizeFunction(int Width, int Height) 70 | { 71 | CurrentWidth = Width; 72 | CurrentHeight = Height; 73 | glViewport(0, 0, CurrentWidth, CurrentHeight); 74 | } 75 | 76 | void RenderFunction(void) 77 | { 78 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 79 | 80 | glutSwapBuffers(); 81 | } -------------------------------------------------------------------------------- /chapter-1/chapter.1.2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #define WINDOW_TITLE_PREFIX "Chapter 1" 7 | 8 | int CurrentWidth = 800, 9 | CurrentHeight = 600, 10 | WindowHandle = 0; 11 | 12 | void Initialize(int, char*[]); 13 | void InitWindow(int, char*[]); 14 | void ResizeFunction(int, int); 15 | void RenderFunction(void); 16 | 17 | int main(int argc, char* argv[]) 18 | { 19 | Initialize(argc, argv); 20 | 21 | glutMainLoop(); 22 | 23 | exit(EXIT_SUCCESS); 24 | } 25 | 26 | void Initialize(int argc, char* argv[]) 27 | { 28 | GLenum GlewInitResult; 29 | 30 | InitWindow(argc, argv); 31 | 32 | GlewInitResult = glewInit(); 33 | 34 | if (GLEW_OK != GlewInitResult) { 35 | fprintf( 36 | stderr, 37 | "ERROR: %s\n", 38 | glewGetErrorString(GlewInitResult) 39 | ); 40 | exit(EXIT_FAILURE); 41 | } 42 | 43 | fprintf( 44 | stdout, 45 | "INFO: OpenGL Version: %s\n", 46 | glGetString(GL_VERSION) 47 | ); 48 | 49 | glClearColor(0.0f, 0.0f, 0.0f, 0.0f); 50 | } 51 | 52 | void InitWindow(int argc, char* argv[]) 53 | { 54 | glutInit(&argc, argv); 55 | 56 | glutInitContextVersion(4, 0); 57 | glutInitContextFlags(GLUT_FORWARD_COMPATIBLE); 58 | glutInitContextProfile(GLUT_CORE_PROFILE); 59 | 60 | glutSetOption( 61 | GLUT_ACTION_ON_WINDOW_CLOSE, 62 | GLUT_ACTION_GLUTMAINLOOP_RETURNS 63 | ); 64 | 65 | glutInitWindowSize(CurrentWidth, CurrentHeight); 66 | 67 | glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA); 68 | 69 | WindowHandle = glutCreateWindow(WINDOW_TITLE_PREFIX); 70 | 71 | if(WindowHandle < 1) { 72 | fprintf( 73 | stderr, 74 | "ERROR: Could not create a new rendering window.\n" 75 | ); 76 | exit(EXIT_FAILURE); 77 | } 78 | 79 | glutReshapeFunc(ResizeFunction); 80 | glutDisplayFunc(RenderFunction); 81 | } 82 | 83 | void ResizeFunction(int Width, int Height) 84 | { 85 | CurrentWidth = Width; 86 | CurrentHeight = Height; 87 | glViewport(0, 0, CurrentWidth, CurrentHeight); 88 | } 89 | 90 | void RenderFunction(void) 91 | { 92 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 93 | 94 | glutSwapBuffers(); 95 | } -------------------------------------------------------------------------------- /chapter-1/chapter.1.3.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #define WINDOW_TITLE_PREFIX "Chapter 1" 7 | 8 | int CurrentWidth = 800, 9 | CurrentHeight = 600, 10 | WindowHandle = 0; 11 | 12 | unsigned FrameCount = 0; 13 | 14 | void Initialize(int, char*[]); 15 | void InitWindow(int, char*[]); 16 | void ResizeFunction(int, int); 17 | void RenderFunction(void); 18 | void TimerFunction(int); 19 | void IdleFunction(void); 20 | 21 | int main(int argc, char* argv[]) 22 | { 23 | Initialize(argc, argv); 24 | 25 | glutMainLoop(); 26 | 27 | exit(EXIT_SUCCESS); 28 | } 29 | 30 | void Initialize(int argc, char* argv[]) 31 | { 32 | GLenum GlewInitResult; 33 | 34 | InitWindow(argc, argv); 35 | 36 | GlewInitResult = glewInit(); 37 | 38 | if (GLEW_OK != GlewInitResult) { 39 | fprintf( 40 | stderr, 41 | "ERROR: %s\n", 42 | glewGetErrorString(GlewInitResult) 43 | ); 44 | exit(EXIT_FAILURE); 45 | } 46 | 47 | fprintf( 48 | stdout, 49 | "INFO: OpenGL Version: %s\n", 50 | glGetString(GL_VERSION) 51 | ); 52 | 53 | glClearColor(0.0f, 0.0f, 0.0f, 0.0f); 54 | } 55 | 56 | void InitWindow(int argc, char* argv[]) 57 | { 58 | glutInit(&argc, argv); 59 | 60 | glutInitContextVersion(4, 0); 61 | glutInitContextFlags(GLUT_FORWARD_COMPATIBLE); 62 | glutInitContextProfile(GLUT_CORE_PROFILE); 63 | 64 | glutSetOption( 65 | GLUT_ACTION_ON_WINDOW_CLOSE, 66 | GLUT_ACTION_GLUTMAINLOOP_RETURNS 67 | ); 68 | 69 | glutInitWindowSize(CurrentWidth, CurrentHeight); 70 | 71 | glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA); 72 | 73 | WindowHandle = glutCreateWindow(WINDOW_TITLE_PREFIX); 74 | 75 | if(WindowHandle < 1) { 76 | fprintf( 77 | stderr, 78 | "ERROR: Could not create a new rendering window.\n" 79 | ); 80 | exit(EXIT_FAILURE); 81 | } 82 | 83 | glutReshapeFunc(ResizeFunction); 84 | glutDisplayFunc(RenderFunction); 85 | glutIdleFunc(IdleFunction); 86 | glutTimerFunc(0, TimerFunction, 0); 87 | } 88 | 89 | void ResizeFunction(int Width, int Height) 90 | { 91 | CurrentWidth = Width; 92 | CurrentHeight = Height; 93 | glViewport(0, 0, CurrentWidth, CurrentHeight); 94 | } 95 | 96 | void RenderFunction(void) 97 | { 98 | ++FrameCount; 99 | 100 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 101 | 102 | glutSwapBuffers(); 103 | } 104 | 105 | void IdleFunction(void) 106 | { 107 | glutPostRedisplay(); 108 | } 109 | 110 | void TimerFunction(int Value) 111 | { 112 | if (0 != Value) { 113 | char* TempString = (char*) 114 | malloc(512 + strlen(WINDOW_TITLE_PREFIX)); 115 | 116 | sprintf( 117 | TempString, 118 | "%s: %d Frames Per Second @ %d x %d", 119 | WINDOW_TITLE_PREFIX, 120 | FrameCount * 4, 121 | CurrentWidth, 122 | CurrentHeight 123 | ); 124 | 125 | glutSetWindowTitle(TempString); 126 | free(TempString); 127 | } 128 | 129 | FrameCount = 0; 130 | glutTimerFunc(250, TimerFunction, 1); 131 | } 132 | -------------------------------------------------------------------------------- /chapter-1/compatibility/chapter.1.1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #define WINDOW_TITLE_PREFIX "Chapter 1" 6 | 7 | int CurrentWidth = 800, 8 | CurrentHeight = 600, 9 | WindowHandle = 0; 10 | 11 | void Initialize(int, char*[]); 12 | void InitWindow(int, char*[]); 13 | void ResizeFunction(int, int); 14 | void RenderFunction(void); 15 | 16 | int main(int argc, char* argv[]) 17 | { 18 | Initialize(argc, argv); 19 | 20 | glutMainLoop(); 21 | 22 | exit(EXIT_SUCCESS); 23 | } 24 | 25 | void Initialize(int argc, char* argv[]) 26 | { 27 | InitWindow(argc, argv); 28 | 29 | fprintf( 30 | stdout, 31 | "INFO: OpenGL Version: %s\n", 32 | glGetString(GL_VERSION) 33 | ); 34 | 35 | glClearColor(0.0f, 0.0f, 0.0f, 0.0f); 36 | } 37 | 38 | void InitWindow(int argc, char* argv[]) 39 | { 40 | glutInit(&argc, argv); 41 | 42 | glutInitContextVersion(3, 3); 43 | glutInitContextFlags(GLUT_FORWARD_COMPATIBLE); 44 | glutInitContextProfile(GLUT_CORE_PROFILE); 45 | 46 | glutSetOption( 47 | GLUT_ACTION_ON_WINDOW_CLOSE, 48 | GLUT_ACTION_GLUTMAINLOOP_RETURNS 49 | ); 50 | 51 | glutInitWindowSize(CurrentWidth, CurrentHeight); 52 | 53 | glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA); 54 | 55 | WindowHandle = glutCreateWindow(WINDOW_TITLE_PREFIX); 56 | 57 | if(WindowHandle < 1) { 58 | fprintf( 59 | stderr, 60 | "ERROR: Could not create a new rendering window.\n" 61 | ); 62 | exit(EXIT_FAILURE); 63 | } 64 | 65 | glutReshapeFunc(ResizeFunction); 66 | glutDisplayFunc(RenderFunction); 67 | } 68 | 69 | void ResizeFunction(int Width, int Height) 70 | { 71 | CurrentWidth = Width; 72 | CurrentHeight = Height; 73 | glViewport(0, 0, CurrentWidth, CurrentHeight); 74 | } 75 | 76 | void RenderFunction(void) 77 | { 78 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 79 | 80 | glutSwapBuffers(); 81 | } -------------------------------------------------------------------------------- /chapter-1/compatibility/chapter.1.2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #define WINDOW_TITLE_PREFIX "Chapter 1" 7 | 8 | int CurrentWidth = 800, 9 | CurrentHeight = 600, 10 | WindowHandle = 0; 11 | 12 | void Initialize(int, char*[]); 13 | void InitWindow(int, char*[]); 14 | void ResizeFunction(int, int); 15 | void RenderFunction(void); 16 | 17 | int main(int argc, char* argv[]) 18 | { 19 | Initialize(argc, argv); 20 | 21 | glutMainLoop(); 22 | 23 | exit(EXIT_SUCCESS); 24 | } 25 | 26 | void Initialize(int argc, char* argv[]) 27 | { 28 | GLenum GlewInitResult; 29 | 30 | InitWindow(argc, argv); 31 | 32 | GlewInitResult = glewInit(); 33 | 34 | if (GLEW_OK != GlewInitResult) { 35 | fprintf( 36 | stderr, 37 | "ERROR: %s\n", 38 | glewGetErrorString(GlewInitResult) 39 | ); 40 | exit(EXIT_FAILURE); 41 | } 42 | 43 | fprintf( 44 | stdout, 45 | "INFO: OpenGL Version: %s\n", 46 | glGetString(GL_VERSION) 47 | ); 48 | 49 | glClearColor(0.0f, 0.0f, 0.0f, 0.0f); 50 | } 51 | 52 | void InitWindow(int argc, char* argv[]) 53 | { 54 | glutInit(&argc, argv); 55 | 56 | glutInitContextVersion(3, 3); 57 | glutInitContextFlags(GLUT_FORWARD_COMPATIBLE); 58 | glutInitContextProfile(GLUT_CORE_PROFILE); 59 | 60 | glutSetOption( 61 | GLUT_ACTION_ON_WINDOW_CLOSE, 62 | GLUT_ACTION_GLUTMAINLOOP_RETURNS 63 | ); 64 | 65 | glutInitWindowSize(CurrentWidth, CurrentHeight); 66 | 67 | glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA); 68 | 69 | WindowHandle = glutCreateWindow(WINDOW_TITLE_PREFIX); 70 | 71 | if(WindowHandle < 1) { 72 | fprintf( 73 | stderr, 74 | "ERROR: Could not create a new rendering window.\n" 75 | ); 76 | exit(EXIT_FAILURE); 77 | } 78 | 79 | glutReshapeFunc(ResizeFunction); 80 | glutDisplayFunc(RenderFunction); 81 | } 82 | 83 | void ResizeFunction(int Width, int Height) 84 | { 85 | CurrentWidth = Width; 86 | CurrentHeight = Height; 87 | glViewport(0, 0, CurrentWidth, CurrentHeight); 88 | } 89 | 90 | void RenderFunction(void) 91 | { 92 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 93 | 94 | glutSwapBuffers(); 95 | } -------------------------------------------------------------------------------- /chapter-1/compatibility/chapter.1.3.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #define WINDOW_TITLE_PREFIX "Chapter 1" 7 | 8 | int CurrentWidth = 800, 9 | CurrentHeight = 600, 10 | WindowHandle = 0; 11 | 12 | unsigned FrameCount = 0; 13 | 14 | void Initialize(int, char*[]); 15 | void InitWindow(int, char*[]); 16 | void ResizeFunction(int, int); 17 | void RenderFunction(void); 18 | void TimerFunction(int); 19 | void IdleFunction(void); 20 | 21 | int main(int argc, char* argv[]) 22 | { 23 | Initialize(argc, argv); 24 | 25 | glutMainLoop(); 26 | 27 | exit(EXIT_SUCCESS); 28 | } 29 | 30 | void Initialize(int argc, char* argv[]) 31 | { 32 | GLenum GlewInitResult; 33 | 34 | InitWindow(argc, argv); 35 | 36 | GlewInitResult = glewInit(); 37 | 38 | if (GLEW_OK != GlewInitResult) { 39 | fprintf( 40 | stderr, 41 | "ERROR: %s\n", 42 | glewGetErrorString(GlewInitResult) 43 | ); 44 | exit(EXIT_FAILURE); 45 | } 46 | 47 | fprintf( 48 | stdout, 49 | "INFO: OpenGL Version: %s\n", 50 | glGetString(GL_VERSION) 51 | ); 52 | 53 | glClearColor(0.0f, 0.0f, 0.0f, 0.0f); 54 | } 55 | 56 | void InitWindow(int argc, char* argv[]) 57 | { 58 | glutInit(&argc, argv); 59 | 60 | glutInitContextVersion(3, 3); 61 | glutInitContextFlags(GLUT_FORWARD_COMPATIBLE); 62 | glutInitContextProfile(GLUT_CORE_PROFILE); 63 | 64 | glutSetOption( 65 | GLUT_ACTION_ON_WINDOW_CLOSE, 66 | GLUT_ACTION_GLUTMAINLOOP_RETURNS 67 | ); 68 | 69 | glutInitWindowSize(CurrentWidth, CurrentHeight); 70 | 71 | glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA); 72 | 73 | WindowHandle = glutCreateWindow(WINDOW_TITLE_PREFIX); 74 | 75 | if(WindowHandle < 1) { 76 | fprintf( 77 | stderr, 78 | "ERROR: Could not create a new rendering window.\n" 79 | ); 80 | exit(EXIT_FAILURE); 81 | } 82 | 83 | glutReshapeFunc(ResizeFunction); 84 | glutDisplayFunc(RenderFunction); 85 | glutIdleFunc(IdleFunction); 86 | glutTimerFunc(0, TimerFunction, 0); 87 | } 88 | 89 | void ResizeFunction(int Width, int Height) 90 | { 91 | CurrentWidth = Width; 92 | CurrentHeight = Height; 93 | glViewport(0, 0, CurrentWidth, CurrentHeight); 94 | } 95 | 96 | void RenderFunction(void) 97 | { 98 | ++FrameCount; 99 | 100 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 101 | 102 | glutSwapBuffers(); 103 | } 104 | 105 | void IdleFunction(void) 106 | { 107 | glutPostRedisplay(); 108 | } 109 | 110 | void TimerFunction(int Value) 111 | { 112 | if (0 != Value) { 113 | char* TempString = (char*) 114 | malloc(512 + strlen(WINDOW_TITLE_PREFIX)); 115 | 116 | sprintf( 117 | TempString, 118 | "%s: %d Frames Per Second @ %d x %d", 119 | WINDOW_TITLE_PREFIX, 120 | FrameCount * 4, 121 | CurrentWidth, 122 | CurrentHeight 123 | ); 124 | 125 | glutSetWindowTitle(TempString); 126 | free(TempString); 127 | } 128 | 129 | FrameCount = 0; 130 | glutTimerFunc(250, TimerFunction, 1); 131 | } 132 | -------------------------------------------------------------------------------- /chapter-2/chapter.2.1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #define WINDOW_TITLE_PREFIX "Chapter 2" 7 | 8 | int 9 | CurrentWidth = 800, 10 | CurrentHeight = 600, 11 | WindowHandle = 0; 12 | 13 | unsigned FrameCount = 0; 14 | 15 | GLuint 16 | VertexShaderId, 17 | FragmentShaderId, 18 | ProgramId, 19 | VaoId, 20 | VboId, 21 | ColorBufferId; 22 | 23 | const GLchar* VertexShader = 24 | { 25 | "#version 400\n"\ 26 | 27 | "layout(location=0) in vec4 in_Position;\n"\ 28 | "layout(location=1) in vec4 in_Color;\n"\ 29 | "out vec4 ex_Color;\n"\ 30 | 31 | "void main(void)\n"\ 32 | "{\n"\ 33 | " gl_Position = in_Position;\n"\ 34 | " ex_Color = in_Color;\n"\ 35 | "}\n" 36 | }; 37 | 38 | const GLchar* FragmentShader = 39 | { 40 | "#version 400\n"\ 41 | 42 | "in vec4 ex_Color;\n"\ 43 | "out vec4 out_Color;\n"\ 44 | 45 | "void main(void)\n"\ 46 | "{\n"\ 47 | " out_Color = ex_Color;\n"\ 48 | "}\n" 49 | }; 50 | 51 | void Initialize(int, char*[]); 52 | void InitWindow(int, char*[]); 53 | void ResizeFunction(int, int); 54 | void RenderFunction(void); 55 | void TimerFunction(int); 56 | void IdleFunction(void); 57 | void Cleanup(void); 58 | void CreateVBO(void); 59 | void DestroyVBO(void); 60 | void CreateShaders(void); 61 | void DestroyShaders(void); 62 | 63 | int main(int argc, char* argv[]) 64 | { 65 | Initialize(argc, argv); 66 | 67 | glutMainLoop(); 68 | 69 | exit(EXIT_SUCCESS); 70 | } 71 | 72 | void Initialize(int argc, char* argv[]) 73 | { 74 | GLenum GlewInitResult; 75 | 76 | InitWindow(argc, argv); 77 | 78 | glewExperimental = GL_TRUE; 79 | GlewInitResult = glewInit(); 80 | 81 | if (GLEW_OK != GlewInitResult) { 82 | fprintf( 83 | stderr, 84 | "ERROR: %s\n", 85 | glewGetErrorString(GlewInitResult) 86 | ); 87 | exit(EXIT_FAILURE); 88 | } 89 | 90 | fprintf( 91 | stdout, 92 | "INFO: OpenGL Version: %s\n", 93 | glGetString(GL_VERSION) 94 | ); 95 | 96 | CreateShaders(); 97 | CreateVBO(); 98 | 99 | glClearColor(0.0f, 0.0f, 0.0f, 0.0f); 100 | } 101 | 102 | void InitWindow(int argc, char* argv[]) 103 | { 104 | glutInit(&argc, argv); 105 | 106 | glutInitContextVersion(4, 0); 107 | glutInitContextFlags(GLUT_FORWARD_COMPATIBLE); 108 | glutInitContextProfile(GLUT_CORE_PROFILE); 109 | 110 | glutSetOption( 111 | GLUT_ACTION_ON_WINDOW_CLOSE, 112 | GLUT_ACTION_GLUTMAINLOOP_RETURNS 113 | ); 114 | 115 | glutInitWindowSize(CurrentWidth, CurrentHeight); 116 | 117 | glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA); 118 | 119 | WindowHandle = glutCreateWindow(WINDOW_TITLE_PREFIX); 120 | 121 | if(WindowHandle < 1) { 122 | fprintf( 123 | stderr, 124 | "ERROR: Could not create a new rendering window.\n" 125 | ); 126 | exit(EXIT_FAILURE); 127 | } 128 | 129 | glutReshapeFunc(ResizeFunction); 130 | glutDisplayFunc(RenderFunction); 131 | glutIdleFunc(IdleFunction); 132 | glutTimerFunc(0, TimerFunction, 0); 133 | glutCloseFunc(Cleanup); 134 | } 135 | 136 | void ResizeFunction(int Width, int Height) 137 | { 138 | CurrentWidth = Width; 139 | CurrentHeight = Height; 140 | glViewport(0, 0, CurrentWidth, CurrentHeight); 141 | } 142 | 143 | void RenderFunction(void) 144 | { 145 | ++FrameCount; 146 | 147 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 148 | 149 | glDrawArrays(GL_TRIANGLES, 0, 3); 150 | 151 | glutSwapBuffers(); 152 | } 153 | 154 | void IdleFunction(void) 155 | { 156 | glutPostRedisplay(); 157 | } 158 | 159 | void TimerFunction(int Value) 160 | { 161 | if (0 != Value) { 162 | char* TempString = (char*) 163 | malloc(512 + strlen(WINDOW_TITLE_PREFIX)); 164 | 165 | sprintf( 166 | TempString, 167 | "%s: %d Frames Per Second @ %d x %d", 168 | WINDOW_TITLE_PREFIX, 169 | FrameCount * 4, 170 | CurrentWidth, 171 | CurrentHeight 172 | ); 173 | 174 | glutSetWindowTitle(TempString); 175 | free(TempString); 176 | } 177 | 178 | FrameCount = 0; 179 | glutTimerFunc(250, TimerFunction, 1); 180 | } 181 | 182 | void Cleanup(void) 183 | { 184 | DestroyShaders(); 185 | DestroyVBO(); 186 | } 187 | 188 | void CreateVBO(void) 189 | { 190 | GLfloat Vertices[] = { 191 | -0.8f, -0.8f, 0.0f, 1.0f, 192 | 0.0f, 0.8f, 0.0f, 1.0f, 193 | 0.8f, -0.8f, 0.0f, 1.0f 194 | }; 195 | 196 | GLfloat Colors[] = { 197 | 1.0f, 0.0f, 0.0f, 1.0f, 198 | 0.0f, 1.0f, 0.0f, 1.0f, 199 | 0.0f, 0.0f, 1.0f, 1.0f 200 | }; 201 | 202 | GLenum ErrorCheckValue = glGetError(); 203 | 204 | glGenVertexArrays(1, &VaoId); 205 | glBindVertexArray(VaoId); 206 | 207 | glGenBuffers(1, &VboId); 208 | glBindBuffer(GL_ARRAY_BUFFER, VboId); 209 | glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices), Vertices, GL_STATIC_DRAW); 210 | glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0); 211 | glEnableVertexAttribArray(0); 212 | 213 | glGenBuffers(1, &ColorBufferId); 214 | glBindBuffer(GL_ARRAY_BUFFER, ColorBufferId); 215 | glBufferData(GL_ARRAY_BUFFER, sizeof(Colors), Colors, GL_STATIC_DRAW); 216 | glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, 0); 217 | glEnableVertexAttribArray(1); 218 | 219 | ErrorCheckValue = glGetError(); 220 | if (ErrorCheckValue != GL_NO_ERROR) 221 | { 222 | fprintf( 223 | stderr, 224 | "ERROR: Could not create a VBO: %s \n", 225 | gluErrorString(ErrorCheckValue) 226 | ); 227 | 228 | exit(-1); 229 | } 230 | } 231 | 232 | void DestroyVBO(void) 233 | { 234 | GLenum ErrorCheckValue = glGetError(); 235 | 236 | glDisableVertexAttribArray(1); 237 | glDisableVertexAttribArray(0); 238 | 239 | glBindBuffer(GL_ARRAY_BUFFER, 0); 240 | 241 | glDeleteBuffers(1, &ColorBufferId); 242 | glDeleteBuffers(1, &VboId); 243 | 244 | glBindVertexArray(0); 245 | glDeleteVertexArrays(1, &VaoId); 246 | 247 | ErrorCheckValue = glGetError(); 248 | if (ErrorCheckValue != GL_NO_ERROR) 249 | { 250 | fprintf( 251 | stderr, 252 | "ERROR: Could not destroy the VBO: %s \n", 253 | gluErrorString(ErrorCheckValue) 254 | ); 255 | 256 | exit(-1); 257 | } 258 | } 259 | 260 | void CreateShaders(void) 261 | { 262 | GLenum ErrorCheckValue = glGetError(); 263 | 264 | VertexShaderId = glCreateShader(GL_VERTEX_SHADER); 265 | glShaderSource(VertexShaderId, 1, &VertexShader, NULL); 266 | glCompileShader(VertexShaderId); 267 | 268 | FragmentShaderId = glCreateShader(GL_FRAGMENT_SHADER); 269 | glShaderSource(FragmentShaderId, 1, &FragmentShader, NULL); 270 | glCompileShader(FragmentShaderId); 271 | 272 | ProgramId = glCreateProgram(); 273 | glAttachShader(ProgramId, VertexShaderId); 274 | glAttachShader(ProgramId, FragmentShaderId); 275 | glLinkProgram(ProgramId); 276 | glUseProgram(ProgramId); 277 | 278 | ErrorCheckValue = glGetError(); 279 | if (ErrorCheckValue != GL_NO_ERROR) 280 | { 281 | fprintf( 282 | stderr, 283 | "ERROR: Could not create the shaders: %s \n", 284 | gluErrorString(ErrorCheckValue) 285 | ); 286 | 287 | exit(-1); 288 | } 289 | } 290 | 291 | void DestroyShaders(void) 292 | { 293 | GLenum ErrorCheckValue = glGetError(); 294 | 295 | glUseProgram(0); 296 | 297 | glDetachShader(ProgramId, VertexShaderId); 298 | glDetachShader(ProgramId, FragmentShaderId); 299 | 300 | glDeleteShader(FragmentShaderId); 301 | glDeleteShader(VertexShaderId); 302 | 303 | glDeleteProgram(ProgramId); 304 | 305 | ErrorCheckValue = glGetError(); 306 | if (ErrorCheckValue != GL_NO_ERROR) 307 | { 308 | fprintf( 309 | stderr, 310 | "ERROR: Could not destroy the shaders: %s \n", 311 | gluErrorString(ErrorCheckValue) 312 | ); 313 | 314 | exit(-1); 315 | } 316 | } -------------------------------------------------------------------------------- /chapter-2/chapter.2.2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #define WINDOW_TITLE_PREFIX "Chapter 2" 7 | 8 | int 9 | CurrentWidth = 800, 10 | CurrentHeight = 600, 11 | WindowHandle = 0; 12 | 13 | unsigned FrameCount = 0; 14 | 15 | GLuint 16 | VertexShaderId, 17 | FragmentShaderId, 18 | ProgramId, 19 | VaoId, 20 | VboId, 21 | ColorBufferId; 22 | 23 | const GLchar* VertexShader = 24 | { 25 | "#version 400\n"\ 26 | 27 | "layout(location=0) in vec4 in_Position;\n"\ 28 | "layout(location=1) in vec4 in_Color;\n"\ 29 | "out vec4 ex_Color;\n"\ 30 | 31 | "void main(void)\n"\ 32 | "{\n"\ 33 | " gl_Position = in_Position;\n"\ 34 | " ex_Color = in_Color;\n"\ 35 | "}\n" 36 | }; 37 | 38 | const GLchar* FragmentShader = 39 | { 40 | "#version 400\n"\ 41 | 42 | "in vec4 ex_Color;\n"\ 43 | "out vec4 out_Color;\n"\ 44 | 45 | "void main(void)\n"\ 46 | "{\n"\ 47 | " out_Color = ex_Color;\n"\ 48 | "}\n" 49 | }; 50 | 51 | void Initialize(int, char*[]); 52 | void InitWindow(int, char*[]); 53 | void ResizeFunction(int, int); 54 | void RenderFunction(void); 55 | void TimerFunction(int); 56 | void IdleFunction(void); 57 | void Cleanup(void); 58 | void CreateVBO(void); 59 | void DestroyVBO(void); 60 | void CreateShaders(void); 61 | void DestroyShaders(void); 62 | 63 | int main(int argc, char* argv[]) 64 | { 65 | Initialize(argc, argv); 66 | 67 | glutMainLoop(); 68 | 69 | exit(EXIT_SUCCESS); 70 | } 71 | 72 | void Initialize(int argc, char* argv[]) 73 | { 74 | GLenum GlewInitResult; 75 | 76 | InitWindow(argc, argv); 77 | 78 | glewExperimental = GL_TRUE; 79 | GlewInitResult = glewInit(); 80 | 81 | if (GLEW_OK != GlewInitResult) { 82 | fprintf( 83 | stderr, 84 | "ERROR: %s\n", 85 | glewGetErrorString(GlewInitResult) 86 | ); 87 | exit(EXIT_FAILURE); 88 | } 89 | 90 | fprintf( 91 | stdout, 92 | "INFO: OpenGL Version: %s\n", 93 | glGetString(GL_VERSION) 94 | ); 95 | 96 | CreateShaders(); 97 | CreateVBO(); 98 | 99 | glClearColor(0.0f, 0.0f, 0.0f, 0.0f); 100 | } 101 | 102 | void InitWindow(int argc, char* argv[]) 103 | { 104 | glutInit(&argc, argv); 105 | 106 | glutInitContextVersion(4, 0); 107 | glutInitContextFlags(GLUT_FORWARD_COMPATIBLE); 108 | glutInitContextProfile(GLUT_CORE_PROFILE); 109 | 110 | glutSetOption( 111 | GLUT_ACTION_ON_WINDOW_CLOSE, 112 | GLUT_ACTION_GLUTMAINLOOP_RETURNS 113 | ); 114 | 115 | glutInitWindowSize(CurrentWidth, CurrentHeight); 116 | 117 | glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA); 118 | 119 | WindowHandle = glutCreateWindow(WINDOW_TITLE_PREFIX); 120 | 121 | if(WindowHandle < 1) { 122 | fprintf( 123 | stderr, 124 | "ERROR: Could not create a new rendering window.\n" 125 | ); 126 | exit(EXIT_FAILURE); 127 | } 128 | 129 | glutReshapeFunc(ResizeFunction); 130 | glutDisplayFunc(RenderFunction); 131 | glutIdleFunc(IdleFunction); 132 | glutTimerFunc(0, TimerFunction, 0); 133 | glutCloseFunc(Cleanup); 134 | } 135 | 136 | void ResizeFunction(int Width, int Height) 137 | { 138 | CurrentWidth = Width; 139 | CurrentHeight = Height; 140 | glViewport(0, 0, CurrentWidth, CurrentHeight); 141 | } 142 | 143 | void RenderFunction(void) 144 | { 145 | ++FrameCount; 146 | 147 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 148 | 149 | glDrawArrays(GL_TRIANGLES, 0, 6); 150 | 151 | glutSwapBuffers(); 152 | } 153 | 154 | void IdleFunction(void) 155 | { 156 | glutPostRedisplay(); 157 | } 158 | 159 | void TimerFunction(int Value) 160 | { 161 | if (0 != Value) { 162 | char* TempString = (char*) 163 | malloc(512 + strlen(WINDOW_TITLE_PREFIX)); 164 | 165 | sprintf( 166 | TempString, 167 | "%s: %d Frames Per Second @ %d x %d", 168 | WINDOW_TITLE_PREFIX, 169 | FrameCount * 4, 170 | CurrentWidth, 171 | CurrentHeight 172 | ); 173 | 174 | glutSetWindowTitle(TempString); 175 | free(TempString); 176 | } 177 | 178 | FrameCount = 0; 179 | glutTimerFunc(250, TimerFunction, 1); 180 | } 181 | 182 | void Cleanup(void) 183 | { 184 | DestroyShaders(); 185 | DestroyVBO(); 186 | } 187 | 188 | void CreateVBO(void) 189 | { 190 | GLfloat Vertices[] = { 191 | -0.8f, 0.8f, 0.0f, 1.0f, 192 | 0.8f, 0.8f, 0.0f, 1.0f, 193 | -0.8f, -0.8f, 0.0f, 1.0f, 194 | 195 | -0.8f, -0.8f, 0.0f, 1.0f, 196 | 0.8f, 0.8f, 0.0f, 1.0f, 197 | 0.8f, -0.8f, 0.0f, 1.0f 198 | }; 199 | 200 | GLfloat Colors[] = { 201 | 1.0f, 0.0f, 0.0f, 1.0f, 202 | 0.0f, 1.0f, 0.0f, 1.0f, 203 | 0.0f, 0.0f, 1.0f, 1.0f, 204 | 205 | 0.0f, 0.0f, 1.0f, 1.0f, 206 | 0.0f, 1.0f, 0.0f, 1.0f, 207 | 1.0f, 1.0f, 1.0f, 1.0f 208 | }; 209 | 210 | GLenum ErrorCheckValue = glGetError(); 211 | 212 | glGenVertexArrays(1, &VaoId); 213 | glBindVertexArray(VaoId); 214 | 215 | glGenBuffers(1, &VboId); 216 | glBindBuffer(GL_ARRAY_BUFFER, VboId); 217 | glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices), Vertices, GL_STATIC_DRAW); 218 | glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0); 219 | glEnableVertexAttribArray(0); 220 | 221 | glGenBuffers(1, &ColorBufferId); 222 | glBindBuffer(GL_ARRAY_BUFFER, ColorBufferId); 223 | glBufferData(GL_ARRAY_BUFFER, sizeof(Colors), Colors, GL_STATIC_DRAW); 224 | glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, 0); 225 | glEnableVertexAttribArray(1); 226 | 227 | ErrorCheckValue = glGetError(); 228 | if (ErrorCheckValue != GL_NO_ERROR) 229 | { 230 | fprintf( 231 | stderr, 232 | "ERROR: Could not create a VBO: %s \n", 233 | gluErrorString(ErrorCheckValue) 234 | ); 235 | 236 | exit(-1); 237 | } 238 | } 239 | 240 | void DestroyVBO(void) 241 | { 242 | GLenum ErrorCheckValue = glGetError(); 243 | 244 | glDisableVertexAttribArray(1); 245 | glDisableVertexAttribArray(0); 246 | 247 | glBindBuffer(GL_ARRAY_BUFFER, 0); 248 | 249 | glDeleteBuffers(1, &ColorBufferId); 250 | glDeleteBuffers(1, &VboId); 251 | 252 | glBindVertexArray(0); 253 | glDeleteVertexArrays(1, &VaoId); 254 | 255 | ErrorCheckValue = glGetError(); 256 | if (ErrorCheckValue != GL_NO_ERROR) 257 | { 258 | fprintf( 259 | stderr, 260 | "ERROR: Could not destroy the VBO: %s \n", 261 | gluErrorString(ErrorCheckValue) 262 | ); 263 | 264 | exit(-1); 265 | } 266 | } 267 | 268 | void CreateShaders(void) 269 | { 270 | GLenum ErrorCheckValue = glGetError(); 271 | 272 | VertexShaderId = glCreateShader(GL_VERTEX_SHADER); 273 | glShaderSource(VertexShaderId, 1, &VertexShader, NULL); 274 | glCompileShader(VertexShaderId); 275 | 276 | FragmentShaderId = glCreateShader(GL_FRAGMENT_SHADER); 277 | glShaderSource(FragmentShaderId, 1, &FragmentShader, NULL); 278 | glCompileShader(FragmentShaderId); 279 | 280 | ProgramId = glCreateProgram(); 281 | glAttachShader(ProgramId, VertexShaderId); 282 | glAttachShader(ProgramId, FragmentShaderId); 283 | glLinkProgram(ProgramId); 284 | glUseProgram(ProgramId); 285 | 286 | ErrorCheckValue = glGetError(); 287 | if (ErrorCheckValue != GL_NO_ERROR) 288 | { 289 | fprintf( 290 | stderr, 291 | "ERROR: Could not create the shaders: %s \n", 292 | gluErrorString(ErrorCheckValue) 293 | ); 294 | 295 | exit(-1); 296 | } 297 | } 298 | 299 | void DestroyShaders(void) 300 | { 301 | GLenum ErrorCheckValue = glGetError(); 302 | 303 | glUseProgram(0); 304 | 305 | glDetachShader(ProgramId, VertexShaderId); 306 | glDetachShader(ProgramId, FragmentShaderId); 307 | 308 | glDeleteShader(FragmentShaderId); 309 | glDeleteShader(VertexShaderId); 310 | 311 | glDeleteProgram(ProgramId); 312 | 313 | ErrorCheckValue = glGetError(); 314 | if (ErrorCheckValue != GL_NO_ERROR) 315 | { 316 | fprintf( 317 | stderr, 318 | "ERROR: Could not destroy the shaders: %s \n", 319 | gluErrorString(ErrorCheckValue) 320 | ); 321 | 322 | exit(-1); 323 | } 324 | } -------------------------------------------------------------------------------- /chapter-2/chapter.2.3.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #define WINDOW_TITLE_PREFIX "Chapter 2" 7 | 8 | int 9 | CurrentWidth = 800, 10 | CurrentHeight = 600, 11 | WindowHandle = 0; 12 | 13 | unsigned FrameCount = 0; 14 | 15 | GLuint 16 | VertexShaderId, 17 | FragmentShaderId, 18 | ProgramId, 19 | VaoId, 20 | VboId, 21 | ColorBufferId; 22 | 23 | const GLchar* VertexShader = 24 | { 25 | "#version 400\n"\ 26 | 27 | "layout(location=0) in vec4 in_Position;\n"\ 28 | "layout(location=1) in vec4 in_Color;\n"\ 29 | "out vec4 ex_Color;\n"\ 30 | 31 | "void main(void)\n"\ 32 | "{\n"\ 33 | " gl_Position = in_Position;\n"\ 34 | " ex_Color = in_Color;\n"\ 35 | "}\n" 36 | }; 37 | 38 | const GLchar* FragmentShader = 39 | { 40 | "#version 400\n"\ 41 | 42 | "in vec4 ex_Color;\n"\ 43 | "out vec4 out_Color;\n"\ 44 | 45 | "void main(void)\n"\ 46 | "{\n"\ 47 | " out_Color = ex_Color;\n"\ 48 | "}\n" 49 | }; 50 | 51 | void Initialize(int, char*[]); 52 | void InitWindow(int, char*[]); 53 | void ResizeFunction(int, int); 54 | void RenderFunction(void); 55 | void TimerFunction(int); 56 | void IdleFunction(void); 57 | void Cleanup(void); 58 | void CreateVBO(void); 59 | void DestroyVBO(void); 60 | void CreateShaders(void); 61 | void DestroyShaders(void); 62 | 63 | int main(int argc, char* argv[]) 64 | { 65 | Initialize(argc, argv); 66 | 67 | glutMainLoop(); 68 | 69 | exit(EXIT_SUCCESS); 70 | } 71 | 72 | void Initialize(int argc, char* argv[]) 73 | { 74 | GLenum GlewInitResult; 75 | 76 | glewExperimental = GL_TRUE; 77 | InitWindow(argc, argv); 78 | 79 | GlewInitResult = glewInit(); 80 | 81 | if (GLEW_OK != GlewInitResult) { 82 | fprintf( 83 | stderr, 84 | "ERROR: %s\n", 85 | glewGetErrorString(GlewInitResult) 86 | ); 87 | exit(EXIT_FAILURE); 88 | } 89 | 90 | fprintf( 91 | stdout, 92 | "INFO: OpenGL Version: %s\n", 93 | glGetString(GL_VERSION) 94 | ); 95 | 96 | CreateShaders(); 97 | CreateVBO(); 98 | 99 | glClearColor(0.0f, 0.0f, 0.0f, 0.0f); 100 | } 101 | 102 | void InitWindow(int argc, char* argv[]) 103 | { 104 | glutInit(&argc, argv); 105 | 106 | glutInitContextVersion(4, 0); 107 | glutInitContextFlags(GLUT_FORWARD_COMPATIBLE); 108 | glutInitContextProfile(GLUT_CORE_PROFILE); 109 | 110 | glutSetOption( 111 | GLUT_ACTION_ON_WINDOW_CLOSE, 112 | GLUT_ACTION_GLUTMAINLOOP_RETURNS 113 | ); 114 | 115 | glutInitWindowSize(CurrentWidth, CurrentHeight); 116 | 117 | glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA); 118 | 119 | WindowHandle = glutCreateWindow(WINDOW_TITLE_PREFIX); 120 | 121 | if(WindowHandle < 1) { 122 | fprintf( 123 | stderr, 124 | "ERROR: Could not create a new rendering window.\n" 125 | ); 126 | exit(EXIT_FAILURE); 127 | } 128 | 129 | glutReshapeFunc(ResizeFunction); 130 | glutDisplayFunc(RenderFunction); 131 | glutIdleFunc(IdleFunction); 132 | glutTimerFunc(0, TimerFunction, 0); 133 | glutCloseFunc(Cleanup); 134 | } 135 | 136 | void ResizeFunction(int Width, int Height) 137 | { 138 | CurrentWidth = Width; 139 | CurrentHeight = Height; 140 | glViewport(0, 0, CurrentWidth, CurrentHeight); 141 | } 142 | 143 | void RenderFunction(void) 144 | { 145 | ++FrameCount; 146 | 147 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 148 | 149 | glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 150 | 151 | glutSwapBuffers(); 152 | } 153 | 154 | void IdleFunction(void) 155 | { 156 | glutPostRedisplay(); 157 | } 158 | 159 | void TimerFunction(int Value) 160 | { 161 | if (0 != Value) { 162 | char* TempString = (char*) 163 | malloc(512 + strlen(WINDOW_TITLE_PREFIX)); 164 | 165 | sprintf( 166 | TempString, 167 | "%s: %d Frames Per Second @ %d x %d", 168 | WINDOW_TITLE_PREFIX, 169 | FrameCount * 4, 170 | CurrentWidth, 171 | CurrentHeight 172 | ); 173 | 174 | glutSetWindowTitle(TempString); 175 | free(TempString); 176 | } 177 | 178 | FrameCount = 0; 179 | glutTimerFunc(250, TimerFunction, 1); 180 | } 181 | 182 | void Cleanup(void) 183 | { 184 | DestroyShaders(); 185 | DestroyVBO(); 186 | } 187 | 188 | void CreateVBO(void) 189 | { 190 | GLfloat Vertices[] = { 191 | -0.8f, 0.8f, 0.0f, 1.0f, 192 | 0.8f, 0.8f, 0.0f, 1.0f, 193 | -0.8f, -0.8f, 0.0f, 1.0f, 194 | 0.8f, -0.8f, 0.0f, 1.0f 195 | }; 196 | 197 | GLfloat Colors[] = { 198 | 1.0f, 0.0f, 0.0f, 1.0f, 199 | 0.0f, 1.0f, 0.0f, 1.0f, 200 | 0.0f, 0.0f, 1.0f, 1.0f, 201 | 1.0f, 1.0f, 1.0f, 1.0f 202 | }; 203 | 204 | GLenum ErrorCheckValue = glGetError(); 205 | 206 | glGenVertexArrays(1, &VaoId); 207 | glBindVertexArray(VaoId); 208 | 209 | glGenBuffers(1, &VboId); 210 | glBindBuffer(GL_ARRAY_BUFFER, VboId); 211 | glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices), Vertices, GL_STATIC_DRAW); 212 | glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0); 213 | glEnableVertexAttribArray(0); 214 | 215 | glGenBuffers(1, &ColorBufferId); 216 | glBindBuffer(GL_ARRAY_BUFFER, ColorBufferId); 217 | glBufferData(GL_ARRAY_BUFFER, sizeof(Colors), Colors, GL_STATIC_DRAW); 218 | glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, 0); 219 | glEnableVertexAttribArray(1); 220 | 221 | ErrorCheckValue = glGetError(); 222 | if (ErrorCheckValue != GL_NO_ERROR) 223 | { 224 | fprintf( 225 | stderr, 226 | "ERROR: Could not create a VBO: %s \n", 227 | gluErrorString(ErrorCheckValue) 228 | ); 229 | 230 | exit(-1); 231 | } 232 | } 233 | 234 | void DestroyVBO(void) 235 | { 236 | GLenum ErrorCheckValue = glGetError(); 237 | 238 | glDisableVertexAttribArray(1); 239 | glDisableVertexAttribArray(0); 240 | 241 | glBindBuffer(GL_ARRAY_BUFFER, 0); 242 | 243 | glDeleteBuffers(1, &ColorBufferId); 244 | glDeleteBuffers(1, &VboId); 245 | 246 | glBindVertexArray(0); 247 | glDeleteVertexArrays(1, &VaoId); 248 | 249 | ErrorCheckValue = glGetError(); 250 | if (ErrorCheckValue != GL_NO_ERROR) 251 | { 252 | fprintf( 253 | stderr, 254 | "ERROR: Could not destroy the VBO: %s \n", 255 | gluErrorString(ErrorCheckValue) 256 | ); 257 | 258 | exit(-1); 259 | } 260 | } 261 | 262 | void CreateShaders(void) 263 | { 264 | GLenum ErrorCheckValue = glGetError(); 265 | 266 | VertexShaderId = glCreateShader(GL_VERTEX_SHADER); 267 | glShaderSource(VertexShaderId, 1, &VertexShader, NULL); 268 | glCompileShader(VertexShaderId); 269 | 270 | FragmentShaderId = glCreateShader(GL_FRAGMENT_SHADER); 271 | glShaderSource(FragmentShaderId, 1, &FragmentShader, NULL); 272 | glCompileShader(FragmentShaderId); 273 | 274 | ProgramId = glCreateProgram(); 275 | glAttachShader(ProgramId, VertexShaderId); 276 | glAttachShader(ProgramId, FragmentShaderId); 277 | glLinkProgram(ProgramId); 278 | glUseProgram(ProgramId); 279 | 280 | ErrorCheckValue = glGetError(); 281 | if (ErrorCheckValue != GL_NO_ERROR) 282 | { 283 | fprintf( 284 | stderr, 285 | "ERROR: Could not create the shaders: %s \n", 286 | gluErrorString(ErrorCheckValue) 287 | ); 288 | 289 | exit(-1); 290 | } 291 | } 292 | 293 | void DestroyShaders(void) 294 | { 295 | GLenum ErrorCheckValue = glGetError(); 296 | 297 | glUseProgram(0); 298 | 299 | glDetachShader(ProgramId, VertexShaderId); 300 | glDetachShader(ProgramId, FragmentShaderId); 301 | 302 | glDeleteShader(FragmentShaderId); 303 | glDeleteShader(VertexShaderId); 304 | 305 | glDeleteProgram(ProgramId); 306 | 307 | ErrorCheckValue = glGetError(); 308 | if (ErrorCheckValue != GL_NO_ERROR) 309 | { 310 | fprintf( 311 | stderr, 312 | "ERROR: Could not destroy the shaders: %s \n", 313 | gluErrorString(ErrorCheckValue) 314 | ); 315 | 316 | exit(-1); 317 | } 318 | } -------------------------------------------------------------------------------- /chapter-2/chapter.2.4.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #define WINDOW_TITLE_PREFIX "Chapter 2" 7 | 8 | typedef struct 9 | { 10 | float XYZW[4]; 11 | float RGBA[4]; 12 | } Vertex; 13 | 14 | int 15 | CurrentWidth = 800, 16 | CurrentHeight = 600, 17 | WindowHandle = 0; 18 | 19 | unsigned FrameCount = 0; 20 | 21 | GLuint 22 | VertexShaderId, 23 | FragmentShaderId, 24 | ProgramId, 25 | VaoId, 26 | VboId; 27 | 28 | const GLchar* VertexShader = 29 | { 30 | "#version 400\n"\ 31 | 32 | "layout(location=0) in vec4 in_Position;\n"\ 33 | "layout(location=1) in vec4 in_Color;\n"\ 34 | "out vec4 ex_Color;\n"\ 35 | 36 | "void main(void)\n"\ 37 | "{\n"\ 38 | " gl_Position = in_Position;\n"\ 39 | " ex_Color = in_Color;\n"\ 40 | "}\n" 41 | }; 42 | 43 | const GLchar* FragmentShader = 44 | { 45 | "#version 400\n"\ 46 | 47 | "in vec4 ex_Color;\n"\ 48 | "out vec4 out_Color;\n"\ 49 | 50 | "void main(void)\n"\ 51 | "{\n"\ 52 | " out_Color = ex_Color;\n"\ 53 | "}\n" 54 | }; 55 | 56 | void Initialize(int, char*[]); 57 | void InitWindow(int, char*[]); 58 | void ResizeFunction(int, int); 59 | void RenderFunction(void); 60 | void TimerFunction(int); 61 | void IdleFunction(void); 62 | void Cleanup(void); 63 | void CreateVBO(void); 64 | void DestroyVBO(void); 65 | void CreateShaders(void); 66 | void DestroyShaders(void); 67 | 68 | int main(int argc, char* argv[]) 69 | { 70 | Initialize(argc, argv); 71 | 72 | glutMainLoop(); 73 | 74 | exit(EXIT_SUCCESS); 75 | } 76 | 77 | void Initialize(int argc, char* argv[]) 78 | { 79 | GLenum GlewInitResult; 80 | 81 | InitWindow(argc, argv); 82 | 83 | glewExperimental = GL_TRUE; 84 | GlewInitResult = glewInit(); 85 | 86 | if (GLEW_OK != GlewInitResult) { 87 | fprintf( 88 | stderr, 89 | "ERROR: %s\n", 90 | glewGetErrorString(GlewInitResult) 91 | ); 92 | exit(EXIT_FAILURE); 93 | } 94 | 95 | fprintf( 96 | stdout, 97 | "INFO: OpenGL Version: %s\n", 98 | glGetString(GL_VERSION) 99 | ); 100 | 101 | CreateShaders(); 102 | CreateVBO(); 103 | 104 | glClearColor(0.0f, 0.0f, 0.0f, 0.0f); 105 | } 106 | 107 | void InitWindow(int argc, char* argv[]) 108 | { 109 | glutInit(&argc, argv); 110 | 111 | glutInitContextVersion(4, 0); 112 | glutInitContextFlags(GLUT_FORWARD_COMPATIBLE); 113 | glutInitContextProfile(GLUT_CORE_PROFILE); 114 | 115 | glutSetOption( 116 | GLUT_ACTION_ON_WINDOW_CLOSE, 117 | GLUT_ACTION_GLUTMAINLOOP_RETURNS 118 | ); 119 | 120 | glutInitWindowSize(CurrentWidth, CurrentHeight); 121 | 122 | glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA); 123 | 124 | WindowHandle = glutCreateWindow(WINDOW_TITLE_PREFIX); 125 | 126 | if(WindowHandle < 1) { 127 | fprintf( 128 | stderr, 129 | "ERROR: Could not create a new rendering window.\n" 130 | ); 131 | exit(EXIT_FAILURE); 132 | } 133 | 134 | glutReshapeFunc(ResizeFunction); 135 | glutDisplayFunc(RenderFunction); 136 | glutIdleFunc(IdleFunction); 137 | glutTimerFunc(0, TimerFunction, 0); 138 | glutCloseFunc(Cleanup); 139 | } 140 | 141 | void ResizeFunction(int Width, int Height) 142 | { 143 | CurrentWidth = Width; 144 | CurrentHeight = Height; 145 | glViewport(0, 0, CurrentWidth, CurrentHeight); 146 | } 147 | 148 | void RenderFunction(void) 149 | { 150 | ++FrameCount; 151 | 152 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 153 | 154 | glDrawArrays(GL_TRIANGLES, 0, 3); 155 | 156 | glutSwapBuffers(); 157 | } 158 | 159 | void IdleFunction(void) 160 | { 161 | glutPostRedisplay(); 162 | } 163 | 164 | void TimerFunction(int Value) 165 | { 166 | if (0 != Value) { 167 | char* TempString = (char*) 168 | malloc(512 + strlen(WINDOW_TITLE_PREFIX)); 169 | 170 | sprintf( 171 | TempString, 172 | "%s: %d Frames Per Second @ %d x %d", 173 | WINDOW_TITLE_PREFIX, 174 | FrameCount * 4, 175 | CurrentWidth, 176 | CurrentHeight 177 | ); 178 | 179 | glutSetWindowTitle(TempString); 180 | free(TempString); 181 | } 182 | 183 | FrameCount = 0; 184 | glutTimerFunc(250, TimerFunction, 1); 185 | } 186 | 187 | void Cleanup(void) 188 | { 189 | DestroyShaders(); 190 | DestroyVBO(); 191 | } 192 | 193 | void CreateVBO(void) 194 | { 195 | Vertex Vertices[] = 196 | { 197 | { { -0.8f, -0.8f, 0.0f, 1.0f }, { 1.0f, 0.0f, 0.0f, 1.0f } }, 198 | { { 0.0f, 0.8f, 0.0f, 1.0f }, { 0.0f, 1.0f, 0.0f, 1.0f } }, 199 | { { 0.8f, -0.8f, 0.0f, 1.0f }, { 0.0f, 0.0f, 1.0f, 1.0f } } 200 | }; 201 | 202 | GLenum ErrorCheckValue = glGetError(); 203 | const size_t BufferSize = sizeof(Vertices); 204 | const size_t VertexSize = sizeof(Vertices[0]); 205 | const size_t RgbOffset = sizeof(Vertices[0].XYZW); 206 | 207 | glGenVertexArrays(1, &VaoId); 208 | glBindVertexArray(VaoId); 209 | 210 | glGenBuffers(1, &VboId); 211 | glBindBuffer(GL_ARRAY_BUFFER, VboId); 212 | glBufferData(GL_ARRAY_BUFFER, BufferSize, Vertices, GL_STATIC_DRAW); 213 | 214 | glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, VertexSize, 0); 215 | glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, VertexSize, (GLvoid*)RgbOffset); 216 | 217 | glEnableVertexAttribArray(0); 218 | glEnableVertexAttribArray(1); 219 | 220 | ErrorCheckValue = glGetError(); 221 | if (ErrorCheckValue != GL_NO_ERROR) 222 | { 223 | fprintf( 224 | stderr, 225 | "ERROR: Could not create a VBO: %s \n", 226 | gluErrorString(ErrorCheckValue) 227 | ); 228 | 229 | exit(-1); 230 | } 231 | } 232 | 233 | void DestroyVBO(void) 234 | { 235 | GLenum ErrorCheckValue = glGetError(); 236 | 237 | glDisableVertexAttribArray(1); 238 | glDisableVertexAttribArray(0); 239 | 240 | glBindBuffer(GL_ARRAY_BUFFER, 0); 241 | glDeleteBuffers(1, &VboId); 242 | 243 | glBindVertexArray(0); 244 | glDeleteVertexArrays(1, &VaoId); 245 | 246 | ErrorCheckValue = glGetError(); 247 | if (ErrorCheckValue != GL_NO_ERROR) 248 | { 249 | fprintf( 250 | stderr, 251 | "ERROR: Could not destroy the VBO: %s \n", 252 | gluErrorString(ErrorCheckValue) 253 | ); 254 | 255 | exit(-1); 256 | } 257 | } 258 | 259 | void CreateShaders(void) 260 | { 261 | GLenum ErrorCheckValue = glGetError(); 262 | 263 | VertexShaderId = glCreateShader(GL_VERTEX_SHADER); 264 | glShaderSource(VertexShaderId, 1, &VertexShader, NULL); 265 | glCompileShader(VertexShaderId); 266 | 267 | FragmentShaderId = glCreateShader(GL_FRAGMENT_SHADER); 268 | glShaderSource(FragmentShaderId, 1, &FragmentShader, NULL); 269 | glCompileShader(FragmentShaderId); 270 | 271 | ProgramId = glCreateProgram(); 272 | glAttachShader(ProgramId, VertexShaderId); 273 | glAttachShader(ProgramId, FragmentShaderId); 274 | glLinkProgram(ProgramId); 275 | glUseProgram(ProgramId); 276 | 277 | ErrorCheckValue = glGetError(); 278 | if (ErrorCheckValue != GL_NO_ERROR) 279 | { 280 | fprintf( 281 | stderr, 282 | "ERROR: Could not create the shaders: %s \n", 283 | gluErrorString(ErrorCheckValue) 284 | ); 285 | 286 | exit(-1); 287 | } 288 | } 289 | 290 | void DestroyShaders(void) 291 | { 292 | GLenum ErrorCheckValue = glGetError(); 293 | 294 | glUseProgram(0); 295 | 296 | glDetachShader(ProgramId, VertexShaderId); 297 | glDetachShader(ProgramId, FragmentShaderId); 298 | 299 | glDeleteShader(FragmentShaderId); 300 | glDeleteShader(VertexShaderId); 301 | 302 | glDeleteProgram(ProgramId); 303 | 304 | ErrorCheckValue = glGetError(); 305 | if (ErrorCheckValue != GL_NO_ERROR) 306 | { 307 | fprintf( 308 | stderr, 309 | "ERROR: Could not destroy the shaders: %s \n", 310 | gluErrorString(ErrorCheckValue) 311 | ); 312 | 313 | exit(-1); 314 | } 315 | } -------------------------------------------------------------------------------- /chapter-2/compatibility/chapter.2.1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #define WINDOW_TITLE_PREFIX "Chapter 2" 7 | 8 | int 9 | CurrentWidth = 800, 10 | CurrentHeight = 600, 11 | WindowHandle = 0; 12 | 13 | unsigned FrameCount = 0; 14 | 15 | GLuint 16 | VertexShaderId, 17 | FragmentShaderId, 18 | ProgramId, 19 | VaoId, 20 | VboId, 21 | ColorBufferId; 22 | 23 | const GLchar* VertexShader = 24 | { 25 | "#version 330\n"\ 26 | 27 | "layout(location=0) in vec4 in_Position;\n"\ 28 | "layout(location=1) in vec4 in_Color;\n"\ 29 | "out vec4 ex_Color;\n"\ 30 | 31 | "void main(void)\n"\ 32 | "{\n"\ 33 | " gl_Position = in_Position;\n"\ 34 | " ex_Color = in_Color;\n"\ 35 | "}\n" 36 | }; 37 | 38 | const GLchar* FragmentShader = 39 | { 40 | "#version 330\n"\ 41 | 42 | "in vec4 ex_Color;\n"\ 43 | "out vec4 out_Color;\n"\ 44 | 45 | "void main(void)\n"\ 46 | "{\n"\ 47 | " out_Color = ex_Color;\n"\ 48 | "}\n" 49 | }; 50 | 51 | void Initialize(int, char*[]); 52 | void InitWindow(int, char*[]); 53 | void ResizeFunction(int, int); 54 | void RenderFunction(void); 55 | void TimerFunction(int); 56 | void IdleFunction(void); 57 | void Cleanup(void); 58 | void CreateVBO(void); 59 | void DestroyVBO(void); 60 | void CreateShaders(void); 61 | void DestroyShaders(void); 62 | 63 | int main(int argc, char* argv[]) 64 | { 65 | Initialize(argc, argv); 66 | 67 | glutMainLoop(); 68 | 69 | exit(EXIT_SUCCESS); 70 | } 71 | 72 | void Initialize(int argc, char* argv[]) 73 | { 74 | GLenum GlewInitResult; 75 | 76 | InitWindow(argc, argv); 77 | 78 | glewExperimental = GL_TRUE; 79 | GlewInitResult = glewInit(); 80 | 81 | if (GLEW_OK != GlewInitResult) { 82 | fprintf( 83 | stderr, 84 | "ERROR: %s\n", 85 | glewGetErrorString(GlewInitResult) 86 | ); 87 | exit(EXIT_FAILURE); 88 | } 89 | 90 | fprintf( 91 | stdout, 92 | "INFO: OpenGL Version: %s\n", 93 | glGetString(GL_VERSION) 94 | ); 95 | 96 | CreateShaders(); 97 | CreateVBO(); 98 | 99 | glClearColor(0.0f, 0.0f, 0.0f, 0.0f); 100 | } 101 | 102 | void InitWindow(int argc, char* argv[]) 103 | { 104 | glutInit(&argc, argv); 105 | 106 | glutInitContextVersion(3, 3); 107 | glutInitContextFlags(GLUT_FORWARD_COMPATIBLE); 108 | glutInitContextProfile(GLUT_CORE_PROFILE); 109 | 110 | glutSetOption( 111 | GLUT_ACTION_ON_WINDOW_CLOSE, 112 | GLUT_ACTION_GLUTMAINLOOP_RETURNS 113 | ); 114 | 115 | glutInitWindowSize(CurrentWidth, CurrentHeight); 116 | 117 | glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA); 118 | 119 | WindowHandle = glutCreateWindow(WINDOW_TITLE_PREFIX); 120 | 121 | if(WindowHandle < 1) { 122 | fprintf( 123 | stderr, 124 | "ERROR: Could not create a new rendering window.\n" 125 | ); 126 | exit(EXIT_FAILURE); 127 | } 128 | 129 | glutReshapeFunc(ResizeFunction); 130 | glutDisplayFunc(RenderFunction); 131 | glutIdleFunc(IdleFunction); 132 | glutTimerFunc(0, TimerFunction, 0); 133 | glutCloseFunc(Cleanup); 134 | } 135 | 136 | void ResizeFunction(int Width, int Height) 137 | { 138 | CurrentWidth = Width; 139 | CurrentHeight = Height; 140 | glViewport(0, 0, CurrentWidth, CurrentHeight); 141 | } 142 | 143 | void RenderFunction(void) 144 | { 145 | ++FrameCount; 146 | 147 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 148 | 149 | glDrawArrays(GL_TRIANGLES, 0, 3); 150 | 151 | glutSwapBuffers(); 152 | } 153 | 154 | void IdleFunction(void) 155 | { 156 | glutPostRedisplay(); 157 | } 158 | 159 | void TimerFunction(int Value) 160 | { 161 | if (0 != Value) { 162 | char* TempString = (char*) 163 | malloc(512 + strlen(WINDOW_TITLE_PREFIX)); 164 | 165 | sprintf( 166 | TempString, 167 | "%s: %d Frames Per Second @ %d x %d", 168 | WINDOW_TITLE_PREFIX, 169 | FrameCount * 4, 170 | CurrentWidth, 171 | CurrentHeight 172 | ); 173 | 174 | glutSetWindowTitle(TempString); 175 | free(TempString); 176 | } 177 | 178 | FrameCount = 0; 179 | glutTimerFunc(250, TimerFunction, 1); 180 | } 181 | 182 | void Cleanup(void) 183 | { 184 | DestroyShaders(); 185 | DestroyVBO(); 186 | } 187 | 188 | void CreateVBO(void) 189 | { 190 | GLfloat Vertices[] = { 191 | -0.8f, -0.8f, 0.0f, 1.0f, 192 | 0.0f, 0.8f, 0.0f, 1.0f, 193 | 0.8f, -0.8f, 0.0f, 1.0f 194 | }; 195 | 196 | GLfloat Colors[] = { 197 | 1.0f, 0.0f, 0.0f, 1.0f, 198 | 0.0f, 1.0f, 0.0f, 1.0f, 199 | 0.0f, 0.0f, 1.0f, 1.0f 200 | }; 201 | 202 | GLenum ErrorCheckValue = glGetError(); 203 | 204 | glGenVertexArrays(1, &VaoId); 205 | glBindVertexArray(VaoId); 206 | 207 | glGenBuffers(1, &VboId); 208 | glBindBuffer(GL_ARRAY_BUFFER, VboId); 209 | glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices), Vertices, GL_STATIC_DRAW); 210 | glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0); 211 | glEnableVertexAttribArray(0); 212 | 213 | glGenBuffers(1, &ColorBufferId); 214 | glBindBuffer(GL_ARRAY_BUFFER, ColorBufferId); 215 | glBufferData(GL_ARRAY_BUFFER, sizeof(Colors), Colors, GL_STATIC_DRAW); 216 | glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, 0); 217 | glEnableVertexAttribArray(1); 218 | 219 | ErrorCheckValue = glGetError(); 220 | if (ErrorCheckValue != GL_NO_ERROR) 221 | { 222 | fprintf( 223 | stderr, 224 | "ERROR: Could not create a VBO: %s \n", 225 | gluErrorString(ErrorCheckValue) 226 | ); 227 | 228 | exit(-1); 229 | } 230 | } 231 | 232 | void DestroyVBO(void) 233 | { 234 | GLenum ErrorCheckValue = glGetError(); 235 | 236 | glDisableVertexAttribArray(1); 237 | glDisableVertexAttribArray(0); 238 | 239 | glBindBuffer(GL_ARRAY_BUFFER, 0); 240 | 241 | glDeleteBuffers(1, &ColorBufferId); 242 | glDeleteBuffers(1, &VboId); 243 | 244 | glBindVertexArray(0); 245 | glDeleteVertexArrays(1, &VaoId); 246 | 247 | ErrorCheckValue = glGetError(); 248 | if (ErrorCheckValue != GL_NO_ERROR) 249 | { 250 | fprintf( 251 | stderr, 252 | "ERROR: Could not destroy the VBO: %s \n", 253 | gluErrorString(ErrorCheckValue) 254 | ); 255 | 256 | exit(-1); 257 | } 258 | } 259 | 260 | void CreateShaders(void) 261 | { 262 | GLenum ErrorCheckValue = glGetError(); 263 | 264 | VertexShaderId = glCreateShader(GL_VERTEX_SHADER); 265 | glShaderSource(VertexShaderId, 1, &VertexShader, NULL); 266 | glCompileShader(VertexShaderId); 267 | 268 | FragmentShaderId = glCreateShader(GL_FRAGMENT_SHADER); 269 | glShaderSource(FragmentShaderId, 1, &FragmentShader, NULL); 270 | glCompileShader(FragmentShaderId); 271 | 272 | ProgramId = glCreateProgram(); 273 | glAttachShader(ProgramId, VertexShaderId); 274 | glAttachShader(ProgramId, FragmentShaderId); 275 | glLinkProgram(ProgramId); 276 | glUseProgram(ProgramId); 277 | 278 | ErrorCheckValue = glGetError(); 279 | if (ErrorCheckValue != GL_NO_ERROR) 280 | { 281 | fprintf( 282 | stderr, 283 | "ERROR: Could not create the shaders: %s \n", 284 | gluErrorString(ErrorCheckValue) 285 | ); 286 | 287 | exit(-1); 288 | } 289 | } 290 | 291 | void DestroyShaders(void) 292 | { 293 | GLenum ErrorCheckValue = glGetError(); 294 | 295 | glUseProgram(0); 296 | 297 | glDetachShader(ProgramId, VertexShaderId); 298 | glDetachShader(ProgramId, FragmentShaderId); 299 | 300 | glDeleteShader(FragmentShaderId); 301 | glDeleteShader(VertexShaderId); 302 | 303 | glDeleteProgram(ProgramId); 304 | 305 | ErrorCheckValue = glGetError(); 306 | if (ErrorCheckValue != GL_NO_ERROR) 307 | { 308 | fprintf( 309 | stderr, 310 | "ERROR: Could not destroy the shaders: %s \n", 311 | gluErrorString(ErrorCheckValue) 312 | ); 313 | 314 | exit(-1); 315 | } 316 | } -------------------------------------------------------------------------------- /chapter-2/compatibility/chapter.2.2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #define WINDOW_TITLE_PREFIX "Chapter 2" 7 | 8 | int 9 | CurrentWidth = 800, 10 | CurrentHeight = 600, 11 | WindowHandle = 0; 12 | 13 | unsigned FrameCount = 0; 14 | 15 | GLuint 16 | VertexShaderId, 17 | FragmentShaderId, 18 | ProgramId, 19 | VaoId, 20 | VboId, 21 | ColorBufferId; 22 | 23 | const GLchar* VertexShader = 24 | { 25 | "#version 330\n"\ 26 | 27 | "layout(location=0) in vec4 in_Position;\n"\ 28 | "layout(location=1) in vec4 in_Color;\n"\ 29 | "out vec4 ex_Color;\n"\ 30 | 31 | "void main(void)\n"\ 32 | "{\n"\ 33 | " gl_Position = in_Position;\n"\ 34 | " ex_Color = in_Color;\n"\ 35 | "}\n" 36 | }; 37 | 38 | const GLchar* FragmentShader = 39 | { 40 | "#version 330\n"\ 41 | 42 | "in vec4 ex_Color;\n"\ 43 | "out vec4 out_Color;\n"\ 44 | 45 | "void main(void)\n"\ 46 | "{\n"\ 47 | " out_Color = ex_Color;\n"\ 48 | "}\n" 49 | }; 50 | 51 | void Initialize(int, char*[]); 52 | void InitWindow(int, char*[]); 53 | void ResizeFunction(int, int); 54 | void RenderFunction(void); 55 | void TimerFunction(int); 56 | void IdleFunction(void); 57 | void Cleanup(void); 58 | void CreateVBO(void); 59 | void DestroyVBO(void); 60 | void CreateShaders(void); 61 | void DestroyShaders(void); 62 | 63 | int main(int argc, char* argv[]) 64 | { 65 | Initialize(argc, argv); 66 | 67 | glutMainLoop(); 68 | 69 | exit(EXIT_SUCCESS); 70 | } 71 | 72 | void Initialize(int argc, char* argv[]) 73 | { 74 | GLenum GlewInitResult; 75 | 76 | InitWindow(argc, argv); 77 | 78 | glewExperimental = GL_TRUE; 79 | GlewInitResult = glewInit(); 80 | 81 | if (GLEW_OK != GlewInitResult) { 82 | fprintf( 83 | stderr, 84 | "ERROR: %s\n", 85 | glewGetErrorString(GlewInitResult) 86 | ); 87 | exit(EXIT_FAILURE); 88 | } 89 | 90 | fprintf( 91 | stdout, 92 | "INFO: OpenGL Version: %s\n", 93 | glGetString(GL_VERSION) 94 | ); 95 | 96 | CreateShaders(); 97 | CreateVBO(); 98 | 99 | glClearColor(0.0f, 0.0f, 0.0f, 0.0f); 100 | } 101 | 102 | void InitWindow(int argc, char* argv[]) 103 | { 104 | glutInit(&argc, argv); 105 | 106 | glutInitContextVersion(3, 3); 107 | glutInitContextFlags(GLUT_FORWARD_COMPATIBLE); 108 | glutInitContextProfile(GLUT_CORE_PROFILE); 109 | 110 | glutSetOption( 111 | GLUT_ACTION_ON_WINDOW_CLOSE, 112 | GLUT_ACTION_GLUTMAINLOOP_RETURNS 113 | ); 114 | 115 | glutInitWindowSize(CurrentWidth, CurrentHeight); 116 | 117 | glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA); 118 | 119 | WindowHandle = glutCreateWindow(WINDOW_TITLE_PREFIX); 120 | 121 | if(WindowHandle < 1) { 122 | fprintf( 123 | stderr, 124 | "ERROR: Could not create a new rendering window.\n" 125 | ); 126 | exit(EXIT_FAILURE); 127 | } 128 | 129 | glutReshapeFunc(ResizeFunction); 130 | glutDisplayFunc(RenderFunction); 131 | glutIdleFunc(IdleFunction); 132 | glutTimerFunc(0, TimerFunction, 0); 133 | glutCloseFunc(Cleanup); 134 | } 135 | 136 | void ResizeFunction(int Width, int Height) 137 | { 138 | CurrentWidth = Width; 139 | CurrentHeight = Height; 140 | glViewport(0, 0, CurrentWidth, CurrentHeight); 141 | } 142 | 143 | void RenderFunction(void) 144 | { 145 | ++FrameCount; 146 | 147 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 148 | 149 | glDrawArrays(GL_TRIANGLES, 0, 6); 150 | 151 | glutSwapBuffers(); 152 | } 153 | 154 | void IdleFunction(void) 155 | { 156 | glutPostRedisplay(); 157 | } 158 | 159 | void TimerFunction(int Value) 160 | { 161 | if (0 != Value) { 162 | char* TempString = (char*) 163 | malloc(512 + strlen(WINDOW_TITLE_PREFIX)); 164 | 165 | sprintf( 166 | TempString, 167 | "%s: %d Frames Per Second @ %d x %d", 168 | WINDOW_TITLE_PREFIX, 169 | FrameCount * 4, 170 | CurrentWidth, 171 | CurrentHeight 172 | ); 173 | 174 | glutSetWindowTitle(TempString); 175 | free(TempString); 176 | } 177 | 178 | FrameCount = 0; 179 | glutTimerFunc(250, TimerFunction, 1); 180 | } 181 | 182 | void Cleanup(void) 183 | { 184 | DestroyShaders(); 185 | DestroyVBO(); 186 | } 187 | 188 | void CreateVBO(void) 189 | { 190 | GLfloat Vertices[] = { 191 | -0.8f, 0.8f, 0.0f, 1.0f, 192 | 0.8f, 0.8f, 0.0f, 1.0f, 193 | -0.8f, -0.8f, 0.0f, 1.0f, 194 | 195 | -0.8f, -0.8f, 0.0f, 1.0f, 196 | 0.8f, 0.8f, 0.0f, 1.0f, 197 | 0.8f, -0.8f, 0.0f, 1.0f 198 | }; 199 | 200 | GLfloat Colors[] = { 201 | 1.0f, 0.0f, 0.0f, 1.0f, 202 | 0.0f, 1.0f, 0.0f, 1.0f, 203 | 0.0f, 0.0f, 1.0f, 1.0f, 204 | 205 | 0.0f, 0.0f, 1.0f, 1.0f, 206 | 0.0f, 1.0f, 0.0f, 1.0f, 207 | 1.0f, 1.0f, 1.0f, 1.0f 208 | }; 209 | 210 | GLenum ErrorCheckValue = glGetError(); 211 | 212 | glGenVertexArrays(1, &VaoId); 213 | glBindVertexArray(VaoId); 214 | 215 | glGenBuffers(1, &VboId); 216 | glBindBuffer(GL_ARRAY_BUFFER, VboId); 217 | glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices), Vertices, GL_STATIC_DRAW); 218 | glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0); 219 | glEnableVertexAttribArray(0); 220 | 221 | glGenBuffers(1, &ColorBufferId); 222 | glBindBuffer(GL_ARRAY_BUFFER, ColorBufferId); 223 | glBufferData(GL_ARRAY_BUFFER, sizeof(Colors), Colors, GL_STATIC_DRAW); 224 | glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, 0); 225 | glEnableVertexAttribArray(1); 226 | 227 | ErrorCheckValue = glGetError(); 228 | if (ErrorCheckValue != GL_NO_ERROR) 229 | { 230 | fprintf( 231 | stderr, 232 | "ERROR: Could not create a VBO: %s \n", 233 | gluErrorString(ErrorCheckValue) 234 | ); 235 | 236 | exit(-1); 237 | } 238 | } 239 | 240 | void DestroyVBO(void) 241 | { 242 | GLenum ErrorCheckValue = glGetError(); 243 | 244 | glDisableVertexAttribArray(1); 245 | glDisableVertexAttribArray(0); 246 | 247 | glBindBuffer(GL_ARRAY_BUFFER, 0); 248 | 249 | glDeleteBuffers(1, &ColorBufferId); 250 | glDeleteBuffers(1, &VboId); 251 | 252 | glBindVertexArray(0); 253 | glDeleteVertexArrays(1, &VaoId); 254 | 255 | ErrorCheckValue = glGetError(); 256 | if (ErrorCheckValue != GL_NO_ERROR) 257 | { 258 | fprintf( 259 | stderr, 260 | "ERROR: Could not destroy the VBO: %s \n", 261 | gluErrorString(ErrorCheckValue) 262 | ); 263 | 264 | exit(-1); 265 | } 266 | } 267 | 268 | void CreateShaders(void) 269 | { 270 | GLenum ErrorCheckValue = glGetError(); 271 | 272 | VertexShaderId = glCreateShader(GL_VERTEX_SHADER); 273 | glShaderSource(VertexShaderId, 1, &VertexShader, NULL); 274 | glCompileShader(VertexShaderId); 275 | 276 | FragmentShaderId = glCreateShader(GL_FRAGMENT_SHADER); 277 | glShaderSource(FragmentShaderId, 1, &FragmentShader, NULL); 278 | glCompileShader(FragmentShaderId); 279 | 280 | ProgramId = glCreateProgram(); 281 | glAttachShader(ProgramId, VertexShaderId); 282 | glAttachShader(ProgramId, FragmentShaderId); 283 | glLinkProgram(ProgramId); 284 | glUseProgram(ProgramId); 285 | 286 | ErrorCheckValue = glGetError(); 287 | if (ErrorCheckValue != GL_NO_ERROR) 288 | { 289 | fprintf( 290 | stderr, 291 | "ERROR: Could not create the shaders: %s \n", 292 | gluErrorString(ErrorCheckValue) 293 | ); 294 | 295 | exit(-1); 296 | } 297 | } 298 | 299 | void DestroyShaders(void) 300 | { 301 | GLenum ErrorCheckValue = glGetError(); 302 | 303 | glUseProgram(0); 304 | 305 | glDetachShader(ProgramId, VertexShaderId); 306 | glDetachShader(ProgramId, FragmentShaderId); 307 | 308 | glDeleteShader(FragmentShaderId); 309 | glDeleteShader(VertexShaderId); 310 | 311 | glDeleteProgram(ProgramId); 312 | 313 | ErrorCheckValue = glGetError(); 314 | if (ErrorCheckValue != GL_NO_ERROR) 315 | { 316 | fprintf( 317 | stderr, 318 | "ERROR: Could not destroy the shaders: %s \n", 319 | gluErrorString(ErrorCheckValue) 320 | ); 321 | 322 | exit(-1); 323 | } 324 | } -------------------------------------------------------------------------------- /chapter-2/compatibility/chapter.2.3.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #define WINDOW_TITLE_PREFIX "Chapter 2" 7 | 8 | int 9 | CurrentWidth = 800, 10 | CurrentHeight = 600, 11 | WindowHandle = 0; 12 | 13 | unsigned FrameCount = 0; 14 | 15 | GLuint 16 | VertexShaderId, 17 | FragmentShaderId, 18 | ProgramId, 19 | VaoId, 20 | VboId, 21 | ColorBufferId; 22 | 23 | const GLchar* VertexShader = 24 | { 25 | "#version 330\n"\ 26 | 27 | "layout(location=0) in vec4 in_Position;\n"\ 28 | "layout(location=1) in vec4 in_Color;\n"\ 29 | "out vec4 ex_Color;\n"\ 30 | 31 | "void main(void)\n"\ 32 | "{\n"\ 33 | " gl_Position = in_Position;\n"\ 34 | " ex_Color = in_Color;\n"\ 35 | "}\n" 36 | }; 37 | 38 | const GLchar* FragmentShader = 39 | { 40 | "#version 330\n"\ 41 | 42 | "in vec4 ex_Color;\n"\ 43 | "out vec4 out_Color;\n"\ 44 | 45 | "void main(void)\n"\ 46 | "{\n"\ 47 | " out_Color = ex_Color;\n"\ 48 | "}\n" 49 | }; 50 | 51 | void Initialize(int, char*[]); 52 | void InitWindow(int, char*[]); 53 | void ResizeFunction(int, int); 54 | void RenderFunction(void); 55 | void TimerFunction(int); 56 | void IdleFunction(void); 57 | void Cleanup(void); 58 | void CreateVBO(void); 59 | void DestroyVBO(void); 60 | void CreateShaders(void); 61 | void DestroyShaders(void); 62 | 63 | int main(int argc, char* argv[]) 64 | { 65 | Initialize(argc, argv); 66 | 67 | glutMainLoop(); 68 | 69 | exit(EXIT_SUCCESS); 70 | } 71 | 72 | void Initialize(int argc, char* argv[]) 73 | { 74 | GLenum GlewInitResult; 75 | 76 | glewExperimental = GL_TRUE; 77 | InitWindow(argc, argv); 78 | 79 | GlewInitResult = glewInit(); 80 | 81 | if (GLEW_OK != GlewInitResult) { 82 | fprintf( 83 | stderr, 84 | "ERROR: %s\n", 85 | glewGetErrorString(GlewInitResult) 86 | ); 87 | exit(EXIT_FAILURE); 88 | } 89 | 90 | fprintf( 91 | stdout, 92 | "INFO: OpenGL Version: %s\n", 93 | glGetString(GL_VERSION) 94 | ); 95 | 96 | CreateShaders(); 97 | CreateVBO(); 98 | 99 | glClearColor(0.0f, 0.0f, 0.0f, 0.0f); 100 | } 101 | 102 | void InitWindow(int argc, char* argv[]) 103 | { 104 | glutInit(&argc, argv); 105 | 106 | glutInitContextVersion(3, 3); 107 | glutInitContextFlags(GLUT_FORWARD_COMPATIBLE); 108 | glutInitContextProfile(GLUT_CORE_PROFILE); 109 | 110 | glutSetOption( 111 | GLUT_ACTION_ON_WINDOW_CLOSE, 112 | GLUT_ACTION_GLUTMAINLOOP_RETURNS 113 | ); 114 | 115 | glutInitWindowSize(CurrentWidth, CurrentHeight); 116 | 117 | glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA); 118 | 119 | WindowHandle = glutCreateWindow(WINDOW_TITLE_PREFIX); 120 | 121 | if(WindowHandle < 1) { 122 | fprintf( 123 | stderr, 124 | "ERROR: Could not create a new rendering window.\n" 125 | ); 126 | exit(EXIT_FAILURE); 127 | } 128 | 129 | glutReshapeFunc(ResizeFunction); 130 | glutDisplayFunc(RenderFunction); 131 | glutIdleFunc(IdleFunction); 132 | glutTimerFunc(0, TimerFunction, 0); 133 | glutCloseFunc(Cleanup); 134 | } 135 | 136 | void ResizeFunction(int Width, int Height) 137 | { 138 | CurrentWidth = Width; 139 | CurrentHeight = Height; 140 | glViewport(0, 0, CurrentWidth, CurrentHeight); 141 | } 142 | 143 | void RenderFunction(void) 144 | { 145 | ++FrameCount; 146 | 147 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 148 | 149 | glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 150 | 151 | glutSwapBuffers(); 152 | } 153 | 154 | void IdleFunction(void) 155 | { 156 | glutPostRedisplay(); 157 | } 158 | 159 | void TimerFunction(int Value) 160 | { 161 | if (0 != Value) { 162 | char* TempString = (char*) 163 | malloc(512 + strlen(WINDOW_TITLE_PREFIX)); 164 | 165 | sprintf( 166 | TempString, 167 | "%s: %d Frames Per Second @ %d x %d", 168 | WINDOW_TITLE_PREFIX, 169 | FrameCount * 4, 170 | CurrentWidth, 171 | CurrentHeight 172 | ); 173 | 174 | glutSetWindowTitle(TempString); 175 | free(TempString); 176 | } 177 | 178 | FrameCount = 0; 179 | glutTimerFunc(250, TimerFunction, 1); 180 | } 181 | 182 | void Cleanup(void) 183 | { 184 | DestroyShaders(); 185 | DestroyVBO(); 186 | } 187 | 188 | void CreateVBO(void) 189 | { 190 | GLfloat Vertices[] = { 191 | -0.8f, 0.8f, 0.0f, 1.0f, 192 | 0.8f, 0.8f, 0.0f, 1.0f, 193 | -0.8f, -0.8f, 0.0f, 1.0f, 194 | 0.8f, -0.8f, 0.0f, 1.0f 195 | }; 196 | 197 | GLfloat Colors[] = { 198 | 1.0f, 0.0f, 0.0f, 1.0f, 199 | 0.0f, 1.0f, 0.0f, 1.0f, 200 | 0.0f, 0.0f, 1.0f, 1.0f, 201 | 1.0f, 1.0f, 1.0f, 1.0f 202 | }; 203 | 204 | GLenum ErrorCheckValue = glGetError(); 205 | 206 | glGenVertexArrays(1, &VaoId); 207 | glBindVertexArray(VaoId); 208 | 209 | glGenBuffers(1, &VboId); 210 | glBindBuffer(GL_ARRAY_BUFFER, VboId); 211 | glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices), Vertices, GL_STATIC_DRAW); 212 | glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0); 213 | glEnableVertexAttribArray(0); 214 | 215 | glGenBuffers(1, &ColorBufferId); 216 | glBindBuffer(GL_ARRAY_BUFFER, ColorBufferId); 217 | glBufferData(GL_ARRAY_BUFFER, sizeof(Colors), Colors, GL_STATIC_DRAW); 218 | glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, 0); 219 | glEnableVertexAttribArray(1); 220 | 221 | ErrorCheckValue = glGetError(); 222 | if (ErrorCheckValue != GL_NO_ERROR) 223 | { 224 | fprintf( 225 | stderr, 226 | "ERROR: Could not create a VBO: %s \n", 227 | gluErrorString(ErrorCheckValue) 228 | ); 229 | 230 | exit(-1); 231 | } 232 | } 233 | 234 | void DestroyVBO(void) 235 | { 236 | GLenum ErrorCheckValue = glGetError(); 237 | 238 | glDisableVertexAttribArray(1); 239 | glDisableVertexAttribArray(0); 240 | 241 | glBindBuffer(GL_ARRAY_BUFFER, 0); 242 | 243 | glDeleteBuffers(1, &ColorBufferId); 244 | glDeleteBuffers(1, &VboId); 245 | 246 | glBindVertexArray(0); 247 | glDeleteVertexArrays(1, &VaoId); 248 | 249 | ErrorCheckValue = glGetError(); 250 | if (ErrorCheckValue != GL_NO_ERROR) 251 | { 252 | fprintf( 253 | stderr, 254 | "ERROR: Could not destroy the VBO: %s \n", 255 | gluErrorString(ErrorCheckValue) 256 | ); 257 | 258 | exit(-1); 259 | } 260 | } 261 | 262 | void CreateShaders(void) 263 | { 264 | GLenum ErrorCheckValue = glGetError(); 265 | 266 | VertexShaderId = glCreateShader(GL_VERTEX_SHADER); 267 | glShaderSource(VertexShaderId, 1, &VertexShader, NULL); 268 | glCompileShader(VertexShaderId); 269 | 270 | FragmentShaderId = glCreateShader(GL_FRAGMENT_SHADER); 271 | glShaderSource(FragmentShaderId, 1, &FragmentShader, NULL); 272 | glCompileShader(FragmentShaderId); 273 | 274 | ProgramId = glCreateProgram(); 275 | glAttachShader(ProgramId, VertexShaderId); 276 | glAttachShader(ProgramId, FragmentShaderId); 277 | glLinkProgram(ProgramId); 278 | glUseProgram(ProgramId); 279 | 280 | ErrorCheckValue = glGetError(); 281 | if (ErrorCheckValue != GL_NO_ERROR) 282 | { 283 | fprintf( 284 | stderr, 285 | "ERROR: Could not create the shaders: %s \n", 286 | gluErrorString(ErrorCheckValue) 287 | ); 288 | 289 | exit(-1); 290 | } 291 | } 292 | 293 | void DestroyShaders(void) 294 | { 295 | GLenum ErrorCheckValue = glGetError(); 296 | 297 | glUseProgram(0); 298 | 299 | glDetachShader(ProgramId, VertexShaderId); 300 | glDetachShader(ProgramId, FragmentShaderId); 301 | 302 | glDeleteShader(FragmentShaderId); 303 | glDeleteShader(VertexShaderId); 304 | 305 | glDeleteProgram(ProgramId); 306 | 307 | ErrorCheckValue = glGetError(); 308 | if (ErrorCheckValue != GL_NO_ERROR) 309 | { 310 | fprintf( 311 | stderr, 312 | "ERROR: Could not destroy the shaders: %s \n", 313 | gluErrorString(ErrorCheckValue) 314 | ); 315 | 316 | exit(-1); 317 | } 318 | } 319 | -------------------------------------------------------------------------------- /chapter-2/compatibility/chapter.2.4.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #define WINDOW_TITLE_PREFIX "Chapter 2" 7 | 8 | typedef struct 9 | { 10 | float XYZW[4]; 11 | float RGBA[4]; 12 | } Vertex; 13 | 14 | int 15 | CurrentWidth = 800, 16 | CurrentHeight = 600, 17 | WindowHandle = 0; 18 | 19 | unsigned FrameCount = 0; 20 | 21 | GLuint 22 | VertexShaderId, 23 | FragmentShaderId, 24 | ProgramId, 25 | VaoId, 26 | BufferId; 27 | 28 | const GLchar* VertexShader = 29 | { 30 | "#version 330\n"\ 31 | 32 | "layout(location=0) in vec4 in_Position;\n"\ 33 | "layout(location=1) in vec4 in_Color;\n"\ 34 | "out vec4 ex_Color;\n"\ 35 | 36 | "void main(void)\n"\ 37 | "{\n"\ 38 | " gl_Position = in_Position;\n"\ 39 | " ex_Color = in_Color;\n"\ 40 | "}\n" 41 | }; 42 | 43 | const GLchar* FragmentShader = 44 | { 45 | "#version 330\n"\ 46 | 47 | "in vec4 ex_Color;\n"\ 48 | "out vec4 out_Color;\n"\ 49 | 50 | "void main(void)\n"\ 51 | "{\n"\ 52 | " out_Color = ex_Color;\n"\ 53 | "}\n" 54 | }; 55 | 56 | void Initialize(int, char*[]); 57 | void InitWindow(int, char*[]); 58 | void ResizeFunction(int, int); 59 | void RenderFunction(void); 60 | void TimerFunction(int); 61 | void IdleFunction(void); 62 | void Cleanup(void); 63 | void CreateVBO(void); 64 | void DestroyVBO(void); 65 | void CreateShaders(void); 66 | void DestroyShaders(void); 67 | 68 | int main(int argc, char* argv[]) 69 | { 70 | Initialize(argc, argv); 71 | 72 | glutMainLoop(); 73 | 74 | exit(EXIT_SUCCESS); 75 | } 76 | 77 | void Initialize(int argc, char* argv[]) 78 | { 79 | GLenum GlewInitResult; 80 | 81 | InitWindow(argc, argv); 82 | 83 | glewExperimental = GL_TRUE; 84 | GlewInitResult = glewInit(); 85 | 86 | if (GLEW_OK != GlewInitResult) { 87 | fprintf( 88 | stderr, 89 | "ERROR: %s\n", 90 | glewGetErrorString(GlewInitResult) 91 | ); 92 | exit(EXIT_FAILURE); 93 | } 94 | 95 | fprintf( 96 | stdout, 97 | "INFO: OpenGL Version: %s\n", 98 | glGetString(GL_VERSION) 99 | ); 100 | 101 | CreateShaders(); 102 | CreateVBO(); 103 | 104 | glClearColor(0.0f, 0.0f, 0.0f, 0.0f); 105 | } 106 | 107 | void InitWindow(int argc, char* argv[]) 108 | { 109 | glutInit(&argc, argv); 110 | 111 | glutInitContextVersion(3, 3); 112 | glutInitContextFlags(GLUT_FORWARD_COMPATIBLE); 113 | glutInitContextProfile(GLUT_CORE_PROFILE); 114 | 115 | glutSetOption( 116 | GLUT_ACTION_ON_WINDOW_CLOSE, 117 | GLUT_ACTION_GLUTMAINLOOP_RETURNS 118 | ); 119 | 120 | glutInitWindowSize(CurrentWidth, CurrentHeight); 121 | 122 | glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA); 123 | 124 | WindowHandle = glutCreateWindow(WINDOW_TITLE_PREFIX); 125 | 126 | if(WindowHandle < 1) { 127 | fprintf( 128 | stderr, 129 | "ERROR: Could not create a new rendering window.\n" 130 | ); 131 | exit(EXIT_FAILURE); 132 | } 133 | 134 | glutReshapeFunc(ResizeFunction); 135 | glutDisplayFunc(RenderFunction); 136 | glutIdleFunc(IdleFunction); 137 | glutTimerFunc(0, TimerFunction, 0); 138 | glutCloseFunc(Cleanup); 139 | } 140 | 141 | void ResizeFunction(int Width, int Height) 142 | { 143 | CurrentWidth = Width; 144 | CurrentHeight = Height; 145 | glViewport(0, 0, CurrentWidth, CurrentHeight); 146 | } 147 | 148 | void RenderFunction(void) 149 | { 150 | ++FrameCount; 151 | 152 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 153 | 154 | glDrawArrays(GL_TRIANGLES, 0, 3); 155 | 156 | glutSwapBuffers(); 157 | } 158 | 159 | void IdleFunction(void) 160 | { 161 | glutPostRedisplay(); 162 | } 163 | 164 | void TimerFunction(int Value) 165 | { 166 | if (0 != Value) { 167 | char* TempString = (char*) 168 | malloc(512 + strlen(WINDOW_TITLE_PREFIX)); 169 | 170 | sprintf( 171 | TempString, 172 | "%s: %d Frames Per Second @ %d x %d", 173 | WINDOW_TITLE_PREFIX, 174 | FrameCount * 4, 175 | CurrentWidth, 176 | CurrentHeight 177 | ); 178 | 179 | glutSetWindowTitle(TempString); 180 | free(TempString); 181 | } 182 | 183 | FrameCount = 0; 184 | glutTimerFunc(250, TimerFunction, 1); 185 | } 186 | 187 | void Cleanup(void) 188 | { 189 | DestroyShaders(); 190 | DestroyVBO(); 191 | } 192 | 193 | void CreateVBO(void) 194 | { 195 | Vertex Vertices[] = 196 | { 197 | { { -0.8f, -0.8f, 0.0f, 1.0f }, { 1.0f, 0.0f, 0.0f, 1.0f } }, 198 | { { 0.0f, 0.8f, 0.0f, 1.0f }, { 0.0f, 1.0f, 0.0f, 1.0f } }, 199 | { { 0.8f, -0.8f, 0.0f, 1.0f }, { 0.0f, 0.0f, 1.0f, 1.0f } } 200 | }; 201 | 202 | GLenum ErrorCheckValue = glGetError(); 203 | const size_t BufferSize = sizeof(Vertices); 204 | const size_t VertexSize = sizeof(Vertices[0]); 205 | const size_t RgbOffset = sizeof(Vertices[0].XYZW); 206 | 207 | glGenVertexArrays(1, &VaoId); 208 | glBindVertexArray(VaoId); 209 | 210 | glGenBuffers(1, &BufferId); 211 | glBindBuffer(GL_ARRAY_BUFFER, BufferId); 212 | glBufferData(GL_ARRAY_BUFFER, BufferSize, Vertices, GL_STATIC_DRAW); 213 | 214 | glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, VertexSize, 0); 215 | glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, VertexSize, (GLvoid*)RgbOffset); 216 | 217 | glEnableVertexAttribArray(0); 218 | glEnableVertexAttribArray(1); 219 | 220 | ErrorCheckValue = glGetError(); 221 | if (ErrorCheckValue != GL_NO_ERROR) 222 | { 223 | fprintf( 224 | stderr, 225 | "ERROR: Could not create a VBO: %s \n", 226 | gluErrorString(ErrorCheckValue) 227 | ); 228 | 229 | exit(-1); 230 | } 231 | } 232 | 233 | void DestroyVBO(void) 234 | { 235 | GLenum ErrorCheckValue = glGetError(); 236 | 237 | glDisableVertexAttribArray(1); 238 | glDisableVertexAttribArray(0); 239 | 240 | glBindBuffer(GL_ARRAY_BUFFER, 0); 241 | glDeleteBuffers(1, &BufferId); 242 | 243 | glBindVertexArray(0); 244 | glDeleteVertexArrays(1, &VaoId); 245 | 246 | ErrorCheckValue = glGetError(); 247 | if (ErrorCheckValue != GL_NO_ERROR) 248 | { 249 | fprintf( 250 | stderr, 251 | "ERROR: Could not destroy the VBO: %s \n", 252 | gluErrorString(ErrorCheckValue) 253 | ); 254 | 255 | exit(-1); 256 | } 257 | } 258 | 259 | void CreateShaders(void) 260 | { 261 | GLenum ErrorCheckValue = glGetError(); 262 | 263 | VertexShaderId = glCreateShader(GL_VERTEX_SHADER); 264 | glShaderSource(VertexShaderId, 1, &VertexShader, NULL); 265 | glCompileShader(VertexShaderId); 266 | 267 | FragmentShaderId = glCreateShader(GL_FRAGMENT_SHADER); 268 | glShaderSource(FragmentShaderId, 1, &FragmentShader, NULL); 269 | glCompileShader(FragmentShaderId); 270 | 271 | ProgramId = glCreateProgram(); 272 | glAttachShader(ProgramId, VertexShaderId); 273 | glAttachShader(ProgramId, FragmentShaderId); 274 | glLinkProgram(ProgramId); 275 | glUseProgram(ProgramId); 276 | 277 | ErrorCheckValue = glGetError(); 278 | if (ErrorCheckValue != GL_NO_ERROR) 279 | { 280 | fprintf( 281 | stderr, 282 | "ERROR: Could not create the shaders: %s \n", 283 | gluErrorString(ErrorCheckValue) 284 | ); 285 | 286 | exit(-1); 287 | } 288 | } 289 | 290 | void DestroyShaders(void) 291 | { 292 | GLenum ErrorCheckValue = glGetError(); 293 | 294 | glUseProgram(0); 295 | 296 | glDetachShader(ProgramId, VertexShaderId); 297 | glDetachShader(ProgramId, FragmentShaderId); 298 | 299 | glDeleteShader(FragmentShaderId); 300 | glDeleteShader(VertexShaderId); 301 | 302 | glDeleteProgram(ProgramId); 303 | 304 | ErrorCheckValue = glGetError(); 305 | if (ErrorCheckValue != GL_NO_ERROR) 306 | { 307 | fprintf( 308 | stderr, 309 | "ERROR: Could not destroy the shaders: %s \n", 310 | gluErrorString(ErrorCheckValue) 311 | ); 312 | 313 | exit(-1); 314 | } 315 | } -------------------------------------------------------------------------------- /chapter-3/chapter.3.0.1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #define WINDOW_TITLE_PREFIX "Chapter 3" 7 | 8 | typedef struct 9 | { 10 | float XYZW[4]; 11 | float RGBA[4]; 12 | } Vertex; 13 | 14 | int 15 | CurrentWidth = 600, 16 | CurrentHeight = 600, 17 | WindowHandle = 0; 18 | 19 | unsigned FrameCount = 0; 20 | 21 | GLuint 22 | VertexShaderId, 23 | FragmentShaderId, 24 | ProgramId, 25 | VaoId, 26 | BufferId; 27 | 28 | const GLchar* VertexShader = 29 | { 30 | "#version 400\n"\ 31 | 32 | "layout(location=0) in vec4 in_Position;\n"\ 33 | "layout(location=1) in vec4 in_Color;\n"\ 34 | "out vec4 ex_Color;\n"\ 35 | 36 | "void main(void)\n"\ 37 | "{\n"\ 38 | " gl_Position = in_Position;\n"\ 39 | " ex_Color = in_Color;\n"\ 40 | "}\n" 41 | }; 42 | 43 | const GLchar* FragmentShader = 44 | { 45 | "#version 400\n"\ 46 | 47 | "in vec4 ex_Color;\n"\ 48 | "out vec4 out_Color;\n"\ 49 | 50 | "void main(void)\n"\ 51 | "{\n"\ 52 | " out_Color = ex_Color;\n"\ 53 | "}\n" 54 | }; 55 | 56 | void Initialize(int, char*[]); 57 | void InitWindow(int, char*[]); 58 | void ResizeFunction(int, int); 59 | void RenderFunction(void); 60 | void TimerFunction(int); 61 | void IdleFunction(void); 62 | void Cleanup(void); 63 | void CreateVBO(void); 64 | void DestroyVBO(void); 65 | void CreateShaders(void); 66 | void DestroyShaders(void); 67 | 68 | int main(int argc, char* argv[]) 69 | { 70 | Initialize(argc, argv); 71 | 72 | glutMainLoop(); 73 | 74 | exit(EXIT_SUCCESS); 75 | } 76 | 77 | void Initialize(int argc, char* argv[]) 78 | { 79 | GLenum GlewInitResult; 80 | 81 | InitWindow(argc, argv); 82 | 83 | glewExperimental = GL_TRUE; 84 | GlewInitResult = glewInit(); 85 | 86 | if (GLEW_OK != GlewInitResult) { 87 | fprintf( 88 | stderr, 89 | "ERROR: %s\n", 90 | glewGetErrorString(GlewInitResult) 91 | ); 92 | exit(EXIT_FAILURE); 93 | } 94 | 95 | fprintf( 96 | stdout, 97 | "INFO: OpenGL Version: %s\n", 98 | glGetString(GL_VERSION) 99 | ); 100 | 101 | CreateShaders(); 102 | CreateVBO(); 103 | 104 | glClearColor(0.0f, 0.0f, 0.0f, 0.0f); 105 | } 106 | 107 | void InitWindow(int argc, char* argv[]) 108 | { 109 | glutInit(&argc, argv); 110 | 111 | glutInitContextVersion(4, 0); 112 | glutInitContextFlags(GLUT_FORWARD_COMPATIBLE); 113 | glutInitContextProfile(GLUT_CORE_PROFILE); 114 | 115 | glutSetOption( 116 | GLUT_ACTION_ON_WINDOW_CLOSE, 117 | GLUT_ACTION_GLUTMAINLOOP_RETURNS 118 | ); 119 | 120 | glutInitWindowSize(CurrentWidth, CurrentHeight); 121 | 122 | glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA); 123 | 124 | WindowHandle = glutCreateWindow(WINDOW_TITLE_PREFIX); 125 | 126 | if(WindowHandle < 1) { 127 | fprintf( 128 | stderr, 129 | "ERROR: Could not create a new rendering window.\n" 130 | ); 131 | exit(EXIT_FAILURE); 132 | } 133 | 134 | glutReshapeFunc(ResizeFunction); 135 | glutDisplayFunc(RenderFunction); 136 | glutIdleFunc(IdleFunction); 137 | glutTimerFunc(0, TimerFunction, 0); 138 | glutCloseFunc(Cleanup); 139 | } 140 | 141 | void ResizeFunction(int Width, int Height) 142 | { 143 | CurrentWidth = Width; 144 | CurrentHeight = Height; 145 | glViewport(0, 0, CurrentWidth, CurrentHeight); 146 | } 147 | 148 | void RenderFunction(void) 149 | { 150 | ++FrameCount; 151 | 152 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 153 | 154 | glDrawArrays(GL_TRIANGLES, 0, 48); 155 | 156 | glutSwapBuffers(); 157 | } 158 | 159 | void IdleFunction(void) 160 | { 161 | glutPostRedisplay(); 162 | } 163 | 164 | void TimerFunction(int Value) 165 | { 166 | if (0 != Value) { 167 | char* TempString = (char*) 168 | malloc(512 + strlen(WINDOW_TITLE_PREFIX)); 169 | 170 | sprintf( 171 | TempString, 172 | "%s: %d Frames Per Second @ %d x %d", 173 | WINDOW_TITLE_PREFIX, 174 | FrameCount * 4, 175 | CurrentWidth, 176 | CurrentHeight 177 | ); 178 | 179 | glutSetWindowTitle(TempString); 180 | free(TempString); 181 | } 182 | 183 | FrameCount = 0; 184 | glutTimerFunc(250, TimerFunction, 1); 185 | } 186 | 187 | void Cleanup(void) 188 | { 189 | DestroyShaders(); 190 | DestroyVBO(); 191 | } 192 | 193 | void CreateVBO(void) 194 | { 195 | Vertex Vertices[] = 196 | { 197 | // Top 198 | { { 0.0f, 0.0f, 0.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, // 0 199 | { { -0.2f, 0.8f, 0.0f, 1.0f }, { 0.0f, 1.0f, 0.0f, 1.0f } }, // 1 200 | { { 0.0f, 0.8f, 0.0f, 1.0f }, { 0.0f, 1.0f, 1.0f, 1.0f } }, //3 201 | 202 | { { 0.0f, 0.0f, 0.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, // 0 203 | { { 0.0f, 0.8f, 0.0f, 1.0f }, { 0.0f, 1.0f, 1.0f, 1.0f } }, //3 204 | { { 0.2f, 0.8f, 0.0f, 1.0f }, { 0.0f, 0.0f, 1.0f, 1.0f } }, // 2 205 | 206 | { { 0.0f, 0.8f, 0.0f, 1.0f }, { 0.0f, 1.0f, 1.0f, 1.0f } }, //3 207 | { { -0.2f, 0.8f, 0.0f, 1.0f }, { 0.0f, 1.0f, 0.0f, 1.0f } }, // 1 208 | { { 0.0f, 1.0f, 0.0f, 1.0f }, { 1.0f, 0.0f, 0.0f, 1.0f } }, // 4 209 | 210 | { { 0.0f, 0.8f, 0.0f, 1.0f }, { 0.0f, 1.0f, 1.0f, 1.0f } }, //3 211 | { { 0.0f, 1.0f, 0.0f, 1.0f }, { 1.0f, 0.0f, 0.0f, 1.0f } }, // 4 212 | { { 0.2f, 0.8f, 0.0f, 1.0f }, { 0.0f, 0.0f, 1.0f, 1.0f } }, // 2 213 | 214 | // Bottom 215 | { { 0.0f, 0.0f, 0.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, // 0 216 | { { 0.0f, -0.8f, 0.0f, 1.0f }, { 0.0f, 1.0f, 1.0f, 1.0f } }, //7 217 | { { -0.2f, -0.8f, 0.0f, 1.0f }, { 0.0f, 1.0f, 0.0f, 1.0f } }, // 5 218 | 219 | { { 0.0f, 0.0f, 0.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, // 0 220 | { { 0.0f, -0.8f, 0.0f, 1.0f }, { 0.0f, 1.0f, 1.0f, 1.0f } }, //7 221 | { { 0.2f, -0.8f, 0.0f, 1.0f }, { 0.0f, 0.0f, 1.0f, 1.0f } }, // 6 222 | 223 | { { 0.0f, -0.8f, 0.0f, 1.0f }, { 0.0f, 1.0f, 1.0f, 1.0f } }, //7 224 | { { -0.2f, -0.8f, 0.0f, 1.0f }, { 0.0f, 1.0f, 0.0f, 1.0f } }, // 5 225 | { { 0.0f, -1.0f, 0.0f, 1.0f }, { 1.0f, 0.0f, 0.0f, 1.0f } }, // 8 226 | 227 | { { 0.0f, -0.8f, 0.0f, 1.0f }, { 0.0f, 1.0f, 1.0f, 1.0f } }, //7 228 | { { 0.2f, -0.8f, 0.0f, 1.0f }, { 0.0f, 0.0f, 1.0f, 1.0f } }, // 6 229 | { { 0.0f, -1.0f, 0.0f, 1.0f }, { 1.0f, 0.0f, 0.0f, 1.0f } }, // 8 230 | 231 | // Left 232 | { { 0.0f, 0.0f, 0.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, // 0 233 | { { -0.8f, -0.2f, 0.0f, 1.0f }, { 0.0f, 1.0f, 0.0f, 1.0f } }, // 9 234 | { { -0.8f, 0.0f, 0.0f, 1.0f }, { 0.0f, 1.0f, 1.0f, 1.0f } }, //11 235 | 236 | { { 0.0f, 0.0f, 0.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, // 0 237 | { { -0.8f, 0.0f, 0.0f, 1.0f }, { 0.0f, 1.0f, 1.0f, 1.0f } }, //11 238 | { { -0.8f, 0.2f, 0.0f, 1.0f }, { 0.0f, 0.0f, 1.0f, 1.0f } }, // 10 239 | 240 | { { -0.8f, 0.0f, 0.0f, 1.0f }, { 0.0f, 1.0f, 1.0f, 1.0f } }, //11 241 | { { -0.8f, 0.2f, 0.0f, 1.0f }, { 0.0f, 0.0f, 1.0f, 1.0f } }, // 10 242 | { { -1.0f, 0.0f, 0.0f, 1.0f }, { 1.0f, 0.0f, 0.0f, 1.0f } }, // 12 243 | 244 | { { -0.8f, 0.0f, 0.0f, 1.0f }, { 0.0f, 1.0f, 1.0f, 1.0f } }, //11 245 | { { -1.0f, 0.0f, 0.0f, 1.0f }, { 1.0f, 0.0f, 0.0f, 1.0f } }, // 12 246 | { { -0.8f, -0.2f, 0.0f, 1.0f }, { 0.0f, 1.0f, 0.0f, 1.0f } }, // 9 247 | 248 | // Right 249 | { { 0.0f, 0.0f, 0.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, // 0 250 | { { 0.8f, 0.2f, 0.0f, 1.0f }, { 0.0f, 0.0f, 1.0f, 1.0f } }, // 14 251 | { { 0.8f, 0.0f, 0.0f, 1.0f }, { 0.0f, 1.0f, 1.0f, 1.0f } }, //15 252 | 253 | { { 0.0f, 0.0f, 0.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, // 0 254 | { { 0.8f, 0.0f, 0.0f, 1.0f }, { 0.0f, 1.0f, 1.0f, 1.0f } }, //15 255 | { { 0.8f, -0.2f, 0.0f, 1.0f }, { 0.0f, 1.0f, 0.0f, 1.0f } }, // 13 256 | 257 | { { 0.8f, 0.0f, 0.0f, 1.0f }, { 0.0f, 1.0f, 1.0f, 1.0f } }, //15 258 | { { 0.8f, -0.2f, 0.0f, 1.0f }, { 0.0f, 1.0f, 0.0f, 1.0f } }, // 13 259 | { { 1.0f, 0.0f, 0.0f, 1.0f }, { 1.0f, 0.0f, 0.0f, 1.0f } }, // 16 260 | 261 | { { 0.8f, 0.2f, 0.0f, 1.0f }, { 0.0f, 0.0f, 1.0f, 1.0f } }, // 14 262 | { { 0.8f, 0.0f, 0.0f, 1.0f }, { 0.0f, 1.0f, 1.0f, 1.0f } }, //15 263 | { { 1.0f, 0.0f, 0.0f, 1.0f }, { 1.0f, 0.0f, 0.0f, 1.0f } } // 16 264 | }; 265 | 266 | GLenum ErrorCheckValue = glGetError(); 267 | const size_t BufferSize = sizeof(Vertices); 268 | const size_t VertexSize = sizeof(Vertices[0]); 269 | const size_t RgbOffset = sizeof(Vertices[0].XYZW); 270 | 271 | glGenVertexArrays(1, &VaoId); 272 | glBindVertexArray(VaoId); 273 | 274 | glGenBuffers(1, &BufferId); 275 | glBindBuffer(GL_ARRAY_BUFFER, BufferId); 276 | glBufferData(GL_ARRAY_BUFFER, BufferSize, Vertices, GL_STATIC_DRAW); 277 | 278 | glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, VertexSize, 0); 279 | glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, VertexSize, (GLvoid*)RgbOffset); 280 | 281 | glEnableVertexAttribArray(0); 282 | glEnableVertexAttribArray(1); 283 | 284 | ErrorCheckValue = glGetError(); 285 | if (ErrorCheckValue != GL_NO_ERROR) 286 | { 287 | fprintf( 288 | stderr, 289 | "ERROR: Could not create a VBO: %s \n", 290 | gluErrorString(ErrorCheckValue) 291 | ); 292 | 293 | exit(-1); 294 | } 295 | } 296 | 297 | void DestroyVBO(void) 298 | { 299 | GLenum ErrorCheckValue = glGetError(); 300 | 301 | glDisableVertexAttribArray(1); 302 | glDisableVertexAttribArray(0); 303 | 304 | glBindBuffer(GL_ARRAY_BUFFER, 0); 305 | glDeleteBuffers(1, &BufferId); 306 | 307 | glBindVertexArray(0); 308 | glDeleteVertexArrays(1, &VaoId); 309 | 310 | ErrorCheckValue = glGetError(); 311 | if (ErrorCheckValue != GL_NO_ERROR) 312 | { 313 | fprintf( 314 | stderr, 315 | "ERROR: Could not destroy the VBO: %s \n", 316 | gluErrorString(ErrorCheckValue) 317 | ); 318 | 319 | exit(-1); 320 | } 321 | } 322 | 323 | void CreateShaders(void) 324 | { 325 | GLenum ErrorCheckValue = glGetError(); 326 | 327 | VertexShaderId = glCreateShader(GL_VERTEX_SHADER); 328 | glShaderSource(VertexShaderId, 1, &VertexShader, NULL); 329 | glCompileShader(VertexShaderId); 330 | 331 | FragmentShaderId = glCreateShader(GL_FRAGMENT_SHADER); 332 | glShaderSource(FragmentShaderId, 1, &FragmentShader, NULL); 333 | glCompileShader(FragmentShaderId); 334 | 335 | ProgramId = glCreateProgram(); 336 | glAttachShader(ProgramId, VertexShaderId); 337 | glAttachShader(ProgramId, FragmentShaderId); 338 | glLinkProgram(ProgramId); 339 | glUseProgram(ProgramId); 340 | 341 | ErrorCheckValue = glGetError(); 342 | if (ErrorCheckValue != GL_NO_ERROR) 343 | { 344 | fprintf( 345 | stderr, 346 | "ERROR: Could not create the shaders: %s \n", 347 | gluErrorString(ErrorCheckValue) 348 | ); 349 | 350 | exit(-1); 351 | } 352 | } 353 | 354 | void DestroyShaders(void) 355 | { 356 | GLenum ErrorCheckValue = glGetError(); 357 | 358 | glUseProgram(0); 359 | 360 | glDetachShader(ProgramId, VertexShaderId); 361 | glDetachShader(ProgramId, FragmentShaderId); 362 | 363 | glDeleteShader(FragmentShaderId); 364 | glDeleteShader(VertexShaderId); 365 | 366 | glDeleteProgram(ProgramId); 367 | 368 | ErrorCheckValue = glGetError(); 369 | if (ErrorCheckValue != GL_NO_ERROR) 370 | { 371 | fprintf( 372 | stderr, 373 | "ERROR: Could not destroy the shaders: %s \n", 374 | gluErrorString(ErrorCheckValue) 375 | ); 376 | 377 | exit(-1); 378 | } 379 | } -------------------------------------------------------------------------------- /chapter-3/chapter.3.0.2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #define WINDOW_TITLE_PREFIX "Chapter 3" 7 | 8 | typedef struct 9 | { 10 | float XYZW[4]; 11 | float RGBA[4]; 12 | } Vertex; 13 | 14 | int 15 | CurrentWidth = 600, 16 | CurrentHeight = 600, 17 | WindowHandle = 0; 18 | 19 | unsigned FrameCount = 0; 20 | 21 | GLuint 22 | VertexShaderId, 23 | FragmentShaderId, 24 | ProgramId, 25 | VaoId, 26 | BufferId; 27 | 28 | const GLchar* VertexShader = 29 | { 30 | "#version 400\n"\ 31 | 32 | "layout(location=0) in vec4 in_Position;\n"\ 33 | "layout(location=1) in vec4 in_Color;\n"\ 34 | "out vec4 ex_Color;\n"\ 35 | 36 | "void main(void)\n"\ 37 | "{\n"\ 38 | " gl_Position = in_Position;\n"\ 39 | " ex_Color = in_Color;\n"\ 40 | "}\n" 41 | }; 42 | 43 | const GLchar* FragmentShader = 44 | { 45 | "#version 400\n"\ 46 | 47 | "in vec4 ex_Color;\n"\ 48 | "out vec4 out_Color;\n"\ 49 | 50 | "void main(void)\n"\ 51 | "{\n"\ 52 | " out_Color = ex_Color;\n"\ 53 | "}\n" 54 | }; 55 | 56 | void Initialize(int, char*[]); 57 | void InitWindow(int, char*[]); 58 | void ResizeFunction(int, int); 59 | void RenderFunction(void); 60 | void TimerFunction(int); 61 | void IdleFunction(void); 62 | void Cleanup(void); 63 | void CreateVBO(void); 64 | void DestroyVBO(void); 65 | void CreateShaders(void); 66 | void DestroyShaders(void); 67 | 68 | int main(int argc, char* argv[]) 69 | { 70 | Initialize(argc, argv); 71 | 72 | glutMainLoop(); 73 | 74 | exit(EXIT_SUCCESS); 75 | } 76 | 77 | void Initialize(int argc, char* argv[]) 78 | { 79 | GLenum GlewInitResult; 80 | 81 | InitWindow(argc, argv); 82 | 83 | glewExperimental = GL_TRUE; 84 | GlewInitResult = glewInit(); 85 | 86 | if (GLEW_OK != GlewInitResult) { 87 | fprintf( 88 | stderr, 89 | "ERROR: %s\n", 90 | glewGetErrorString(GlewInitResult) 91 | ); 92 | exit(EXIT_FAILURE); 93 | } 94 | 95 | fprintf( 96 | stdout, 97 | "INFO: OpenGL Version: %s\n", 98 | glGetString(GL_VERSION) 99 | ); 100 | 101 | CreateShaders(); 102 | CreateVBO(); 103 | 104 | glClearColor(0.0f, 0.0f, 0.0f, 0.0f); 105 | } 106 | 107 | void InitWindow(int argc, char* argv[]) 108 | { 109 | glutInit(&argc, argv); 110 | 111 | glutInitContextVersion(4, 0); 112 | glutInitContextFlags(GLUT_FORWARD_COMPATIBLE); 113 | glutInitContextProfile(GLUT_CORE_PROFILE); 114 | 115 | glutSetOption( 116 | GLUT_ACTION_ON_WINDOW_CLOSE, 117 | GLUT_ACTION_GLUTMAINLOOP_RETURNS 118 | ); 119 | 120 | glutInitWindowSize(CurrentWidth, CurrentHeight); 121 | 122 | glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA); 123 | 124 | WindowHandle = glutCreateWindow(WINDOW_TITLE_PREFIX); 125 | 126 | if(WindowHandle < 1) { 127 | fprintf( 128 | stderr, 129 | "ERROR: Could not create a new rendering window.\n" 130 | ); 131 | exit(EXIT_FAILURE); 132 | } 133 | 134 | glutReshapeFunc(ResizeFunction); 135 | glutDisplayFunc(RenderFunction); 136 | glutIdleFunc(IdleFunction); 137 | glutTimerFunc(0, TimerFunction, 0); 138 | glutCloseFunc(Cleanup); 139 | } 140 | 141 | void ResizeFunction(int Width, int Height) 142 | { 143 | CurrentWidth = Width; 144 | CurrentHeight = Height; 145 | glViewport(0, 0, CurrentWidth, CurrentHeight); 146 | } 147 | 148 | void RenderFunction(void) 149 | { 150 | ++FrameCount; 151 | 152 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 153 | 154 | glDrawArrays(GL_TRIANGLE_STRIP, 0, 28); 155 | 156 | glutSwapBuffers(); 157 | } 158 | 159 | void IdleFunction(void) 160 | { 161 | glutPostRedisplay(); 162 | } 163 | 164 | void TimerFunction(int Value) 165 | { 166 | if (0 != Value) { 167 | char* TempString = (char*) 168 | malloc(512 + strlen(WINDOW_TITLE_PREFIX)); 169 | 170 | sprintf( 171 | TempString, 172 | "%s: %d Frames Per Second @ %d x %d", 173 | WINDOW_TITLE_PREFIX, 174 | FrameCount * 4, 175 | CurrentWidth, 176 | CurrentHeight 177 | ); 178 | 179 | glutSetWindowTitle(TempString); 180 | free(TempString); 181 | } 182 | 183 | FrameCount = 0; 184 | glutTimerFunc(250, TimerFunction, 1); 185 | } 186 | 187 | void Cleanup(void) 188 | { 189 | DestroyShaders(); 190 | DestroyVBO(); 191 | } 192 | 193 | void CreateVBO(void) 194 | { 195 | Vertex Vertices[] = 196 | { 197 | // Top 198 | { { 0.0f, 0.0f, 0.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, // 0 199 | { { -0.2f, 0.8f, 0.0f, 1.0f }, { 0.0f, 1.0f, 0.0f, 1.0f } }, // 1 200 | { { 0.0f, 0.8f, 0.0f, 1.0f }, { 0.0f, 1.0f, 1.0f, 1.0f } }, //3 201 | { { 0.0f, 1.0f, 0.0f, 1.0f }, { 1.0f, 0.0f, 0.0f, 1.0f } }, // 4 202 | { { 0.0f, 0.8f, 0.0f, 1.0f }, { 0.0f, 1.0f, 1.0f, 1.0f } }, //3 203 | { { 0.2f, 0.8f, 0.0f, 1.0f }, { 0.0f, 0.0f, 1.0f, 1.0f } }, // 2 204 | { { 0.0f, 0.0f, 0.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, // 0 205 | 206 | //// Bottom 207 | { { 0.0f, 0.0f, 0.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, // 0 208 | { { 0.2f, -0.8f, 0.0f, 1.0f }, { 0.0f, 0.0f, 1.0f, 1.0f } }, // 6 209 | { { 0.0f, -0.8f, 0.0f, 1.0f }, { 0.0f, 1.0f, 1.0f, 1.0f } }, //7 210 | { { 0.0f, -1.0f, 0.0f, 1.0f }, { 1.0f, 0.0f, 0.0f, 1.0f } }, // 8 211 | { { 0.0f, -0.8f, 0.0f, 1.0f }, { 0.0f, 1.0f, 1.0f, 1.0f } }, //7 212 | { { -0.2f, -0.8f, 0.0f, 1.0f }, { 0.0f, 1.0f, 0.0f, 1.0f } }, // 5 213 | { { 0.0f, 0.0f, 0.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, // 0 214 | 215 | //// Left 216 | { { 0.0f, 0.0f, 0.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, // 0 217 | { { -0.8f, -0.2f, 0.0f, 1.0f }, { 0.0f, 1.0f, 0.0f, 1.0f } }, // 9 218 | { { -0.8f, 0.0f, 0.0f, 1.0f }, { 0.0f, 1.0f, 1.0f, 1.0f } }, //11 219 | { { -1.0f, 0.0f, 0.0f, 1.0f }, { 1.0f, 0.0f, 0.0f, 1.0f } }, // 12 220 | { { -0.8f, 0.0f, 0.0f, 1.0f }, { 0.0f, 1.0f, 1.0f, 1.0f } }, //11 221 | { { -0.8f, 0.2f, 0.0f, 1.0f }, { 0.0f, 0.0f, 1.0f, 1.0f } }, // 10 222 | { { 0.0f, 0.0f, 0.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, // 0 223 | 224 | //// Right 225 | { { 0.0f, 0.0f, 0.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, // 0 226 | { { 0.8f, 0.2f, 0.0f, 1.0f }, { 0.0f, 0.0f, 1.0f, 1.0f } }, // 14 227 | { { 0.8f, 0.0f, 0.0f, 1.0f }, { 0.0f, 1.0f, 1.0f, 1.0f } }, //15 228 | { { 1.0f, 0.0f, 0.0f, 1.0f }, { 1.0f, 0.0f, 0.0f, 1.0f } }, // 16 229 | { { 0.8f, 0.0f, 0.0f, 1.0f }, { 0.0f, 1.0f, 1.0f, 1.0f } }, //15 230 | { { 0.8f, -0.2f, 0.0f, 1.0f }, { 0.0f, 1.0f, 0.0f, 1.0f } }, // 13 231 | { { 0.0f, 0.0f, 0.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, // 0 232 | }; 233 | 234 | GLenum ErrorCheckValue = glGetError(); 235 | const size_t BufferSize = sizeof(Vertices); 236 | const size_t VertexSize = sizeof(Vertices[0]); 237 | const size_t RgbOffset = sizeof(Vertices[0].XYZW); 238 | 239 | glGenVertexArrays(1, &VaoId); 240 | glBindVertexArray(VaoId); 241 | 242 | glGenBuffers(1, &BufferId); 243 | glBindBuffer(GL_ARRAY_BUFFER, BufferId); 244 | glBufferData(GL_ARRAY_BUFFER, BufferSize, Vertices, GL_STATIC_DRAW); 245 | 246 | glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, VertexSize, 0); 247 | glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, VertexSize, (GLvoid*)RgbOffset); 248 | 249 | glEnableVertexAttribArray(0); 250 | glEnableVertexAttribArray(1); 251 | 252 | ErrorCheckValue = glGetError(); 253 | if (ErrorCheckValue != GL_NO_ERROR) 254 | { 255 | fprintf( 256 | stderr, 257 | "ERROR: Could not create a VBO: %s \n", 258 | gluErrorString(ErrorCheckValue) 259 | ); 260 | 261 | exit(-1); 262 | } 263 | } 264 | 265 | void DestroyVBO(void) 266 | { 267 | GLenum ErrorCheckValue = glGetError(); 268 | 269 | glDisableVertexAttribArray(1); 270 | glDisableVertexAttribArray(0); 271 | 272 | glBindBuffer(GL_ARRAY_BUFFER, 0); 273 | glDeleteBuffers(1, &BufferId); 274 | 275 | glBindVertexArray(0); 276 | glDeleteVertexArrays(1, &VaoId); 277 | 278 | ErrorCheckValue = glGetError(); 279 | if (ErrorCheckValue != GL_NO_ERROR) 280 | { 281 | fprintf( 282 | stderr, 283 | "ERROR: Could not destroy the VBO: %s \n", 284 | gluErrorString(ErrorCheckValue) 285 | ); 286 | 287 | exit(-1); 288 | } 289 | } 290 | 291 | void CreateShaders(void) 292 | { 293 | GLenum ErrorCheckValue = glGetError(); 294 | 295 | VertexShaderId = glCreateShader(GL_VERTEX_SHADER); 296 | glShaderSource(VertexShaderId, 1, &VertexShader, NULL); 297 | glCompileShader(VertexShaderId); 298 | 299 | FragmentShaderId = glCreateShader(GL_FRAGMENT_SHADER); 300 | glShaderSource(FragmentShaderId, 1, &FragmentShader, NULL); 301 | glCompileShader(FragmentShaderId); 302 | 303 | ProgramId = glCreateProgram(); 304 | glAttachShader(ProgramId, VertexShaderId); 305 | glAttachShader(ProgramId, FragmentShaderId); 306 | glLinkProgram(ProgramId); 307 | glUseProgram(ProgramId); 308 | 309 | ErrorCheckValue = glGetError(); 310 | if (ErrorCheckValue != GL_NO_ERROR) 311 | { 312 | fprintf( 313 | stderr, 314 | "ERROR: Could not create the shaders: %s \n", 315 | gluErrorString(ErrorCheckValue) 316 | ); 317 | 318 | exit(-1); 319 | } 320 | } 321 | 322 | void DestroyShaders(void) 323 | { 324 | GLenum ErrorCheckValue = glGetError(); 325 | 326 | glUseProgram(0); 327 | 328 | glDetachShader(ProgramId, VertexShaderId); 329 | glDetachShader(ProgramId, FragmentShaderId); 330 | 331 | glDeleteShader(FragmentShaderId); 332 | glDeleteShader(VertexShaderId); 333 | 334 | glDeleteProgram(ProgramId); 335 | 336 | ErrorCheckValue = glGetError(); 337 | if (ErrorCheckValue != GL_NO_ERROR) 338 | { 339 | fprintf( 340 | stderr, 341 | "ERROR: Could not destroy the shaders: %s \n", 342 | gluErrorString(ErrorCheckValue) 343 | ); 344 | 345 | exit(-1); 346 | } 347 | } -------------------------------------------------------------------------------- /chapter-3/chapter.3.1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #define WINDOW_TITLE_PREFIX "Chapter 3" 7 | 8 | typedef struct 9 | { 10 | float XYZW[4]; 11 | float RGBA[4]; 12 | } Vertex; 13 | 14 | int 15 | CurrentWidth = 600, 16 | CurrentHeight = 600, 17 | WindowHandle = 0; 18 | 19 | unsigned FrameCount = 0; 20 | 21 | GLuint 22 | VertexShaderId, 23 | FragmentShaderId, 24 | ProgramId, 25 | VaoId, 26 | BufferId, 27 | IndexBufferId; 28 | 29 | const GLchar* VertexShader = 30 | { 31 | "#version 400\n"\ 32 | 33 | "layout(location=0) in vec4 in_Position;\n"\ 34 | "layout(location=1) in vec4 in_Color;\n"\ 35 | "out vec4 ex_Color;\n"\ 36 | 37 | "void main(void)\n"\ 38 | "{\n"\ 39 | " gl_Position = in_Position;\n"\ 40 | " ex_Color = in_Color;\n"\ 41 | "}\n" 42 | }; 43 | 44 | const GLchar* FragmentShader = 45 | { 46 | "#version 400\n"\ 47 | 48 | "in vec4 ex_Color;\n"\ 49 | "out vec4 out_Color;\n"\ 50 | 51 | "void main(void)\n"\ 52 | "{\n"\ 53 | " out_Color = ex_Color;\n"\ 54 | "}\n" 55 | }; 56 | 57 | void Initialize(int, char*[]); 58 | void InitWindow(int, char*[]); 59 | void ResizeFunction(int, int); 60 | void RenderFunction(void); 61 | void TimerFunction(int); 62 | void IdleFunction(void); 63 | void Cleanup(void); 64 | void CreateVBO(void); 65 | void DestroyVBO(void); 66 | void CreateShaders(void); 67 | void DestroyShaders(void); 68 | 69 | int main(int argc, char* argv[]) 70 | { 71 | Initialize(argc, argv); 72 | 73 | glutMainLoop(); 74 | 75 | exit(EXIT_SUCCESS); 76 | } 77 | 78 | void Initialize(int argc, char* argv[]) 79 | { 80 | GLenum GlewInitResult; 81 | 82 | InitWindow(argc, argv); 83 | 84 | glewExperimental = GL_TRUE; 85 | GlewInitResult = glewInit(); 86 | 87 | if (GLEW_OK != GlewInitResult) { 88 | fprintf( 89 | stderr, 90 | "ERROR: %s\n", 91 | glewGetErrorString(GlewInitResult) 92 | ); 93 | exit(EXIT_FAILURE); 94 | } 95 | 96 | fprintf( 97 | stdout, 98 | "INFO: OpenGL Version: %s\n", 99 | glGetString(GL_VERSION) 100 | ); 101 | 102 | CreateShaders(); 103 | CreateVBO(); 104 | 105 | glClearColor(0.0f, 0.0f, 0.0f, 0.0f); 106 | } 107 | 108 | void InitWindow(int argc, char* argv[]) 109 | { 110 | glutInit(&argc, argv); 111 | 112 | glutInitContextVersion(4, 0); 113 | glutInitContextFlags(GLUT_FORWARD_COMPATIBLE); 114 | glutInitContextProfile(GLUT_CORE_PROFILE); 115 | 116 | glutSetOption( 117 | GLUT_ACTION_ON_WINDOW_CLOSE, 118 | GLUT_ACTION_GLUTMAINLOOP_RETURNS 119 | ); 120 | 121 | glutInitWindowSize(CurrentWidth, CurrentHeight); 122 | 123 | glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA); 124 | 125 | WindowHandle = glutCreateWindow(WINDOW_TITLE_PREFIX); 126 | 127 | if(WindowHandle < 1) { 128 | fprintf( 129 | stderr, 130 | "ERROR: Could not create a new rendering window.\n" 131 | ); 132 | exit(EXIT_FAILURE); 133 | } 134 | 135 | glutReshapeFunc(ResizeFunction); 136 | glutDisplayFunc(RenderFunction); 137 | glutIdleFunc(IdleFunction); 138 | glutTimerFunc(0, TimerFunction, 0); 139 | glutCloseFunc(Cleanup); 140 | } 141 | 142 | void ResizeFunction(int Width, int Height) 143 | { 144 | CurrentWidth = Width; 145 | CurrentHeight = Height; 146 | glViewport(0, 0, CurrentWidth, CurrentHeight); 147 | } 148 | 149 | void RenderFunction(void) 150 | { 151 | ++FrameCount; 152 | 153 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 154 | 155 | glDrawElements(GL_TRIANGLES, 48, GL_UNSIGNED_BYTE, NULL); 156 | 157 | glutSwapBuffers(); 158 | } 159 | 160 | void IdleFunction(void) 161 | { 162 | glutPostRedisplay(); 163 | } 164 | 165 | void TimerFunction(int Value) 166 | { 167 | if (0 != Value) { 168 | char* TempString = (char*) 169 | malloc(512 + strlen(WINDOW_TITLE_PREFIX)); 170 | 171 | sprintf( 172 | TempString, 173 | "%s: %d Frames Per Second @ %d x %d", 174 | WINDOW_TITLE_PREFIX, 175 | FrameCount * 4, 176 | CurrentWidth, 177 | CurrentHeight 178 | ); 179 | 180 | glutSetWindowTitle(TempString); 181 | free(TempString); 182 | } 183 | 184 | FrameCount = 0; 185 | glutTimerFunc(250, TimerFunction, 1); 186 | } 187 | 188 | void Cleanup(void) 189 | { 190 | DestroyShaders(); 191 | DestroyVBO(); 192 | } 193 | 194 | void CreateVBO(void) 195 | { 196 | Vertex Vertices[] = 197 | { 198 | { { 0.0f, 0.0f, 0.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, // 0 199 | 200 | // Top 201 | { { -0.2f, 0.8f, 0.0f, 1.0f }, { 0.0f, 1.0f, 0.0f, 1.0f } }, // 1 202 | { { 0.2f, 0.8f, 0.0f, 1.0f }, { 0.0f, 0.0f, 1.0f, 1.0f } }, // 2 203 | { { 0.0f, 0.8f, 0.0f, 1.0f }, { 0.0f, 1.0f, 1.0f, 1.0f } }, //3 204 | { { 0.0f, 1.0f, 0.0f, 1.0f }, { 1.0f, 0.0f, 0.0f, 1.0f } }, // 4 205 | 206 | // Bottom 207 | { { -0.2f, -0.8f, 0.0f, 1.0f }, { 0.0f, 0.0f, 1.0f, 1.0f } }, // 5 208 | { { 0.2f, -0.8f, 0.0f, 1.0f }, { 0.0f, 1.0f, 0.0f, 1.0f } }, // 6 209 | { { 0.0f, -0.8f, 0.0f, 1.0f }, { 0.0f, 1.0f, 1.0f, 1.0f } }, //7 210 | { { 0.0f, -1.0f, 0.0f, 1.0f }, { 1.0f, 0.0f, 0.0f, 1.0f } }, // 8 211 | 212 | // Left 213 | { { -0.8f, -0.2f, 0.0f, 1.0f }, { 0.0f, 1.0f, 0.0f, 1.0f } }, // 9 214 | { { -0.8f, 0.2f, 0.0f, 1.0f }, { 0.0f, 0.0f, 1.0f, 1.0f } }, // 10 215 | { { -0.8f, 0.0f, 0.0f, 1.0f }, { 0.0f, 1.0f, 1.0f, 1.0f } }, //11 216 | { { -1.0f, 0.0f, 0.0f, 1.0f }, { 1.0f, 0.0f, 0.0f, 1.0f } }, // 12 217 | 218 | // Right 219 | { { 0.8f, -0.2f, 0.0f, 1.0f }, { 0.0f, 0.0f, 1.0f, 1.0f } }, // 13 220 | { { 0.8f, 0.2f, 0.0f, 1.0f }, { 0.0f, 1.0f, 0.0f, 1.0f } }, // 14 221 | { { 0.8f, 0.0f, 0.0f, 1.0f }, { 0.0f, 1.0f, 1.0f, 1.0f } }, //15 222 | { { 1.0f, 0.0f, 0.0f, 1.0f }, { 1.0f, 0.0f, 0.0f, 1.0f } } // 16 223 | }; 224 | 225 | GLubyte Indices[] = { 226 | // Top 227 | 0, 1, 3, 228 | 0, 3, 2, 229 | 3, 1, 4, 230 | 3, 4, 2, 231 | 232 | // Bottom 233 | 0, 5, 7, 234 | 0, 7, 6, 235 | 7, 5, 8, 236 | 7, 8, 6, 237 | 238 | // Left 239 | 0, 9, 11, 240 | 0, 11, 10, 241 | 11, 9, 12, 242 | 11, 12, 10, 243 | 244 | // Right 245 | 0, 13, 15, 246 | 0, 15, 14, 247 | 15, 13, 16, 248 | 15, 16, 14 249 | }; 250 | 251 | GLenum ErrorCheckValue = glGetError(); 252 | const size_t BufferSize = sizeof(Vertices); 253 | const size_t VertexSize = sizeof(Vertices[0]); 254 | const size_t RgbOffset = sizeof(Vertices[0].XYZW); 255 | 256 | glGenVertexArrays(1, &VaoId); 257 | glBindVertexArray(VaoId); 258 | 259 | glGenBuffers(1, &BufferId); 260 | glBindBuffer(GL_ARRAY_BUFFER, BufferId); 261 | glBufferData(GL_ARRAY_BUFFER, BufferSize, Vertices, GL_STATIC_DRAW); 262 | 263 | glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, VertexSize, 0); 264 | glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, VertexSize, (GLvoid*)RgbOffset); 265 | 266 | glEnableVertexAttribArray(0); 267 | glEnableVertexAttribArray(1); 268 | 269 | glGenBuffers(1, &IndexBufferId); 270 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IndexBufferId); 271 | glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(Indices), Indices, GL_STATIC_DRAW); 272 | 273 | ErrorCheckValue = glGetError(); 274 | if (ErrorCheckValue != GL_NO_ERROR) 275 | { 276 | fprintf( 277 | stderr, 278 | "ERROR: Could not create a VBO: %s \n", 279 | gluErrorString(ErrorCheckValue) 280 | ); 281 | 282 | exit(-1); 283 | } 284 | } 285 | 286 | void DestroyVBO(void) 287 | { 288 | GLenum ErrorCheckValue = glGetError(); 289 | 290 | glDisableVertexAttribArray(1); 291 | glDisableVertexAttribArray(0); 292 | 293 | glBindBuffer(GL_ARRAY_BUFFER, 0); 294 | glDeleteBuffers(1, &BufferId); 295 | 296 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 297 | glDeleteBuffers(1, &IndexBufferId); 298 | 299 | glBindVertexArray(0); 300 | glDeleteVertexArrays(1, &VaoId); 301 | 302 | ErrorCheckValue = glGetError(); 303 | if (ErrorCheckValue != GL_NO_ERROR) 304 | { 305 | fprintf( 306 | stderr, 307 | "ERROR: Could not destroy the VBO: %s \n", 308 | gluErrorString(ErrorCheckValue) 309 | ); 310 | 311 | exit(-1); 312 | } 313 | } 314 | 315 | void CreateShaders(void) 316 | { 317 | GLenum ErrorCheckValue = glGetError(); 318 | 319 | VertexShaderId = glCreateShader(GL_VERTEX_SHADER); 320 | glShaderSource(VertexShaderId, 1, &VertexShader, NULL); 321 | glCompileShader(VertexShaderId); 322 | 323 | FragmentShaderId = glCreateShader(GL_FRAGMENT_SHADER); 324 | glShaderSource(FragmentShaderId, 1, &FragmentShader, NULL); 325 | glCompileShader(FragmentShaderId); 326 | 327 | ProgramId = glCreateProgram(); 328 | glAttachShader(ProgramId, VertexShaderId); 329 | glAttachShader(ProgramId, FragmentShaderId); 330 | glLinkProgram(ProgramId); 331 | glUseProgram(ProgramId); 332 | 333 | ErrorCheckValue = glGetError(); 334 | if (ErrorCheckValue != GL_NO_ERROR) 335 | { 336 | fprintf( 337 | stderr, 338 | "ERROR: Could not create the shaders: %s \n", 339 | gluErrorString(ErrorCheckValue) 340 | ); 341 | 342 | exit(-1); 343 | } 344 | } 345 | 346 | void DestroyShaders(void) 347 | { 348 | GLenum ErrorCheckValue = glGetError(); 349 | 350 | glUseProgram(0); 351 | 352 | glDetachShader(ProgramId, VertexShaderId); 353 | glDetachShader(ProgramId, FragmentShaderId); 354 | 355 | glDeleteShader(FragmentShaderId); 356 | glDeleteShader(VertexShaderId); 357 | 358 | glDeleteProgram(ProgramId); 359 | 360 | ErrorCheckValue = glGetError(); 361 | if (ErrorCheckValue != GL_NO_ERROR) 362 | { 363 | fprintf( 364 | stderr, 365 | "ERROR: Could not destroy the shaders: %s \n", 366 | gluErrorString(ErrorCheckValue) 367 | ); 368 | 369 | exit(-1); 370 | } 371 | } -------------------------------------------------------------------------------- /chapter-3/chapter.3.2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #define WINDOW_TITLE_PREFIX "Chapter 3" 7 | 8 | typedef struct 9 | { 10 | float XYZW[4]; 11 | float RGBA[4]; 12 | } Vertex; 13 | 14 | int 15 | CurrentWidth = 600, 16 | CurrentHeight = 600, 17 | WindowHandle = 0; 18 | 19 | unsigned FrameCount = 0; 20 | 21 | GLuint 22 | VertexShaderId, 23 | FragmentShaderId, 24 | ProgramId, 25 | VaoId, 26 | BufferId, 27 | IndexBufferId[2], 28 | ActiveIndexBuffer = 0; 29 | 30 | const GLchar* VertexShader = 31 | { 32 | "#version 400\n"\ 33 | 34 | "layout(location=0) in vec4 in_Position;\n"\ 35 | "layout(location=1) in vec4 in_Color;\n"\ 36 | "out vec4 ex_Color;\n"\ 37 | 38 | "void main(void)\n"\ 39 | "{\n"\ 40 | " gl_Position = in_Position;\n"\ 41 | " ex_Color = in_Color;\n"\ 42 | "}\n" 43 | }; 44 | 45 | const GLchar* FragmentShader = 46 | { 47 | "#version 400\n"\ 48 | 49 | "in vec4 ex_Color;\n"\ 50 | "out vec4 out_Color;\n"\ 51 | 52 | "void main(void)\n"\ 53 | "{\n"\ 54 | " out_Color = ex_Color;\n"\ 55 | "}\n" 56 | }; 57 | 58 | void Initialize(int, char*[]); 59 | void InitWindow(int, char*[]); 60 | void ResizeFunction(int, int); 61 | void RenderFunction(void); 62 | void TimerFunction(int); 63 | void IdleFunction(void); 64 | void KeyboardFunction(unsigned char, int, int); 65 | void Cleanup(void); 66 | void CreateVBO(void); 67 | void DestroyVBO(void); 68 | void CreateShaders(void); 69 | void DestroyShaders(void); 70 | 71 | int main(int argc, char* argv[]) 72 | { 73 | Initialize(argc, argv); 74 | 75 | glutMainLoop(); 76 | 77 | exit(EXIT_SUCCESS); 78 | } 79 | 80 | void Initialize(int argc, char* argv[]) 81 | { 82 | GLenum GlewInitResult; 83 | 84 | InitWindow(argc, argv); 85 | 86 | glewExperimental = GL_TRUE; 87 | GlewInitResult = glewInit(); 88 | 89 | if (GLEW_OK != GlewInitResult) { 90 | fprintf( 91 | stderr, 92 | "ERROR: %s\n", 93 | glewGetErrorString(GlewInitResult) 94 | ); 95 | exit(EXIT_FAILURE); 96 | } 97 | 98 | fprintf( 99 | stdout, 100 | "INFO: OpenGL Version: %s\n", 101 | glGetString(GL_VERSION) 102 | ); 103 | 104 | CreateShaders(); 105 | CreateVBO(); 106 | 107 | glClearColor(0.0f, 0.0f, 0.0f, 0.0f); 108 | } 109 | 110 | void InitWindow(int argc, char* argv[]) 111 | { 112 | glutInit(&argc, argv); 113 | 114 | glutInitContextVersion(4, 0); 115 | glutInitContextFlags(GLUT_FORWARD_COMPATIBLE); 116 | glutInitContextProfile(GLUT_CORE_PROFILE); 117 | 118 | glutSetOption( 119 | GLUT_ACTION_ON_WINDOW_CLOSE, 120 | GLUT_ACTION_GLUTMAINLOOP_RETURNS 121 | ); 122 | 123 | glutInitWindowSize(CurrentWidth, CurrentHeight); 124 | 125 | glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA); 126 | 127 | WindowHandle = glutCreateWindow(WINDOW_TITLE_PREFIX); 128 | 129 | if(WindowHandle < 1) { 130 | fprintf( 131 | stderr, 132 | "ERROR: Could not create a new rendering window.\n" 133 | ); 134 | exit(EXIT_FAILURE); 135 | } 136 | 137 | glutReshapeFunc(ResizeFunction); 138 | glutDisplayFunc(RenderFunction); 139 | glutIdleFunc(IdleFunction); 140 | glutTimerFunc(0, TimerFunction, 0); 141 | glutCloseFunc(Cleanup); 142 | glutKeyboardFunc(KeyboardFunction); 143 | } 144 | 145 | void KeyboardFunction(unsigned char Key, int X, int Y) 146 | { 147 | X; Y; // Resolves warning C4100: unreferenced formal parameter 148 | 149 | switch (Key) 150 | { 151 | case 'T': 152 | case 't': 153 | { 154 | ActiveIndexBuffer = (ActiveIndexBuffer == 1 ? 0 : 1); 155 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IndexBufferId[ActiveIndexBuffer]); 156 | break; 157 | } 158 | default: 159 | break; 160 | } 161 | } 162 | 163 | void ResizeFunction(int Width, int Height) 164 | { 165 | CurrentWidth = Width; 166 | CurrentHeight = Height; 167 | glViewport(0, 0, CurrentWidth, CurrentHeight); 168 | } 169 | 170 | void RenderFunction(void) 171 | { 172 | ++FrameCount; 173 | 174 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 175 | 176 | if (ActiveIndexBuffer == 0) { 177 | glDrawElements(GL_TRIANGLES, 48, GL_UNSIGNED_BYTE, NULL); 178 | } else { 179 | glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_BYTE, NULL); 180 | } 181 | 182 | glutSwapBuffers(); 183 | } 184 | 185 | void IdleFunction(void) 186 | { 187 | glutPostRedisplay(); 188 | } 189 | 190 | void TimerFunction(int Value) 191 | { 192 | if (0 != Value) { 193 | char* TempString = (char*) 194 | malloc(512 + strlen(WINDOW_TITLE_PREFIX)); 195 | 196 | sprintf( 197 | TempString, 198 | "%s: %d Frames Per Second @ %d x %d", 199 | WINDOW_TITLE_PREFIX, 200 | FrameCount * 4, 201 | CurrentWidth, 202 | CurrentHeight 203 | ); 204 | 205 | glutSetWindowTitle(TempString); 206 | free(TempString); 207 | } 208 | 209 | FrameCount = 0; 210 | glutTimerFunc(250, TimerFunction, 1); 211 | } 212 | 213 | void Cleanup(void) 214 | { 215 | DestroyShaders(); 216 | DestroyVBO(); 217 | } 218 | 219 | void CreateVBO(void) 220 | { 221 | Vertex Vertices[] = 222 | { 223 | { { 0.0f, 0.0f, 0.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, // 0 224 | 225 | // Top 226 | { { -0.2f, 0.8f, 0.0f, 1.0f }, { 0.0f, 1.0f, 0.0f, 1.0f } }, // 1 227 | { { 0.2f, 0.8f, 0.0f, 1.0f }, { 0.0f, 0.0f, 1.0f, 1.0f } }, // 2 228 | { { 0.0f, 0.8f, 0.0f, 1.0f }, { 0.0f, 1.0f, 1.0f, 1.0f } }, //3 229 | { { 0.0f, 1.0f, 0.0f, 1.0f }, { 1.0f, 0.0f, 0.0f, 1.0f } }, // 4 230 | 231 | // Bottom 232 | { { -0.2f, -0.8f, 0.0f, 1.0f }, { 0.0f, 0.0f, 1.0f, 1.0f } }, // 5 233 | { { 0.2f, -0.8f, 0.0f, 1.0f }, { 0.0f, 1.0f, 0.0f, 1.0f } }, // 6 234 | { { 0.0f, -0.8f, 0.0f, 1.0f }, { 0.0f, 1.0f, 1.0f, 1.0f } }, //7 235 | { { 0.0f, -1.0f, 0.0f, 1.0f }, { 1.0f, 0.0f, 0.0f, 1.0f } }, // 8 236 | 237 | // Left 238 | { { -0.8f, -0.2f, 0.0f, 1.0f }, { 0.0f, 1.0f, 0.0f, 1.0f } }, // 9 239 | { { -0.8f, 0.2f, 0.0f, 1.0f }, { 0.0f, 0.0f, 1.0f, 1.0f } }, // 10 240 | { { -0.8f, 0.0f, 0.0f, 1.0f }, { 0.0f, 1.0f, 1.0f, 1.0f } }, //11 241 | { { -1.0f, 0.0f, 0.0f, 1.0f }, { 1.0f, 0.0f, 0.0f, 1.0f } }, // 12 242 | 243 | // Right 244 | { { 0.8f, -0.2f, 0.0f, 1.0f }, { 0.0f, 0.0f, 1.0f, 1.0f } }, // 13 245 | { { 0.8f, 0.2f, 0.0f, 1.0f }, { 0.0f, 1.0f, 0.0f, 1.0f } }, // 14 246 | { { 0.8f, 0.0f, 0.0f, 1.0f }, { 0.0f, 1.0f, 1.0f, 1.0f } }, //15 247 | { { 1.0f, 0.0f, 0.0f, 1.0f }, { 1.0f, 0.0f, 0.0f, 1.0f } } // 16 248 | }; 249 | 250 | GLubyte Indices[] = { 251 | // Top 252 | 0, 1, 3, 253 | 0, 3, 2, 254 | 3, 1, 4, 255 | 3, 4, 2, 256 | 257 | // Bottom 258 | 0, 5, 7, 259 | 0, 7, 6, 260 | 7, 5, 8, 261 | 7, 8, 6, 262 | 263 | // Left 264 | 0, 9, 11, 265 | 0, 11, 10, 266 | 11, 9, 12, 267 | 11, 12, 10, 268 | 269 | // Right 270 | 0, 13, 15, 271 | 0, 15, 14, 272 | 15, 13, 16, 273 | 15, 16, 14 274 | }; 275 | 276 | GLubyte AlternateIndices[] = { 277 | // Outer square border: 278 | 3, 4, 16, 279 | 3, 15, 16, 280 | 15, 16, 8, 281 | 15, 7, 8, 282 | 7, 8, 12, 283 | 7, 11, 12, 284 | 11, 12, 4, 285 | 11, 3, 4, 286 | 287 | // Inner square 288 | 0, 11, 3, 289 | 0, 3, 15, 290 | 0, 15, 7, 291 | 0, 7, 11 292 | }; 293 | 294 | GLenum ErrorCheckValue = glGetError(); 295 | const size_t BufferSize = sizeof(Vertices); 296 | const size_t VertexSize = sizeof(Vertices[0]); 297 | const size_t RgbOffset = sizeof(Vertices[0].XYZW); 298 | 299 | glGenVertexArrays(1, &VaoId); 300 | glBindVertexArray(VaoId); 301 | 302 | glGenBuffers(1, &BufferId); 303 | glBindBuffer(GL_ARRAY_BUFFER, BufferId); 304 | glBufferData(GL_ARRAY_BUFFER, BufferSize, Vertices, GL_STATIC_DRAW); 305 | 306 | glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, VertexSize, 0); 307 | glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, VertexSize, (GLvoid*)RgbOffset); 308 | 309 | glEnableVertexAttribArray(0); 310 | glEnableVertexAttribArray(1); 311 | 312 | glGenBuffers(2, IndexBufferId); 313 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IndexBufferId[0]); 314 | glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(Indices), Indices, GL_STATIC_DRAW); 315 | 316 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IndexBufferId[1]); 317 | glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(AlternateIndices), AlternateIndices, GL_STATIC_DRAW); 318 | 319 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IndexBufferId[0]); 320 | 321 | ErrorCheckValue = glGetError(); 322 | if (ErrorCheckValue != GL_NO_ERROR) 323 | { 324 | fprintf( 325 | stderr, 326 | "ERROR: Could not create a VBO: %s \n", 327 | gluErrorString(ErrorCheckValue) 328 | ); 329 | 330 | exit(-1); 331 | } 332 | } 333 | 334 | void DestroyVBO(void) 335 | { 336 | GLenum ErrorCheckValue = glGetError(); 337 | 338 | glDisableVertexAttribArray(1); 339 | glDisableVertexAttribArray(0); 340 | 341 | glBindBuffer(GL_ARRAY_BUFFER, 0); 342 | glDeleteBuffers(1, &BufferId); 343 | 344 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 345 | glDeleteBuffers(2, IndexBufferId); 346 | 347 | glBindVertexArray(0); 348 | glDeleteVertexArrays(1, &VaoId); 349 | 350 | ErrorCheckValue = glGetError(); 351 | if (ErrorCheckValue != GL_NO_ERROR) 352 | { 353 | fprintf( 354 | stderr, 355 | "ERROR: Could not destroy the VBO: %s \n", 356 | gluErrorString(ErrorCheckValue) 357 | ); 358 | 359 | exit(-1); 360 | } 361 | } 362 | 363 | void CreateShaders(void) 364 | { 365 | GLenum ErrorCheckValue = glGetError(); 366 | 367 | VertexShaderId = glCreateShader(GL_VERTEX_SHADER); 368 | glShaderSource(VertexShaderId, 1, &VertexShader, NULL); 369 | glCompileShader(VertexShaderId); 370 | 371 | FragmentShaderId = glCreateShader(GL_FRAGMENT_SHADER); 372 | glShaderSource(FragmentShaderId, 1, &FragmentShader, NULL); 373 | glCompileShader(FragmentShaderId); 374 | 375 | ProgramId = glCreateProgram(); 376 | glAttachShader(ProgramId, VertexShaderId); 377 | glAttachShader(ProgramId, FragmentShaderId); 378 | glLinkProgram(ProgramId); 379 | glUseProgram(ProgramId); 380 | 381 | ErrorCheckValue = glGetError(); 382 | if (ErrorCheckValue != GL_NO_ERROR) 383 | { 384 | fprintf( 385 | stderr, 386 | "ERROR: Could not create the shaders: %s \n", 387 | gluErrorString(ErrorCheckValue) 388 | ); 389 | 390 | exit(-1); 391 | } 392 | } 393 | 394 | void DestroyShaders(void) 395 | { 396 | GLenum ErrorCheckValue = glGetError(); 397 | 398 | glUseProgram(0); 399 | 400 | glDetachShader(ProgramId, VertexShaderId); 401 | glDetachShader(ProgramId, FragmentShaderId); 402 | 403 | glDeleteShader(FragmentShaderId); 404 | glDeleteShader(VertexShaderId); 405 | 406 | glDeleteProgram(ProgramId); 407 | 408 | ErrorCheckValue = glGetError(); 409 | if (ErrorCheckValue != GL_NO_ERROR) 410 | { 411 | fprintf( 412 | stderr, 413 | "ERROR: Could not destroy the shaders: %s \n", 414 | gluErrorString(ErrorCheckValue) 415 | ); 416 | 417 | exit(-1); 418 | } 419 | } -------------------------------------------------------------------------------- /chapter-3/compatibility/chapter.3.0.1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #define WINDOW_TITLE_PREFIX "Chapter 3" 7 | 8 | typedef struct 9 | { 10 | float XYZW[4]; 11 | float RGBA[4]; 12 | } Vertex; 13 | 14 | int 15 | CurrentWidth = 600, 16 | CurrentHeight = 600, 17 | WindowHandle = 0; 18 | 19 | unsigned FrameCount = 0; 20 | 21 | GLuint 22 | VertexShaderId, 23 | FragmentShaderId, 24 | ProgramId, 25 | VaoId, 26 | BufferId; 27 | 28 | const GLchar* VertexShader = 29 | { 30 | "#version 330\n"\ 31 | 32 | "layout(location=0) in vec4 in_Position;\n"\ 33 | "layout(location=1) in vec4 in_Color;\n"\ 34 | "out vec4 ex_Color;\n"\ 35 | 36 | "void main(void)\n"\ 37 | "{\n"\ 38 | " gl_Position = in_Position;\n"\ 39 | " ex_Color = in_Color;\n"\ 40 | "}\n" 41 | }; 42 | 43 | const GLchar* FragmentShader = 44 | { 45 | "#version 330\n"\ 46 | 47 | "in vec4 ex_Color;\n"\ 48 | "out vec4 out_Color;\n"\ 49 | 50 | "void main(void)\n"\ 51 | "{\n"\ 52 | " out_Color = ex_Color;\n"\ 53 | "}\n" 54 | }; 55 | 56 | void Initialize(int, char*[]); 57 | void InitWindow(int, char*[]); 58 | void ResizeFunction(int, int); 59 | void RenderFunction(void); 60 | void TimerFunction(int); 61 | void IdleFunction(void); 62 | void Cleanup(void); 63 | void CreateVBO(void); 64 | void DestroyVBO(void); 65 | void CreateShaders(void); 66 | void DestroyShaders(void); 67 | 68 | int main(int argc, char* argv[]) 69 | { 70 | Initialize(argc, argv); 71 | 72 | glutMainLoop(); 73 | 74 | exit(EXIT_SUCCESS); 75 | } 76 | 77 | void Initialize(int argc, char* argv[]) 78 | { 79 | GLenum GlewInitResult; 80 | 81 | InitWindow(argc, argv); 82 | 83 | glewExperimental = GL_TRUE; 84 | GlewInitResult = glewInit(); 85 | 86 | if (GLEW_OK != GlewInitResult) { 87 | fprintf( 88 | stderr, 89 | "ERROR: %s\n", 90 | glewGetErrorString(GlewInitResult) 91 | ); 92 | exit(EXIT_FAILURE); 93 | } 94 | 95 | fprintf( 96 | stdout, 97 | "INFO: OpenGL Version: %s\n", 98 | glGetString(GL_VERSION) 99 | ); 100 | 101 | CreateShaders(); 102 | CreateVBO(); 103 | 104 | glClearColor(0.0f, 0.0f, 0.0f, 0.0f); 105 | } 106 | 107 | void InitWindow(int argc, char* argv[]) 108 | { 109 | glutInit(&argc, argv); 110 | 111 | glutInitContextVersion(3, 3); 112 | glutInitContextFlags(GLUT_FORWARD_COMPATIBLE); 113 | glutInitContextProfile(GLUT_CORE_PROFILE); 114 | 115 | glutSetOption( 116 | GLUT_ACTION_ON_WINDOW_CLOSE, 117 | GLUT_ACTION_GLUTMAINLOOP_RETURNS 118 | ); 119 | 120 | glutInitWindowSize(CurrentWidth, CurrentHeight); 121 | 122 | glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA); 123 | 124 | WindowHandle = glutCreateWindow(WINDOW_TITLE_PREFIX); 125 | 126 | if(WindowHandle < 1) { 127 | fprintf( 128 | stderr, 129 | "ERROR: Could not create a new rendering window.\n" 130 | ); 131 | exit(EXIT_FAILURE); 132 | } 133 | 134 | glutReshapeFunc(ResizeFunction); 135 | glutDisplayFunc(RenderFunction); 136 | glutIdleFunc(IdleFunction); 137 | glutTimerFunc(0, TimerFunction, 0); 138 | glutCloseFunc(Cleanup); 139 | } 140 | 141 | void ResizeFunction(int Width, int Height) 142 | { 143 | CurrentWidth = Width; 144 | CurrentHeight = Height; 145 | glViewport(0, 0, CurrentWidth, CurrentHeight); 146 | } 147 | 148 | void RenderFunction(void) 149 | { 150 | ++FrameCount; 151 | 152 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 153 | 154 | glDrawArrays(GL_TRIANGLES, 0, 48); 155 | 156 | glutSwapBuffers(); 157 | } 158 | 159 | void IdleFunction(void) 160 | { 161 | glutPostRedisplay(); 162 | } 163 | 164 | void TimerFunction(int Value) 165 | { 166 | if (0 != Value) { 167 | char* TempString = (char*) 168 | malloc(512 + strlen(WINDOW_TITLE_PREFIX)); 169 | 170 | sprintf( 171 | TempString, 172 | "%s: %d Frames Per Second @ %d x %d", 173 | WINDOW_TITLE_PREFIX, 174 | FrameCount * 4, 175 | CurrentWidth, 176 | CurrentHeight 177 | ); 178 | 179 | glutSetWindowTitle(TempString); 180 | free(TempString); 181 | } 182 | 183 | FrameCount = 0; 184 | glutTimerFunc(250, TimerFunction, 1); 185 | } 186 | 187 | void Cleanup(void) 188 | { 189 | DestroyShaders(); 190 | DestroyVBO(); 191 | } 192 | 193 | void CreateVBO(void) 194 | { 195 | Vertex Vertices[] = 196 | { 197 | // Top 198 | { { 0.0f, 0.0f, 0.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, // 0 199 | { { -0.2f, 0.8f, 0.0f, 1.0f }, { 0.0f, 1.0f, 0.0f, 1.0f } }, // 1 200 | { { 0.0f, 0.8f, 0.0f, 1.0f }, { 0.0f, 1.0f, 1.0f, 1.0f } }, //3 201 | 202 | { { 0.0f, 0.0f, 0.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, // 0 203 | { { 0.0f, 0.8f, 0.0f, 1.0f }, { 0.0f, 1.0f, 1.0f, 1.0f } }, //3 204 | { { 0.2f, 0.8f, 0.0f, 1.0f }, { 0.0f, 0.0f, 1.0f, 1.0f } }, // 2 205 | 206 | { { 0.0f, 0.8f, 0.0f, 1.0f }, { 0.0f, 1.0f, 1.0f, 1.0f } }, //3 207 | { { -0.2f, 0.8f, 0.0f, 1.0f }, { 0.0f, 1.0f, 0.0f, 1.0f } }, // 1 208 | { { 0.0f, 1.0f, 0.0f, 1.0f }, { 1.0f, 0.0f, 0.0f, 1.0f } }, // 4 209 | 210 | { { 0.0f, 0.8f, 0.0f, 1.0f }, { 0.0f, 1.0f, 1.0f, 1.0f } }, //3 211 | { { 0.0f, 1.0f, 0.0f, 1.0f }, { 1.0f, 0.0f, 0.0f, 1.0f } }, // 4 212 | { { 0.2f, 0.8f, 0.0f, 1.0f }, { 0.0f, 0.0f, 1.0f, 1.0f } }, // 2 213 | 214 | // Bottom 215 | { { 0.0f, 0.0f, 0.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, // 0 216 | { { 0.0f, -0.8f, 0.0f, 1.0f }, { 0.0f, 1.0f, 1.0f, 1.0f } }, //7 217 | { { -0.2f, -0.8f, 0.0f, 1.0f }, { 0.0f, 1.0f, 0.0f, 1.0f } }, // 5 218 | 219 | { { 0.0f, 0.0f, 0.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, // 0 220 | { { 0.0f, -0.8f, 0.0f, 1.0f }, { 0.0f, 1.0f, 1.0f, 1.0f } }, //7 221 | { { 0.2f, -0.8f, 0.0f, 1.0f }, { 0.0f, 0.0f, 1.0f, 1.0f } }, // 6 222 | 223 | { { 0.0f, -0.8f, 0.0f, 1.0f }, { 0.0f, 1.0f, 1.0f, 1.0f } }, //7 224 | { { -0.2f, -0.8f, 0.0f, 1.0f }, { 0.0f, 1.0f, 0.0f, 1.0f } }, // 5 225 | { { 0.0f, -1.0f, 0.0f, 1.0f }, { 1.0f, 0.0f, 0.0f, 1.0f } }, // 8 226 | 227 | { { 0.0f, -0.8f, 0.0f, 1.0f }, { 0.0f, 1.0f, 1.0f, 1.0f } }, //7 228 | { { 0.2f, -0.8f, 0.0f, 1.0f }, { 0.0f, 0.0f, 1.0f, 1.0f } }, // 6 229 | { { 0.0f, -1.0f, 0.0f, 1.0f }, { 1.0f, 0.0f, 0.0f, 1.0f } }, // 8 230 | 231 | // Left 232 | { { 0.0f, 0.0f, 0.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, // 0 233 | { { -0.8f, -0.2f, 0.0f, 1.0f }, { 0.0f, 1.0f, 0.0f, 1.0f } }, // 9 234 | { { -0.8f, 0.0f, 0.0f, 1.0f }, { 0.0f, 1.0f, 1.0f, 1.0f } }, //11 235 | 236 | { { 0.0f, 0.0f, 0.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, // 0 237 | { { -0.8f, 0.0f, 0.0f, 1.0f }, { 0.0f, 1.0f, 1.0f, 1.0f } }, //11 238 | { { -0.8f, 0.2f, 0.0f, 1.0f }, { 0.0f, 0.0f, 1.0f, 1.0f } }, // 10 239 | 240 | { { -0.8f, 0.0f, 0.0f, 1.0f }, { 0.0f, 1.0f, 1.0f, 1.0f } }, //11 241 | { { -0.8f, 0.2f, 0.0f, 1.0f }, { 0.0f, 0.0f, 1.0f, 1.0f } }, // 10 242 | { { -1.0f, 0.0f, 0.0f, 1.0f }, { 1.0f, 0.0f, 0.0f, 1.0f } }, // 12 243 | 244 | { { -0.8f, 0.0f, 0.0f, 1.0f }, { 0.0f, 1.0f, 1.0f, 1.0f } }, //11 245 | { { -1.0f, 0.0f, 0.0f, 1.0f }, { 1.0f, 0.0f, 0.0f, 1.0f } }, // 12 246 | { { -0.8f, -0.2f, 0.0f, 1.0f }, { 0.0f, 1.0f, 0.0f, 1.0f } }, // 9 247 | 248 | // Right 249 | { { 0.0f, 0.0f, 0.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, // 0 250 | { { 0.8f, 0.2f, 0.0f, 1.0f }, { 0.0f, 0.0f, 1.0f, 1.0f } }, // 14 251 | { { 0.8f, 0.0f, 0.0f, 1.0f }, { 0.0f, 1.0f, 1.0f, 1.0f } }, //15 252 | 253 | { { 0.0f, 0.0f, 0.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, // 0 254 | { { 0.8f, 0.0f, 0.0f, 1.0f }, { 0.0f, 1.0f, 1.0f, 1.0f } }, //15 255 | { { 0.8f, -0.2f, 0.0f, 1.0f }, { 0.0f, 1.0f, 0.0f, 1.0f } }, // 13 256 | 257 | { { 0.8f, 0.0f, 0.0f, 1.0f }, { 0.0f, 1.0f, 1.0f, 1.0f } }, //15 258 | { { 0.8f, -0.2f, 0.0f, 1.0f }, { 0.0f, 1.0f, 0.0f, 1.0f } }, // 13 259 | { { 1.0f, 0.0f, 0.0f, 1.0f }, { 1.0f, 0.0f, 0.0f, 1.0f } }, // 16 260 | 261 | { { 0.8f, 0.2f, 0.0f, 1.0f }, { 0.0f, 0.0f, 1.0f, 1.0f } }, // 14 262 | { { 0.8f, 0.0f, 0.0f, 1.0f }, { 0.0f, 1.0f, 1.0f, 1.0f } }, //15 263 | { { 1.0f, 0.0f, 0.0f, 1.0f }, { 1.0f, 0.0f, 0.0f, 1.0f } } // 16 264 | }; 265 | 266 | GLenum ErrorCheckValue = glGetError(); 267 | const size_t BufferSize = sizeof(Vertices); 268 | const size_t VertexSize = sizeof(Vertices[0]); 269 | const size_t RgbOffset = sizeof(Vertices[0].XYZW); 270 | 271 | glGenVertexArrays(1, &VaoId); 272 | glBindVertexArray(VaoId); 273 | 274 | glGenBuffers(1, &BufferId); 275 | glBindBuffer(GL_ARRAY_BUFFER, BufferId); 276 | glBufferData(GL_ARRAY_BUFFER, BufferSize, Vertices, GL_STATIC_DRAW); 277 | 278 | glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, VertexSize, 0); 279 | glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, VertexSize, (GLvoid*)RgbOffset); 280 | 281 | glEnableVertexAttribArray(0); 282 | glEnableVertexAttribArray(1); 283 | 284 | ErrorCheckValue = glGetError(); 285 | if (ErrorCheckValue != GL_NO_ERROR) 286 | { 287 | fprintf( 288 | stderr, 289 | "ERROR: Could not create a VBO: %s \n", 290 | gluErrorString(ErrorCheckValue) 291 | ); 292 | 293 | exit(-1); 294 | } 295 | } 296 | 297 | void DestroyVBO(void) 298 | { 299 | GLenum ErrorCheckValue = glGetError(); 300 | 301 | glDisableVertexAttribArray(1); 302 | glDisableVertexAttribArray(0); 303 | 304 | glBindBuffer(GL_ARRAY_BUFFER, 0); 305 | glDeleteBuffers(1, &BufferId); 306 | 307 | glBindVertexArray(0); 308 | glDeleteVertexArrays(1, &VaoId); 309 | 310 | ErrorCheckValue = glGetError(); 311 | if (ErrorCheckValue != GL_NO_ERROR) 312 | { 313 | fprintf( 314 | stderr, 315 | "ERROR: Could not destroy the VBO: %s \n", 316 | gluErrorString(ErrorCheckValue) 317 | ); 318 | 319 | exit(-1); 320 | } 321 | } 322 | 323 | void CreateShaders(void) 324 | { 325 | GLenum ErrorCheckValue = glGetError(); 326 | 327 | VertexShaderId = glCreateShader(GL_VERTEX_SHADER); 328 | glShaderSource(VertexShaderId, 1, &VertexShader, NULL); 329 | glCompileShader(VertexShaderId); 330 | 331 | FragmentShaderId = glCreateShader(GL_FRAGMENT_SHADER); 332 | glShaderSource(FragmentShaderId, 1, &FragmentShader, NULL); 333 | glCompileShader(FragmentShaderId); 334 | 335 | ProgramId = glCreateProgram(); 336 | glAttachShader(ProgramId, VertexShaderId); 337 | glAttachShader(ProgramId, FragmentShaderId); 338 | glLinkProgram(ProgramId); 339 | glUseProgram(ProgramId); 340 | 341 | ErrorCheckValue = glGetError(); 342 | if (ErrorCheckValue != GL_NO_ERROR) 343 | { 344 | fprintf( 345 | stderr, 346 | "ERROR: Could not create the shaders: %s \n", 347 | gluErrorString(ErrorCheckValue) 348 | ); 349 | 350 | exit(-1); 351 | } 352 | } 353 | 354 | void DestroyShaders(void) 355 | { 356 | GLenum ErrorCheckValue = glGetError(); 357 | 358 | glUseProgram(0); 359 | 360 | glDetachShader(ProgramId, VertexShaderId); 361 | glDetachShader(ProgramId, FragmentShaderId); 362 | 363 | glDeleteShader(FragmentShaderId); 364 | glDeleteShader(VertexShaderId); 365 | 366 | glDeleteProgram(ProgramId); 367 | 368 | ErrorCheckValue = glGetError(); 369 | if (ErrorCheckValue != GL_NO_ERROR) 370 | { 371 | fprintf( 372 | stderr, 373 | "ERROR: Could not destroy the shaders: %s \n", 374 | gluErrorString(ErrorCheckValue) 375 | ); 376 | 377 | exit(-1); 378 | } 379 | } -------------------------------------------------------------------------------- /chapter-3/compatibility/chapter.3.0.2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #define WINDOW_TITLE_PREFIX "Chapter 3" 7 | 8 | typedef struct 9 | { 10 | float XYZW[4]; 11 | float RGBA[4]; 12 | } Vertex; 13 | 14 | int 15 | CurrentWidth = 600, 16 | CurrentHeight = 600, 17 | WindowHandle = 0; 18 | 19 | unsigned FrameCount = 0; 20 | 21 | GLuint 22 | VertexShaderId, 23 | FragmentShaderId, 24 | ProgramId, 25 | VaoId, 26 | BufferId; 27 | 28 | const GLchar* VertexShader = 29 | { 30 | "#version 330\n"\ 31 | 32 | "layout(location=0) in vec4 in_Position;\n"\ 33 | "layout(location=1) in vec4 in_Color;\n"\ 34 | "out vec4 ex_Color;\n"\ 35 | 36 | "void main(void)\n"\ 37 | "{\n"\ 38 | " gl_Position = in_Position;\n"\ 39 | " ex_Color = in_Color;\n"\ 40 | "}\n" 41 | }; 42 | 43 | const GLchar* FragmentShader = 44 | { 45 | "#version 330\n"\ 46 | 47 | "in vec4 ex_Color;\n"\ 48 | "out vec4 out_Color;\n"\ 49 | 50 | "void main(void)\n"\ 51 | "{\n"\ 52 | " out_Color = ex_Color;\n"\ 53 | "}\n" 54 | }; 55 | 56 | void Initialize(int, char*[]); 57 | void InitWindow(int, char*[]); 58 | void ResizeFunction(int, int); 59 | void RenderFunction(void); 60 | void TimerFunction(int); 61 | void IdleFunction(void); 62 | void Cleanup(void); 63 | void CreateVBO(void); 64 | void DestroyVBO(void); 65 | void CreateShaders(void); 66 | void DestroyShaders(void); 67 | 68 | int main(int argc, char* argv[]) 69 | { 70 | Initialize(argc, argv); 71 | 72 | glutMainLoop(); 73 | 74 | exit(EXIT_SUCCESS); 75 | } 76 | 77 | void Initialize(int argc, char* argv[]) 78 | { 79 | GLenum GlewInitResult; 80 | 81 | InitWindow(argc, argv); 82 | 83 | glewExperimental = GL_TRUE; 84 | GlewInitResult = glewInit(); 85 | 86 | if (GLEW_OK != GlewInitResult) { 87 | fprintf( 88 | stderr, 89 | "ERROR: %s\n", 90 | glewGetErrorString(GlewInitResult) 91 | ); 92 | exit(EXIT_FAILURE); 93 | } 94 | 95 | fprintf( 96 | stdout, 97 | "INFO: OpenGL Version: %s\n", 98 | glGetString(GL_VERSION) 99 | ); 100 | 101 | CreateShaders(); 102 | CreateVBO(); 103 | 104 | glClearColor(0.0f, 0.0f, 0.0f, 0.0f); 105 | } 106 | 107 | void InitWindow(int argc, char* argv[]) 108 | { 109 | glutInit(&argc, argv); 110 | 111 | glutInitContextVersion(3, 3); 112 | glutInitContextFlags(GLUT_FORWARD_COMPATIBLE); 113 | glutInitContextProfile(GLUT_CORE_PROFILE); 114 | 115 | glutSetOption( 116 | GLUT_ACTION_ON_WINDOW_CLOSE, 117 | GLUT_ACTION_GLUTMAINLOOP_RETURNS 118 | ); 119 | 120 | glutInitWindowSize(CurrentWidth, CurrentHeight); 121 | 122 | glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA); 123 | 124 | WindowHandle = glutCreateWindow(WINDOW_TITLE_PREFIX); 125 | 126 | if(WindowHandle < 1) { 127 | fprintf( 128 | stderr, 129 | "ERROR: Could not create a new rendering window.\n" 130 | ); 131 | exit(EXIT_FAILURE); 132 | } 133 | 134 | glutReshapeFunc(ResizeFunction); 135 | glutDisplayFunc(RenderFunction); 136 | glutIdleFunc(IdleFunction); 137 | glutTimerFunc(0, TimerFunction, 0); 138 | glutCloseFunc(Cleanup); 139 | } 140 | 141 | void ResizeFunction(int Width, int Height) 142 | { 143 | CurrentWidth = Width; 144 | CurrentHeight = Height; 145 | glViewport(0, 0, CurrentWidth, CurrentHeight); 146 | } 147 | 148 | void RenderFunction(void) 149 | { 150 | ++FrameCount; 151 | 152 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 153 | 154 | glDrawArrays(GL_TRIANGLE_STRIP, 0, 28); 155 | 156 | glutSwapBuffers(); 157 | } 158 | 159 | void IdleFunction(void) 160 | { 161 | glutPostRedisplay(); 162 | } 163 | 164 | void TimerFunction(int Value) 165 | { 166 | if (0 != Value) { 167 | char* TempString = (char*) 168 | malloc(512 + strlen(WINDOW_TITLE_PREFIX)); 169 | 170 | sprintf( 171 | TempString, 172 | "%s: %d Frames Per Second @ %d x %d", 173 | WINDOW_TITLE_PREFIX, 174 | FrameCount * 4, 175 | CurrentWidth, 176 | CurrentHeight 177 | ); 178 | 179 | glutSetWindowTitle(TempString); 180 | free(TempString); 181 | } 182 | 183 | FrameCount = 0; 184 | glutTimerFunc(250, TimerFunction, 1); 185 | } 186 | 187 | void Cleanup(void) 188 | { 189 | DestroyShaders(); 190 | DestroyVBO(); 191 | } 192 | 193 | void CreateVBO(void) 194 | { 195 | Vertex Vertices[] = 196 | { 197 | // Top 198 | { { 0.0f, 0.0f, 0.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, // 0 199 | { { -0.2f, 0.8f, 0.0f, 1.0f }, { 0.0f, 1.0f, 0.0f, 1.0f } }, // 1 200 | { { 0.0f, 0.8f, 0.0f, 1.0f }, { 0.0f, 1.0f, 1.0f, 1.0f } }, //3 201 | { { 0.0f, 1.0f, 0.0f, 1.0f }, { 1.0f, 0.0f, 0.0f, 1.0f } }, // 4 202 | { { 0.0f, 0.8f, 0.0f, 1.0f }, { 0.0f, 1.0f, 1.0f, 1.0f } }, //3 203 | { { 0.2f, 0.8f, 0.0f, 1.0f }, { 0.0f, 0.0f, 1.0f, 1.0f } }, // 2 204 | { { 0.0f, 0.0f, 0.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, // 0 205 | 206 | //// Bottom 207 | { { 0.0f, 0.0f, 0.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, // 0 208 | { { 0.2f, -0.8f, 0.0f, 1.0f }, { 0.0f, 0.0f, 1.0f, 1.0f } }, // 6 209 | { { 0.0f, -0.8f, 0.0f, 1.0f }, { 0.0f, 1.0f, 1.0f, 1.0f } }, //7 210 | { { 0.0f, -1.0f, 0.0f, 1.0f }, { 1.0f, 0.0f, 0.0f, 1.0f } }, // 8 211 | { { 0.0f, -0.8f, 0.0f, 1.0f }, { 0.0f, 1.0f, 1.0f, 1.0f } }, //7 212 | { { -0.2f, -0.8f, 0.0f, 1.0f }, { 0.0f, 1.0f, 0.0f, 1.0f } }, // 5 213 | { { 0.0f, 0.0f, 0.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, // 0 214 | 215 | //// Left 216 | { { 0.0f, 0.0f, 0.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, // 0 217 | { { -0.8f, -0.2f, 0.0f, 1.0f }, { 0.0f, 1.0f, 0.0f, 1.0f } }, // 9 218 | { { -0.8f, 0.0f, 0.0f, 1.0f }, { 0.0f, 1.0f, 1.0f, 1.0f } }, //11 219 | { { -1.0f, 0.0f, 0.0f, 1.0f }, { 1.0f, 0.0f, 0.0f, 1.0f } }, // 12 220 | { { -0.8f, 0.0f, 0.0f, 1.0f }, { 0.0f, 1.0f, 1.0f, 1.0f } }, //11 221 | { { -0.8f, 0.2f, 0.0f, 1.0f }, { 0.0f, 0.0f, 1.0f, 1.0f } }, // 10 222 | { { 0.0f, 0.0f, 0.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, // 0 223 | 224 | //// Right 225 | { { 0.0f, 0.0f, 0.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, // 0 226 | { { 0.8f, 0.2f, 0.0f, 1.0f }, { 0.0f, 0.0f, 1.0f, 1.0f } }, // 14 227 | { { 0.8f, 0.0f, 0.0f, 1.0f }, { 0.0f, 1.0f, 1.0f, 1.0f } }, //15 228 | { { 1.0f, 0.0f, 0.0f, 1.0f }, { 1.0f, 0.0f, 0.0f, 1.0f } }, // 16 229 | { { 0.8f, 0.0f, 0.0f, 1.0f }, { 0.0f, 1.0f, 1.0f, 1.0f } }, //15 230 | { { 0.8f, -0.2f, 0.0f, 1.0f }, { 0.0f, 1.0f, 0.0f, 1.0f } }, // 13 231 | { { 0.0f, 0.0f, 0.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, // 0 232 | }; 233 | 234 | GLenum ErrorCheckValue = glGetError(); 235 | const size_t BufferSize = sizeof(Vertices); 236 | const size_t VertexSize = sizeof(Vertices[0]); 237 | const size_t RgbOffset = sizeof(Vertices[0].XYZW); 238 | 239 | glGenVertexArrays(1, &VaoId); 240 | glBindVertexArray(VaoId); 241 | 242 | glGenBuffers(1, &BufferId); 243 | glBindBuffer(GL_ARRAY_BUFFER, BufferId); 244 | glBufferData(GL_ARRAY_BUFFER, BufferSize, Vertices, GL_STATIC_DRAW); 245 | 246 | glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, VertexSize, 0); 247 | glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, VertexSize, (GLvoid*)RgbOffset); 248 | 249 | glEnableVertexAttribArray(0); 250 | glEnableVertexAttribArray(1); 251 | 252 | ErrorCheckValue = glGetError(); 253 | if (ErrorCheckValue != GL_NO_ERROR) 254 | { 255 | fprintf( 256 | stderr, 257 | "ERROR: Could not create a VBO: %s \n", 258 | gluErrorString(ErrorCheckValue) 259 | ); 260 | 261 | exit(-1); 262 | } 263 | } 264 | 265 | void DestroyVBO(void) 266 | { 267 | GLenum ErrorCheckValue = glGetError(); 268 | 269 | glDisableVertexAttribArray(1); 270 | glDisableVertexAttribArray(0); 271 | 272 | glBindBuffer(GL_ARRAY_BUFFER, 0); 273 | glDeleteBuffers(1, &BufferId); 274 | 275 | glBindVertexArray(0); 276 | glDeleteVertexArrays(1, &VaoId); 277 | 278 | ErrorCheckValue = glGetError(); 279 | if (ErrorCheckValue != GL_NO_ERROR) 280 | { 281 | fprintf( 282 | stderr, 283 | "ERROR: Could not destroy the VBO: %s \n", 284 | gluErrorString(ErrorCheckValue) 285 | ); 286 | 287 | exit(-1); 288 | } 289 | } 290 | 291 | void CreateShaders(void) 292 | { 293 | GLenum ErrorCheckValue = glGetError(); 294 | 295 | VertexShaderId = glCreateShader(GL_VERTEX_SHADER); 296 | glShaderSource(VertexShaderId, 1, &VertexShader, NULL); 297 | glCompileShader(VertexShaderId); 298 | 299 | FragmentShaderId = glCreateShader(GL_FRAGMENT_SHADER); 300 | glShaderSource(FragmentShaderId, 1, &FragmentShader, NULL); 301 | glCompileShader(FragmentShaderId); 302 | 303 | ProgramId = glCreateProgram(); 304 | glAttachShader(ProgramId, VertexShaderId); 305 | glAttachShader(ProgramId, FragmentShaderId); 306 | glLinkProgram(ProgramId); 307 | glUseProgram(ProgramId); 308 | 309 | ErrorCheckValue = glGetError(); 310 | if (ErrorCheckValue != GL_NO_ERROR) 311 | { 312 | fprintf( 313 | stderr, 314 | "ERROR: Could not create the shaders: %s \n", 315 | gluErrorString(ErrorCheckValue) 316 | ); 317 | 318 | exit(-1); 319 | } 320 | } 321 | 322 | void DestroyShaders(void) 323 | { 324 | GLenum ErrorCheckValue = glGetError(); 325 | 326 | glUseProgram(0); 327 | 328 | glDetachShader(ProgramId, VertexShaderId); 329 | glDetachShader(ProgramId, FragmentShaderId); 330 | 331 | glDeleteShader(FragmentShaderId); 332 | glDeleteShader(VertexShaderId); 333 | 334 | glDeleteProgram(ProgramId); 335 | 336 | ErrorCheckValue = glGetError(); 337 | if (ErrorCheckValue != GL_NO_ERROR) 338 | { 339 | fprintf( 340 | stderr, 341 | "ERROR: Could not destroy the shaders: %s \n", 342 | gluErrorString(ErrorCheckValue) 343 | ); 344 | 345 | exit(-1); 346 | } 347 | } 348 | -------------------------------------------------------------------------------- /chapter-3/compatibility/chapter.3.1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #define WINDOW_TITLE_PREFIX "Chapter 3" 7 | 8 | typedef struct 9 | { 10 | float XYZW[4]; 11 | float RGBA[4]; 12 | } Vertex; 13 | 14 | int 15 | CurrentWidth = 600, 16 | CurrentHeight = 600, 17 | WindowHandle = 0; 18 | 19 | unsigned FrameCount = 0; 20 | 21 | GLuint 22 | VertexShaderId, 23 | FragmentShaderId, 24 | ProgramId, 25 | VaoId, 26 | BufferId, 27 | IndexBufferId; 28 | 29 | const GLchar* VertexShader = 30 | { 31 | "#version 330\n"\ 32 | 33 | "layout(location=0) in vec4 in_Position;\n"\ 34 | "layout(location=1) in vec4 in_Color;\n"\ 35 | "out vec4 ex_Color;\n"\ 36 | 37 | "void main(void)\n"\ 38 | "{\n"\ 39 | " gl_Position = in_Position;\n"\ 40 | " ex_Color = in_Color;\n"\ 41 | "}\n" 42 | }; 43 | 44 | const GLchar* FragmentShader = 45 | { 46 | "#version 330\n"\ 47 | 48 | "in vec4 ex_Color;\n"\ 49 | "out vec4 out_Color;\n"\ 50 | 51 | "void main(void)\n"\ 52 | "{\n"\ 53 | " out_Color = ex_Color;\n"\ 54 | "}\n" 55 | }; 56 | 57 | void Initialize(int, char*[]); 58 | void InitWindow(int, char*[]); 59 | void ResizeFunction(int, int); 60 | void RenderFunction(void); 61 | void TimerFunction(int); 62 | void IdleFunction(void); 63 | void Cleanup(void); 64 | void CreateVBO(void); 65 | void DestroyVBO(void); 66 | void CreateShaders(void); 67 | void DestroyShaders(void); 68 | 69 | int main(int argc, char* argv[]) 70 | { 71 | Initialize(argc, argv); 72 | 73 | glutMainLoop(); 74 | 75 | exit(EXIT_SUCCESS); 76 | } 77 | 78 | void Initialize(int argc, char* argv[]) 79 | { 80 | GLenum GlewInitResult; 81 | 82 | InitWindow(argc, argv); 83 | 84 | glewExperimental = GL_TRUE; 85 | GlewInitResult = glewInit(); 86 | 87 | if (GLEW_OK != GlewInitResult) { 88 | fprintf( 89 | stderr, 90 | "ERROR: %s\n", 91 | glewGetErrorString(GlewInitResult) 92 | ); 93 | exit(EXIT_FAILURE); 94 | } 95 | 96 | fprintf( 97 | stdout, 98 | "INFO: OpenGL Version: %s\n", 99 | glGetString(GL_VERSION) 100 | ); 101 | 102 | CreateShaders(); 103 | CreateVBO(); 104 | 105 | glClearColor(0.0f, 0.0f, 0.0f, 0.0f); 106 | } 107 | 108 | void InitWindow(int argc, char* argv[]) 109 | { 110 | glutInit(&argc, argv); 111 | 112 | glutInitContextVersion(3, 3); 113 | glutInitContextFlags(GLUT_FORWARD_COMPATIBLE); 114 | glutInitContextProfile(GLUT_CORE_PROFILE); 115 | 116 | glutSetOption( 117 | GLUT_ACTION_ON_WINDOW_CLOSE, 118 | GLUT_ACTION_GLUTMAINLOOP_RETURNS 119 | ); 120 | 121 | glutInitWindowSize(CurrentWidth, CurrentHeight); 122 | 123 | glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA); 124 | 125 | WindowHandle = glutCreateWindow(WINDOW_TITLE_PREFIX); 126 | 127 | if(WindowHandle < 1) { 128 | fprintf( 129 | stderr, 130 | "ERROR: Could not create a new rendering window.\n" 131 | ); 132 | exit(EXIT_FAILURE); 133 | } 134 | 135 | glutReshapeFunc(ResizeFunction); 136 | glutDisplayFunc(RenderFunction); 137 | glutIdleFunc(IdleFunction); 138 | glutTimerFunc(0, TimerFunction, 0); 139 | glutCloseFunc(Cleanup); 140 | } 141 | 142 | void ResizeFunction(int Width, int Height) 143 | { 144 | CurrentWidth = Width; 145 | CurrentHeight = Height; 146 | glViewport(0, 0, CurrentWidth, CurrentHeight); 147 | } 148 | 149 | void RenderFunction(void) 150 | { 151 | ++FrameCount; 152 | 153 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 154 | 155 | glDrawElements(GL_TRIANGLES, 48, GL_UNSIGNED_BYTE, NULL); 156 | 157 | glutSwapBuffers(); 158 | } 159 | 160 | void IdleFunction(void) 161 | { 162 | glutPostRedisplay(); 163 | } 164 | 165 | void TimerFunction(int Value) 166 | { 167 | if (0 != Value) { 168 | char* TempString = (char*) 169 | malloc(512 + strlen(WINDOW_TITLE_PREFIX)); 170 | 171 | sprintf( 172 | TempString, 173 | "%s: %d Frames Per Second @ %d x %d", 174 | WINDOW_TITLE_PREFIX, 175 | FrameCount * 4, 176 | CurrentWidth, 177 | CurrentHeight 178 | ); 179 | 180 | glutSetWindowTitle(TempString); 181 | free(TempString); 182 | } 183 | 184 | FrameCount = 0; 185 | glutTimerFunc(250, TimerFunction, 1); 186 | } 187 | 188 | void Cleanup(void) 189 | { 190 | DestroyShaders(); 191 | DestroyVBO(); 192 | } 193 | 194 | void CreateVBO(void) 195 | { 196 | Vertex Vertices[] = 197 | { 198 | { { 0.0f, 0.0f, 0.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, // 0 199 | 200 | // Top 201 | { { -0.2f, 0.8f, 0.0f, 1.0f }, { 0.0f, 1.0f, 0.0f, 1.0f } }, // 1 202 | { { 0.2f, 0.8f, 0.0f, 1.0f }, { 0.0f, 0.0f, 1.0f, 1.0f } }, // 2 203 | { { 0.0f, 0.8f, 0.0f, 1.0f }, { 0.0f, 1.0f, 1.0f, 1.0f } }, //3 204 | { { 0.0f, 1.0f, 0.0f, 1.0f }, { 1.0f, 0.0f, 0.0f, 1.0f } }, // 4 205 | 206 | // Bottom 207 | { { -0.2f, -0.8f, 0.0f, 1.0f }, { 0.0f, 0.0f, 1.0f, 1.0f } }, // 5 208 | { { 0.2f, -0.8f, 0.0f, 1.0f }, { 0.0f, 1.0f, 0.0f, 1.0f } }, // 6 209 | { { 0.0f, -0.8f, 0.0f, 1.0f }, { 0.0f, 1.0f, 1.0f, 1.0f } }, //7 210 | { { 0.0f, -1.0f, 0.0f, 1.0f }, { 1.0f, 0.0f, 0.0f, 1.0f } }, // 8 211 | 212 | // Left 213 | { { -0.8f, -0.2f, 0.0f, 1.0f }, { 0.0f, 1.0f, 0.0f, 1.0f } }, // 9 214 | { { -0.8f, 0.2f, 0.0f, 1.0f }, { 0.0f, 0.0f, 1.0f, 1.0f } }, // 10 215 | { { -0.8f, 0.0f, 0.0f, 1.0f }, { 0.0f, 1.0f, 1.0f, 1.0f } }, //11 216 | { { -1.0f, 0.0f, 0.0f, 1.0f }, { 1.0f, 0.0f, 0.0f, 1.0f } }, // 12 217 | 218 | // Right 219 | { { 0.8f, -0.2f, 0.0f, 1.0f }, { 0.0f, 0.0f, 1.0f, 1.0f } }, // 13 220 | { { 0.8f, 0.2f, 0.0f, 1.0f }, { 0.0f, 1.0f, 0.0f, 1.0f } }, // 14 221 | { { 0.8f, 0.0f, 0.0f, 1.0f }, { 0.0f, 1.0f, 1.0f, 1.0f } }, //15 222 | { { 1.0f, 0.0f, 0.0f, 1.0f }, { 1.0f, 0.0f, 0.0f, 1.0f } } // 16 223 | }; 224 | 225 | GLubyte Indices[] = { 226 | // Top 227 | 0, 1, 3, 228 | 0, 3, 2, 229 | 3, 1, 4, 230 | 3, 4, 2, 231 | 232 | // Bottom 233 | 0, 5, 7, 234 | 0, 7, 6, 235 | 7, 5, 8, 236 | 7, 8, 6, 237 | 238 | // Left 239 | 0, 9, 11, 240 | 0, 11, 10, 241 | 11, 9, 12, 242 | 11, 12, 10, 243 | 244 | // Right 245 | 0, 13, 15, 246 | 0, 15, 14, 247 | 15, 13, 16, 248 | 15, 16, 14 249 | }; 250 | 251 | GLenum ErrorCheckValue = glGetError(); 252 | const size_t BufferSize = sizeof(Vertices); 253 | const size_t VertexSize = sizeof(Vertices[0]); 254 | const size_t RgbOffset = sizeof(Vertices[0].XYZW); 255 | 256 | glGenVertexArrays(1, &VaoId); 257 | glBindVertexArray(VaoId); 258 | 259 | glGenBuffers(1, &BufferId); 260 | glBindBuffer(GL_ARRAY_BUFFER, BufferId); 261 | glBufferData(GL_ARRAY_BUFFER, BufferSize, Vertices, GL_STATIC_DRAW); 262 | 263 | glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, VertexSize, 0); 264 | glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, VertexSize, (GLvoid*)RgbOffset); 265 | 266 | glEnableVertexAttribArray(0); 267 | glEnableVertexAttribArray(1); 268 | 269 | glGenBuffers(1, &IndexBufferId); 270 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IndexBufferId); 271 | glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(Indices), Indices, GL_STATIC_DRAW); 272 | 273 | ErrorCheckValue = glGetError(); 274 | if (ErrorCheckValue != GL_NO_ERROR) 275 | { 276 | fprintf( 277 | stderr, 278 | "ERROR: Could not create a VBO: %s \n", 279 | gluErrorString(ErrorCheckValue) 280 | ); 281 | 282 | exit(-1); 283 | } 284 | } 285 | 286 | void DestroyVBO(void) 287 | { 288 | GLenum ErrorCheckValue = glGetError(); 289 | 290 | glDisableVertexAttribArray(1); 291 | glDisableVertexAttribArray(0); 292 | 293 | glBindBuffer(GL_ARRAY_BUFFER, 0); 294 | glDeleteBuffers(1, &BufferId); 295 | 296 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 297 | glDeleteBuffers(1, &IndexBufferId); 298 | 299 | glBindVertexArray(0); 300 | glDeleteVertexArrays(1, &VaoId); 301 | 302 | ErrorCheckValue = glGetError(); 303 | if (ErrorCheckValue != GL_NO_ERROR) 304 | { 305 | fprintf( 306 | stderr, 307 | "ERROR: Could not destroy the VBO: %s \n", 308 | gluErrorString(ErrorCheckValue) 309 | ); 310 | 311 | exit(-1); 312 | } 313 | } 314 | 315 | void CreateShaders(void) 316 | { 317 | GLenum ErrorCheckValue = glGetError(); 318 | 319 | VertexShaderId = glCreateShader(GL_VERTEX_SHADER); 320 | glShaderSource(VertexShaderId, 1, &VertexShader, NULL); 321 | glCompileShader(VertexShaderId); 322 | 323 | FragmentShaderId = glCreateShader(GL_FRAGMENT_SHADER); 324 | glShaderSource(FragmentShaderId, 1, &FragmentShader, NULL); 325 | glCompileShader(FragmentShaderId); 326 | 327 | ProgramId = glCreateProgram(); 328 | glAttachShader(ProgramId, VertexShaderId); 329 | glAttachShader(ProgramId, FragmentShaderId); 330 | glLinkProgram(ProgramId); 331 | glUseProgram(ProgramId); 332 | 333 | ErrorCheckValue = glGetError(); 334 | if (ErrorCheckValue != GL_NO_ERROR) 335 | { 336 | fprintf( 337 | stderr, 338 | "ERROR: Could not create the shaders: %s \n", 339 | gluErrorString(ErrorCheckValue) 340 | ); 341 | 342 | exit(-1); 343 | } 344 | } 345 | 346 | void DestroyShaders(void) 347 | { 348 | GLenum ErrorCheckValue = glGetError(); 349 | 350 | glUseProgram(0); 351 | 352 | glDetachShader(ProgramId, VertexShaderId); 353 | glDetachShader(ProgramId, FragmentShaderId); 354 | 355 | glDeleteShader(FragmentShaderId); 356 | glDeleteShader(VertexShaderId); 357 | 358 | glDeleteProgram(ProgramId); 359 | 360 | ErrorCheckValue = glGetError(); 361 | if (ErrorCheckValue != GL_NO_ERROR) 362 | { 363 | fprintf( 364 | stderr, 365 | "ERROR: Could not destroy the shaders: %s \n", 366 | gluErrorString(ErrorCheckValue) 367 | ); 368 | 369 | exit(-1); 370 | } 371 | } -------------------------------------------------------------------------------- /chapter-3/compatibility/chapter.3.2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #define WINDOW_TITLE_PREFIX "Chapter 3" 7 | 8 | typedef struct 9 | { 10 | float XYZW[4]; 11 | float RGBA[4]; 12 | } Vertex; 13 | 14 | int 15 | CurrentWidth = 600, 16 | CurrentHeight = 600, 17 | WindowHandle = 0; 18 | 19 | unsigned FrameCount = 0; 20 | 21 | GLuint 22 | VertexShaderId, 23 | FragmentShaderId, 24 | ProgramId, 25 | VaoId, 26 | BufferId, 27 | IndexBufferId[2], 28 | ActiveIndexBuffer = 0; 29 | 30 | const GLchar* VertexShader = 31 | { 32 | "#version 330\n"\ 33 | 34 | "layout(location=0) in vec4 in_Position;\n"\ 35 | "layout(location=1) in vec4 in_Color;\n"\ 36 | "out vec4 ex_Color;\n"\ 37 | 38 | "void main(void)\n"\ 39 | "{\n"\ 40 | " gl_Position = in_Position;\n"\ 41 | " ex_Color = in_Color;\n"\ 42 | "}\n" 43 | }; 44 | 45 | const GLchar* FragmentShader = 46 | { 47 | "#version 330\n"\ 48 | 49 | "in vec4 ex_Color;\n"\ 50 | "out vec4 out_Color;\n"\ 51 | 52 | "void main(void)\n"\ 53 | "{\n"\ 54 | " out_Color = ex_Color;\n"\ 55 | "}\n" 56 | }; 57 | 58 | void Initialize(int, char*[]); 59 | void InitWindow(int, char*[]); 60 | void ResizeFunction(int, int); 61 | void RenderFunction(void); 62 | void TimerFunction(int); 63 | void IdleFunction(void); 64 | void KeyboardFunction(unsigned char, int, int); 65 | void Cleanup(void); 66 | void CreateVBO(void); 67 | void DestroyVBO(void); 68 | void CreateShaders(void); 69 | void DestroyShaders(void); 70 | 71 | int main(int argc, char* argv[]) 72 | { 73 | Initialize(argc, argv); 74 | 75 | glutMainLoop(); 76 | 77 | exit(EXIT_SUCCESS); 78 | } 79 | 80 | void Initialize(int argc, char* argv[]) 81 | { 82 | GLenum GlewInitResult; 83 | 84 | InitWindow(argc, argv); 85 | 86 | glewExperimental = GL_TRUE; 87 | GlewInitResult = glewInit(); 88 | 89 | if (GLEW_OK != GlewInitResult) { 90 | fprintf( 91 | stderr, 92 | "ERROR: %s\n", 93 | glewGetErrorString(GlewInitResult) 94 | ); 95 | exit(EXIT_FAILURE); 96 | } 97 | 98 | fprintf( 99 | stdout, 100 | "INFO: OpenGL Version: %s\n", 101 | glGetString(GL_VERSION) 102 | ); 103 | 104 | CreateShaders(); 105 | CreateVBO(); 106 | 107 | glClearColor(0.0f, 0.0f, 0.0f, 0.0f); 108 | } 109 | 110 | void InitWindow(int argc, char* argv[]) 111 | { 112 | glutInit(&argc, argv); 113 | 114 | glutInitContextVersion(3, 3); 115 | glutInitContextFlags(GLUT_FORWARD_COMPATIBLE); 116 | glutInitContextProfile(GLUT_CORE_PROFILE); 117 | 118 | glutSetOption( 119 | GLUT_ACTION_ON_WINDOW_CLOSE, 120 | GLUT_ACTION_GLUTMAINLOOP_RETURNS 121 | ); 122 | 123 | glutInitWindowSize(CurrentWidth, CurrentHeight); 124 | 125 | glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA); 126 | 127 | WindowHandle = glutCreateWindow(WINDOW_TITLE_PREFIX); 128 | 129 | if(WindowHandle < 1) { 130 | fprintf( 131 | stderr, 132 | "ERROR: Could not create a new rendering window.\n" 133 | ); 134 | exit(EXIT_FAILURE); 135 | } 136 | 137 | glutReshapeFunc(ResizeFunction); 138 | glutDisplayFunc(RenderFunction); 139 | glutIdleFunc(IdleFunction); 140 | glutTimerFunc(0, TimerFunction, 0); 141 | glutCloseFunc(Cleanup); 142 | glutKeyboardFunc(KeyboardFunction); 143 | } 144 | 145 | void KeyboardFunction(unsigned char Key, int X, int Y) 146 | { 147 | switch (Key) 148 | { 149 | case 'T': 150 | case 't': 151 | { 152 | ActiveIndexBuffer = (ActiveIndexBuffer == 1 ? 0 : 1); 153 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IndexBufferId[ActiveIndexBuffer]); 154 | break; 155 | } 156 | default: 157 | break; 158 | } 159 | } 160 | 161 | void ResizeFunction(int Width, int Height) 162 | { 163 | CurrentWidth = Width; 164 | CurrentHeight = Height; 165 | glViewport(0, 0, CurrentWidth, CurrentHeight); 166 | } 167 | 168 | void RenderFunction(void) 169 | { 170 | ++FrameCount; 171 | 172 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 173 | 174 | if (ActiveIndexBuffer == 0) { 175 | glDrawElements(GL_TRIANGLES, 48, GL_UNSIGNED_BYTE, NULL); 176 | } else { 177 | glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_BYTE, NULL); 178 | } 179 | 180 | glutSwapBuffers(); 181 | } 182 | 183 | void IdleFunction(void) 184 | { 185 | glutPostRedisplay(); 186 | } 187 | 188 | void TimerFunction(int Value) 189 | { 190 | if (0 != Value) { 191 | char* TempString = (char*) 192 | malloc(512 + strlen(WINDOW_TITLE_PREFIX)); 193 | 194 | sprintf( 195 | TempString, 196 | "%s: %d Frames Per Second @ %d x %d", 197 | WINDOW_TITLE_PREFIX, 198 | FrameCount * 4, 199 | CurrentWidth, 200 | CurrentHeight 201 | ); 202 | 203 | glutSetWindowTitle(TempString); 204 | free(TempString); 205 | } 206 | 207 | FrameCount = 0; 208 | glutTimerFunc(250, TimerFunction, 1); 209 | } 210 | 211 | void Cleanup(void) 212 | { 213 | DestroyShaders(); 214 | DestroyVBO(); 215 | } 216 | 217 | void CreateVBO(void) 218 | { 219 | Vertex Vertices[] = 220 | { 221 | { { 0.0f, 0.0f, 0.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, // 0 222 | 223 | // Top 224 | { { -0.2f, 0.8f, 0.0f, 1.0f }, { 0.0f, 1.0f, 0.0f, 1.0f } }, // 1 225 | { { 0.2f, 0.8f, 0.0f, 1.0f }, { 0.0f, 0.0f, 1.0f, 1.0f } }, // 2 226 | { { 0.0f, 0.8f, 0.0f, 1.0f }, { 0.0f, 1.0f, 1.0f, 1.0f } }, //3 227 | { { 0.0f, 1.0f, 0.0f, 1.0f }, { 1.0f, 0.0f, 0.0f, 1.0f } }, // 4 228 | 229 | // Bottom 230 | { { -0.2f, -0.8f, 0.0f, 1.0f }, { 0.0f, 0.0f, 1.0f, 1.0f } }, // 5 231 | { { 0.2f, -0.8f, 0.0f, 1.0f }, { 0.0f, 1.0f, 0.0f, 1.0f } }, // 6 232 | { { 0.0f, -0.8f, 0.0f, 1.0f }, { 0.0f, 1.0f, 1.0f, 1.0f } }, //7 233 | { { 0.0f, -1.0f, 0.0f, 1.0f }, { 1.0f, 0.0f, 0.0f, 1.0f } }, // 8 234 | 235 | // Left 236 | { { -0.8f, -0.2f, 0.0f, 1.0f }, { 0.0f, 1.0f, 0.0f, 1.0f } }, // 9 237 | { { -0.8f, 0.2f, 0.0f, 1.0f }, { 0.0f, 0.0f, 1.0f, 1.0f } }, // 10 238 | { { -0.8f, 0.0f, 0.0f, 1.0f }, { 0.0f, 1.0f, 1.0f, 1.0f } }, //11 239 | { { -1.0f, 0.0f, 0.0f, 1.0f }, { 1.0f, 0.0f, 0.0f, 1.0f } }, // 12 240 | 241 | // Right 242 | { { 0.8f, -0.2f, 0.0f, 1.0f }, { 0.0f, 0.0f, 1.0f, 1.0f } }, // 13 243 | { { 0.8f, 0.2f, 0.0f, 1.0f }, { 0.0f, 1.0f, 0.0f, 1.0f } }, // 14 244 | { { 0.8f, 0.0f, 0.0f, 1.0f }, { 0.0f, 1.0f, 1.0f, 1.0f } }, //15 245 | { { 1.0f, 0.0f, 0.0f, 1.0f }, { 1.0f, 0.0f, 0.0f, 1.0f } } // 16 246 | }; 247 | 248 | GLubyte Indices[] = { 249 | // Top 250 | 0, 1, 3, 251 | 0, 3, 2, 252 | 3, 1, 4, 253 | 3, 4, 2, 254 | 255 | // Bottom 256 | 0, 5, 7, 257 | 0, 7, 6, 258 | 7, 5, 8, 259 | 7, 8, 6, 260 | 261 | // Left 262 | 0, 9, 11, 263 | 0, 11, 10, 264 | 11, 9, 12, 265 | 11, 12, 10, 266 | 267 | // Right 268 | 0, 13, 15, 269 | 0, 15, 14, 270 | 15, 13, 16, 271 | 15, 16, 14 272 | }; 273 | 274 | GLubyte AlternateIndices[] = { 275 | // Outer square border: 276 | 3, 4, 16, 277 | 3, 15, 16, 278 | 15, 16, 8, 279 | 15, 7, 8, 280 | 7, 8, 12, 281 | 7, 11, 12, 282 | 11, 12, 4, 283 | 11, 3, 4, 284 | 285 | // Inner square 286 | 0, 11, 3, 287 | 0, 3, 15, 288 | 0, 15, 7, 289 | 0, 7, 11 290 | }; 291 | 292 | GLenum ErrorCheckValue = glGetError(); 293 | const size_t BufferSize = sizeof(Vertices); 294 | const size_t VertexSize = sizeof(Vertices[0]); 295 | const size_t RgbOffset = sizeof(Vertices[0].XYZW); 296 | 297 | glGenVertexArrays(1, &VaoId); 298 | glBindVertexArray(VaoId); 299 | 300 | glGenBuffers(1, &BufferId); 301 | glBindBuffer(GL_ARRAY_BUFFER, BufferId); 302 | glBufferData(GL_ARRAY_BUFFER, BufferSize, Vertices, GL_STATIC_DRAW); 303 | 304 | glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, VertexSize, 0); 305 | glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, VertexSize, (GLvoid*)RgbOffset); 306 | 307 | glEnableVertexAttribArray(0); 308 | glEnableVertexAttribArray(1); 309 | 310 | glGenBuffers(2, IndexBufferId); 311 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IndexBufferId[0]); 312 | glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(Indices), Indices, GL_STATIC_DRAW); 313 | 314 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IndexBufferId[1]); 315 | glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(AlternateIndices), AlternateIndices, GL_STATIC_DRAW); 316 | 317 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IndexBufferId[0]); 318 | 319 | ErrorCheckValue = glGetError(); 320 | if (ErrorCheckValue != GL_NO_ERROR) 321 | { 322 | fprintf( 323 | stderr, 324 | "ERROR: Could not create a VBO: %s \n", 325 | gluErrorString(ErrorCheckValue) 326 | ); 327 | 328 | exit(-1); 329 | } 330 | } 331 | 332 | void DestroyVBO(void) 333 | { 334 | GLenum ErrorCheckValue = glGetError(); 335 | 336 | glDisableVertexAttribArray(1); 337 | glDisableVertexAttribArray(0); 338 | 339 | glBindBuffer(GL_ARRAY_BUFFER, 0); 340 | glDeleteBuffers(1, &BufferId); 341 | 342 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 343 | glDeleteBuffers(2, IndexBufferId); 344 | 345 | glBindVertexArray(0); 346 | glDeleteVertexArrays(1, &VaoId); 347 | 348 | ErrorCheckValue = glGetError(); 349 | if (ErrorCheckValue != GL_NO_ERROR) 350 | { 351 | fprintf( 352 | stderr, 353 | "ERROR: Could not destroy the VBO: %s \n", 354 | gluErrorString(ErrorCheckValue) 355 | ); 356 | 357 | exit(-1); 358 | } 359 | } 360 | 361 | void CreateShaders(void) 362 | { 363 | GLenum ErrorCheckValue = glGetError(); 364 | 365 | VertexShaderId = glCreateShader(GL_VERTEX_SHADER); 366 | glShaderSource(VertexShaderId, 1, &VertexShader, NULL); 367 | glCompileShader(VertexShaderId); 368 | 369 | FragmentShaderId = glCreateShader(GL_FRAGMENT_SHADER); 370 | glShaderSource(FragmentShaderId, 1, &FragmentShader, NULL); 371 | glCompileShader(FragmentShaderId); 372 | 373 | ProgramId = glCreateProgram(); 374 | glAttachShader(ProgramId, VertexShaderId); 375 | glAttachShader(ProgramId, FragmentShaderId); 376 | glLinkProgram(ProgramId); 377 | glUseProgram(ProgramId); 378 | 379 | ErrorCheckValue = glGetError(); 380 | if (ErrorCheckValue != GL_NO_ERROR) 381 | { 382 | fprintf( 383 | stderr, 384 | "ERROR: Could not create the shaders: %s \n", 385 | gluErrorString(ErrorCheckValue) 386 | ); 387 | 388 | exit(-1); 389 | } 390 | } 391 | 392 | void DestroyShaders(void) 393 | { 394 | GLenum ErrorCheckValue = glGetError(); 395 | 396 | glUseProgram(0); 397 | 398 | glDetachShader(ProgramId, VertexShaderId); 399 | glDetachShader(ProgramId, FragmentShaderId); 400 | 401 | glDeleteShader(FragmentShaderId); 402 | glDeleteShader(VertexShaderId); 403 | 404 | glDeleteProgram(ProgramId); 405 | 406 | ErrorCheckValue = glGetError(); 407 | if (ErrorCheckValue != GL_NO_ERROR) 408 | { 409 | fprintf( 410 | stderr, 411 | "ERROR: Could not destroy the shaders: %s \n", 412 | gluErrorString(ErrorCheckValue) 413 | ); 414 | 415 | exit(-1); 416 | } 417 | } -------------------------------------------------------------------------------- /chapter-4/SimpleShader.fragment.glsl: -------------------------------------------------------------------------------- 1 | #version 400 2 | 3 | in vec4 ex_Color; 4 | out vec4 out_Color; 5 | 6 | void main(void) 7 | { 8 | out_Color = ex_Color; 9 | } -------------------------------------------------------------------------------- /chapter-4/SimpleShader.vertex.glsl: -------------------------------------------------------------------------------- 1 | #version 400 2 | 3 | layout(location=0) in vec4 in_Position; 4 | layout(location=1) in vec4 in_Color; 5 | out vec4 ex_Color; 6 | 7 | uniform mat4 ModelMatrix; 8 | uniform mat4 ViewMatrix; 9 | uniform mat4 ProjectionMatrix; 10 | 11 | void main(void) 12 | { 13 | gl_Position = (ProjectionMatrix * ViewMatrix * ModelMatrix) * in_Position; 14 | ex_Color = in_Color; 15 | } -------------------------------------------------------------------------------- /chapter-4/Utils.c: -------------------------------------------------------------------------------- 1 | #include "Utils.h" 2 | 3 | const Matrix IDENTITY_MATRIX = { { 4 | 1, 0, 0, 0, 5 | 0, 1, 0, 0, 6 | 0, 0, 1, 0, 7 | 0, 0, 0, 1 8 | } }; 9 | 10 | float Cotangent(float angle) 11 | { 12 | return (float)(1.0 / tan(angle)); 13 | } 14 | 15 | float DegreesToRadians(float degrees) 16 | { 17 | return degrees * (float)(PI / 180); 18 | } 19 | 20 | float RadiansToDegrees(float radians) 21 | { 22 | return radians * (float)(180 / PI); 23 | } 24 | 25 | Matrix MultiplyMatrices(const Matrix* m1, const Matrix* m2) 26 | { 27 | Matrix out = IDENTITY_MATRIX; 28 | unsigned int row, column, row_offset; 29 | 30 | for (row = 0, row_offset = row * 4; row < 4; ++row, row_offset = row * 4) 31 | for (column = 0; column < 4; ++column) 32 | out.m[row_offset + column] = 33 | (m1->m[row_offset + 0] * m2->m[column + 0]) + 34 | (m1->m[row_offset + 1] * m2->m[column + 4]) + 35 | (m1->m[row_offset + 2] * m2->m[column + 8]) + 36 | (m1->m[row_offset + 3] * m2->m[column + 12]); 37 | 38 | return out; 39 | } 40 | 41 | void ScaleMatrix(Matrix* m, float x, float y, float z) 42 | { 43 | Matrix scale = IDENTITY_MATRIX; 44 | 45 | scale.m[0] = x; 46 | scale.m[5] = y; 47 | scale.m[10] = z; 48 | 49 | memcpy(m->m, MultiplyMatrices(m, &scale).m, sizeof(m->m)); 50 | } 51 | 52 | void TranslateMatrix(Matrix* m, float x, float y, float z) 53 | { 54 | Matrix translation = IDENTITY_MATRIX; 55 | 56 | translation.m[12] = x; 57 | translation.m[13] = y; 58 | translation.m[14] = z; 59 | 60 | memcpy(m->m, MultiplyMatrices(m, &translation).m, sizeof(m->m)); 61 | } 62 | 63 | void RotateAboutX(Matrix* m, float angle) 64 | { 65 | Matrix rotation = IDENTITY_MATRIX; 66 | float sine = (float)sin(angle); 67 | float cosine = (float)cos(angle); 68 | 69 | rotation.m[5] = cosine; 70 | rotation.m[6] = -sine; 71 | rotation.m[9] = sine; 72 | rotation.m[10] = cosine; 73 | 74 | memcpy(m->m, MultiplyMatrices(m, &rotation).m, sizeof(m->m)); 75 | } 76 | 77 | void RotateAboutY(Matrix* m, float angle) 78 | { 79 | Matrix rotation = IDENTITY_MATRIX; 80 | float sine = (float)sin(angle); 81 | float cosine = (float)cos(angle); 82 | 83 | rotation.m[0] = cosine; 84 | rotation.m[8] = sine; 85 | rotation.m[2] = -sine; 86 | rotation.m[10] = cosine; 87 | 88 | memcpy(m->m, MultiplyMatrices(m, &rotation).m, sizeof(m->m)); 89 | } 90 | 91 | void RotateAboutZ(Matrix* m, float angle) 92 | { 93 | Matrix rotation = IDENTITY_MATRIX; 94 | float sine = (float)sin(angle); 95 | float cosine = (float)cos(angle); 96 | 97 | rotation.m[0] = cosine; 98 | rotation.m[1] = -sine; 99 | rotation.m[4] = sine; 100 | rotation.m[5] = cosine; 101 | 102 | memcpy(m->m, MultiplyMatrices(m, &rotation).m, sizeof(m->m)); 103 | } 104 | 105 | Matrix CreateProjectionMatrix( 106 | float fovy, 107 | float aspect_ratio, 108 | float near_plane, 109 | float far_plane 110 | ) 111 | { 112 | Matrix out = { { 0 } }; 113 | 114 | const float 115 | y_scale = Cotangent(DegreesToRadians(fovy / 2)), 116 | x_scale = y_scale / aspect_ratio, 117 | frustum_length = far_plane - near_plane; 118 | 119 | out.m[0] = x_scale; 120 | out.m[5] = y_scale; 121 | out.m[10] = -((far_plane + near_plane) / frustum_length); 122 | out.m[11] = -1; 123 | out.m[14] = -((2 * near_plane * far_plane) / frustum_length); 124 | 125 | return out; 126 | } 127 | 128 | void ExitOnGLError(const char* error_message) 129 | { 130 | const GLenum ErrorValue = glGetError(); 131 | 132 | if (ErrorValue != GL_NO_ERROR) 133 | { 134 | fprintf(stderr, "%s: %s\n", error_message, gluErrorString(ErrorValue)); 135 | exit(EXIT_FAILURE); 136 | } 137 | } 138 | 139 | GLuint LoadShader(const char* filename, GLenum shader_type) 140 | { 141 | GLuint shader_id = 0; 142 | FILE* file; 143 | long file_size = -1; 144 | char* glsl_source; 145 | 146 | if (NULL != (file = fopen(filename, "rb")) && 147 | 0 == fseek(file, 0, SEEK_END) && 148 | -1 != (file_size = ftell(file))) 149 | { 150 | rewind(file); 151 | 152 | if (NULL != (glsl_source = (char*)malloc(file_size + 1))) 153 | { 154 | if (file_size == (long)fread(glsl_source, sizeof(char), file_size, file)) 155 | { 156 | glsl_source[file_size] = '\0'; 157 | 158 | if (0 != (shader_id = glCreateShader(shader_type))) 159 | { 160 | glShaderSource(shader_id, 1, &glsl_source, NULL); 161 | glCompileShader(shader_id); 162 | ExitOnGLError("Could not compile a shader"); 163 | } 164 | else 165 | fprintf(stderr, "ERROR: Could not create a shader.\n"); 166 | } 167 | else 168 | fprintf(stderr, "ERROR: Could not read file %s\n", filename); 169 | 170 | free(glsl_source); 171 | } 172 | else 173 | fprintf(stderr, "ERROR: Could not allocate %i bytes.\n", file_size); 174 | 175 | fclose(file); 176 | } 177 | else 178 | { 179 | if (NULL != file) 180 | fclose(file); 181 | fprintf(stderr, "ERROR: Could not open file %s\n", filename); 182 | } 183 | 184 | return shader_id; 185 | } -------------------------------------------------------------------------------- /chapter-4/Utils.h: -------------------------------------------------------------------------------- 1 | #ifndef UTILS_H 2 | #define UTILS_H 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | static const double PI = 3.14159265358979323846; 12 | 13 | typedef struct Vertex 14 | { 15 | float Position[4]; 16 | float Color[4]; 17 | } Vertex; 18 | 19 | typedef struct Matrix 20 | { 21 | float m[16]; 22 | } Matrix; 23 | 24 | extern const Matrix IDENTITY_MATRIX; 25 | 26 | float Cotangent(float angle); 27 | float DegreesToRadians(float degrees); 28 | float RadiansToDegrees(float radians); 29 | 30 | Matrix MultiplyMatrices(const Matrix* m1, const Matrix* m2); 31 | void RotateAboutX(Matrix* m, float angle); 32 | void RotateAboutY(Matrix* m, float angle); 33 | void RotateAboutZ(Matrix* m, float angle); 34 | void ScaleMatrix(Matrix* m, float x, float y, float z); 35 | void TranslateMatrix(Matrix* m, float x, float y, float z); 36 | 37 | Matrix CreateProjectionMatrix( 38 | float fovy, 39 | float aspect_ratio, 40 | float near_plane, 41 | float far_plane 42 | ); 43 | 44 | void ExitOnGLError(const char* error_message); 45 | GLuint LoadShader(const char* filename, GLenum shader_type); 46 | 47 | #endif -------------------------------------------------------------------------------- /chapter-4/chapter.4.1.c: -------------------------------------------------------------------------------- 1 | #include "Utils.h" 2 | #define WINDOW_TITLE_PREFIX "Chapter 4" 3 | 4 | int 5 | CurrentWidth = 800, 6 | CurrentHeight = 600, 7 | WindowHandle = 0; 8 | 9 | unsigned FrameCount = 0; 10 | 11 | GLuint 12 | ProjectionMatrixUniformLocation, 13 | ViewMatrixUniformLocation, 14 | ModelMatrixUniformLocation, 15 | BufferIds[3] = { 0 }, 16 | ShaderIds[3] = { 0 }; 17 | 18 | Matrix 19 | ProjectionMatrix, 20 | ViewMatrix, 21 | ModelMatrix; 22 | 23 | float CubeRotation = 0; 24 | clock_t LastTime = 0; 25 | 26 | void Initialize(int, char*[]); 27 | void InitWindow(int, char*[]); 28 | void ResizeFunction(int, int); 29 | void RenderFunction(void); 30 | void TimerFunction(int); 31 | void IdleFunction(void); 32 | void CreateCube(void); 33 | void DestroyCube(void); 34 | void DrawCube(void); 35 | 36 | int main(int argc, char* argv[]) 37 | { 38 | Initialize(argc, argv); 39 | 40 | glutMainLoop(); 41 | 42 | exit(EXIT_SUCCESS); 43 | } 44 | 45 | void Initialize(int argc, char* argv[]) 46 | { 47 | GLenum GlewInitResult; 48 | 49 | InitWindow(argc, argv); 50 | 51 | glewExperimental = GL_TRUE; 52 | GlewInitResult = glewInit(); 53 | 54 | if (GLEW_OK != GlewInitResult) { 55 | fprintf( 56 | stderr, 57 | "ERROR: %s\n", 58 | glewGetErrorString(GlewInitResult) 59 | ); 60 | exit(EXIT_FAILURE); 61 | } 62 | 63 | fprintf( 64 | stdout, 65 | "INFO: OpenGL Version: %s\n", 66 | glGetString(GL_VERSION) 67 | ); 68 | 69 | glGetError(); 70 | glClearColor(0.0f, 0.0f, 0.0f, 0.0f); 71 | 72 | glEnable(GL_DEPTH_TEST); 73 | glDepthFunc(GL_LESS); 74 | ExitOnGLError("ERROR: Could not set OpenGL depth testing options"); 75 | 76 | glEnable(GL_CULL_FACE); 77 | glCullFace(GL_BACK); 78 | glFrontFace(GL_CCW); 79 | ExitOnGLError("ERROR: Could not set OpenGL culling options"); 80 | 81 | ModelMatrix = IDENTITY_MATRIX; 82 | ProjectionMatrix = IDENTITY_MATRIX; 83 | ViewMatrix = IDENTITY_MATRIX; 84 | TranslateMatrix(&ViewMatrix, 0, 0, -2); 85 | 86 | CreateCube(); 87 | } 88 | 89 | void InitWindow(int argc, char* argv[]) 90 | { 91 | glutInit(&argc, argv); 92 | 93 | glutInitContextVersion(4, 0); 94 | glutInitContextFlags(GLUT_FORWARD_COMPATIBLE); 95 | glutInitContextProfile(GLUT_CORE_PROFILE); 96 | 97 | glutSetOption( 98 | GLUT_ACTION_ON_WINDOW_CLOSE, 99 | GLUT_ACTION_GLUTMAINLOOP_RETURNS 100 | ); 101 | 102 | glutInitWindowSize(CurrentWidth, CurrentHeight); 103 | 104 | glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA); 105 | 106 | WindowHandle = glutCreateWindow(WINDOW_TITLE_PREFIX); 107 | 108 | if(WindowHandle < 1) { 109 | fprintf( 110 | stderr, 111 | "ERROR: Could not create a new rendering window.\n" 112 | ); 113 | exit(EXIT_FAILURE); 114 | } 115 | 116 | glutReshapeFunc(ResizeFunction); 117 | glutDisplayFunc(RenderFunction); 118 | glutIdleFunc(IdleFunction); 119 | glutTimerFunc(0, TimerFunction, 0); 120 | glutCloseFunc(DestroyCube); 121 | } 122 | 123 | void ResizeFunction(int Width, int Height) 124 | { 125 | CurrentWidth = Width; 126 | CurrentHeight = Height; 127 | glViewport(0, 0, CurrentWidth, CurrentHeight); 128 | ProjectionMatrix = 129 | CreateProjectionMatrix( 130 | 60, 131 | (float)CurrentWidth / CurrentHeight, 132 | 1.0f, 133 | 100.0f 134 | ); 135 | 136 | glUseProgram(ShaderIds[0]); 137 | glUniformMatrix4fv(ProjectionMatrixUniformLocation, 1, GL_FALSE, ProjectionMatrix.m); 138 | glUseProgram(0); 139 | } 140 | 141 | void RenderFunction(void) 142 | { 143 | ++FrameCount; 144 | 145 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 146 | 147 | DrawCube(); 148 | 149 | glutSwapBuffers(); 150 | } 151 | 152 | void IdleFunction(void) 153 | { 154 | glutPostRedisplay(); 155 | } 156 | 157 | void TimerFunction(int Value) 158 | { 159 | if (0 != Value) { 160 | char* TempString = (char*) 161 | malloc(512 + strlen(WINDOW_TITLE_PREFIX)); 162 | 163 | sprintf( 164 | TempString, 165 | "%s: %d Frames Per Second @ %d x %d", 166 | WINDOW_TITLE_PREFIX, 167 | FrameCount * 4, 168 | CurrentWidth, 169 | CurrentHeight 170 | ); 171 | 172 | glutSetWindowTitle(TempString); 173 | free(TempString); 174 | } 175 | 176 | FrameCount = 0; 177 | glutTimerFunc(250, TimerFunction, 1); 178 | } 179 | 180 | void CreateCube() 181 | { 182 | const Vertex VERTICES[8] = 183 | { 184 | { { -.5f, -.5f, .5f, 1 }, { 0, 0, 1, 1 } }, 185 | { { -.5f, .5f, .5f, 1 }, { 1, 0, 0, 1 } }, 186 | { { .5f, .5f, .5f, 1 }, { 0, 1, 0, 1 } }, 187 | { { .5f, -.5f, .5f, 1 }, { 1, 1, 0, 1 } }, 188 | { { -.5f, -.5f, -.5f, 1 }, { 1, 1, 1, 1 } }, 189 | { { -.5f, .5f, -.5f, 1 }, { 1, 0, 0, 1 } }, 190 | { { .5f, .5f, -.5f, 1 }, { 1, 0, 1, 1 } }, 191 | { { .5f, -.5f, -.5f, 1 }, { 0, 0, 1, 1 } } 192 | }; 193 | 194 | const GLuint INDICES[36] = 195 | { 196 | 0,2,1, 0,3,2, 197 | 4,3,0, 4,7,3, 198 | 4,1,5, 4,0,1, 199 | 3,6,2, 3,7,6, 200 | 1,6,5, 1,2,6, 201 | 7,5,6, 7,4,5 202 | }; 203 | 204 | ShaderIds[0] = glCreateProgram(); 205 | ExitOnGLError("ERROR: Could not create the shader program"); 206 | { 207 | ShaderIds[1] = LoadShader("SimpleShader.fragment.glsl", GL_FRAGMENT_SHADER); 208 | ShaderIds[2] = LoadShader("SimpleShader.vertex.glsl", GL_VERTEX_SHADER); 209 | glAttachShader(ShaderIds[0], ShaderIds[1]); 210 | glAttachShader(ShaderIds[0], ShaderIds[2]); 211 | } 212 | glLinkProgram(ShaderIds[0]); 213 | ExitOnGLError("ERROR: Could not link the shader program"); 214 | 215 | ModelMatrixUniformLocation = glGetUniformLocation(ShaderIds[0], "ModelMatrix"); 216 | ViewMatrixUniformLocation = glGetUniformLocation(ShaderIds[0], "ViewMatrix"); 217 | ProjectionMatrixUniformLocation = glGetUniformLocation(ShaderIds[0], "ProjectionMatrix"); 218 | ExitOnGLError("ERROR: Could not get shader uniform locations"); 219 | 220 | glGenVertexArrays(1, &BufferIds[0]); 221 | ExitOnGLError("ERROR: Could not generate the VAO"); 222 | glBindVertexArray(BufferIds[0]); 223 | ExitOnGLError("ERROR: Could not bind the VAO"); 224 | 225 | glEnableVertexAttribArray(0); 226 | glEnableVertexAttribArray(1); 227 | ExitOnGLError("ERROR: Could not enable vertex attributes"); 228 | 229 | glGenBuffers(2, &BufferIds[1]); 230 | ExitOnGLError("ERROR: Could not generate the buffer objects"); 231 | 232 | glBindBuffer(GL_ARRAY_BUFFER, BufferIds[1]); 233 | glBufferData(GL_ARRAY_BUFFER, sizeof(VERTICES), VERTICES, GL_STATIC_DRAW); 234 | ExitOnGLError("ERROR: Could not bind the VBO to the VAO"); 235 | 236 | glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(VERTICES[0]), (GLvoid*)0); 237 | glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, sizeof(VERTICES[0]), (GLvoid*)sizeof(VERTICES[0].Position)); 238 | ExitOnGLError("ERROR: Could not set VAO attributes"); 239 | 240 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, BufferIds[2]); 241 | glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(INDICES), INDICES, GL_STATIC_DRAW); 242 | ExitOnGLError("ERROR: Could not bind the IBO to the VAO"); 243 | 244 | glBindVertexArray(0); 245 | } 246 | 247 | void DestroyCube() 248 | { 249 | glDetachShader(ShaderIds[0], ShaderIds[1]); 250 | glDetachShader(ShaderIds[0], ShaderIds[2]); 251 | glDeleteShader(ShaderIds[1]); 252 | glDeleteShader(ShaderIds[2]); 253 | glDeleteProgram(ShaderIds[0]); 254 | ExitOnGLError("ERROR: Could not destroy the shaders"); 255 | 256 | glDeleteBuffers(2, &BufferIds[1]); 257 | glDeleteVertexArrays(1, &BufferIds[0]); 258 | ExitOnGLError("ERROR: Could not destroy the buffer objects"); 259 | } 260 | 261 | void DrawCube(void) 262 | { 263 | float CubeAngle; 264 | clock_t Now = clock(); 265 | 266 | if (LastTime == 0) 267 | LastTime = Now; 268 | 269 | CubeRotation += 45.0f * ((float)(Now - LastTime) / CLOCKS_PER_SEC); 270 | CubeAngle = DegreesToRadians(CubeRotation); 271 | LastTime = Now; 272 | 273 | ModelMatrix = IDENTITY_MATRIX; 274 | RotateAboutY(&ModelMatrix, CubeAngle); 275 | RotateAboutX(&ModelMatrix, CubeAngle); 276 | 277 | glUseProgram(ShaderIds[0]); 278 | ExitOnGLError("ERROR: Could not use the shader program"); 279 | 280 | glUniformMatrix4fv(ModelMatrixUniformLocation, 1, GL_FALSE, ModelMatrix.m); 281 | glUniformMatrix4fv(ViewMatrixUniformLocation, 1, GL_FALSE, ViewMatrix.m); 282 | ExitOnGLError("ERROR: Could not set the shader uniforms"); 283 | 284 | glBindVertexArray(BufferIds[0]); 285 | ExitOnGLError("ERROR: Could not bind the VAO for drawing purposes"); 286 | 287 | glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, (GLvoid*)0); 288 | ExitOnGLError("ERROR: Could not draw the cube"); 289 | 290 | glBindVertexArray(0); 291 | glUseProgram(0); 292 | } -------------------------------------------------------------------------------- /chapter-4/compatibility/SimpleShader.fragment.3.3.glsl: -------------------------------------------------------------------------------- 1 | #version 330 2 | 3 | in vec4 ex_Color; 4 | out vec4 out_Color; 5 | 6 | void main(void) 7 | { 8 | out_Color = ex_Color; 9 | } 10 | -------------------------------------------------------------------------------- /chapter-4/compatibility/SimpleShader.vertex.3.3.glsl: -------------------------------------------------------------------------------- 1 | #version 330 2 | 3 | layout(location=0) in vec4 in_Position; 4 | layout(location=1) in vec4 in_Color; 5 | out vec4 ex_Color; 6 | 7 | uniform mat4 ModelMatrix; 8 | uniform mat4 ViewMatrix; 9 | uniform mat4 ProjectionMatrix; 10 | 11 | void main(void) 12 | { 13 | gl_Position = (ProjectionMatrix * ViewMatrix * ModelMatrix) * in_Position; 14 | ex_Color = in_Color; 15 | } 16 | -------------------------------------------------------------------------------- /chapter-4/compatibility/chapter.4.1.c: -------------------------------------------------------------------------------- 1 | #include "../Utils.h" 2 | #define WINDOW_TITLE_PREFIX "Chapter 4" 3 | 4 | int 5 | CurrentWidth = 800, 6 | CurrentHeight = 600, 7 | WindowHandle = 0; 8 | 9 | unsigned FrameCount = 0; 10 | 11 | GLuint 12 | ProjectionMatrixUniformLocation, 13 | ViewMatrixUniformLocation, 14 | ModelMatrixUniformLocation, 15 | BufferIds[3] = { 0 }, 16 | ShaderIds[3] = { 0 }; 17 | 18 | Matrix 19 | ProjectionMatrix, 20 | ViewMatrix, 21 | ModelMatrix; 22 | 23 | float CubeRotation = 0; 24 | clock_t LastTime = 0; 25 | 26 | void Initialize(int, char*[]); 27 | void InitWindow(int, char*[]); 28 | void ResizeFunction(int, int); 29 | void RenderFunction(void); 30 | void TimerFunction(int); 31 | void IdleFunction(void); 32 | void CreateCube(void); 33 | void DestroyCube(void); 34 | void DrawCube(void); 35 | 36 | int main(int argc, char* argv[]) 37 | { 38 | Initialize(argc, argv); 39 | 40 | glutMainLoop(); 41 | 42 | exit(EXIT_SUCCESS); 43 | } 44 | 45 | void Initialize(int argc, char* argv[]) 46 | { 47 | GLenum GlewInitResult; 48 | 49 | InitWindow(argc, argv); 50 | 51 | glewExperimental = GL_TRUE; 52 | GlewInitResult = glewInit(); 53 | 54 | if (GLEW_OK != GlewInitResult) { 55 | fprintf( 56 | stderr, 57 | "ERROR: %s\n", 58 | glewGetErrorString(GlewInitResult) 59 | ); 60 | exit(EXIT_FAILURE); 61 | } 62 | 63 | fprintf( 64 | stdout, 65 | "INFO: OpenGL Version: %s\n", 66 | glGetString(GL_VERSION) 67 | ); 68 | 69 | glGetError(); 70 | glClearColor(0.0f, 0.0f, 0.0f, 0.0f); 71 | 72 | glEnable(GL_DEPTH_TEST); 73 | glDepthFunc(GL_LESS); 74 | ExitOnGLError("ERROR: Could not set OpenGL depth testing options"); 75 | 76 | glEnable(GL_CULL_FACE); 77 | glCullFace(GL_BACK); 78 | glFrontFace(GL_CCW); 79 | ExitOnGLError("ERROR: Could not set OpenGL culling options"); 80 | 81 | ModelMatrix = IDENTITY_MATRIX; 82 | ProjectionMatrix = IDENTITY_MATRIX; 83 | ViewMatrix = IDENTITY_MATRIX; 84 | TranslateMatrix(&ViewMatrix, 0, 0, -2); 85 | 86 | CreateCube(); 87 | } 88 | 89 | void InitWindow(int argc, char* argv[]) 90 | { 91 | glutInit(&argc, argv); 92 | 93 | glutInitContextVersion(3, 3); 94 | glutInitContextFlags(GLUT_FORWARD_COMPATIBLE); 95 | glutInitContextProfile(GLUT_CORE_PROFILE); 96 | 97 | glutSetOption( 98 | GLUT_ACTION_ON_WINDOW_CLOSE, 99 | GLUT_ACTION_GLUTMAINLOOP_RETURNS 100 | ); 101 | 102 | glutInitWindowSize(CurrentWidth, CurrentHeight); 103 | 104 | glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA); 105 | 106 | WindowHandle = glutCreateWindow(WINDOW_TITLE_PREFIX); 107 | 108 | if(WindowHandle < 1) { 109 | fprintf( 110 | stderr, 111 | "ERROR: Could not create a new rendering window.\n" 112 | ); 113 | exit(EXIT_FAILURE); 114 | } 115 | 116 | glutReshapeFunc(ResizeFunction); 117 | glutDisplayFunc(RenderFunction); 118 | glutIdleFunc(IdleFunction); 119 | glutTimerFunc(0, TimerFunction, 0); 120 | glutCloseFunc(DestroyCube); 121 | } 122 | 123 | void ResizeFunction(int Width, int Height) 124 | { 125 | CurrentWidth = Width; 126 | CurrentHeight = Height; 127 | glViewport(0, 0, CurrentWidth, CurrentHeight); 128 | ProjectionMatrix = 129 | CreateProjectionMatrix( 130 | 60, 131 | (float)CurrentWidth / CurrentHeight, 132 | 1.0f, 133 | 100.0f 134 | ); 135 | 136 | glUseProgram(ShaderIds[0]); 137 | glUniformMatrix4fv(ProjectionMatrixUniformLocation, 1, GL_FALSE, ProjectionMatrix.m); 138 | glUseProgram(0); 139 | } 140 | 141 | void RenderFunction(void) 142 | { 143 | ++FrameCount; 144 | 145 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 146 | 147 | DrawCube(); 148 | 149 | glutSwapBuffers(); 150 | } 151 | 152 | void IdleFunction(void) 153 | { 154 | glutPostRedisplay(); 155 | } 156 | 157 | void TimerFunction(int Value) 158 | { 159 | if (0 != Value) { 160 | char* TempString = (char*) 161 | malloc(512 + strlen(WINDOW_TITLE_PREFIX)); 162 | 163 | sprintf( 164 | TempString, 165 | "%s: %d Frames Per Second @ %d x %d", 166 | WINDOW_TITLE_PREFIX, 167 | FrameCount * 4, 168 | CurrentWidth, 169 | CurrentHeight 170 | ); 171 | 172 | glutSetWindowTitle(TempString); 173 | free(TempString); 174 | } 175 | 176 | FrameCount = 0; 177 | glutTimerFunc(250, TimerFunction, 1); 178 | } 179 | 180 | void CreateCube() 181 | { 182 | const Vertex VERTICES[8] = 183 | { 184 | { { -.5f, -.5f, .5f, 1 }, { 0, 0, 1, 1 } }, 185 | { { -.5f, .5f, .5f, 1 }, { 1, 0, 0, 1 } }, 186 | { { .5f, .5f, .5f, 1 }, { 0, 1, 0, 1 } }, 187 | { { .5f, -.5f, .5f, 1 }, { 1, 1, 0, 1 } }, 188 | { { -.5f, -.5f, -.5f, 1 }, { 1, 1, 1, 1 } }, 189 | { { -.5f, .5f, -.5f, 1 }, { 1, 0, 0, 1 } }, 190 | { { .5f, .5f, -.5f, 1 }, { 1, 0, 1, 1 } }, 191 | { { .5f, -.5f, -.5f, 1 }, { 0, 0, 1, 1 } } 192 | }; 193 | 194 | const GLuint INDICES[36] = 195 | { 196 | 0,2,1, 0,3,2, 197 | 4,3,0, 4,7,3, 198 | 4,1,5, 4,0,1, 199 | 3,6,2, 3,7,6, 200 | 1,6,5, 1,2,6, 201 | 7,5,6, 7,4,5 202 | }; 203 | 204 | ShaderIds[0] = glCreateProgram(); 205 | ExitOnGLError("ERROR: Could not create the shader program"); 206 | { 207 | ShaderIds[1] = LoadShader("./OpenGL 3.3/SimpleShader.fragment.3.3.glsl", GL_FRAGMENT_SHADER); 208 | ShaderIds[2] = LoadShader("./OpenGL 3.3/SimpleShader.vertex.3.3.glsl", GL_VERTEX_SHADER); 209 | glAttachShader(ShaderIds[0], ShaderIds[1]); 210 | glAttachShader(ShaderIds[0], ShaderIds[2]); 211 | } 212 | glLinkProgram(ShaderIds[0]); 213 | ExitOnGLError("ERROR: Could not link the shader program"); 214 | 215 | ModelMatrixUniformLocation = glGetUniformLocation(ShaderIds[0], "ModelMatrix"); 216 | ViewMatrixUniformLocation = glGetUniformLocation(ShaderIds[0], "ViewMatrix"); 217 | ProjectionMatrixUniformLocation = glGetUniformLocation(ShaderIds[0], "ProjectionMatrix"); 218 | ExitOnGLError("ERROR: Could not get shader uniform locations"); 219 | 220 | glGenVertexArrays(1, &BufferIds[0]); 221 | ExitOnGLError("ERROR: Could not generate the VAO"); 222 | glBindVertexArray(BufferIds[0]); 223 | ExitOnGLError("ERROR: Could not bind the VAO"); 224 | 225 | glEnableVertexAttribArray(0); 226 | glEnableVertexAttribArray(1); 227 | ExitOnGLError("ERROR: Could not enable vertex attributes"); 228 | 229 | glGenBuffers(2, &BufferIds[1]); 230 | ExitOnGLError("ERROR: Could not generate the buffer objects"); 231 | 232 | glBindBuffer(GL_ARRAY_BUFFER, BufferIds[1]); 233 | glBufferData(GL_ARRAY_BUFFER, sizeof(VERTICES), VERTICES, GL_STATIC_DRAW); 234 | ExitOnGLError("ERROR: Could not bind the VBO to the VAO"); 235 | 236 | glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(VERTICES[0]), (GLvoid*)0); 237 | glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, sizeof(VERTICES[0]), (GLvoid*)sizeof(VERTICES[0].Position)); 238 | ExitOnGLError("ERROR: Could not set VAO attributes"); 239 | 240 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, BufferIds[2]); 241 | glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(INDICES), INDICES, GL_STATIC_DRAW); 242 | ExitOnGLError("ERROR: Could not bind the IBO to the VAO"); 243 | 244 | glBindVertexArray(0); 245 | } 246 | 247 | void DestroyCube() 248 | { 249 | glDetachShader(ShaderIds[0], ShaderIds[1]); 250 | glDetachShader(ShaderIds[0], ShaderIds[2]); 251 | glDeleteShader(ShaderIds[1]); 252 | glDeleteShader(ShaderIds[2]); 253 | glDeleteProgram(ShaderIds[0]); 254 | ExitOnGLError("ERROR: Could not destroy the shaders"); 255 | 256 | glDeleteBuffers(2, &BufferIds[1]); 257 | glDeleteVertexArrays(1, &BufferIds[0]); 258 | ExitOnGLError("ERROR: Could not destroy the buffer objects"); 259 | } 260 | 261 | void DrawCube(void) 262 | { 263 | float CubeAngle; 264 | clock_t Now = clock(); 265 | 266 | if (LastTime == 0) 267 | LastTime = Now; 268 | 269 | CubeRotation += 45.0f * ((float)(Now - LastTime) / CLOCKS_PER_SEC); 270 | CubeAngle = DegreesToRadians(CubeRotation); 271 | LastTime = Now; 272 | 273 | ModelMatrix = IDENTITY_MATRIX; 274 | RotateAboutY(&ModelMatrix, CubeAngle); 275 | RotateAboutX(&ModelMatrix, CubeAngle); 276 | 277 | glUseProgram(ShaderIds[0]); 278 | ExitOnGLError("ERROR: Could not use the shader program"); 279 | 280 | glUniformMatrix4fv(ModelMatrixUniformLocation, 1, GL_FALSE, ModelMatrix.m); 281 | glUniformMatrix4fv(ViewMatrixUniformLocation, 1, GL_FALSE, ViewMatrix.m); 282 | ExitOnGLError("ERROR: Could not set the shader uniforms"); 283 | 284 | glBindVertexArray(BufferIds[0]); 285 | ExitOnGLError("ERROR: Could not bind the VAO for drawing purposes"); 286 | 287 | glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, (GLvoid*)0); 288 | ExitOnGLError("ERROR: Could not draw the cube"); 289 | 290 | glBindVertexArray(0); 291 | glUseProgram(0); 292 | } --------------------------------------------------------------------------------