我想通過使用現代OpenGL(使用VBO和着色器渲染)在LWJGL中渲染文本,但我不知道如何去做。如何在現代OpenGL中使用GLSL渲染文本
5
A
回答
9
這裏有一個辦法:
- 創建一個包含所有角色,在一定的尺寸光柵紋理。
- 對於每個字符,存儲紋理的包含字符
class CharCoords {
public int x, y, width, height;
}
- 上傳到GPU的補丁的位置的二維正方形幾何形狀,頂點
(0,0), (0,1), (1,0), (1,1)
- 頂點着色器可能如下所示
#version 120
uniform mat4 PVMmat; // The projection-view-model matrix
uniform vec4 charCoords; // The CharCoord struct for the character you are rendering, {x, y, w, h}
uniform float texSize; // The size of the texture which contains the rasterized characters (assuming it is square)
uniform vec2 offset; // The offset at which to paint, w.r.t the first character
attribute vec2 vertex;
varying vec2 tc;
void main(){
// Transform from absolute texture coordinates to normalized texture coordinates
// This works because the rectangle spans [0,1] x [0,1]
// Depending on where the origin lies in your texture (i.e. topleft or bottom left corner), you need to replace "1. - vertex.y" with just "vertex.y"
tc = (charCoords.xy + charCoords.zw * vec2(vertex.x, 1. - vertex.y))/texSize;
// Map the vertices of the unit square to a rectangle with correct aspect ratio and positioned at the correct offset
float x = (charCoords[2] * vertex.x + offset.x)/charCoords[3];
float y = vertex.y + offset.y/charCoords[3];
// Apply the model, view and projection transformations
gl_Position = PVMmat * vec4(x, y, 0., 1.);
}
- 片段着色器很簡單:
#version 120
uniform vec4 color;
uniform sampler2D tex;
varying vec2 tc;
void main() {
gl_FragColor = color * texture2D(tex, tc);
}
- 您的繪圖功能,那麼可以看看如下(注意:C頌是使用一些方便的方法着色器類,但這個想法應該清楚):
public void drawString(Matrix4f PVMmat, String text, Color color, HAlign halign, VAlign valign) {
Vector2f offset = new Vector2f();
// Font alignment
if(halign == HAlign.Center){
offset.x = -(int) (0.5f * getWidth(text));
}else if(halign == HAlign.Right){
offset.x = -getWidth(text);
}
if(valign == VAlign.Middle){
offset.y = -(int) (0.5f * getHeight());
}else if(valign == VAlign.Top){
offset.y = -getHeight();
}
m_shader.bind();
m_shader.setAttributeBuffer("vertex", m_vertexBuffer, 2);
m_shader.setUniformMatrix("PVMmat", PVMmat);
m_shader.setUniformVector("color", color);
m_shader.setUniformScalar("texSize", (float)m_textureSize);
m_shader.setTexture("tex", m_fontTexture, GL11.GL_TEXTURE_2D);
GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, m_model.getIndexBuffer());
for(int i = 0; i < text.length(); ++i) {
CharCoords coo = m_charMap.get(text.charAt(i));
m_shader.setUniformVector("charCoords", new Vector4f(coo.x, coo.y, coo.width, coo.height));
m_shader.setUniformVector("offset", offset);
GL11.glDrawElements(GL11.GL_TRIANGLES, m_indexCount, GL11.GL_UNSIGNED_INT, 0);
offset.x += coo.width;
}
GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, 0);
m_shader.unbind();
}
其中函數getHeigth
和getWidth
是:
public int getWidth(String text) {
int totalwidth = 0;
for (int i = 0; i < text.length(); i++) {
CharCoords coo = m_charMap.get(text.charAt(i));
totalwidth += coo.width;
}
return totalwidth;
}
public int getHeight() {
return m_fontMetrics.getHeight();
}
- 注意:要設置文字的比例和位置,請相應修改模型矩陣。
+0
但我認爲這會很慢,因爲我必須爲每個字符兩次更換制服。 –
+0
請記住,繪製文本的固定功能流水線方式會將繪製的每個角色的頂點和紋理座標發送給GPU,因此它已經明顯比此方法更快。但我建議嘗試一下,看看性能是否足夠,否則會根據需要進行優化。在這裏它表現的不錯。 – smani
相關問題
- 1. 用現代OpenGL渲染文本
- 2. 「GL_HALF_FLOAT」使用OpenGL渲染和GLSL
- 3. Opengl GLSL渲染紋理
- 4. 在OpenGL和GLSL中的點渲染
- 5. 現代opengl渲染管道
- 6. 渲染現代OpenGL中的大圓點
- 7. GLSL OpenGL多邊形不渲染
- 8. 如何在OpenGL中渲染3D文字?
- 9. iPhone OpenGl渲染文本
- 10. 如何在現代OpenGL中設置Stereoscoic渲染?
- 11. 如何在現代OpenGL中渲染多個紋理?
- 12. 渲染使用OpenGL
- 13. 如果使用gl_color,GLSL無渲染
- 14. OpenGL渲染不使用OpenCV的GLSL着色器
- 15. HDR Bloom效果使用OpenGL/GLSL渲染管線
- 16. 轉換GLSL現代OpenGL 3.2
- 17. 如何使用OpenGL ES渲染圖像?
- 18. 在Delphi中使用OpenGL渲染紋理
- 19. QQuiickWidgets渲染的OpenGL代碼
- 20. 如何在opengl es android中直接渲染VR渲染?
- 21. 如何在opengl中渲染橫截面
- 22. 如何在OpenGL中剪裁渲染(C++)
- 23. 使用OpenGL渲染錯誤
- 24. 使用OpenGL渲染QImage
- 25. 使用現代OpenGL進行2D渲染的正交投影
- 26. OpenGL如何渲染背景
- 27. 使用GLSL渲染矩形紋理
- 28. 使用GLSL framebuffer渲染時出錯
- 29. 使用OpenGL版本3+渲染文本/ UI
- 30. 在opengl中渲染迷宮
的可能的複製[如何使用OpenGL的唯一方法繪製文本?](http://stackoverflow.com/questions/8847899/how-to-draw-text-using-only-opengl-methods) –