今天抓到一堆bug,但是還是沒debug完,被我弄丟的小方塊(矩形)回不來了。目前還在努力Debug中....
這是目前的結果,看起來跟之前預設貼圖沒有差別,但這邊主要算是優化的部分(過早優化?)
一開始碰到的問題是閃退,我就猜可能跟我配置的陣列大小有問題。
之前有提到(如果讀者還記得的話),會初始化一個很大的陣列儲存頂點資料,我是這樣new出來的
CONTEXT.RenderState.vertex_buffer.vertices = (V2f*)calloc(DEFAULT_MAX_RECT * VERICES_PER_RECT, DEFAULT_MAX_RECT * VERICES_PER_RECT * sizeof(V2f));
這是一個非常單純的錯誤,calloc
的用法用錯了arg0
是「數量大小」;arg1
是「物件」大小,但arg1
我代成「記憶體區塊」大小了。
所以,要改成這樣
CONTEXT.RenderState.vertex_buffer.vertices = (V2f*)calloc(DEFAULT_MAX_RECT * VERICES_PER_RECT, sizeof(V2f));
後來正常進入Game Loop了,但是只有看到背景顏色,沒有看到圖,於是我直接在RenderCurrentBatch
放上計數器與繪出的定點數目,我還沒正式介紹整個詳細流程作法,之後會詳細介紹,先說這個function功能是繪出目前所有Draw call裡記錄的頂點。
結果,發現雖然Game Loop一直在更新,但是RenderCurrentBatch
只有呼叫一次 O_O
後來發現是這裡
...
// draw!!
size_t vertex_offset = 0;
for (size_t i = 0; i < CONTEXT.RenderState.draw_calls_count; i++) { // 這裡會看draw call陣列的長度
glDrawElements(GL_TRIANGLES, (CONTEXT.RenderState.draw_calls[i].vertices_count / VERICES_PER_RECT * INDICES_PER_RECT), GL_UNSIGNED_INT, (const GLvoid*)(sizeof(unsigned int) * vertex_offset / VERICES_PER_RECT * INDICES_PER_RECT));
vertex_offset += CONTEXT.RenderState.draw_calls[i].vertices_count;
// LogInfo("Current draw %d, vertices count %d", (i + 1), CONTEXT.RenderState.draw_calls[i].vertices_count);
}
glBindVertexArray(0);
// reset vertex buffer and draw calls
CONTEXT.RenderState.vertex_buffer.vertices_count = 0;
CONTEXT.RenderState.vertex_buffer.texcoords_count = 0;
CONTEXT.RenderState.vertex_buffer.colors_count = 0;
CONTEXT.RenderState.vertex_buffer.indices_count = 0;
for (int i = 0; i < MAX_DRAW_CALL_PER_FRAME; i++) {
CONTEXT.RenderState.draw_calls[i].vertices_count = 0;
}
CONTEXT.RenderState.draw_calls_count = 1; // 這一行,原本是指派為0,之會導致下一幀,沒有初始數量的draw call計數,直接跳開堆送頂點與渲染的功能
...
問題出在預設的shader上,_Color
從原本的uniform變為從vertex shader就開始設置的屬性(VertexAttribute
),原本是這樣:
// default vertex sahder
static const char* DEFAULT_2D_VERTEX_SHADER_CODE = "#version 330 core\n"
"in vec2 _Pos;\n"
"in vec2 _Texcoords;\n"
"out vec2 Texcoords;\n"
"out vec4 Color;\n"
"uniform mat4 _MVP;\n"
"void main() {\n"
" gl_Position = _MVP * vec4(_Pos, 0.0, 1.0);\n"
" Texcoords = _Texcoords;\n"
"}\n\0";
// * texture(_Texture2D, Texcoords)
// default fragment shader
static const char* DEFAULT_2D_FRAGMENT_SHADER_CODE = "#version 330 core\n"
"in vec2 Texcoords;\n"
"uniform vec4 Color;\n" // 這裡
"uniform sampler2D _Texture2D;"
"out vec4 _FragColor;\n"
"void main() {\n"
" _FragColor = _Color * texture(_Texture2D, Texcoords);\n" // TODO: can't draw the default texture over here
"}\n\0";
改成這樣
// default vertex sahder
static const char* DEFAULT_2D_VERTEX_SHADER_CODE = "#version 330 core\n"
"in vec2 _Pos;\n"
"in vec2 _Texcoords;\n"
"in vec4 _Color;\n" // 這裡
"out vec2 Texcoords;\n"
"out vec4 Color;\n" // 這裡
"uniform mat4 _MVP;\n"
"void main() {\n"
" gl_Position = _MVP * vec4(_Pos, 0.0, 1.0);\n"
" Texcoords = _Texcoords;\n"
" Color = _Color;\n" // 這裡
"}\n\0";
// * texture(_Texture2D, Texcoords)
// default fragment shader
static const char* DEFAULT_2D_FRAGMENT_SHADER_CODE = "#version 330 core\n"
"in vec2 Texcoords;\n"
"in vec4 Color;\n" // 這裡
"uniform sampler2D _Texture2D;"
"out vec4 _FragColor;\n"
"void main() {\n"
" _FragColor = Color * texture(_Texture2D, Texcoords);\n" // TODO: can't draw the default texture over here
"}\n\0";
但我在iron_asset
內載入shader的屬性,沒有改寫,依舊是
int color_location = glGetUniformLocation(shader->id, "_Color");
shader->attribs_locations[SHADER_ATTRIB_VEC4_COLOR] = color_location;
要改成
int color_location = glGetAttribLocation(shader->id, "_Color");
shader->attribs_locations[SHADER_ATTRIB_VEC4_COLOR] = color_location;
請注意: 雖說我都是說屬性(Attribute),但是在OpenGL狀態機中紀錄的
uniform
與attribute
是分開的,畢竟兩個的功能面確實都不一樣。
原本參加鐵人賽應該是發技術文章的,但不知不覺已經變成開發日誌了,老實說,之前參加(2020年)會去囤積文章,這樣有問題就可以先發出去了。
今年(2021年)想說這次參加來點限制與挑戰,「不」囤積一天寫或學多少,就做多少,結果到現在20天過了,也沒有個雛型出來,如果真的要完成就要突破30天限制了...
老實說,漸漸的不太像是單純的完成一款2D Platformer了,比較像是從「引擎」開始做起。