2

我有一个名为 PointCloud 的类,它是一个 vbo 缓冲区对象,我正在用不同的数据渲染其中的几个,一个作为球体,一个作为 xyz 的数据集,数据集有颜色,而球体没有颜色。问题是两者似乎共享相同的颜色,而不是单独的颜色集,球体的颜色实际上设置为空,所以我很困惑为什么要应用颜色。

我想要做的是绘制球体“白色”,而另一个点云是它各自的颜色。

在此处输入图像描述

如果你看不到图片试试这个(http://s8.postimg.org/q1j0nlkol/pcerror.png

http://pastebin.com/3fM9K87A

我的问题是谁能解释为什么会发生这种情况以及我做错了什么?

这是点云类:

using System;
using OpenTK.Graphics.OpenGL;
using OpenTK;

internal class PointCloud : IDisposable
{
    protected int[] vbo_id = new int[2];
    protected int vbo_size;
    public bool HasColor;

    public float[] Vertices = null;
    public int[] Colors = null;

    public float PointSize { get; set; }
    public bool Visible { get; set; }

    ~PointCloud()
    {
        EmptyBuffer();
    }

    private void EmptyBuffer()
    {
        Vertices = (float[])null;
        Colors = (int[])null;
    }

    public void Delete()
    {
        Dispose();
    }

    public PointCloud(float[] points)
    {
        this.vbo_size = points.Length;
        GL.GenBuffers(2, this.vbo_id);
        GL.BindBuffer(BufferTarget.ArrayBuffer, this.vbo_id[0]);
        GL.BufferData<float>(BufferTarget.ArrayBuffer, new IntPtr(points.Length * BlittableValueType.StrideOf<float>(points)), points, BufferUsageHint.StaticDraw);

        Vertices = points;
    }

    public void ApplyColorMap(int[] colors)
    {
        GL.BindBuffer(BufferTarget.ArrayBuffer, this.vbo_id[1]);
        GL.BufferData<int>(BufferTarget.ArrayBuffer, new IntPtr(colors.Length * BlittableValueType.StrideOf<int>(colors)), colors, BufferUsageHint.StaticDraw);

        Colors = colors;

        this.HasColor = true;
    }

    public void Render(FrameEventArgs e)
    {
        GL.EnableClientState(ArrayCap.VertexArray);
        GL.BindBuffer(BufferTarget.ArrayBuffer, this.vbo_id[0]);
        GL.VertexPointer(3, VertexPointerType.Float, Vector3.SizeInBytes, new IntPtr(0));
        GL.DrawArrays(BeginMode.Points, 0, this.vbo_size);
        if (!this.HasColor)
        {
            return;
        }
        GL.BindBuffer(BufferTarget.ArrayBuffer, this.vbo_id[1]);
        GL.ColorPointer(4, ColorPointerType.UnsignedByte, 4, IntPtr.Zero);
        GL.EnableClientState(ArrayCap.ColorArray);
    }

    public void Dispose()
    {
        EmptyBuffer();

        GL.DeleteBuffers(vbo_id.Length, vbo_id);
        this.vbo_id = new int[2];
    }
}

这是我的渲染代码:

protected override void OnRenderFrame(FrameEventArgs e)
{
    base.OnRenderFrame(e);
    GL.MatrixMode(MatrixMode.Modelview);
    GL.Clear(ClearBufferMask.DepthBufferBit | ClearBufferMask.ColorBufferBit);
    GL.LoadMatrix(ref this.CameraMatrix);


    GL.PushMatrix();
    this.pointclouds.ForEach((Action<PointCloud>)(i =>
    {
        //blend
        GL.Enable(EnableCap.Blend);

        if (i.Visible)
        {
            GL.PushMatrix();
            GL.PointSize(2.0f);
            if (!i.HasColor)
            {
                GL.Color4(Color.White);
            }
            i.Render(e);
            GL.PopMatrix();
        }
    }));

    GL.PopMatrix();
}
4

2 回答 2

2

它不起作用的原因是您从不禁用 clientState(ArrayCap.ColorArray)。这将导致 OpenGL 无休止地重用这些信息。一个好的方法是在您离开渲染方法之前始终禁用您在函数开始时启用的所有客户端状态。在您的情况下,您可以通过完全删除颜色 VBO 来简化事情,因为您的点无论如何只有一种颜色。无论如何,您已经尝试为 !hasColor 案例执行此操作

其次,我不确定这是不是故意的。在您的渲染函数中,您永远不会设置正确的颜色:当您调用 drawArrays 时,您将信息发送到 GPU,然后加载颜色。这将导致下一个点具有以前的颜色。

像这样的东西:

public void Render(FrameEventArgs e)
{
    GL.EnableClientState(ArrayCap.VertexArray);
    GL.BindBuffer(BufferTarget.ArrayBuffer, this.vbo_id[0]);
    GL.VertexPointer(3, VertexPointerType.Float, Vector3.SizeInBytes, new IntPtr(0));
    if (!this.HasColor) GL.Color4f(0,0,0);
    else GL.Color4f(putcolorvalue);
    GL.DrawArrays(BeginMode.Points, 0, this.vbo_size);
    GL.DisableClientState(ArrayCap.VertexArray);
}
于 2013-07-25T03:31:07.237 回答
0

我认为您必须禁用 ArrayCap.ColorArray 状态,如果不是,将使用最新应用的颜色数组:

GL.DisableClientState(ArrayCap.ColorArray);
于 2013-07-25T03:26:37.453 回答