openGL+freetype 动态加载中文

   能搜索这个相信你已经openGL已经入门了,所以我只上传了加载freetype的类。如果你根据我写的实现不出效果的话,可以私信我,发你项目源码(如果我看到的话)

.h文件

#pragma once

#define GLEW_STATIC
#include <GL/glew.h>
#include <GLFW/glfw3.h>

#include <iostream>
#include <vector>

#include "Shader.h"

struct word {
    unsigned int texture;
    unsigned int VAO;
};

class LoadText
{
public:
	LoadText(std::string rootPath);

    void loadText(const wchar_t* text, GLfloat x, GLfloat y);

    void drawText();

    ~LoadText()
    {
        delete this->shader;
    }
private:
    std::string rootPath;

    Shader* shader;
    std::vector< word> textVecs;

    void loadShader(); //加载shader的
};

.cpp文件

#include "LoadText.h"

#include <fstream>
#include <sstream>

#include <ft2build.h>
#include FT_FREETYPE_H

#include<wchar.h>

LoadText::LoadText(std::string rootPath):rootPath(rootPath)
{
	this->loadShader();
}

// 文本 坐标
void LoadText::loadText(const wchar_t* text, GLfloat x, GLfloat y)
{
	std::string fontPath = this->rootPath + "\\simkai.ttf";

	glm::mat4 projection = glm::ortho(0.0f, 800.0f, 0.0f, 600.0f);
	this->shader->use();
	this->shader->setMat4("projection", projection);
    //字体颜色
	this->shader->set3f("textColor", glm::vec3(0.0f, 1.0f, 0.0f));

	//初始化FreeType库
	FT_Library ft;
	if (FT_Init_FreeType(&ft))
		std::cout << "FreeType初始化失败" << std::endl;

	FT_Face face;
	if (FT_New_Face(ft, fontPath.c_str(), 0, &face))
		std::cout << "字体加载失败" << std::endl;

	//定义字体大小
	FT_Set_Pixel_Sizes(face, 0, 48);

	glPixelStorei(GL_UNPACK_ALIGNMENT, 1); //禁用字节对齐限制
	int lew_w = wcslen(text);

	for (GLubyte i = 0; i < lew_w; i++)
	{
		// 加载字符的字形 
		if (FT_Load_Char(face, text[i], FT_LOAD_RENDER))
		{
			std::cout << "字形加载失败" << std::endl;
			continue;
		}
		// 字形大小
		int font_width = face->glyph->bitmap.width;
		int font_rows = face->glyph->bitmap.rows;
		// 从基准线到字形左部/顶部的偏移值
		int font_left = face->glyph->bitmap_left;
		int font_top  = face->glyph->bitmap_top;
		// 原点距下一个字形原点的距离
		int font_x = face->glyph->advance.x;
		//
		unsigned char* data = face->glyph->bitmap.buffer;
		// 生成纹理
		GLuint texture;
		glGenTextures(1, &texture);
		glBindTexture(GL_TEXTURE_2D, texture);
		glTexImage2D(GL_TEXTURE_2D,0,GL_RED,font_width,font_rows,0,GL_RED,GL_UNSIGNED_BYTE,data);
		// 设置纹理选项
		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);

		GLfloat xpos = x + font_left;
		GLfloat ypos = y - (font_rows - font_top);

		GLfloat w = font_width;
		GLfloat h = font_rows;
		// 对每个字符更新VBO
		GLfloat vertices[6][4] = {
			{ xpos,			     ypos + font_rows,   0.0, 0.0 },
			{ xpos,				 ypos,				 0.0, 1.0 },
			{ xpos + font_width, ypos,				 1.0, 1.0 },

			{ xpos,				 ypos + font_rows,   0.0, 0.0 },
			{ xpos + font_width, ypos,				 1.0, 1.0 },
			{ xpos + font_width, ypos + font_rows,   1.0, 0.0 }
		};

		unsigned int VAO, VBO;
		glGenVertexArrays(1, &VAO);
		glBindVertexArray(VAO);

		glGenBuffers(1, &VBO);
		glBindBuffer(GL_ARRAY_BUFFER, VBO);
		glBufferData(GL_ARRAY_BUFFER, sizeof(vertices) * 4, &vertices[0][0], GL_STATIC_DRAW);

		glEnableVertexAttribArray(0);
		glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), 0);

		glBindBuffer(GL_ARRAY_BUFFER, 0);
		glBindVertexArray(0);

		word fw1;
		fw1.texture = texture;
		fw1.VAO = VAO;
		this->textVecs.push_back(fw1);

		x += (font_x >> 6);
	}
	glBindVertexArray(0);
	glBindTexture(GL_TEXTURE_2D, 0);
	
}

void LoadText::drawText()
{
	for (int i = 0; i < this->textVecs.size(); i++)
	{
		word wf = this->textVecs[i];

		glActiveTexture(GL_TEXTURE0);
		glBindTexture(GL_TEXTURE_2D, wf.texture);

		glBindVertexArray(wf.VAO);
		glDrawArrays(GL_TRIANGLES, 0, 6);


		glBindVertexArray(0);
		glActiveTexture(GL_TEXTURE0);
	}
}

void LoadText::loadShader()
{
	std::string vertCode, fragCode;
	std::stringstream vertexSStream, fragmentSStream;
	const char* vertexSource;
	const char* fragmentSource;
	try
	{
		std::ifstream vertexFile("v1.vert");
		std::ifstream fragmentFile("f1.frag");

		vertexFile.exceptions(std::ifstream::failbit || std::ifstream::badbit);
		fragmentFile.exceptions(std::ifstream::failbit || std::ifstream::badbit);

		if (!vertexFile.is_open() || !fragmentFile.is_open()) {
			throw std::exception("文件打开失败");
		}

		vertexSStream << vertexFile.rdbuf();
		vertCode = vertexSStream.str();
		vertexFile.close();

		fragmentSStream << fragmentFile.rdbuf();
		fragCode = fragmentSStream.str();

		fragmentFile.close();

		vertexSource = vertCode.c_str();
		fragmentSource = fragCode.c_str();

		this->shader = new Shader;
		this->shader->setID(vertexSource, fragmentSource);
	}
	catch (const std::exception& e)
	{
		printf(e.what());
	}
	
}

这是我自学来的,就是想分享一下经验,如果有语法方面的不足,勿怪哈

  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值