iT邦幫忙

2021 iThome 鐵人賽

DAY 21
0
自我挑戰組

翻車機率極高的2D平台遊戲(2D Platformer)製作系列 第 21

[Day 21] 2D批次渲染 (三) - Bug!一堆Bug

今日目標

  • 繼續完成批次渲染

結果...

今天抓到一堆bug,但是還是沒debug完,被我弄丟的小方塊(矩形)回不來了。目前還在努力Debug中....

這是目前的結果,看起來跟之前預設貼圖沒有差別,但這邊主要算是優化的部分(過早優化?)

Bug001 - buffer的初始化大小

一開始碰到的問題是閃退,我就猜可能跟我配置的陣列大小有問題。

之前有提到(如果讀者還記得的話),會初始化一個很大的陣列儲存頂點資料,我是這樣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));

參考 calloc - cppreference

Bug002 - draw call計數被清掉了

後來正常進入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計數,直接跳開堆送頂點與渲染的功能

...

Bug003 - 顏色(Color)的attribute沒有抓到...

問題出在預設的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狀態機中紀錄的uniformattribute是分開的,畢竟兩個的功能面確實都不一樣。

說說最近...

原本參加鐵人賽應該是發技術文章的,但不知不覺已經變成開發日誌了,老實說,之前參加(2020年)會去囤積文章,這樣有問題就可以先發出去了。

今年(2021年)想說這次參加來點限制與挑戰,「不」囤積一天寫或學多少,就做多少,結果到現在20天過了,也沒有個雛型出來,如果真的要完成就要突破30天限制了...

老實說,漸漸的不太像是單純的完成一款2D Platformer了,比較像是從「引擎」開始做起。

有把這幾個bug修正上傳了,但是就如同最開始說的....還是有很bug,這裡是連結


上一篇
[Day 20] 2D 批次渲染 (二) - BURN OUT
下一篇
[Day 22] 2D批次渲染 (三) - 終於找到問題了
系列文
翻車機率極高的2D平台遊戲(2D Platformer)製作33

尚未有邦友留言

立即登入留言