opengl 高级技巧
Posted qianbo_insist
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了opengl 高级技巧相关的知识,希望对你有一定的参考价值。
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 << "显卡供应商 : " << vendor << endl;
cout << "显卡型号 : " << renderer << endl;
cout << "OpenGL版本 : " << version << endl;
cout << "GLSL版本 : " << glslVersion << endl;
以上是关于opengl 高级技巧的主要内容,如果未能解决你的问题,请参考以下文章
带有顶点/片段着色器的光。使用不同的变量。 (openGL)