//GLSL脚本程序标识符
static GLuint program;
//OpenGL顶点标识符
GLuint vao;
//OpenGL buffer标识符
GLuint vbo;
//OpenGL 纹理标识符
GLuint tex;
static const GLfloat quad_data[] =
{
//OpenGL绘制坐标点初始值
0.0f, 0.0f,
0.0f, 0.0f,
0.0f, 0.0f,
0.0f, 0.0f,
//OpenGL纹理坐标点初始值
0.0f, 0.0f,
1.0f, 0.0f,
1.0f, 1.0f,
0.0f, 1.0f
};
顶点着色器脚本,主要是确定文字的绘制坐标,以及纹理坐标位置
#version 400 core
layout (location = 0) in vec2 in_position;
layout (location = 1) in vec2 in_tex_coord;
out vec2 tex_coord;
void main(void)
{
gl_Position = vec4(in_position, 0.0f, 1.0);
tex_coord = in_tex_coord;
}
片段着色器脚本,定义一个纹理器,输出对应坐标的纹理颜色信息
#version 450 core
in vec2 tex_coord;
layout (location = 0) out vec4 color;
uniform sampler2D tex;
void main(void)
{
color = texture(tex, tex_coord);
}
编译GLSL脚本
/* Create and compile a shader */
/* type指示编译的是顶点脚本,还是片段脚本 */
/* src是对应脚本的字符串 */
static GLuint
create_shader (int type,
const char *src)
{
GLuint shader;
int status;
//创建一个着色器
shader = glCreateShader (type);
//将脚本与着色器绑定
glShaderSource (shader, 1, &src, NULL);
//编译GLSL脚本
glCompileShader (shader);
//获取编译信息
glGetShaderiv (shader, GL_COMPILE_STATUS, &status);
if (status == GL_FALSE)
{
int log_len;
char *buffer;
//编译失败,获取失败log
glGetShaderiv (shader, GL_INFO_LOG_LENGTH, &log_len);
buffer = g_malloc (log_len + 1);
glGetShaderInfoLog (shader, log_len, NULL, buffer);
g_warning ("Compile failure in %s shader:\n%s",
type == GL_VERTEX_SHADER ? "vertex" : "fragment",
buffer);
g_free (buffer);
glDeleteShader (shader);
return 0;
}
//返回着色器编译结果
return shader;
}
链接着色器
/* Initialize the shaders and link them into a program */
/* vertex_path:顶点着色器脚本路径 */
/* fragment_path:片段着色器脚本路径 */
/* program_out:生成的着色器程序 */
static void
init_shaders (const char *vertex_path,
const char *fragment_path,
GLuint *program_out)
{
GLuint vertex, fragment;
GLuint _program = 0;
int status;
GBytes *source;
//获取顶点着色器文件索引
source = g_resources_lookup_data (vertex_path, 0, NULL);
//获取顶点着色器脚本文件内容,并编译着色器程序
vertex = create_shader (GL_VERTEX_SHADER, g_bytes_get_data (source, NULL));
g_bytes_unref (source);
if (vertex == 0)
{
*program_out = 0;
return;
}
//获取片段着色器文件索引
source = g_resources_lookup_data (fragment_path, 0, NULL);
//获取片段着色器脚本文件内容,并编译着色器程序
fragment = create_shader (GL_FRAGMENT_SHADER, g_bytes_get_data (source, NULL));
g_bytes_unref (source);
if (fragment == 0)
{
glDeleteShader (vertex);
*program_out = 0;
return;
}
//创建一个着色器程序
_program = glCreateProgram ();
//将顶点着色器与新创建的着色器程序绑定起来
glAttachShader (_program, vertex);
//将片段着色器与新创建的着色器程序绑定起来
glAttachShader (_program, fragment);
//链接着色器程序
glLinkProgram (_program);
//获取链接信息
glGetProgramiv (_program, GL_LINK_STATUS, &status);
if (status == GL_FALSE)
{
int log_len;
char *buffer;
//获取链接错误信息
glGetProgramiv (_program, GL_INFO_LOG_LENGTH, &log_len);
buffer = g_malloc (log_len + 1);
glGetProgramInfoLog (_program, log_len, NULL, buffer);
g_warning ("Linking failure:\n%s", buffer);
g_free (buffer);
glDeleteProgram (_program);
_program = 0;
goto out;
}
glDetachShader (_program, vertex);
glDetachShader (_program, fragment);
out:
glDeleteShader (vertex);
glDeleteShader (fragment);
//返回着色器程序
if (program_out != NULL)
*program_out = _program;
}
创建顶点对象、缓存对象和纹理对象,并设置顶点参数和纹理参数信息
static void
realize (GtkWidget *widget)
{
......
//创建一个缓存buffer
glGenBuffers(1, &vbo);
//将vbo绑定到GL_ARRAY_BUFFER
glBindBuffer(GL_ARRAY_BUFFER, vbo);
//初始化缓存数据
glBufferData(GL_ARRAY_BUFFER, sizeof(quad_data), quad_data, GL_STATIC_DRAW);
//生成并绑定一个顶点数组对象
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
//设置顶点数组对象参数
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, (void*)(8 * sizeof(float)));
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
//生成并绑定一个纹理对象
glGenTextures(1, &tex);
glBindTexture(GL_TEXTURE_2D, tex);
//设置纹理参数
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexEnvi(GL_TEXTURE_2D, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glGenerateMipmap(GL_TEXTURE_2D);
......
}
vao与vbo的关系如下图
①定义并绑定vbo,初始化vbo绑定的buffer数据
②定义并绑定vao,设置vao中的pointer0 和 pointer1属性,其实就是设置如何获取vbo绑定的buffer中的数据
③开启pointer0 和 pointer1属性
static gboolean
render (GtkGLArea *area,
GdkGLContext *context)
{
......
/* Clear the viewport */
glClearColor(0.11765f, 0.11765f, 0.11765f, 1.0f);
glClearDepth(1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDisable(GL_CULL_FACE);
glUseProgram(program);
glBindTexture(GL_TEXTURE_2D,tex);
glBindVertexArray(vao);
glEnable(GL_BLEND);
//设置像素算法
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
......
}
下一篇文章会介绍OpenGL、FreeType2与GTK4结合使用
返回系列目录页