// // Tiny OpenGL v3 + glut demo program for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2024 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // https://www.fltk.org/COPYING.php // // Please see the following page on how to report bugs and issues: // // https://www.fltk.org/bugs.php // #include #if defined(__APPLE__) # define GL_DO_NOT_WARN_IF_MULTI_GL_VERSION_HEADERS_INCLUDED 1 # include // defines OpenGL 3.0+ functions #else // Note: GLEW_STATIC is defined by CMake if the static lib is linked # include #endif #include #include #include #include // Globals // Real programs don't use globals :-D // Data would normally be read from files GLfloat vertices[] = { -1.0f,0.0f,0.0f, 0.0f,1.0f,0.0f, 0.0f,0.0f,0.0f }; GLfloat colours[] = { 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f }; GLfloat vertices2[] = { 0.0f,0.0f,0.0f, 0.0f,-1.0f,0.0f, 1.0f,0.0f,0.0f }; // two vertex array objects, one for each object drawn unsigned int vertexArrayObjID[2]; // three vertex buffer objects in this example unsigned int vertexBufferObjID[3]; void printShaderInfoLog(GLint shader) { int infoLogLen = 0; GLchar *infoLog; glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogLen); if (infoLogLen > 0) { infoLog = new GLchar[infoLogLen]; // error check for fail to allocate memory omitted glGetShaderInfoLog(shader,infoLogLen, NULL, infoLog); fprintf(stderr, "InfoLog:\n%s\n", infoLog); delete [] infoLog; } } void init(void) { // Would load objects from file here - but using globals in this example // Allocate Vertex Array Objects glGenVertexArrays(2, &vertexArrayObjID[0]); // Setup first Vertex Array Object glBindVertexArray(vertexArrayObjID[0]); glGenBuffers(2, vertexBufferObjID); // VBO for vertex data glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObjID[0]); glBufferData(GL_ARRAY_BUFFER, 9*sizeof(GLfloat), vertices, GL_STATIC_DRAW); glVertexAttribPointer((GLuint)0, 3, GL_FLOAT, GL_FALSE, 0, 0); glEnableVertexAttribArray(0); // VBO for colour data glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObjID[1]); glBufferData(GL_ARRAY_BUFFER, 9*sizeof(GLfloat), colours, GL_STATIC_DRAW); glVertexAttribPointer((GLuint)1, 3, GL_FLOAT, GL_FALSE, 0, 0); glEnableVertexAttribArray(1); // Setup second Vertex Array Object glBindVertexArray(vertexArrayObjID[1]); glGenBuffers(1, &vertexBufferObjID[2]); // VBO for vertex data glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObjID[2]); glBufferData(GL_ARRAY_BUFFER, 9*sizeof(GLfloat), vertices2, GL_STATIC_DRAW); glVertexAttribPointer((GLuint)0, 3, GL_FLOAT, GL_FALSE, 0, 0); glEnableVertexAttribArray(0); glBindVertexArray(0); } void initShaders(void) { GLuint p, f, v; glClearColor (1.0, 1.0, 1.0, 0.0); v = glCreateShader(GL_VERTEX_SHADER); f = glCreateShader(GL_FRAGMENT_SHADER); #ifdef __APPLE__ #define SHADING_LANG_VERS "140" #else #define SHADING_LANG_VERS "130" #endif // load shaders const char *vv = "#version " SHADING_LANG_VERS "\n\ in vec3 in_Position;\ in vec3 in_Color;\ out vec3 ex_Color;\ void main(void)\ {\ ex_Color = in_Color;\ gl_Position = vec4(in_Position, 1.0);\ }"; const char *ff = "#version " SHADING_LANG_VERS "\n\ precision highp float;\ in vec3 ex_Color;\ out vec4 out_Color;\ void main(void)\ {\ out_Color = vec4(ex_Color,1.0);\ }"; glShaderSource(v, 1, &vv,NULL); glShaderSource(f, 1, &ff,NULL); GLint compiled; glCompileShader(v); glGetShaderiv(v, GL_COMPILE_STATUS, &compiled); if (!compiled) { fprintf(stderr, "Vertex shader not compiled.\n"); printShaderInfoLog(v); } glCompileShader(f); glGetShaderiv(f, GL_COMPILE_STATUS, &compiled); if (!compiled) { fprintf(stderr, "Fragment shader not compiled.\n"); printShaderInfoLog(f); } p = glCreateProgram(); glAttachShader(p,v); glAttachShader(p,f); glBindAttribLocation(p,0, "in_Position"); glBindAttribLocation(p,1, "in_Color"); glLinkProgram(p); glGetProgramiv(p, GL_LINK_STATUS, &compiled); if (compiled != GL_TRUE) { GLchar *infoLog; GLint length; glGetProgramiv(p, GL_INFO_LOG_LENGTH, &length); infoLog = new GLchar[length]; glGetProgramInfoLog(p, length, NULL, infoLog); fprintf(stderr, "Link log=%s\n", infoLog); delete[] infoLog; } glUseProgram(p); } void display(void) { // clear the screen glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glBindVertexArray(vertexArrayObjID[0]); // First VAO glDrawArrays(GL_TRIANGLES, 0, 3); // draw first object glBindVertexArray(vertexArrayObjID[1]); // select second VAO glVertexAttrib3f((GLuint)1, 1.0, 0.0, 0.0); // set constant color attribute glDrawArrays(GL_TRIANGLES, 0, 3); // draw second object } int fullscreen = 0; int main (int argc, char* argv[]) { Fl::use_high_res_GL(true); glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | FL_OPENGL3); glutInitWindowSize(400, 400); glutCreateWindow("Triangle Test"); #ifndef __APPLE__ GLenum err = glewInit(); // defines pters to functions of OpenGL V 1.2 and above #ifdef FLTK_USE_WAYLAND if (fl_wl_display() && err == GLEW_ERROR_NO_GLX_DISPLAY) err = GLEW_OK; #endif if (err != GLEW_OK) Fl::error("glewInit() failed returning %u", err); fprintf(stderr, "Status: Using GLEW %s\n", glewGetString(GLEW_VERSION)); #endif int gl_version_major; const char *glv = (const char*)glGetString(GL_VERSION); sscanf(glv, "%d", &gl_version_major); fprintf(stderr, "OpenGL version %s supported\n", glv); if (gl_version_major < 3) { fprintf(stderr, "\nThis platform does not support OpenGL V3\n\n"); fflush(stderr); // ensure that users see a message on Windows w/o console output: fl_alert("OpenGL version %s supported.\n" "This platform does not support OpenGL V3!",glv); exit(1); } initShaders(); init(); glutDisplayFunc(display); if (fullscreen) Fl::first_window()->fullscreen(); glutMainLoop(); return 0; }