Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/162.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 现代OpenGL投影视图模型转换不起作用_C++_Opengl_Graphics_Glsl - Fatal编程技术网

C++ 现代OpenGL投影视图模型转换不起作用

C++ 现代OpenGL投影视图模型转换不起作用,c++,opengl,graphics,glsl,C++,Opengl,Graphics,Glsl,我试着在我的着色器中只使用一个变换和它的逆转置,但是我的着色结果很奇怪,所以我猜我的法线被错误地变换了。许多在线教程建议使用投影*视图*模型三阶段变换,并在视图*模型变换阶段计算灯光。所以我尝试实现这三个转换,但不仅我的茶壶没有显示,甚至一个简单的三角形也不会显示 以下是我的顶点着色器代码: #version 410 in vec3 position; // position of the vertex (and fragment) in world space in vec3 normal

我试着在我的着色器中只使用一个变换和它的逆转置,但是我的着色结果很奇怪,所以我猜我的法线被错误地变换了。许多在线教程建议使用投影*视图*模型三阶段变换,并在视图*模型变换阶段计算灯光。所以我尝试实现这三个转换,但不仅我的茶壶没有显示,甚至一个简单的三角形也不会显示

以下是我的顶点着色器代码:

#version 410

in vec3 position;  // position of the vertex (and fragment) in world space
in vec3 normal;  // surface normal vector in world space

uniform mat4 model;
uniform mat4 view;
uniform mat4 proj;
uniform mat4 modelView_it;

vec3 l_pos = vec3(10, 10, 10);

out VertexData {
    vec3 normal;
    vec3 eye;
    vec3 lightDir;
} VertexOut;

void main()
{
    vec4 pos = view * model * vec4(position, 1.0);

    VertexOut.normal = normalize(vec3(modelView_it * vec4(normal, 0.0)));
    VertexOut.lightDir = l_pos - vec3(pos);
    VertexOut.eye = vec3(0, 0, 0);

    gl_Position = proj * view * model * vec4(position, 1);
}
这是我的片段着色器代码

#version 150

out vec4 colorOut;

vec3 kd = vec3(0.1, 1, 0.1);
vec3 ka = vec3(1, 1.0, 1.0);
vec3 ks = vec3(0.5, 1, 0.5);
float sp = 90;
vec3 intensity = vec3(1, 1, 1);

in VertexData {
    vec3 normal;
    vec3 eye;
    vec3 lightDir;
} VertexIn;

void main()
{
    vec3 n = normalize(VertexIn.normal);
    vec3 l = normalize(VertexIn.lightDir);
    vec3 e = normalize(VertexIn.eye);

    vec3 diffuse = kd*intensity*max(0, dot(l, n));
    vec3 r = -l + 2*dot(l,n) * n;
    vec3 specular = ks*intensity*max(pow(dot(r, e), sp),0);

// force to be white intentionally to test
    colorOut = vec4(1,1,1,1);
}
下面是我用来生成投影和视图转换矩阵的一些函数,代码取自其他一些类似的堆栈溢出问题

//generate projection matrix
void setPerspective(float fovY, float aspect, float near, float far, Matrix4f& mProjectionMatrix)
{
    float theta = fovY*0.5;
    float range = far - near;
    float invtan = 1./tan(theta);

    mProjectionMatrix(0,0) = invtan / aspect;
    mProjectionMatrix(1,1) = invtan;
    mProjectionMatrix(2,2) = -(near + far) / range;
    mProjectionMatrix(3,2) = -1;
    mProjectionMatrix(2,3) = -2 * near * far / range;
    mProjectionMatrix(3,3) = 0;
}
//generate view matrix
void lookAt(const Vector& position, const Vector& target, const Vector& up, Matrix4f& mViewMatrix)
{
    Matrix3f R;
    R.col(2) = (position-target).normalized();
    R.col(0) = up.cross(R.col(2)).normalized();
    R.col(1) = R.col(2).cross(R.col(0));
    mViewMatrix.topLeftCorner<3,3>() = R.transpose();
    mViewMatrix.topRightCorner<3,1>() = -R.transpose() * position;
}
这些函数如下所示

void transformModel(GLint& modelID, GLint& mvIT_ID, Matrix4f& modelMat, Matrix4f& viewMat) {
    glUniformMatrix4fv(modelID, 1, GL_FALSE, modelMat.data());
    glUniformMatrix4fv(mvIT_ID, 1, GL_FALSE, (viewMat*modelMat).inverse().transpose().data());
}

void transformView(GLint& viewID, GLint& mvIT_ID, Matrix4f& viewMat, Matrix4f& modelMat) {
    glUniformMatrix4fv(viewID, 1, GL_FALSE, viewMat.data());
    glUniformMatrix4fv(mvIT_ID, 1, GL_FALSE, (viewMat*modelMat).inverse().transpose().data());
}

void transformProj(GLint& projID, Matrix4f& projMat) {
    glUniformMatrix4fv(projID, 1, GL_FALSE, projMat.data());
}
尽管如此,屏幕还是黑色的。甚至不在原点使用简单的三角形。如果我在顶点着色器中去掉proj*view*,基本上只有模型是唯一的变换,我就能看到我的形状,并使用键盘事件对其进行精细变换。这意味着我的基本管道不应该成为问题,因为我能够看到形状。只要我在模型之前添加proj*view*,所有内容都会变黑

请帮忙

更新:现在我发现了一个问题:glUniformMatrix4fv给了我GL_INVALID_ENUM错误,它根本没有设置统一变量。我通过将矩阵硬编码到着色器中验证了这一点。我几乎找不到任何在线问题,而且似乎没有人使用此函数得到无效的枚举错误。有什么想法吗?

矩阵运算顺序令许多人难以置信,我就是其中之一

理论上,您希望对顶点进行建模、查看、投影并将其显示在屏幕上。代码看起来就是这样

您可能需要查看投影矩阵

mProjectionMatrix(3,2) = -1;
mProjectionMatrix(2,3) = -2 * near * far / range;
mProjectionMatrix(3,3) = 0;
试着把它转过来

mProjectionMatrix(2,3) = -1;
mProjectionMatrix(3,2) = -2 * near * far / range;
mProjectionMatrix(3,3) = 0;
您可以做的另一件事是将矩阵与gl实现进行比较,方法是使用gluPerspective设置矩阵,然后通过glGet获取它们。

transformXXX函数看起来很奇怪。为什么有三个不同的?通常,模型、视图和投影变换一起进行。TransformModel和TransformView都设置modelview\u IT矩阵

通常情况下,您不会将模型和视图转换矩阵作为单个模板传递。对于未优化的着色器代码中的一个,这将强制对每个顶点执行4×4矩阵乘法,结果可以很容易地进行预计算

您应该将transformModel和transformView合并到一个transformModelView函数中


另一件看起来很奇怪的事情是,你从零矩阵开始。通常情况下,您可以使用标识初始化矩阵并从那里开始工作。

好的,发现了一个潜在问题:我的transformXXX中的glUniformMatrix4fv总是会出现GL_INVALID_ENUM错误,并且会自动失败,因此甚至没有设置统一的开始,我还通过在着色器中硬编码矩阵来验证这一点,结果发现制服没有固定。你知道为什么会发生这种情况吗?@Dovizu:你是如何检索错误的无效枚举不是glUniform产生的错误…?一个鲜为人知的faxt是OpenGL错误累积。您必须在循环中调用glGetError,直到它返回GL\u NO\u ERROR。很有可能你以前因为OpenGL误用而积累了一些其他错误,而且你现在也看到了。我尝试通过错误循环,我得到的唯一一个错误是0x500无效枚举。因此,您建议无效的_ENUM不是glUniformMatrix4fv产生的错误。另外,你知道为什么当我将矩阵硬编码到着色器中时,屏幕上出现的东西只是闪烁,至少不是黑色的,如果我将这些制服设置为代码,它将不起作用吗?@Dovizu:我的最佳选择是,你之前调用的OpenGL之一失败了,这会引发一连串的失败,最终阻止你设置制服。将错误检查添加到每个OpenGL调用中,以便查看失败的地方。@Dovizu:噢,由于您使用的是类:请确保调用这些方法时,线程中的OpenGL上下文处于活动状态。尤其是通过构造函数调用的代码,有时对新手来说非常不直观。在模型和世界空间中发生的模型-视图转换应该在整个场景被压缩到视图截锥体之前发生,这一点也不奇怪。如果您想要像您建议的那样的参考实现,我就使用GLM。
mProjectionMatrix(2,3) = -1;
mProjectionMatrix(3,2) = -2 * near * far / range;
mProjectionMatrix(3,3) = 0;