【问题标题】:OpenTK Text rendering without GL.Begin()没有 GL.Begin() 的 OpenTK 文本渲染
【发布时间】:2020-10-12 20:02:42
【问题描述】:

我正在使用 OpenTK 编写一个应用程序,并达到了我想要呈现文本的地步。从示例中,我使用Graphics.DrawString() 拼凑了一个使用我需要的字符创建位图的版本。该版本工作得很好,但我很生气它依赖GL.Begin(BeginMode.Quads) 和 GL.End() 来呈现文本,这就是我想从现在开始使用 VAO 和 VBO 的原因。

我在程序的某个地方遇到了问题,因为我总是得到单色方块,文本应该出现在哪里。

到目前为止,我为更新我的功能所做的工作如下: 我像以前一样创建位图,我不明白为什么问题应该出在那儿。 之后,我创建一个“Char”对象列表,每个对象创建一个 VBO,存储位置和纹理坐标,如下所示:

float u_step = (float)GlyphWidth / (float)TextureWidth;
浮动 v_step = (float)GlyphHeight / (float)TextureHeight;
float u = (float)(character % GlyphsPerLine) * u_step;
float v = (float)(character / GlyphsPerLine) * v_step;
浮动 x = -GlyphWidth / 2,y = 0;


_vertices = 新浮点数[]{
    x/rect.Width, -GlyphHeight/rect.Height, u, v,
   -x/rect.Width, -GlyphHeight/rect.Height, u + u_step, v,
   -x/rect.Width, y/rect.Height, u + u_step, v + v_step,

    x/rect.Width, -GlyphHeight/rect.Height, u, v,
   -x/rect.Width, y/rect.Height, u + u_step, v + v_step,
    x/rect.Width, y/rect.Height, u, v + v_step
};

_VBO = GL.GenBuffer();
GL.BindBuffer(BufferTarget.ArrayBuffer, _VBO);
GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)(sizeof(float) * _vertices.Length),
 _vertices, BufferUsageHint.DynamicDraw);

接下来我生成一个纹理,将 texture0 设置为活动并将纹理绑定为 TextureTarget.Texture2D。然后我将位图加载到纹理中,执行以下操作:

_shader.Use();
_vertexLocation = _shader.GetAttribLocation("aPosition");
_texCoordLocation = _shader.GetAttribLocation("aTexCoord");

_fontTextureID = GL.GenTexture();

GL.ActiveTexture(TextureUnit.Texture0);
GL.BindTexture(TextureTarget.Texture2D, _fontTextureID);

using (var image = new Bitmap("container.png")) //_fontBitmapFilename))// 
{
    var data = image.LockBits(
        new Rectangle(0, 0, image.Width, image.Height),
        ImageLockMode.ReadOnly,
        System.Drawing.Imaging.PixelFormat.Format32bppArgb);

    GL.TexImage2D(TextureTarget.Texture2D,
        0,
        PixelInternalFormat.Rgba,
        image.Width,
        image.Height,
        0,
        OpenTK.Graphics.OpenGL.PixelFormat.Bgra,
        PixelType.UnsignedByte,
        data.Scan0);
}

GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.Repeat);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.Repeat);

我现在创建一个 VAO,绑定它,然后将一个 VBO 绑定到它。然后我设置 VertexAttribPointers 来解释 VBO 数据:

_VAO = GL.GenVertexArray();
GL.BindVertexArray(_VAO);

GL.BindBuffer(BufferTarget.ArrayBuffer, _charSheet[87].VBO);

GL.EnableVertexAttribArray(_vertexLocation);
GL.VertexAttribPointer(_vertexLocation, 2, VertexAttribPointerType.Float, false, 4 * sizeof(float), 0);

GL.EnableVertexAttribArray(_texCoordLocation);

GL.ActiveTexture(TextureUnit.Texture0);
GL.BindTexture(TextureTarget.Texture2D, _fontTextureID);
GL.VertexAttribPointer(_texCoordLocation, 2, VertexAttribPointerType.Float, false, 4 * sizeof(float), 2);

GL.BindVertexArray(0);
_shader.StopUse();

我的渲染函数首先使用着色器、绑定 VAO 并启用 VertexAttribArrays。然后我绑定 VBO,在这个函数中固定一个用于测试,并重用 VertexAttribPointer 函数,以便 VAO 更新其数据(我也可能是错误的想法......)。最后我画了两个三角形,组成一个正方形,字母应该出现在哪里。

_shader.Use();
GL.BindVertexArray(_VAO);
GL.EnableVertexAttribArray(_texCoordLocation);
GL.EnableVertexAttribArray(_vertexLocation);
GL.BindBuffer(BufferTarget.ArrayBuffer, _charSheet[87].VBO);
GL.VertexAttribPointer(_vertexLocation, 2, VertexAttribPointerType.Float, false, 4 * sizeof(float), 0);

GL.ActiveTexture(TextureUnit.Texture0);
GL.BindTexture(TextureTarget.Texture2D, _fontTextureID);
GL.VertexAttribPointer(_texCoordLocation, 2, VertexAttribPointerType.Float, false, 4 * sizeof(float), 2);

GL.DrawArrays(PrimitiveType.Triangles, 0, 6);
GL.BindVertexArray(0);
_shader.StopUse();

我不知道,我的程序哪里做错了,也许有人给我提示。

顶点着色器

#version 330 core

layout(location = 0) in vec2 aPosition;

layout(location = 1) in vec2 aTexCoord;

out vec2 texCoord;

void main(void)
{
    texCoord = aTexCoord;

    gl_Position = vec4(aPosition, 0.0, 1.0);
}

片段着色器:

#version 330

out vec4 outputColor;

in vec2 texCoord;

uniform sampler2D texture0;

void main()
{
    outputColor = texture(texture0, texCoord);
}

【问题讨论】:

    标签: c# opengl vbo opentk vao


    【解决方案1】:

    如果绑定了命名缓冲区对象,则 GL.VertexAttribPointer 的最后一个参数将被视为缓冲区对象数据存储的字节偏移量。
    偏移量必须是2*sizeof(float) 而不是2

    GL.VertexAttribPointer(_texCoordLocation, 2, VertexAttribPointerType.Float, false, 4 * sizeof(float), 2);

    GL.VertexAttribPointer(_texCoordLocation, 2,
        VertexAttribPointerType.Float, false, 4 * sizeof(float), 2*sizeof(float));
    

    请参阅 glVertexAttribPointerVertex Specification

    【讨论】:

    • 感谢您非常快速的回答,它也非常有效。
    • 您是否同意我处理这个问题的方式?
    • @Pablo 这是一个好的开始,但您可能对this 存储库中的示例感兴趣。
    • 哇,非常感谢!我很高兴听到我走在正确的道路上。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多