博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C#+OpenGL+FreeType显示3D文字(2) - 用GLSL+VBO绘制文字
阅读量:5322 次
发布时间:2019-06-14

本文共 5913 字,大约阅读时间需要 19 分钟。

C#+OpenGL+FreeType显示3D文字(2) - 用GLSL+VBO绘制文字

+BIT祝威+悄悄在此留下版了个权的信息说:

上一篇得到了字形贴图及其位置字典(可导出为XML)。本篇就利用此贴图和位置字典,把文字绘制到OpenGL窗口。

基本流程

+BIT祝威+悄悄在此留下版了个权的信息说:

有了贴图,绘制文字和绘制普通纹理的过程是一样的。我们需要用glTexImage2D设定纹理,然后用GLSL+VBO设置一个长方形,把纹理的某个字形所占据的位置贴到长方形上,就可以绘制一个字符。连续设置多个长方形,就可以显示字符串了。

当然,用legacy opengl里的glVertex和glTexCoord来设置长方形和贴图也可以,不过本文推荐用modern opengl的GLSL+VBO的方式来实现。

 

您可以。为节省空间,此demo只能显示ASCII范围内的字符。实际上它具有显示所有Unicode字符的能力。

 

编辑GLSL

我们只需vertex shader和fragment shader。

Vertex shader只是进行最基本的变换操作,并负责传递纹理坐标。

1 #version 120 2  3 attribute vec3 in_Position; 4 attribute vec2 in_TexCoord; 5 varying vec2 texcoord; 6 uniform mat4 projectionMatrix; 7 uniform mat4 viewMatrix; 8 uniform mat4 modelMatrix; 9 10 void main(void) {11   gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(in_Position, 1);12   texcoord = in_TexCoord;13 }

 

Fragment shader根据纹理坐标所在位置的纹理颜色决定此位置是否显示(透明与否)。这就绘制出了一个字形。 

1 #version 1202 3 varying vec2 texcoord;4 uniform sampler2D tex;5 uniform vec4 color;6 7 void main(void) {8   gl_FragColor = vec4(1, 1, 1, texture2D(tex, texcoord).r) * color;9 }

设定VAO

每个字符的宽度是不同的,所以每个长方形都要据此调整宽度。下面是根据字符串生成VAO/VBO的片段。

1         private void InitVAO(string value) 2         { 3             if (value == null) { value = string.Empty; } 4  5             this.mode = PrimitiveModes.Quads; 6             this.vertexCount = 4 * value.Length; 7  8             //  Create a vertex buffer for the vertex data. 9             UnmanagedArray
in_Position = new UnmanagedArray
(this.vertexCount);10 UnmanagedArray
in_TexCoord = new UnmanagedArray
(this.vertexCount);11 Bitmap bigBitmap = this.ttfTexture.BigBitmap;12 vec3[] tmpPositions = new vec3[this.vertexCount];13 float totalLength = 0;14 for (int i = 0; i < value.Length; i++)15 {16 char c = value[i];17 CharacterInfo cInfo;18 if (this.ttfTexture.CharInfoDict.TryGetValue(c, out cInfo))19 {20 float glyphWidth = (float)cInfo.width / (float)this.ttfTexture.FontHeight;21 if (i == 0)22 {23 tmpPositions[i * 4 + 0] = new vec3(0, 0, 0);24 tmpPositions[i * 4 + 1] = new vec3(glyphWidth, 0, 0);25 tmpPositions[i * 4 + 2] = new vec3(glyphWidth, 1, 0);26 tmpPositions[i * 4 + 3] = new vec3(0, 1, 0);27 }28 else29 {30 tmpPositions[i * 4 + 0] = tmpPositions[i * 4 + 0 - 4 + 1];31 tmpPositions[i * 4 + 1] = tmpPositions[i * 4 + 0] + new vec3(glyphWidth, 0, 0);32 tmpPositions[i * 4 + 3] = tmpPositions[i * 4 + 3 - 4 - 1];33 tmpPositions[i * 4 + 2] = tmpPositions[i * 4 + 3] + new vec3(glyphWidth, 0, 0);34 }35 totalLength += glyphWidth;36 }37 38 }39 for (int i = 0; i < value.Length; i++)40 {41 char c = value[i];42 CharacterInfo cInfo;43 float x1 = 0;44 float x2 = 1;45 float y1 = 0;46 float y2 = 1;47 if (this.ttfTexture.CharInfoDict.TryGetValue(c, out cInfo))48 {49 x1 = (float)cInfo.xoffset / (float)bigBitmap.Width;50 x2 = (float)(cInfo.xoffset + cInfo.width) / (float)bigBitmap.Width;51 y1 = (float)cInfo.yoffset / (float)bigBitmap.Height;52 y2 = (float)(cInfo.yoffset + this.ttfTexture.FontHeight) / (float)bigBitmap.Height;53 }54 55 in_Position[i * 4 + 0] = tmpPositions[i * 4 + 0] - new vec3(totalLength / 2, 0, 0);56 in_Position[i * 4 + 1] = tmpPositions[i * 4 + 1] - new vec3(totalLength / 2, 0, 0);57 in_Position[i * 4 + 2] = tmpPositions[i * 4 + 2] - new vec3(totalLength / 2, 0, 0);58 in_Position[i * 4 + 3] = tmpPositions[i * 4 + 3] - new vec3(totalLength / 2, 0, 0);59 60 in_TexCoord[i * 4 + 0] = new vec2(x1, y2);61 in_TexCoord[i * 4 + 1] = new vec2(x2, y2);62 in_TexCoord[i * 4 + 2] = new vec2(x2, y1);63 in_TexCoord[i * 4 + 3] = new vec2(x1, y1);64 }65 66 GL.GenVertexArrays(1, vao);67 GL.BindVertexArray(vao[0]);68 69 GL.GenBuffers(2, vbo);70 71 uint in_PositionLocation = shaderProgram.GetAttributeLocation(strin_Position);72 GL.BindBuffer(BufferTarget.ArrayBuffer, vbo[0]);73 GL.BufferData(BufferTarget.ArrayBuffer, in_Position, BufferUsage.StaticDraw);74 GL.VertexAttribPointer(in_PositionLocation, 3, GL.GL_FLOAT, false, 0, IntPtr.Zero);75 GL.EnableVertexAttribArray(in_PositionLocation);76 77 uint in_TexCoordLocation = shaderProgram.GetAttributeLocation(strin_TexCoord);78 GL.BindBuffer(BufferTarget.ArrayBuffer, vbo[1]);79 GL.BufferData(BufferTarget.ArrayBuffer, in_TexCoord, BufferUsage.StaticDraw);80 GL.VertexAttribPointer(in_TexCoordLocation, 2, GL.GL_FLOAT, false, 0, IntPtr.Zero);81 GL.EnableVertexAttribArray(in_TexCoordLocation);82 83 GL.BindVertexArray(0);84 85 in_Position.Dispose();86 in_TexCoord.Dispose();87 }
根据字符串生成VAO/VBO

 

其它 

在上一篇,我们通过TTF文件得到了贴图文件及其位置信息(XML文件)。此时其实不再需要借助freetype就可以直接使用这些贴图了。

另外,本文所给的demo已经包含了perspective和ortho两种透视的camera功能,固定在窗口左下角显示坐标系的功能,感兴趣的话通过反编译即可得到。

 

总结

现在能够绘制文字了,但是换行之类的高级功能还没有实现。这已经不熟悉opengl的研究范围,而是更高层的功能了,所以暂时不再深入考虑。

+BIT祝威+悄悄在此留下版了个权的信息说:

转载于:https://www.cnblogs.com/bitzhuwei/p/display-text-using-glsl-and-vbo.html

你可能感兴趣的文章
利用pca分析fmri的生理噪声
查看>>
div水平居中且垂直居中
查看>>
epoll使用具体解释(精髓)
查看>>
AndroidArchitecture
查看>>
安装Endnote X6,但Word插件显示的总是Endnote Web"解决办法
查看>>
python全栈 计算机硬件管理 —— 硬件
查看>>
大数据学习
查看>>
简单工厂模式
查看>>
Delphi7编译的程序自动中Win32.Induc.a病毒的解决办法
查看>>
Objective-C 【关于导入类(@class 和 #import的区别)】
查看>>
倍福TwinCAT(贝福Beckhoff)常见问题(FAQ)-点击运行按钮进入到运行状态报错Error starting TwinCAT System怎么办 AdsWarning1823怎么办...
查看>>
【转】javascript 中的很多有用的东西
查看>>
Centos7.2正常启动关闭CDH5.16.1
查看>>
Android 监听返回键、HOME键
查看>>
Android ContentProvider的实现
查看>>
sqlserver 各种判断是否存在(表名、函数、存储过程等)
查看>>
给C#学习者的建议 - CLR Via C# 读后感
查看>>
Recover Binary Search Tree
查看>>
Java 实践:生产者与消费者
查看>>
[转]IOCP--Socket IO模型终结篇
查看>>