C++ 替换gl_位置=gl_模型视图投影矩阵*gl_顶点;

C++ 替换gl_位置=gl_模型视图投影矩阵*gl_顶点;,c++,opengl,glsl,C++,Opengl,Glsl,有几个问题是这样的,但我仍然没有真正理解。十多年前,我用OpenGL编码,注意到进入现代OpenGL是多么困难。org页面是一个可怕的烂摊子当谈到例子,你永远不知道它是什么版本,任何版本似乎混淆在各种代码的例子。 好的,我有一个旧代码,我想至少更新到OpenGL>3。所以,我做的第一件事是从glVertex3fv开始,最终使用GLVERTEXAttributePointer(在我读到这篇文章之前,glVertexPointer也被弃用了一步)。这很好,但是当试图放置纹理时,我很快就被卡住了,我认

有几个问题是这样的,但我仍然没有真正理解。十多年前,我用OpenGL编码,注意到进入现代OpenGL是多么困难。org页面是一个可怕的烂摊子当谈到例子,你永远不知道它是什么版本,任何版本似乎混淆在各种代码的例子。 好的,我有一个旧代码,我想至少更新到OpenGL>3。所以,我做的第一件事是从glVertex3fv开始,最终使用GLVERTEXAttributePointer(在我读到这篇文章之前,glVertexPointer也被弃用了一步)。这很好,但是当试图放置纹理时,我很快就被卡住了,我认为这是因为错误的定位,我想摆脱C++代码:

glMatrixMode( GL_PROJECTION );
glLoadIdentity();
glFrustum( -RProjZ, +RProjZ, -Aspect*RProjZ, +Aspect*RProjZ, 1.0, 32768.0 );
然后画出来

// bind vertex buffer
glBindBuffer(GL_ARRAY_BUFFER, VertBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * size, verts, GL_STATIC_DRAW);

// enable arrays
glEnableVertexAttribArray(0); 

// set pointers
glVertexAttribPointer(0,3,GL_FLOAT, GL_FALSE, sizeof(float) * floatsPerVertex, 0);

// render ComplexSurface
glDrawArrays(GL_TRIANGLE_FAN, 0, size);
glDisableVertexAttribArray(0);
在vertexshader中使用

gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; 
一切都在神奇地运转。别误会,我是个魔术迷,但是。。。 然后我找到了几个矩阵转换,可以用来得到一个矩阵来替换glFrustum,但是每当我尝试替换它时,它都失败了(尽管我认为我理解glFrustum背后的数学以及到矩阵的转换)

这是什么样的

buildPerspProjMat(g_ProjView,FovAngle,Aspect,1.0,32768.0 );

glUseProgram(g_program);
glUniformMatrix4fv(g_programFrustum, 1, GL_FALSE, g_ProjView );
glUseProgram(0);
使用上面缓冲区中着色器的位置和投影matix,但这根本不起作用

所以我现在不明白在哪里替换这个,用着色器中的内容替换。我不知道glMatrixMode发生在哪一点,以及“何时”用统一矩阵替换它(这里的问题不是将参数作为统一矩阵传递)。 我无法计算我已经读了多少教程,但我总是对所有的混合版本感到困惑。我总是对一些代码示例感到高兴,但请使用OpenGL3或更高版本


下一个是用glTexCoord2f代替纹理,但情况不同:)

好吧,我同意大多数OpenGL教程混淆了不推荐和不推荐的内容。为了让你找到正确的方向,让我解释一下

gl\u ModelViewProjectionMatrix
gl\u ModeView
glMatrixMode()
和矩阵堆栈
glPushMatrix()
glPopMatrix()
都不推荐使用。您需要将自己的矩阵定义为统一变量,然后使用
glUniform*
设置并将其传递给着色器

gl\u Vertex
也不推荐使用,实际上整个固定属性名称都不推荐使用。或者,您需要定义自己的属性名称并将它们绑定到特定位置。然后,您可以使用
glvertexattributepointer
通过将属性位置传递给它来设置它们的值()。例如:

glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, vertices); // for vertices
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, color); // for color
和着色器代码

layout (location = 0) in vec4 vertex;
layout (location = 1) in vec4 color;

uniform mat4 modelview;
uniform mat4 projection;

void main()
{
gl_Position = projection* modelview* vertex;
}
对于属性位置,您可以像我一样在着色器代码中设置它们,或者使用OpenGL API设置它们


如果您习惯于使用旧的OpenGL全局变量,例如
gl\u ModelView
,那么管理统一变量可能会有点棘手。我写了一篇文章,希望能帮助您管理大型项目的统一变量。

我发现,在考虑现代OpenGL时,最好忘记
glMatrixMode
曾经存在过

记住这一点,让我们来看看最基本的绘图操作需要什么:替换
gl\u ModelViewProjectionMatrix
。顾名思义,这是3个不同矩阵的组合:模型矩阵、视图矩阵和投影矩阵

因此,您需要在着色器中容纳3个类型为
mat4
的统一变量。您将这样使用它:

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

layout (location = 0) in vec3 position;

void main()
{
    gl_Position = projMat * viewMat * modelMat * vec4(position, 1.0);
}
这段着色器代码执行与上面相同的功能。改变的是内置的<代码> GLYMyVIEW视图投影矩阵被3个统一变量替换(如果你在C++中传递它们,在将它们自己传递到C++之前,可以将它们组合为一个)。内置的
gl_顶点
被输入变量替换

在C++方面,你需要做2件事。首先,您需要获得这些制服的位置:

GLuint modelMatIdx = glGetUniformLocation(shaderProgId, "modelMat");
GLuint viewMatIdx = glGetUniformLocation(shaderProgId, "viewMat");
GLuint projMatIdx = glGetUniformLocation(shaderProgId, "projMat");
现在,您可以在使用
glUniformMatrix4fv
绘图之前,输入每个均匀体的值

有一个特别的库使得这一点特别容易。例如,要获得与示例中相同的投影矩阵,可以执行以下操作:

glm::mat4 projMat = glm::frustum(-RProjZ, +RProjZ, -Aspect*RProjZ, +Aspect*RProjZ, 1.0, 32768.0);
你可以这样传递:

glUniformMatrix4fv(projMatIdx, 1, GL_FALSE, glm::value_ptr(projMat));
既然你知道怎么做了,我想谈谈“何时”的问题。你说你不清楚矩阵模式的东西,这让我回到我之前的断言“忘了它”。矩阵模式存在,因此您可以告诉opengl哪些内置操作应该受到对opengl矩阵操作(如glTranslate、glFrustum等)的调用的影响,但所有这些现在都消失了。您现在负责管理所涉及的(可能有许多)矩阵。你所要做的就是在画画之前把它们传过来(如我上面所示),你会没事的。在尝试修改程序之前,请确保程序已绑定

下面是一个工作示例(如果您对gl感到惊讶::…而不是gl…这是因为我使用的是由glLoadGen生成的opengl头,它将所有opengl API函数放在gl名称空间中)

最后是片段着色器:

//[FRAGMENT SHADER]
#version 430

in vec2 uv;

out vec4 color;

void main()
{
    color = vec4(uv, 0.0, 1.0);
}
生成的图像是:


谢谢,这已经回答了很多问题。在您的示例中,我现在不确定的是:glm::mat4 modelMat;//身份-我已经阅读了一些关于GLM的教程,并在一些简单的测试程序中使用了它,但我首先感觉到改变了一种魔法,而另一种魔法却不起作用(至少在我试图摆脱gl_ModelViewProjectionMatrix的过程中),所以我想一开始就避免使用它。我想现在我明白为什么它不起作用了。谢谢你!我花了太多的时间试图弄清楚这些事情。我没有意识到这其中有多少
//[VERTEX SHADER]
#version 430

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

layout (location = 0) in vec3 in_position; // matches gl::EnableVertexAttribArray(0);
layout (location = 1) in vec2 in_uv; // matches gl::EnableVertexAttribArray(1);

out vec2 uv;

void main()
{
    gl_Position = projMat * viewMat * modelMat * vec4(in_position, 1.0);
    uv = in_uv;
}
//[FRAGMENT SHADER]
#version 430

in vec2 uv;

out vec4 color;

void main()
{
    color = vec4(uv, 0.0, 1.0);
}