在openTK中创建统一的着色器块

时间:2014-03-18 08:03:59

标签: c# opengl shader opentk uniform

我在openTK中使用统一块时遇到一些问题。我从“OpenGL着色语言手册”(source code)中举了一个例子。

档案:scenebasic_uniformblock.cpp

成功编译并成功连接着色器。

Fragment Shader:

#version 400

// in-Parameter
in vec3 TexCoord;

// out-Parameter
layout (location = 0) out vec4 FragColor;

uniform BlobSettings
{
    vec4 InnerColor;
    vec4 OuterColor;
    float RadiusInner;
    float RadiusOuter;
} Blob;

void main() 
{
    float dx = TexCoord.x - 0.5;
    float dy = TexCoord.y - 0.5;
    float dist = sqrt(dx * dx + dy * dy);
    FragColor = mix(Blob.InnerColor, Blob.OuterColor, smoothstep(Blob.RadiusInner, Blob.RadiusOuter, dist));
}

顶点着色器:

#version 400

// in-Parameter
layout (location = 0) in vec3 VertexPosition;
layout (location = 1) in vec3 VertexTexCoord;

// out-Parameter
out vec3 TexCoord;

void main()
{
    TexCoord = VertexTexCoord;
    gl_Position = vec4(VertexPosition, 1.0);
}

现在我有以下代码:

        // Get the index of the uniform block           
        var blockIndex = GL.GetUniformBlockIndex(program.Handle, "BlobSettings");

        // Allocate space for the buffer
        int blockSize;          
        GL.GetActiveUniformBlock(program.Handle, blockIndex, 
            ActiveUniformBlockParameter.UniformBlockDataSize, out blockSize);
        //var blockBuffer = new IntPtr[blockSize];
        var blockBuffer = new IntPtr();

        // Query for the offsets of each block variable
        var names = new [] {    "BlobSettings.InnerColor", "BlobSettings.OuterColor",
                                "BlobSettings.RadiusInner", "BlobSettings.RadiusOuter" };

        var indices = new int[4];
        GL.GetUniformIndices(program.Handle, 4, names, indices);

        var offset = new int[4];
        GL.GetActiveUniforms(program.Handle, 4, indices, 
            ActiveUniformParameter.UniformOffset, offset);

        // Store data within the buffer at the appropriate offsets
        var outerColor = new[] {0.0f, 0.0f, 0.0f, 0.0f};
        var innerColor = new[] {1.0f, 1.0f, 0.75f, 1.0f};
        var innerRadius = 0.25f;
        var outerRadius = 0.45f;


        // Here is the problem...
        Marshal.Copy(innerColor, offset[0], blockBuffer, 4*sizeof(float));     




        // Create the buffer object and copy the data
        int uboHandle;
        GL.GenBuffers(1, out uboHandle);
        GL.BindBuffer(BufferTarget.UniformBuffer, uboHandle);
        GL.BufferData(BufferTarget.UniformBuffer, 
            (IntPtr)blockSize, (IntPtr)blockBuffer, BufferUsageHint.DynamicDraw);

        GL.BindBufferBase(BufferRangeTarget.UniformBuffer, 1, uboHandle);

在//这是问题所在。我不知道进一步。我如何填充缓冲区? 在c ++中,我有函数memcpy,但是如何在C#中执行此操作?

感谢。

1 个答案:

答案 0 :(得分:0)

GL.BufferData有一个泛型重载,需要struct引用或数组。

struct BlobSettings
{
    public Vector4 OuterColor;
    public Vector4 InnerColor;
    public float InnerRadius;
    public float OuterRadius;

    public static readonly int Size = 
        BlittableValueType<BlobSettings>.Stride;
}

// ...

// Store data within the buffer at the appropriate offsets
var blockBuffer = new BlobSettings
{
    OuterColor = new Vector4(0.0f, 0.0f, 0.0f, 0.0f),
    InnerColor = new Vector4(1.0f, 1.0f, 0.75f, 1.0f),
    InnerRadius = 0.25f,
    OuterRadius = 0.45f
};

// ...

GL.BufferData(BufferTarget.UniformBuffer, 
    (IntPtr)BlockSettings.Size,
    ref blockBuffer,
    BufferUsageHint.DynamicDraw);

编辑:这假设您使用的是std140布局。如果没有,您可能必须使用[StructLayout(LayoutKind.Explicit)]声明C#结构,以确保字段偏移与统一块布局匹配。