解码视频流在opengl中的贴图投影计算
- 修改顶点着色器
- cpp 文件
- 放大缩小
我们把视频当成纹理,首先要确定贴入的坐标,原始坐标如下所示
static float vertices[] = {
// ---- 位置 ---- ---- 颜色 ---- - 纹理坐标 -
1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, // 右上
1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // 右下
-1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // 左下
-1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f // 左上
};
实际上我们要确定的是opengl的投影视窗,视窗大小就是位置,相当于把解码图像放到窗口中的什么位置,这里并不是纹理位置,纹理位置是具体取到那一块的纹理,涉及到放大缩小,我们写一个顶点着色器,如下所示
#version 330 core
layout(location = 0) in vec3 aPos;
layout(location = 1) in vec3 aColor;
layout(location = 2) in vec2 aTexCoord;
out vec4 vertexColor;
out vec2 TexCoord;
void main(){
vec3 pos;
gl_Position = vec4(aPos, 1.0);
vertexColor = vec4(aColor, 1.0);
TexCoord = aTexCoord;
//TexCoord1 = aTexCoord1;
}
没有任何约束,放出来的贴图会随着窗口的变化而变化,问题是不成比例,视频展现失比例拉伸,对展现并不友好。我们要使用向量的运算来修改投影视窗
修改顶点着色器
当然就是使用uniform来做这个事情,窗口事件宽高改变
#version 330 core
layout(location = 0) in vec3 aPos;
layout(location = 1) in vec3 aColor;
layout(location = 2) in vec2 aTexCoord;
out vec4 vertexColor;
out vec2 TexCoord;
//out vec2 TexCoord1;
uniform float v_scalex;
uniform float v_scaley;
void main(){
vec3 pos;
pos = aPos * vec3(v_scalex,v_scaley,1);
//pos.x = aPos.x * v_scalex;
//pos.y = aPos.y * v_scaley;
//pos.z = aPos.z;
gl_Position = vec4(pos, 1.0);
vertexColor = vec4(aColor, 1.0);
TexCoord = aTexCoord;
//TexCoord1 = aTexCoord1;
}
其中,直接运算
pos.x = aPos.x * v_scalex;
pos.y = aPos.y * v_scaley;
pos.z = aPos.z;
也是可以的,不过更为直接的计算是向量积,和矩阵运算不同,向量积是对应的x,y,z 直接运算,不要把它当成直接的矩阵运算。
cpp 文件
窗口事件:
void windowResize_callback(GLFWwindow* window, int width, int height)
{
//printf("windowResize_callback\n");
c_data::Instance().func_calc_scale_vertex(width, height);
}
再使用glUniform1f 改变x 和 y的投影比例
glUniform1f(glGetUniformLocation(myShader.ID, "v_scalex"), c_data::Instance().vetex_scale_x);
glUniform1f(glGetUniformLocation(myShader.ID, "v_scaley"), c_data::Instance().vetex_scale_y);
我们会看到正确的投影视口,与图像成正比,如下所示
放大缩小
放大和缩小又是改变纹理坐标,和视口投影不是一回事,并且涉及到更多的计算,下次再聊。