属性绑定和着色器的问题

时间:2014-06-20 13:13:02

标签: c# opengl

目前我正在将我们的OpenGL-Engine升级到一个新的着色和属性系统,它更具动态性,并且在使用和编程方面不是静态的。

为此,我将旧的VertexBuffer课程替换为分配了多个BufferRendererDataBufferRenderDataBuffer)对象的新RenderIndexBuffer课程,那些拿着我的渲染数据。这个新系统允许使用glDrawElementsInstanced进行实例化,并使用glDrawElements进行静态渲染。

问题

看起来属性会破坏现有的位置属性并导致意外的结果。我用不同的设置测试了这个

测试设置

此代码设置测试数据:

_Shader = new Shader(ShaderSource.FromFile("InstancingShader.xml"));
_VertexBuffer = new BufferRenderer();
RenderDataBuffer positionBuffer = new RenderDataBuffer(ArrayBufferTarget.ARRAY_BUFFER, ArrayBufferUsage.STATIC_DRAW, 
    new VertexDeclaration(DeclarationType.Float, DeclarationSize.Three, AttributeBindingType.Position));
// Set the position data of the quad
positionBuffer.BufferData(new[] { new Vector3(0, 0, 0), new Vector3(0, 0, 1), new Vector3(1, 0, 0), new Vector3(1, 0, 1) });

RenderDataBuffer instanceBuffer = new RenderDataBuffer(ArrayBufferTarget.ARRAY_BUFFER, ArrayBufferUsage.DYNAMIC_DRAW,
    new VertexDeclaration(DeclarationType.Float, DeclarationSize.Four, AttributeBindingType.Instancing),
    new VertexDeclaration(DeclarationType.Float, DeclarationSize.Four, AttributeBindingType.Color));
// Buffer the instance data
instanceBuffer.BufferData<InstanceTestData>(new[] {
        new InstanceTestData() { Color = Colors.Red, PRS = new Color(0.1f, 1f, 0.5f, 1) },
        new InstanceTestData() { Color = Colors.Blue, PRS = new Color(1f, 1f, 0.5f, 1) },
        new InstanceTestData() { Color = Colors.Green, PRS = new Color(0.1f, 1f, 1f, 1) },
        new InstanceTestData() { Color = Colors.Yellow, PRS = new Color(1f, 1f, 1f, 1) }
});
// Set up a index buffer for indexed rendering
RenderIndexBuffer indiciesBuffer = new RenderIndexBuffer(type: IndiciesType.UNSIGNED_BYTE);
indiciesBuffer.BufferData(new Byte[] { 2, 1, 0, 1, 2, 3 });

// Register the buffers ( second parameter is used for glVertexAttribDivisor )
_VertexBuffer.AddBuffer(positionBuffer);
_VertexBuffer.AddBuffer(instanceBuffer, 1);
_VertexBuffer.IndexBuffer = indiciesBuffer;

顶点着色器(像素只输出颜色):

uniform mat4 uModelViewProjection;      
varying vec4 vColor;
attribute vec3 aPosition; // POSITION0
attribute vec4 aColor;   // COLOR 0
attribute vec4 aInstancePosition; // INSTANCING0


void main()
{    
    gl_Position = uModelViewProjection * vec4(vec2((aPosition.x * 20) + (gl_InstanceID * 20), aPosition.z * 20), -3, 1);
    vColor = aColor;
}

渲染(伪代码以简化阅读;对于所有性能人员来说不是最终的)

glUseProgram
foreach (parameter in shader_parameters)
    glUniformX

foreach (buffer in render_buffers)
    glBindBuffer
    foreach (declaration in buffer.vertex_declarations)
        if (shader.Exists(declaration)) // Check if declaration exists in shader
            glEnableVertexAttribArray(shader.attributeLocation(declaration))
            glVertexAttribPointer
            if (instanceDivisor != null)
                glVertexAttribDivisor
glBindBuffer(index_buffer)
glDrawElementsInstanced

着色器属性绑定

着色器属性绑定在初始化时完成,如下所示:

_VertexAttributes = source.Attributes.ToArray();
for (uint i = 0; i < _VertexAttributes.Length; i++)
{
    ShaderAttribute attribute = _VertexAttributes[i];
    GLShaders.BindAttribLocation(_ShaderHandle, i, attribute.Name);
}

因此,着色器中应该没有属性别名,每个都有一个唯一的数字(矩阵尚未实现,我知道它们需要多个索引,但我现在也没有使用它们作为顶点属性)。正如评论中所提到的,我在链接着色器之后过滤了属性,因此没有绑定不存在的位置。

这是属性绑定的代码:

Bind();
Int32 offset = 0;
for (UInt32 i = 0; i < _Declarations.Length; i++)
{
    VertexDeclaration data = _Declarations[i];
    ShaderAttributeLocation location;
    if (shader.GetAttributeLocation(data.Binding, out location))
    {
        GLVertexBuffer.EnableVertexAttribArray(location);
        GLVertexBuffer.VertexAttribPointer(location, (AttributeSize)data.Size, (AttributeType)data.Type, data.Normalized, _StrideSize, new IntPtr(offset));
        if (instanceDivisor != null)
            GLVertexBuffer.VertexAttribDivisor(location, instanceDivisor.Value);
    }
    offset += data.ComponentSize;
}

测试结果

结果如下所示:

Working colors

现在,如果我更改代码端的绑定(AttributeBindingType.Color&lt; - &gt; AttributeBindingType.Instancing),它看起来像这样:

Working PRS

如果我现在将vColor = aColor;更改为vColor = aInstancePosition;,结果很简单:我没有多个带有颜色的小四边形,而是有一个大的全屏四边形,它是红色的。每个属性的位置与其他属性不同,因此从技术上讲,这些值应该是正确的,但它们似乎不是。在着色器中同时使用这两个属性也无法解决问题。

我正在寻找解决这个问题的想法或解决方案。

追踪问题

我已经开始越来越多地跟踪它了,这个复杂的代码花了我几个小时但我发现了一些东西:我正在使用的着色器只在我调用{{1时省略属性索引0时才工作}}。换句话说,这是一种仅适用于指定着色器的解决方法:

BindAttribLocation

我想它与实例化或我用于实例化的多个VBO有关。这是与普通着色器的唯一区别。正常的只有在我将属性位置索引设置为0时才起作用,它们在从1开始时不起作用。

1 个答案:

答案 0 :(得分:0)

我找到了问题的解决方案,而且非常简单。 在使用实例进行渲染之后,我需要在之前启用了除数的属性上调用glVertexAttribDivisor(location, 0);