您当前的位置: 首页 >  ar

Jave.Lin

暂无认证

  • 1浏览

    0关注

    704博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

LearnGL - 05.2 - Texture - 实现类似2D UI流光动画

Jave.Lin 发布时间:2020-06-16 16:54:18 ,浏览量:1

文章目录
  • 思路
  • 着色器
  • 创建三个纹理对象
  • 绑定到纹理单元
  • 加载三个纹理对象
  • 设置采样器采样对应的纹理单元
  • 传入 time 时间控制 uv 纹理坐标动画
  • 运行效果
  • 完整代码
LearnGL - 学习笔记目录

本人才疏学浅,如有什么错误,望不吝指出。

上一篇:LearnGL - 05.1 - Texture Wrap Mode,了解到可以使用纹理坐标来滚动动画。

这一篇:我们使用纹理坐标滚动动画 + 多纹理,实现类似 2D UI 流光动画

实现过程与思路的参考可以查看我之前写的:Unity Shader - 实现类似UI遮罩流光

(个人觉得 Unity 中的 ShaderLab 结合了 GLSL 与 HLSL 的有点,还是比 OpenGL GLSL有好很多的,而且还柔和了多种渲染状态相关的设置在 ShaderLab 里,提升了渲染状态设置的内聚性,便于理解与维护)

思路
  • 准备流光图
  • 准备流光遮罩图
  • 主要显示纹理

流光图(我用GIMP随便画的,还是PS好用) 在这里插入图片描述

流光遮罩图 在这里插入图片描述

主纹理 在这里插入图片描述

着色器
// jave.lin - tex_2d_ui_flash_light.vert - 测试实现 2D UI 流光的顶点着色器
#version 450 compatibility
attribute vec3 vPos;
attribute vec2 vUV;
varying vec2 fUV;
void main() {
	gl_Position = vec4(vPos, 1.0);
	fUV = vUV;
}

// jave.lin - tex_2d_ui_flash_light.frag - 测试实现 2D UI 流光的片段着色器
#version 450 compatibility
varying vec2 fUV;					// uv 坐标

uniform sampler2D main_tex;			// 主纹理
uniform sampler2D mask_tex;			// 遮罩纹理
uniform sampler2D flash_light_tex;	// 闪光/流光纹理

uniform float time;					// 时间(秒)用于动画

void main() {
	vec3 mainCol 	= texture(main_tex, fUV).rgb;
	float mask 		= texture(mask_tex, fUV).r;
	vec4 flashCol 	= texture(flash_light_tex, fUV + vec2(-time, 0));
	flashCol *= flashCol.a * mask;
	mainCol 		= mainCol + flashCol.rgb;
	gl_FragColor 	= vec4(mainCol, 1.0);
}
创建三个纹理对象
	glCreateTextures(GL_TEXTURE_2D, 3, texture);					// 创建 3 个纹理对象
绑定到纹理单元
glActiveTexture(GL_TEXTURE0);									// 激活第 0 索引纹理单元
glBindTextureUnit(0, texture[0]);								// 纹理单元 0 绑定:主纹理
glActiveTexture(GL_TEXTURE1);									// 激活第 1 索引纹理单元
glBindTextureUnit(1, texture[1]);								// 纹理单元 0 绑定:遮罩纹理
glActiveTexture(GL_TEXTURE2);									// 激活第 2 索引纹理单元
glBindTextureUnit(2, texture[2]);								// 纹理单元 0 绑定:闪光/流光纹理
加载三个纹理对象
loadTexture(texture[0], "my_tex.png");							// 加载纹理对象0:主纹理
loadTexture(texture[1], "my_tex_flash_mask.jpg");				// 加载纹理对象1:遮罩纹理
loadTexture(texture[2], "flash.png");							// 加载纹理对象2:闪光/流光纹理
设置采样器采样对应的纹理单元
shaderProgram->setInt("main_tex", 0);					// 主			纹理设置采样器采样 0 索引纹理单元
shaderProgram->setInt("mask_tex", 1);					// 遮罩			纹理设置采样器采样 1 索引纹理单元
shaderProgram->setInt("flash_light_tex", 2);			// 闪光/流光	纹理设置采样器采样 2 索引纹理单元
传入 time 时间控制 uv 纹理坐标动画
shaderProgram->setFloat("time", (float)glfwGetTime());	// 测试用就直接用字符串了,方便一些
运行效果

在这里插入图片描述

完整代码
// jave.lin
#include"glad/glad.h"
#include"GLFW/glfw3.h"
//#include"linmath.h"
// 把linmath.h 放在 iostream 之前include会有错误,所以放到iostream 后include就好了
// 而这个错误正式 xkeycheck.h 文件内 #error 提示的,所以可以使用 #define _XKEYCHECK_H 这个头文件的引用标记宏
// 就可以避免对 xkeycheck.h 头文件的 include 了。
#include
#include"linmath.h"
#include"shader.h"
// 使用 stb_image.h 的加载库
// github 源码:https://github.com/nothings/stb/blob/master/stb_image.h
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
// 将之前的打印版本信息代码包含一下
#include"print_gl_version_info.h"

GLfloat vertices[] = {
	// x,	y,	  z
	// 直接放4个顶点
	-0.5f, -0.5f, 0.0f,						// 第0个顶点,左下角
	 0.5f, -0.5f, 0.0f,						// 第1个顶点,右下角
	 0.5f,  0.5f, 0.0f,						// 第2个顶点,右上角
	-0.5f,  0.5f, 0.0f,						// 第3个顶点,左上角
};

GLfloat uvs[] = {								// 顶点的 uv 坐标
	0.0f, 0.0f,									// 左下角
	1.0f, 0.0f,									// 右下角
	1.0f, 1.0f,									// 右上角
	0.0f, 1.0f,									// 左上角
};

GLuint indices[] = {							// 注意索引从0开始!通过索引缓存来指定 图元 组成 用的 顶点有哪些
	0, 1, 3,									// 放置顶点的索引,第一个三角形
	1, 2, 3										// 放置顶点的索引,第二个三角形
};

// 定义:获取 Shader 目录的回调函数原型
typedef char* (__stdcall* GetShaderPathCallback)(char*, const char*);
GetShaderPathCallback g_GetShaderPathCallback = NULL;
// 定义:获取 Pic 目录的回调函数原型
typedef char* (__stdcall* GetPicturePathCallback)(char*, const char*);
GetPicturePathCallback g_GetPicturePathCallback = NULL;

static void error_callback(int error, const char* description) {
	fprintf(stderr, "ErrorCode : %d(0x%08x), Error: %s\n", error, error, description);
}

static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) { // 当键盘按键ESCAPE按下时,设置该window为:需要关闭
	if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
		glfwSetWindowShouldClose(window, GLFW_TRUE);
}

// 时候开启检测GL的错误
#define CHECK_GL_ERROR

#ifdef CHECK_GL_ERROR
// 检测如果有GL的错误,则提示并退出程序
#define checkGLError() \
{\
	GLenum errorCode = glGetError(); \
	if (errorCode != 0) { \
		std::cout             
关注
打赏
1664331872
查看更多评论
0.1069s