Search code examples
copengl-esglslglfw

OpenGL - Triangles not getting generated with dynamic arrays for color and vertices


#include <GLFW/glfw3.h>
#include <GLES2/gl2.h>
#include <unistd.h>
#include <time.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>


// Vertex Shader source code
const char* vertexShaderSource = R"(
    #version 330 core

    layout(location = 0) in vec3 inPosition; // Vertex positions
    layout(location = 1) in vec3 inColor;    // Vertex colors

    out vec3 fragColor; // Output color to the fragment shader

  void main()
  {
      gl_Position = vec4(inPosition, 1.0);
      fragColor = inColor; // Pass color to the fragment shader
  }
)";

// Fragment Shader source code
const char* fragmentShaderSource = R"(
    #version 330 core

    in vec3 fragColor; // Input color from the vertex shader

    out vec4 outColor; // Output color

    void main()
    {
        outColor = vec4(fragColor, 1.0); // Set the fragment color using the input color
    }

)";


void sleep_for_microseconds(unsigned int microseconds) {
  struct timespec ts;
  ts.tv_sec = 0;
  ts.tv_nsec = microseconds * 1000;
  nanosleep(&ts, NULL);
}

GLfloat vertices[9];
GLfloat colors[9];


void renderloop(GLuint vao, GLuint vbo, GLuint colorBuffer)
{
    define_vertices();
    define_colors();

    glBindBuffer(GL_ARRAY_BUFFER, vbo);
    // Update the VBO with new vertex data
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_DYNAMIC_DRAW);
    glBindBuffer(GL_ARRAY_BUFFER, 0);

    glBindBuffer(GL_ARRAY_BUFFER, colorBuffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(colors), colors, GL_DYNAMIC_DRAW);

    //glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, NULL);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    
    glEnableVertexAttribArray(0);
    glEnableVertexAttribArray(1);

     // Render loop
    // Clear the screen
    glClearColor(0.35f, 0.15f, 0.25f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    // Draw the triangle
    glDrawArrays(GL_TRIANGLES, 0, 3*100);
    glFinish();
}

void render()
{
  static int framecount = 0;
  printf("%d framecount\n", framecount);
  GLuint vao;
  GLuint vbo;
  GLuint colorBuffer;
    if (framecount == 0)
    {
      // Compile and link shaders
      GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
      glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
      glCompileShader(vertexShader);

      GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
      glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
      glCompileShader(fragmentShader);

      GLuint shaderProgram = glCreateProgram();
      glAttachShader(shaderProgram, vertexShader);
      glAttachShader(shaderProgram, fragmentShader);
      glLinkProgram(shaderProgram);

      // Use the shader program for rendering
      glUseProgram(shaderProgram);
      // Vertex array object
      glGenVertexArrays(1, &vao);
      glBindVertexArray(vao);

        // Vertex buffer object
        glGenBuffers(1, &vbo);
        glBindBuffer(GL_ARRAY_BUFFER, vbo);
        // Vertex attribute pointers (positions)
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
        // Vertex attribute pointers (colors)

        glGenBuffers(1, &colorBuffer);
        glBindBuffer(GL_ARRAY_BUFFER, colorBuffer);
        glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, NULL);

        glEnableVertexAttribArray(0); // Vertex attribute location 0 (positions)
        glEnableVertexAttribArray(1); // Vertex attribute location 1 (colors)

        glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_DYNAMIC_DRAW);
        glBufferData(GL_ARRAY_BUFFER, sizeof(colors), colors, GL_DYNAMIC_DRAW);

  }
  framecount+=1;
  renderloop(vao,vbo,colorBuffer);
    framecount++;
}

float randomFloat(float min, float max) {
    return min + ((float)rand() / RAND_MAX) * (max - min);
}

// Main function
void main(void) {
// Initialize GLFW
  glfwInit();
  define_vertices();
  define_colors();
  // Create a window
  GLFWwindow *window = glfwCreateWindow(640, 480, "OpenGL Triangle", NULL, NULL);
  if (window == NULL) {
    glfwTerminate();
    return;
  }

  // Make the window the current context
  glfwMakeContextCurrent(window);
  for(int i=0;i<10000;i++)
  {
    render();
    glfwSwapBuffers(window);
    glfwPollEvents();
    sleep_for_microseconds(40000);
  }
  // Terminate GLFW
  glfwTerminate();

}

define_colors and define_vertices are two functions that update the colors and vertices global variables after each frame. I have verified the code for one frame and is working fine, (When there are static arrays for vertices and colors). But when I'm having dynamic variables for colors and vertices like below, no triangles are getting rendered. What could be the issue here. I verified by adding prints in the vertices generated, it seems to be generating properly.


Solution

  • I ported your code to Visual Studio 2019 and made a few modifications to make it draw a simple rotating triangle with changing colors. The compiler complained about the local variables vao, vbo and colorBuffer are used without initialization. You should initialize at once(at frame 0) and use in next frames. So you should not use local variables for that. Either move them out of the function scope(e.g. global variables) or make them static variables like:

    void render()
    {
        static GLuint vao;
        static GLuint vbo;
        static GLuint colorBuffer;
    
        static int framecount = 0;
        printf("%d framecount\n", framecount);
    
        if (framecount == 0)
        {
            // Compile and link shaders
        ...
        }
        framecount += 1;
        renderloop(vao, vbo, colorBuffer);
        framecount++;
    }
    

    After those updates I could render my rotating triangle without a problem.