【发布时间】: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:如果问题已“解决”,则接受解决问题的答案。不要在标题中加上“[已解决]”。