【发布时间】: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);
}
【问题讨论】: