【问题标题】:I'm having problems with OpenGL and i cannot find where the errors are...?我在使用 OpenGL 时遇到问题,我找不到错误在哪里......?
【发布时间】:2021-08-05 09:58:50
【问题描述】:

我正在尝试学习一些有关计算机图形学的知识,并且我正在使用带有 C 的 OpenGL(我知道,我喜欢痛苦哈哈)。

现在我正在学习 learnopengl.com 上的教程,但尽管对我来说一切都很好,但没有任何东西可以绘制到屏幕上......当我“打开”线框模式时,只会绘制一条线。

这是目前的代码(如果太长或混乱,我很抱歉):

main.cpp

#define m_DEBUG_MODE
#include <Engine/Engine.h>

int main()
{
   /*===============================================*/

   GLFWwindow* window;

   glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
   glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 6);
   glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

   if (!glfwInit()) {
      printf("Could not initialize GLFW...");
      return -1;
   }

   window = glfwCreateWindow(640, 480, "Hello World", NULL, NULL);
   if (!window) {
      printf("Could not create the window...");
      glfwTerminate();
      return -1;
   }
   glfwSwapInterval(1);

   glfwMakeContextCurrent(window);

   GLenum err = glewInit();
   if (GLEW_OK != err) {
      printf("Could not initialize GLEW...");
      return -1;
   }

   printf("%s\n", glGetString(GL_VERSION));

   list_t scene;
   list_new(scene, mesh_t);


   /*===============================================*/


   float vertices[] = {
      /*      posistion         |          rgba            */
      -0.5f, -0.5f, 1.0f, 1.0f,   1.0f, 0.0f, 0.5f, 1.0f,  // 0
       0.5f, -0.5f, 1.0f, 1.0f,   0.5f, 1.0f, 0.0f, 1.0f,  // 1
       0.5f,  0.5f, 1.0f, 1.0f,   0.5f, 0.0f, 1.0f, 1.0f,  // 2
      -0.5f,  0.5f, 1.0f, 1.0f,   0.0f, 0.0f, 1.0f, 1.0f,  // 3
   };
   float indices[6] = {
      0, 1, 2, // tri. 1 
      2, 3, 0, // tri. 2
   };
   buffer_data_t vb = { .size=sizeof(vertices), .data=vertices, .usage=GL_STATIC_DRAW };
   buffer_data_t eb = { .size=sizeof(indices),  .data=indices,  .usage=GL_STATIC_DRAW };
   attrib_layout_t ap[2] = {
      { .index=0, .size=4, .type=GL_FLOAT, .normalized=GL_FALSE, .stride=sizeof(float) * 8, .pointer=(void*)(0 * sizeof(float)) }, // position
      { .index=1, .size=4, .type=GL_FLOAT, .normalized=GL_FALSE, .stride=sizeof(float) * 8, .pointer=(void*)(4 * sizeof(float)) }, // color
   };
   objectID m_shader = create_shader("./res/shaders/vertex.shader", "./res/shaders/fragment.shader");


   mesh_t mesh1;
   DEBUG_GL(mesh_init(
      &mesh1, 4,
      vb, ap, sizeof(ap) / sizeof(attrib_layout_t), eb,
      m_shader
   ));
   list_add(scene, mesh_t, mesh1);
   unbind_all();


   /*===============================================*/


   while (!glfwWindowShouldClose(window))
   {
      // RENDERING
      glClearColor(0.2f, 0.2f, 0.2f, 1.0f);
      glClear(GL_COLOR_BUFFER_BIT);

      for (unsigned int i=0; i<scene.size; i++) {
         DEBUG_GL(render(list_get(scene, mesh_t, i), GL_TRIANGLES, 0));
      }

      glfwSwapBuffers(window);
      glfwPollEvents();
   }


   /*===============================================*/


   list_delete(scene, mesh_t);

   return 0;
}

引擎.h

#ifndef M_TOOLS
#define M_TOOLS

#define GLEW_STATIC
#include <GL/glew.h>
#define GLFW_DLL
#include <GLFW/glfw3.h>

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// remove "unused" warnings
#define USE( x ) (void)x






/*============
 List
============*/

typedef struct list_t {
   void * data;        // typeless data pointer
   unsigned int size;  // count of elements
}list_t;

#define list_new( _list, T )\
   {\
      T* temp_data = (T*)malloc( sizeof(T) * 0 );\
      _list.data = (void*)temp_data;\
      _list.size = 0;\
   }

#define list_add( _list, T, val )\
   { /* make it a scoped block ( so it deletes temp_data ) */\
      /* create a temp array to store old data */\
      T* temp_data = (T*)malloc( sizeof(T) * _list.size );\
      if (_list.data != NULL) {\
         for (unsigned int i=0; i<_list.size; i++) {\
            temp_data[i] = ((T*)_list.data)[i];\
         }\
      }\
      /* clear the old data, create a new array with the right size,
      and put the old values (+ the new one) inside of it */\
      free( (T*)_list.data );\
      _list.size += 1;\
      _list.data = (void*)malloc( sizeof(T) * _list.size );\
      for (unsigned int i=0; i<_list.size - 1; i++) {\
         ((T*)_list.data)[i] = temp_data[i];\
      }\
      ((T*)_list.data)[_list.size - 1] = val;\
      free( temp_data );\
   }

#define list_get( _list, T, index )\
   (index < _list.size) ? &((T*)_list.data)[index] : NULL

#define list_remove( _list, T, index )\
   {\
      T* temp_data = (T*)malloc( sizeof(T) * _list.size );\
      for ( unsigned int i=0; i<_list.size; i++ ) {\
         temp_data[i] = ((T*)_list.data)[i];\
      }\
      _list.size -= 1;\
      for (unsigned int i=0; i<_list.size; i++) {\
         if (i != index) {\
            *((T*)_list.data + i) = temp_data[i];\
         } else {\
            continue;\
         }\
      }\
   }

#define list_delete( _list, T )\
   free( (T*)(_list.data) );\
   _list.data = NULL;\
   _list.size = 0;






/*==============
 misc
==============*/

typedef unsigned int objectID;

// unbind stuff
void unbind_all() {
   glBindVertexArray(0);
   glBindBuffer(GL_ARRAY_BUFFER, 0);
   glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
   glUseProgram(0);
}

void ClearGLErrors() {
   while (glGetError() != GL_NO_ERROR);
}

int LogGLErrors(const char* file, const int line, const char* function) {
   int stop = 0;
   GLenum error = glGetError();
   while (error) {
      printf("[OpenGL Error: %d] %s : %d\n%s\n", error, file, line, function);
      stop = 1;
      error = glGetError();
   }
   if (stop)
      return 0;
   else
      return 1;
}

#define ASSERT(x) if (!(x)) exit(-1)

#ifdef m_DEBUG_MODE
#define DEBUG_GL(x) ClearGLErrors();\
   x;\
   ASSERT(LogGLErrors(__FILE__, __LINE__, #x))
#endif
#ifndef m_DEBUG_MODE
#define DEBUG_GL(x) x;
#endif

// append a char to a string
char* append_to_str(char* str, char c) {
   size_t len = strlen(str);
   /* one for extra char, one for trailing zero */
   char *str2 = malloc(len + 1 + 1);
   strcpy(str2, str);
   str2[len] = c;
   str2[len + 1] = '\0';
   // free temp str and return res
   free(str2);
   return str;
}

// return a copy of the string
char* str_copy(char* str) {
   char* new_str = "";
   for (char* c=str; *c!='\0'; c++) {
      append_to_str(new_str, *c);
   }
   return new_str;
}

// read a file and dump its content in a string
char* read_file(char* filepath) {
   FILE*    file;
   char*    buffer;
   long    numbytes;
   // open file and search for EOF
   file = fopen(filepath, "r");
   fseek(file, 0L, SEEK_END);
   numbytes = ftell(file);
   fseek(file, 0L, SEEK_SET);   
   buffer = (char*)calloc(numbytes, sizeof(char));  
   // dump data into the buffer string
   fread(buffer, sizeof(char), numbytes, file);
   fclose(file);
   return buffer;

   //free(buffer);     <-- idk
}







/*===============
 Shaders
===============*/


// errors logging process
#define shader_error(id, status_type, iv, info_log, delete, index)\
   int log_info##index;\
   iv(id, status_type, &log_info##index);\
   if (log_info##index == GL_FALSE) {\
      int len;\
      iv(id, GL_INFO_LOG_LENGTH, &len);\
      char* error_message = (char*)malloc(sizeof(char*) * len);\
      info_log(id, len, &len, error_message);\
      printf("%s\n", error_message);\
      delete(id);\
      return 0;\
   }

objectID compile_shader(char* source_filepath, GLenum type) {
   // parse shader source file
   char* source_string = read_file(source_filepath);

   // create shader object
   objectID shader_id = glCreateShader(type);
   glShaderSource(shader_id, 1, (const GLchar * const*)(&source_string), NULL);
   glCompileShader(shader_id);

   // check and log errors during compilation
   shader_error(shader_id, GL_COMPILE_STATUS, glGetShaderiv, glGetShaderInfoLog, glDeleteShader, 0);

   return shader_id;
}

objectID create_shader(char* vertex_filepath, char* fragment_filepath) {
   // create the program, and attach compiled shaders
   objectID program = glCreateProgram();
   objectID vs = compile_shader(vertex_filepath, GL_VERTEX_SHADER);
   objectID fs = compile_shader(fragment_filepath, GL_FRAGMENT_SHADER);

   glAttachShader(program, vs);
   glAttachShader(program, fs);
   glLinkProgram(program);
   glValidateProgram(program);

   // check and log errors during program creation
   shader_error(program, GL_ATTACHED_SHADERS, glGetProgramiv, glGetProgramInfoLog, glDeleteProgram, 0);
   shader_error(program, GL_LINK_STATUS, glGetProgramiv, glGetProgramInfoLog, glDeleteProgram, 1);
   shader_error(program, GL_VALIDATE_STATUS, glGetProgramiv, glGetProgramInfoLog, glDeleteProgram, 2);

   glDeleteShader(vs);
   glDeleteShader(fs);

   return program;
}







/*===============
 Mesh object
===============*/

typedef struct buffer_data_t {
   GLsizeiptr size;
   const GLvoid * data;
    GLenum usage;
}buffer_data_t;

typedef struct attrib_layout_t {
   GLuint index;
    GLint size;
    GLenum type;
    GLboolean normalized;
    GLsizei stride;
    const GLvoid * pointer;
}attrib_layout_t;

typedef struct mesh_t {      // actual mesh object
   objectID vao;             // vertex array object
   objectID vbo;             // vertex buffer object
   objectID ebo;             // element buffer object
   objectID shader;          // shader program
   unsigned int vert_count;  // vertices count
}mesh_t;

void mesh_bind(mesh_t* mesh) {
   unbind_all();
   // bind mesh components
   DEBUG_GL(glBindVertexArray(mesh->vao));
   DEBUG_GL(glBindBuffer(GL_ARRAY_BUFFER, mesh->vbo));
   DEBUG_GL(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh->ebo));
   DEBUG_GL(glUseProgram(mesh->shader));
}

void mesh_init(
   mesh_t* mesh, unsigned int _vert_count,   // mesh object
   buffer_data_t vb,                         // vertex buffer
   attrib_layout_t* ap, unsigned int ap_n,   // attribute pointers
   buffer_data_t eb,                         // element buffer
   objectID shader_program                   // shader
) {
   unbind_all();

   mesh->vert_count = _vert_count;
   mesh->shader = shader_program;
   
   // vertex array
   DEBUG_GL(glGenVertexArrays(1, &mesh->vao));
   DEBUG_GL(glBindVertexArray(mesh->vao));

   // vertex buffer object
   DEBUG_GL(glGenBuffers(1, &mesh->vbo));
   DEBUG_GL(glBindBuffer(GL_ARRAY_BUFFER, mesh->vbo));
   DEBUG_GL(glBufferData(GL_ARRAY_BUFFER, vb.size, vb.data, vb.usage));

   // element buffer object
   DEBUG_GL(glGenBuffers(1, &mesh->ebo));
   DEBUG_GL(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh->ebo));
   DEBUG_GL(glBufferData(GL_ELEMENT_ARRAY_BUFFER, eb.size, eb.data, eb.usage));

   // attribute pointers
   for (unsigned int i=0; i<ap_n; i++) {
      DEBUG_GL(glVertexAttribPointer(ap[i].index, ap[i].size, ap[i].type, ap[i].normalized, ap[i].stride, ap[i].pointer));
      DEBUG_GL(glEnableVertexAttribArray(ap[i].index));
   }

   unbind_all();
}







/*===============
 Renderer
===============*/

void render(mesh_t* mesh, GLenum draw_mode, int wireframe) {
   // wireframe mode (polygon fill - polygon line)
   if (wireframe) { glPolygonMode( GL_FRONT_AND_BACK, GL_LINE ); }
   else { glPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); }
   
   // bind - draw - unbind
   mesh_bind(mesh);
   glDrawElements( draw_mode, mesh->vert_count, GL_UNSIGNED_INT, NULL );
   unbind_all();
}





#endif /* M_TOOLS */

如果我做错了什么,请告诉我,我真的找不到任何东西(虽然,我认为这与着色器有关)...

【问题讨论】:

  • “虽然,我认为它与着色器有关” - 你的着色器在哪里?
  • .cpp 文件如何成为 C 文件?公约何时改变?还是我刚刚进入了平行宇宙?无论如何,如果您在早期的 OpenGL 中发现错误,通常是您的:EBO、顶点属性、着色器或绑定怪异。
  • @dumb_ptr:如果问题已“解决”,则接受解决问题的答案。不要在标题中加上“[已解决]”。

标签: c opengl


【解决方案1】:

索引的类型需要是整数并且对应于draw call中指定的类型:

float indices[6] = {

unsigned int indices[6] = {
    0, 1, 2, // tri. 1 
    2, 3, 0, // tri. 2
};

类型说明符GL_UNSIGNED_INT 用于glDrawElements 指令。因此索引的类型必须是unsigned int

【讨论】:

  • 该死....就是这么简单啊哈哈....成功了!谢谢你
  • @dumb_ptr 如果这个答案解决了你的问题,你应该接受它:)
猜你喜欢
  • 1970-01-01
  • 2023-02-04
  • 2015-11-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多