我正在尝试将多个精灵批处理到一个大缓冲区中,但我遇到了一些技术难题。我想我没有正确设置我的 vbo 大小,但让我们看看。
这目前只渲染 1 个彩色四边形,尽管我想渲染两个。
int SPRITE_COUNT = 2;
cg_sprite** sprites;
float* v_buff;
float* c_buff;
float* t_buff;
vec4 *i0, *i1, *i2, *i3; //tmp vec4 used to hold pre transform vertex
vec4 *o0, *o1, *o2, *o3; //tmp vec4 used to hold pos transformed vertex
float v_buffer[16]; //tmp buffers to hold vertex data
float c_buffer[16]; //color
这就是我设置我的vbo的方式。
//setting up the buffers to hold concat vertex and color data
v_buff = (float*)calloc(
1, (sizeof(float) * sizeof(sprites[0]->quad->vertices) * SPRITE_COUNT));
c_buff = (float*)calloc(
1, (sizeof(float) * sizeof(sprites[0]->quad->colors) * SPRITE_COUNT));
t_buff = (float*)calloc(
1,
(sizeof(float) * sizeof(sprites[0]->quad->tex_coords) * SPRITE_COUNT));
i_buff = (short*)calloc(
1, (sizeof(short) * sizeof(sprites[0]->quad->indices) * SPRITE_COUNT));
glGenBuffers(1, &vao);
glBindVertexArray(vao);
glEnableVertexAttribArray(0);
glGenBuffers(1, &vert_buff);
glBindBuffer(GL_ARRAY_BUFFER, vert_buff);
glBufferData(GL_ARRAY_BUFFER,
SPRITE_COUNT * sizeof(sprites[0]->quad->vertices), v_buff,
GL_STREAM_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat),
(GLvoid*)0);
glEnableVertexAttribArray(1);
glGenBuffers(1, &col_buff);
glBindBuffer(GL_ARRAY_BUFFER, col_buff);
glBufferData(GL_ARRAY_BUFFER,
SPRITE_COUNT * sizeof(sprites[0]->quad->colors), c_buff,
GL_STREAM_DRAW);
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat),
(GLvoid*)0);
glGenBuffers(1, &ind_buff);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ind_buff);
glBufferData(GL_ELEMENT_ARRAY_BUFFER,
SPRITE_COUNT * sizeof(sprites[0]->quad->indices), i_buff,
GL_STREAM_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
这是精灵对象。
typedef struct {
vec3 angles;
GLshort vertex_count;
GLfloat vertices[12];
GLfloat colors[16];
GLshort indices[6];
GLfloat tex_coords[8];
} cg_quad;
typedef struct sprite {
cg_quad* quad;
vec3 scale;
vec3 pos;
vec3 angl;
mat4 m_mat;
GLuint texture_id;
}cg_sprite;
由于我试图绘制精灵,我手动创建它们是这样的:精灵函数原型:
cg_sprite* cg_sprite_new(const float x_pos, const float y_pos, const float z, const float w, const float h);
sprites = calloc(1, sizeof(cg_sprite*) * SPRITE_COUNT);
sprites[0] = cg_sprite_new(-100, 50, 0, 100, 100);
sprites[1] = cg_sprite_new(100, -50, 0, 100, 100);
我还创建了一堆临时结构来为每个精灵进行计算,但如果可能的话,我想简化一下:
for(int i = 0; i < SPRITE_COUNT; i++) {
i0 = calloc(1, sizeof(vec4) * SPRITE_COUNT);
i1 = calloc(1, sizeof(vec4) * SPRITE_COUNT);
i2 = calloc(1, sizeof(vec4) * SPRITE_COUNT);
i3 = calloc(1, sizeof(vec4) * SPRITE_COUNT);
o0 = calloc(1, sizeof(vec4) * SPRITE_COUNT);
o1 = calloc(1, sizeof(vec4) * SPRITE_COUNT);
o2 = calloc(1, sizeof(vec4) * SPRITE_COUNT);
o3 = calloc(1, sizeof(vec4) * SPRITE_COUNT);
}
这是渲染循环:
void variable_render(double alpha) {
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(ce_get_default_shader()->shader_program);
glBindVertexArray(vao);
//--------------- update vertex data ---------------------
for (int i = 0; i < SPRITE_COUNT; i++) {
vmathT3MakeIdentity(&rot);
vmathT3MakeIdentity(&scal);
vmathT3MakeIdentity(&trns);
vmathT3MakeIdentity(&tmp);
vmathT3MakeScale(&scal, &sprites[i]->scale);
vmathT3MakeRotationZYX(&rot, &sprites[i]->angl);
vmathT3MakeTranslation(&trns, &sprites[i]->pos);
vmathT3Mul(&tmp, &trns, &scal); // scale then trnslate
vmathT3Mul(&tmp, &tmp, &rot); // scale then translate then rotate
vmathM4MakeFromT3(&sprites[i]->m_mat, &tmp);
cg_quad_getquadverts(&i0[i], &i1[i], &i2[i], &i3[i], sprites[i]->quad);
vmathM4MulV4(&o0[i], &sprites[i]->m_mat, &i0[i]);
vmathM4MulV4(&o1[i], &sprites[i]->m_mat, &i1[i]);
vmathM4MulV4(&o2[i], &sprites[i]->m_mat, &i2[i]);
vmathM4MulV4(&o3[i], &sprites[i]->m_mat, &i3[i]);
v_buff[(i * 12) + 0] = o0[i].x; //copy over vertex data
v_buff[(i * 12) + 1] = o0[i].y;
v_buff[(i * 12) + 2] = o0[i].z;
v_buff[(i * 12) + 3] = o1[i].x;
v_buff[(i * 12) + 4] = o1[i].y;
v_buff[(i * 12) + 5] = o1[i].z;
v_buff[(i * 12) + 6] = o2[i].x;
v_buff[(i * 12) + 7] = o2[i].y;
v_buff[(i * 12) + 8] = o2[i].z;
v_buff[(i * 12) + 9] = o3[i].x;
v_buff[(i * 12) + 10] = o3[i].y;
v_buff[(i * 12) + 11] = o3[i].z;
c_buff[(i * 16) + 0] = sprites[i]->quad->colors[0]; //color
c_buff[(i * 16) + 1] = sprites[i]->quad->colors[1];
c_buff[(i * 16) + 2] = sprites[i]->quad->colors[2];
c_buff[(i * 16) + 3] = sprites[i]->quad->colors[3];
c_buff[(i * 16) + 4] = sprites[i]->quad->colors[4];
c_buff[(i * 16) + 5] = sprites[i]->quad->colors[5];
c_buff[(i * 16) + 6] = sprites[i]->quad->colors[6];
c_buff[(i * 16) + 7] = sprites[i]->quad->colors[7];
c_buff[(i * 16) + 8] = sprites[i]->quad->colors[8];
c_buff[(i * 16) + 9] = sprites[i]->quad->colors[9];
c_buff[(i * 16) + 10] = sprites[i]->quad->colors[10];
c_buff[(i * 16) + 11] = sprites[i]->quad->colors[11];
c_buff[(i * 16) + 12] = sprites[i]->quad->colors[12];
c_buff[(i * 16) + 13] = sprites[i]->quad->colors[13];
c_buff[(i * 16) + 14] = sprites[i]->quad->colors[14];
c_buff[(i * 16) + 15] = sprites[i]->quad->colors[15];
i_buff[(i * 6) + 0] = sprites[i]->quad->indices[0]; //indices
i_buff[(i * 6) + 1] = sprites[i]->quad->indices[1];
i_buff[(i * 6) + 2] = sprites[i]->quad->indices[2];
i_buff[(i * 6) + 3] = sprites[i]->quad->indices[3];
i_buff[(i * 6) + 4] = sprites[i]->quad->indices[4];
i_buff[(i * 6) + 5] = sprites[i]->quad->indices[5];
print_vbuff(v_buff, SPRITE_COUNT, "v_buffer");
print_cbuff(c_buff, SPRITE_COUNT, "c_buffer");
print_ibuff(i_buff, SPRITE_COUNT, "i_buffer");
}
vmathM4Mul(&mvp_mat, &p_mat, &v_mat);
glUniformMatrix4fv(view_mat_loc, 1, GL_FALSE, vmathM4GetData(&v_mat));
glUniformMatrix4fv(proj_mat_loc, 1, GL_FALSE, vmathM4GetData(&p_mat));
glUniformMatrix4fv(mvp_matrix_loc, 1, GL_FALSE, vmathM4GetData(&mvp_mat));
glBindBuffer(GL_ARRAY_BUFFER, vert_buff);
glBufferData(GL_ARRAY_BUFFER,
SPRITE_COUNT * sizeof(sprites[0]->quad->vertices), v_buff,
GL_STREAM_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, col_buff);
glBufferData(GL_ARRAY_BUFFER,
SPRITE_COUNT * sizeof(sprites[0]->quad->colors), c_buff,
GL_STREAM_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ind_buff);
glBufferData(GL_ELEMENT_ARRAY_BUFFER,
SPRITE_COUNT * sizeof(sprites[0]->quad->indices), i_buff,
GL_STREAM_DRAW);
glDrawElements(GL_TRIANGLES, SPRITE_COUNT * sprites[0]->quad->vertex_count,
GL_UNSIGNED_SHORT, 0);
glBindVertexArray(0);
}
目前这只画了 1 个四边形,颜色正确,我的日志输出看起来还不错,所以我不确定我哪里出错了。
这是上述代码的示例输出。
void print_vbuff(float* i, int count, char* tag) {
printf("%s\n", tag);
for (int k = 0; k < count; k++) {
printf(
" v0 v1 v2 v3 \n"
"-------------------------------------\n "
"x%d %3.0f %3.0f %3.0f %3.0f \n "
"y%d %3.0f %3.0f %3.0f %3.0f \n "
"z%d %3.0f %3.0f %3.0f %3.0f \n\n ",
k, i[(12 * k) + 0], i[(12 * k) + 3], i[(12 * k) + 6],
i[(12 * k) + 9], k, i[(12 * k) + 1], i[(12 * k) + 4],
i[(12 * k) + 7], i[(12 * k) + 10], k, i[(12 * k) + 2],
i[(12 * k) + 5], i[(12 * k) + 8], i[(12 * k) + 11]);
}
printf("\n\n\n");
}
void print_cbuff(float* i, int count, char* tag) {
printf("%s\n", tag);
for (int k = 0; k < count; k++) {
printf(
" v0 v1 v2 v3 \n"
"-------------------------------------\n "
"x%d %3.0f %3.0f %3.0f %3.0f \n "
"y%d %3.0f %3.0f %3.0f %3.0f \n "
"z%d %3.0f %3.0f %3.0f %3.0f \n "
"z%d %3.0f %3.0f %3.0f %3.0f \n\n ",
k, i[(16 * k) + 0], i[(16 * k) + 4], i[(16 * k) + 8],
i[(16 * k) + 12], k, i[(16 * k) + 1], i[(16 * k) + 5],
i[(16 * k) + 9], i[(16 * k) + 13], k, i[(16 * k) + 2],
i[(16 * k) + 6], i[(16 * k) + 10], i[(16 * k) + 14], k,
i[(16 * k) + 3], i[(16 * k) + 7], i[(16 * k) + 11],
i[(16 * k) + 15]);
}
printf("\n\n\n");
}
void print_ibuff(short* i, int count, char* tag) {
printf("%s\n", tag);
for (int k = 0; k < count; k++) {
printf(
" v0 v1 \n"
"-------------------------------------\n "
"x%d %3d %3d \n "
"y%d %3d %3d \n "
"z%d %3d %3d \n\n ",
k, i[(6 * k) + 0], i[(6 * k) + 3], k, i[(6 * k) + 1],
i[(6 * k) + 4], k, i[(6 * k) + 2], i[(6 * k) + 5]);
}
printf("\n\n\n");
}
这是运行此代码的一些示例输出:
v_buffer
v0 v1 v2 v3
-------------------------------------
x0 -50 -50 50 50
y0 -50 50 50 -50
z0 0 0 0 0
v0 v1 v2 v3
-------------------------------------
x1 -50 -50 50 50
y1 -50 50 50 -50
z1 0 0 0 0
c_buffer
v0 v1 v2 v3
-------------------------------------
x0 1 0 0 1
y0 0 1 0 1
z0 0 0 1 0
z0 1 1 1 1
v0 v1 v2 v3
-------------------------------------
x1 1 0 0 1
y1 0 1 0 1
z1 0 0 1 0
z1 1 1 1 1
i_buffer
v0 v1
-------------------------------------
x0 0 0
y0 1 2
z0 2 3
v0 v1
-------------------------------------
x1 0 0
y1 1 2
z1 2 3
我是否错误地设置了我的 opengl 缓冲区?为什么它只渲染一个四边形?特别是当输出显示 v_buff 数据结构中两个四边形的顶点信息和颜色信息时?
我不明白为什么我只渲染 1 个四边形。