国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

OpenGL 繪制簡單的英文字符

2019-11-08 03:03:21
字體:
來源:轉載
供稿:網友

http://learnopengl-cn.readthedocs.io/zh/latest/06%20In%20PRactice/02%20Text%20Rendering/

FreeType 配置 下載FreeType2 得到: ft271.zip 解壓 freetype-2.7.1 在CMake中,如下圖 順序 這里寫圖片描述

編譯成功后得到 lib 文件 freetype271.lib 可自行編譯成不同版本 (在此為 LIB Release)

這里寫圖片描述

再用VS 新建一個工程,把 /freetype-2.7.1/include 目錄包含進工程, 并將Lib文件復至工程下 輸入如下代碼,運行成功, 即 freetype271.lib 使用正常

#include <ft2build.h> #include FT_FREETYPE_H #include <iostream> using namespace std; int main() { FT_Library library; FT_Init_FreeType(&library); FT_Face face; FT_New_Face(library, "msyh.ttf", 0, &face); cout<<"num_glyphs:"<<face->num_glyphs<<endl; cout<<"num_faces:"<<face->num_faces<<endl; system("Pause"); return 0; } OpenGL

主程序:

#include <iostream>#include <map>#include <string>#define GLEW_STATIC#include <GL/glew.h>// GLFW#include <GLFW/glfw3.h>// FreeType#include <ft2build.h>#include FT_FREETYPE_H// GL includes#include "Shader.h"#pragma comment (lib, "opengl32.lib")#pragma comment (lib, "glew32s.lib")#pragma comment (lib, "glfw3.lib") #pragma comment (lib, "freetype271.lib")const GLuint WIDTH = 400, HEIGHT = 300;// 保存字體信息struct Character { GLuint TextureID; // 字形紋理ID glm::ivec2 Size; // 字形大大小 glm::ivec2 Bearing; // 字形基于基線和起點的位置 GLuint Advance; // 起點到下一個字形起點的距離};GLuint VAO, VBO;std::map<GLchar, Character> mapCharacters;void RenderText(Shader &shader, std::string text, GLfloat x, GLfloat y, GLfloat scale, glm::vec3 color);// ------------------------------------------------------------------------------// ------------------------------------------------------------------------------int main(){ glfwInit(); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); glfwWindowHint(GLFW_RESIZABLE, GL_FALSE); GLFWwindow* pWnd = glfwCreateWindow(WIDTH, HEIGHT, "LearnOpenGL", nullptr, nullptr); glfwMakeContextCurrent(pWnd); glewExperimental = GL_TRUE; glewInit(); glViewport(0, 0, WIDTH, HEIGHT); glEnable(GL_CULL_FACE); glEnable(GL_BLEND); // 開啟混合 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // Shacer加載編譯 Shader shader("./Shader/text.vs", "./Shader/text.frag"); // 正交投影 glm::mat4 projection = glm::ortho(0.0f, static_cast<GLfloat>(WIDTH), 0.0f, static_cast<GLfloat>(HEIGHT)); shader.useShaderPrograme(); glUniformMatrix4fv(glGetUniformLocation(shader.getPrograme(), "projection"), 1, GL_FALSE, glm::value_ptr(projection)); // FreeType FT_Library ft; if (FT_Init_FreeType(&ft)) std::cout << "ERROR::FREETYPE: Could not init FreeType Library" << std::endl; // 加載字體 FT_Face tfFace; if (FT_New_Face(ft, "./abc.ttf", 0, &tfFace)) std::cout << "ERROR::FREETYPE: Failed to load font" << std::endl; FT_Set_Pixel_Sizes(tfFace, 0, 30); // 字體寬高 0寬 則自動處理 // 1字節對齊 即禁用自動對齊方式 glPixelStorei(GL_UNPACK_ALIGNMENT, 1); // 只生成表示128個ASCII字符的字符表。并為每一個字符儲存紋理和一些度量值 for (GLubyte c = 0; c < 128; c++) { //if (FT_Load_Char(tfFace, c, FT_LOAD_RENDER)) //wchar_t chinese_char = '經'; if (FT_Load_Char(tfFace, c, FT_LOAD_RENDER)) { std::cout << "ERROR::FREETYTPE: Failed to load Glyph" << std::endl; continue; } // 生成紋理 GLuint nTextureID; glGenTextures(1, &nTextureID); glBindTexture(GL_TEXTURE_2D, nTextureID); { //void glTexImage2D (GLenum target, GLint level, GLint internalformat, // GLsizei width, GLsizei height, // GLint border, GLenum format, GLenum type, const void *pixels); glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, tfFace->glyph->bitmap.width, tfFace->glyph->bitmap.rows, 0, GL_RED, GL_UNSIGNED_BYTE, tfFace->glyph->bitmap.buffer); // 紋理設置 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); Character character = { nTextureID, glm::ivec2(tfFace->glyph->bitmap.width, tfFace->glyph->bitmap.rows), glm::ivec2(tfFace->glyph->bitmap_left, tfFace->glyph->bitmap_top), tfFace->glyph->advance.x }; mapCharacters.insert(std::pair<GLchar, Character>(c, character)); } glBindTexture(GL_TEXTURE_2D, 0); } // for // 釋放 FT_Done_Face(tfFace); FT_Done_FreeType(ft); // VAO/VBO glGenVertexArrays(1, &VAO); glBindVertexArray(VAO); { glGenBuffers(1, &VBO); glBindBuffer(GL_ARRAY_BUFFER, VBO); { // GL_DyNAMIC_DRAW:表示該緩存區會被周期性更改 glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 6 * 4, NULL, GL_DYNAMIC_DRAW); glEnableVertexAttribArray(0); glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), 0); } glBindBuffer(GL_ARRAY_BUFFER, 0); } glBindVertexArray(0); // 循環 事件與渲染 while (!glfwWindowShouldClose(pWnd)) { glfwPollEvents(); glClearColor(0.2f, 0.3f, 0.3f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); RenderText(shader, "yulinxx copy", 25.0f, 25.0f, 2.0f, glm::vec3(0.5, 0.8f, 0.2f)); RenderText(shader, "(C) LearnOpenGL.com", 40.0f, 270.0f, 1.0f, glm::vec3(0.3, 0.7f, 0.9f)); glfwSwapBuffers(pWnd); } glfwTerminate(); return 0;}// 渲染文字void RenderText(Shader &shader, std::string strText, GLfloat x, GLfloat y, GLfloat nScale, glm::vec3 vecColor){ shader.useShaderPrograme(); glUniform3f(glGetUniformLocation(shader.getPrograme(), "textColor"), vecColor.x, vecColor.y, vecColor.z); glActiveTexture(GL_TEXTURE0); glBindVertexArray(VAO); { // 遍歷繪制所有文字 std::string::const_iterator c; for (c = strText.begin(); c != strText.end(); c++) { Character ch = mapCharacters[*c]; GLfloat xpos = x + ch.Bearing.x * nScale; GLfloat ypos = y - (ch.Size.y - ch.Bearing.y) * nScale; GLfloat w = ch.Size.x * nScale; GLfloat h = ch.Size.y * nScale; // 每個2D方塊需要6個頂點,每個頂點由一個4維向量(一個紋理坐標和一個頂點坐標)組成 // 當前字符的VBO GLfloat vertices[6][4] = { { xpos, ypos + h, 0.0, 0.0 },{ xpos, ypos, 0.0, 1.0 }, { xpos + w, ypos, 1.0, 1.0 },{ xpos, ypos + h, 0.0, 0.0 }, { xpos + w, ypos, 1.0, 1.0 },{ xpos + w, ypos + h, 1.0, 0.0 } }; // 使用上面生成的指定紋理 glBindTexture(GL_TEXTURE_2D, ch.TextureID); { // 更新字符VBO glBindBuffer(GL_ARRAY_BUFFER, VBO); { glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices); } glBindBuffer(GL_ARRAY_BUFFER, 0); glDrawArrays(GL_TRIANGLES, 0, 6); } glBindTexture(GL_TEXTURE_2D, 0); // 更新位置到下一個字形的原點,注意單位是1/64像素 x += (ch.Advance >> 6) * nScale; // //(2^6 = 64) } } glBindVertexArray(0);}

Shader.h

//Shader.h #pragma once#ifndef TEXTURE_SHADER_H_#define TEXTURE_SHADER_H_#include <string>#include <fstream>#include <sstream>#include <iostream>#include <gl/glew.h>#include <string>#include <fstream>#include <sstream>#include <iostream>#include <GL/glew.h>class Shader{public: Shader(const GLchar* vertexPath, const GLchar* fragmentPath); ~Shader();public: void useShaderPrograme(); GLuint getPrograme() { return this->m_nProgram; }private: GLuint m_nProgram;};Shader::Shader(const GLchar* vertexPath, const GLchar* fragmentPath){ std::string vertexCode; std::string fragmentCode; std::ifstream vertexShaderF; std::ifstream fragementShaderF; vertexShaderF.exceptions(std::ifstream::badbit); fragementShaderF.exceptions(std::ifstream::badbit); try { vertexShaderF.open(vertexPath); // 打開文件 fragementShaderF.open(fragmentPath); std::stringstream vertexShaderStream, fragementShaderStream; vertexShaderStream << vertexShaderF.rdbuf(); // 讀取文件至stringstream中 fragementShaderStream << fragementShaderF.rdbuf(); vertexShaderF.close(); fragementShaderF.close(); vertexCode = vertexShaderStream.str(); // 轉換成string類型 fragmentCode = fragementShaderStream.str(); } catch (std::ifstream::failure e) { std::cout << "ERROR::SHADER::FILE_NOT_SUCCESSFULLY_READ:" << std::endl; } const GLchar* pVertexCode = vertexCode.c_str(); // string 轉 char* const GLchar* pFragementCode = fragmentCode.c_str(); GLuint nVertexShader, nFragementShader; GLint nRes = 0; GLchar chLogInfo[512] = { '/0' }; // 創建頂點著色器 nVertexShader = glCreateShader(GL_VERTEX_SHADER); // 將頂點著色程序的源代碼字符數組綁定到頂點著色器對象 glShaderSource(nVertexShader, 1, &pVertexCode, nullptr); glCompileShader(nVertexShader); // compile shader 編譯著色器 // 獲取編譯結果 glGetShaderiv(nVertexShader, GL_COMPILE_STATUS, &nRes); if (!nRes) { glGetShaderInfoLog(nVertexShader, 512, nullptr, chLogInfo); std::cout << "ERROR::SHADEF::VERTEX::COMPILATION_FAILED:" << chLogInfo << std::endl; } // 創建片斷著色器 nFragementShader = glCreateShader(GL_FRAGMENT_SHADER); // 將片段著色程序的源代碼字符數組綁定到片段著色器對象 glShaderSource(nFragementShader, 1, &pFragementCode, nullptr); glCompileShader(nFragementShader); glGetShaderiv(nFragementShader, GL_COMPILE_STATUS, &nRes); if (!nRes) { glGetShaderInfoLog(nFragementShader, 512, nullptr, chLogInfo); std::cout << "ERROR::SHADEF::FRAGEMENT::COMPILATION_FAILED:" << chLogInfo << std::endl; } this->m_nProgram = glCreateProgram(); // 創建GLSL程序 glAttachShader(this->m_nProgram, nVertexShader); // 綁定shader到program glAttachShader(this->m_nProgram, nFragementShader); // glLinkProgram操作產生最后的可執行程序,它包含最后可以在硬件上執行的硬件指令 glLinkProgram(this->m_nProgram); // 鏈接 glGetProgramiv(this->m_nProgram, GL_LINK_STATUS, &nRes); if (!nRes) { glGetProgramInfoLog(this->m_nProgram, 512, nullptr, chLogInfo); std::cout << "ERROR::SHADEF::FRAGEMENT::LINK_FAILED:" << chLogInfo << std::endl; } glDeleteShader(nVertexShader); glDeleteShader(nFragementShader);}Shader::~Shader(){}#include <glm/glm.hpp>#include <glm/gtc/matrix_transform.hpp>#include <glm/gtc/type_ptr.hpp>void Shader::useShaderPrograme(){ glUseProgram(this->m_nProgram); // 使用porgram}#endifShader部分 GLSL

text.vs

#version 330 corelayout (location = 0) in vec4 vertex; // <vec2 pos, vec2 tex>out vec2 TexCoords;uniform mat4 projection;// 頂點著色器將會將位置坐標與投影矩陣相乘,// 并將紋理坐標轉發給片段著色器:void main(){ gl_Position = projection * vec4(vertex.xy, 0.0, 1.0); TexCoords = vertex.zw;}

text.frag

#version 330 corein vec2 TexCoords;out vec4 color;// 單顏色通道的字形位圖紋理uniform sampler2D text;// 文字的顏色uniform vec3 textColor;// 紋理數據中僅存儲著紅色分量,就通過r分量來作為取樣顏色的aplpha值。// 結果值是一個字形背景為純透明,而字符部分為不透明的白色 的顏色。// 將此顏色與字體顏色uniform值相乘就得到了要輸出的字符顏色了void main(){ vec4 sampled = vec4(1.0, 1.0, 1.0, texture(text, TexCoords).r); color = vec4(textColor, 1.0) * sampled;}

運行效果:

這里寫圖片描述

源碼下載: VS2015 http://download.csdn.net/detail/yulinxx/9757228


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 余姚市| 沈阳市| 西华县| 遂宁市| 洛浦县| 邛崃市| 和平区| 晋宁县| 合水县| 深泽县| 岐山县| 平潭县| 汉中市| 广德县| 永嘉县| 凌源市| 渝中区| 桂平市| 瑞金市| 海伦市| 邮箱| 淮阳县| 伊春市| 石河子市| 德江县| 泊头市| 洪湖市| 梓潼县| 密云县| 大厂| 万荣县| 运城市| 宜兴市| 清涧县| 乐平市| 法库县| 衡阳县| 石楼县| 安平县| 天峻县| 宝坻区|