为什么某些统一的缓冲区对象变量没有传递给着色器?

时间:2019-06-01 20:27:20

标签: c++ opengl

我想通过uniform buffer objectshader storage buffer object传递数据并使用glBindBufferRange()绑定数据。

目前它的编程非常糟糕,因为我更喜欢c ++,而不是c风格,但是我不知道如何将glBindBufferRange()与c ++风格一起使用。

我有一个结构,其中包含要传递的数据和3个模拟std::vector<>的变量

struct Uniforms
{
    glm::mat4x3 paintMat = glm::mat4x3(1.0f);
    Color innerColor = Color(255, 255, 255, 255);
    Color outerColor = Color(255, 255, 255, 255);
    Vector2<float> extent = 0.0f;
    float radius = 0.0f;
    float feather = 1.0f;
    int type = 0;
};

struct DrawCall
{
    //... more stuff that does not affect uniforms
    int uniformOffset = 0;
};

struct Context
{
    //... more stuff that does not affect uniforms


    int AllocUniforms(int n)
    {
        int ret = 0;
        int structSize = fragSize;
        if (nuniform + n > cuniform) {
            unsigned char* newUniforms;
            int newCapacity = Max<int>(nuniform + n, 128) + cuniform / 2;
            newUniforms = (unsigned char*)realloc(uniforms, structSize * newCapacity);
            if (newUniforms == nullptr) 
                    return -1;

            uniforms= newUniforms;
            cuniform = newCapacity;
        }
        ret = nuniform * structSize;
        nuniform += n;
        return ret;
    }

    Uniforms* getUnifPtr(int i)
    {
        return (Uniforms*)&uniforms[i];
    }

    unsigned char* uniforms = nullptr;
    int nuniform = 0;
    int cuniform = 0;

    int fragSize = 0;

    DrawCall drawCall;
};

struct MainStruct
{
    void Create()
    {
        glGenBuffers(1, &ubo);

        //Create shaders... it also does not affect unifoms    

        int align = 4;
        glGetIntegerv(GL_UNIFORM_BUFFER, &align);
        gl.fragSize = sizeof(Uniforms) + align - sizeof(Uniforms) % align;
    }

    void SetupUniforms()
    {
        context.DrawCall.uniformOffset = AllocUniforms(1);
        Uniforms* unif = context.getUnifPtr(context.DrawCall.uniformOffset);
        unif->innerColor = Color(255, 0, 255, 255);
        unif->outerColor = Color(255, 255, 0, 255);
        unif->feather = 5.0f;
        unif->radius = 2.0f;
        unif->type = 1;

        // getPaintMat does not affect uniforms
        // also paint mat is passed properly to the shader
        paintMat = getPaintMat();
    }

    void Present()
    {
        glBindBuffer(GL_UNIFORM_BUFFER, ubo);
        glBufferData(GL_UNIFORM_BUFFER, context.nuniform * context.fragSize, context.uniforms, GL_DYNAMIC_DRAW);

        //it goes through all draw calls and binds suitable uniforms
        for(const auto drawCall : context.drawCall) {
            glBindBufferRange(GL_UNIFORM_BUFFER, 2, ubo, drawCall.uniformOffset, sizeof(Uniforms));

           //Draw call
           glDrawArrays(...);
        }

        context.nuniform = 0;
    }

    Context context;
    GLuint ubo = 0;
};
int main()
{
    //Create windows...
    //Create gl context...

    MainStruct mainS;

    Create();

    bool quit = true;
    while(!quit) {
         mainS.SetupUniforms();
         mainS.Present();

         //Swap buffers...
    }

    return 0;
}
static const char* fragmentShader = R"(
#version 460 core

layout(location = 0) out vec4 f_color;


layout(std140, binding = 2) uniform Unif
{           
    mat3 paintMat;
    vec4 innerCol;
    vec4 outerCol;
    vec2 extent;
    float radius;
    float feather;
    int type;
};

void main()
{       
    vec4 result;

        if(radius == 3) {
            result = vec4(1.0f, 0.0f, 0.0f, 1.0f);
        }
        if(feather == 5) {
           result = vec4(0.0f, 1.0f, 0.0f, 1.0f);
        }
        if(type == 8) {
            result = vec4(0.0f, 0.0f, 1.0f, 1.0f);
        }

    f_color = result;
}

)";

当然可以使用vbo等来设置顶点位置,但是在这种情况下没关系。

前四个统一变量与我添加的evey绘制调用配合良好。 问题来自radiusfeathertype。他们一直都是0。我希望radiusfeathertype是我在SetupUniforms()方法中设置的变量。

那是为什么?我该如何解决?

0 个答案:

没有答案
相关问题