您当前的位置: 首页 > 

qianbo_insist

暂无认证

  • 0浏览

    0关注

    399博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

opengl 高级技巧

qianbo_insist 发布时间:2021-09-30 21:54:35 ,浏览量:0

1 glOrtho 投影变换,使得和uv坐标一致

在二维平面顶点坐标和uv 纹理坐标如何做到一致而不用计算? 像一下这么使用

 glOrtho(0,1,1,0,-1,100);

接下去的坐标就可以由原来的负数变成和uv 一致 //传递顶点和纹理坐标 //顶点 // static const GLfloat ver[] = { // -1.0f,-1.0f, // 1.0f,-1.0f, // -1.0f, 1.0f, // 1.0f,1.0f // };

我们知道opengl 标准坐标是 左右 -1 到 1, 上下是 1 到 -1 ,而整个屏幕的中间才是 0,0,0,也就是原点, 但是经过 glOrtho(0,1,1,0,-1,100); 变换后,就可以变成 左右 0 到1 上下也是0 到 1 ,是不是可以和 uv 坐标一致了,是的! 上面的矩阵变成下面的 static const GLfloat ver[] = { 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f }; 这下,tex 和 ver 可以使用同一个矩阵了。

2 和glsl 兼容问题

一旦使用glOrtho 和 glPers glFrustum 等函数时, glsl 中的顶点坐标依然是 (-1 ,1) , 那么怎么和glOrtho 等投影矩阵一致呢?我们熟知的三个矩阵投影变换模型矩阵 1 变换矩阵 2 投影矩阵 3 模型观察矩阵 要做乘法和顶点相乘,也就是:

uniform mat4 projMat;
uniform mat4 viewMat;
uniform mat4 modelMat; 

三个相乘 我们来写个glsl 以下是顶点着色器

const char *vsrc =   "#version 330\n"
                           "uniform mat4 projMat;\n"
						   "uniform mat4 viewMat;\n"
						   "uniform mat4 modelMat; \n"
                           "in vec3 pos;\n"
                           "in vec2 texin;\n"
                           "out vec2 texCoord;\n"
                           "void main()\n"
                           "{\n"
                           "    gl_Position = * vec4(pos, 1.0);\n"
                           "    texCoord = texin;\n"
                           "}\n";

以下是片元着色器

    const char *fsrc =
                           "#version 330\n"
                           "out mediump vec4 color;\n"
                           "in vec2 texCoord;\n"
                           "uniform sampler2D tex\n;"
                           "void main()\n"
                           "{\n"
                           "    color = texture(tex, texCoord);\n"
                           //"      color = vec4(1.0, 0.0, 0.0, 0.0);\n"
                           "}\n";

计算三个矩阵要传进去才能正确,为了避免使用矩阵传入,一种方法是,在glsl 语言里面依然使用原坐标,二种方法是,使用兼容glsl

 const char *vsrc =   "#version 330 compatibility\n"
                           "in vec3 pos;\n"
                           "in vec2 texin;\n"
                           "out vec2 texCoord;\n"
                           "void main()\n"
                           "{\n"
                           "    gl_Position = gl_ModelViewProjectionMatrix * vec4(pos, 1.0);\n"
                           "    texCoord = texin;\n"
                           "}\n";

神奇的是,以前的的版本有一个全局变量叫gl_ModelViewProjectionMatrix,可以不用我们手动计算,代价是要加上compatibility 。

当然,我们可以手动获取投影矩阵的值,像以下这样:

float mat[16];
glGetFloatv(GL_PROJECTION_MATRIX, mat);
3、使用glm 计算矩阵
当然,除了使用兼容方式,可以使用glm 来计算投影变换模型矩阵
m_mat4View = glm::lookAt(glm::vec3(0, 0, -1), glm::vec3(0, 0, 0), glm::vec3(0, -1, 0));
m_mat4Projection = glm::ortho(-1.0f, 1.0f, -1.0f, 1.0f);
m_mat4Model = glm::mat4(1.0f);
m_mat4Model = glm::translate(m_mat4Model, glm::vec3(m_fXTranslate, m_fYTranslate, m_fZTranslate));
m_mat4Model = glm::rotate(m_mat4Model, glm::radians(m_fXRotateDegree), glm::vec3(1.0f, 0, 0));
m_mat4Model = glm::rotate(m_mat4Model, glm::radians(m_fYRotateDegree), glm::vec3(0, 1.0f, 0));
m_mat4Model = glm::rotate(m_mat4Model, glm::radians(m_fZRotateDegree), glm::vec3(0, 0, 1.0f));
m_mat4Model = glm::scale(m_mat4Model, glm::vec3(m_fXScale, m_fYScale, m_fZScale));
m_mat4ProjectionModelView = m_mat4Projection * m_mat4View * m_mat4Model;
glUniformMatrix4fv(m_iProjectionModelViewIDUniform, 1, GL_FALSE, &m_mat4ProjectionModelView[0][0]);

这样,把计算的m_mat4ProjectionModelView 传到glsl 中也是可以的

#version 330 core
uniform mat4 ProjectionModelView;
in vec4 vertexCoord;
in vec2 textureCoord;
out vec2 outTextureCoord;

void main(void){
gl_Position = ProjectionModelView * vertexCoord;
outTextureCoord = textureCoord;
}

#version 330 core
in vec2 outTextureCoord;
uniform sampler2D textureY;
void main(void)
{
vec3 bgr;
bgr = texture2D(textureY, outTextureCoord).rgb;
gl_FragColor = vec4(bgr, 1.0);
}
3、效率问题

使用RGBA 还是 YUV 还是 RGB 这个很是奇特,yuv数据很小,RGB, 数据翻了一倍,而RGBA 则更多,是不是yuv效率最高?不是,是RGBA。 显卡的4字节对齐就是这样的,不过可以使用glPixelStorei 来指定打包传输的字节对齐,GL_UNPACK_ALIGNMENT,是内存到显卡的传送,如下指定为1字节对齐 glPixelStorei(GL_UNPACK_ALIGNMENT,1); 这个函数在不同的操作系统和不同的驱动下表现不同,为了不用做那么多的测试,请使用RGBA方式。这种方式始终表现良好

4、 查看信息
//查看显卡、GLSL和OpenGL的信息  
	const GLubyte *vendor = glGetString(GL_VENDOR);
	const GLubyte *renderer = glGetString(GL_RENDERER);
	const GLubyte *version = glGetString(GL_VERSION);
	const GLubyte *glslVersion = glGetString(GL_SHADING_LANGUAGE_VERSION);
	cout             
关注
打赏
1663161521
查看更多评论
0.0397s