替换gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; [英] Replacement for gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;

查看:169
本文介绍了替换gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这里有几个问题,但我还是没有真正理解。我在10年前使用OpenGL编程,并注意到进入现代OpenGL有多么困难。 OpenGL.org页面是一个可怕的混乱,当谈到例子,你永远不知道它的版本,任何版本似乎混合了各种代码示例。
好​​吧,我有一个旧代码我想更新到OpenGL> 3至少。所以我做的第一件事是从glVertex3fv移动到终于使用glVertexAttribPointer(通过一个步骤与glVertexPointer,直到我读到这已经过时了,现在也是如此)。这工作得很好,但是当试图放置纹理时,我被卡住了,我认为这是因为错误的定位,我想摆脱c ++代码:

  glMatrixMode(GL_PROJECTION); 
glLoadIdentity();
glFrustum(-RProjZ,+ RProjZ,-Aspect * RProjZ,+ Aspect * RProjZ,1.0,32768.0);

并绘制

  //绑定顶点缓冲区
glBindBuffer(GL_ARRAY_BUFFER,VertBuffer);
glBufferData(GL_ARRAY_BUFFER,sizeof(float)* size,verts,GL_STATIC_DRAW);

//使用数组
glEnableVertexAttribArray(0);

//设置指针
glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,sizeof(float)* floatsPerVertex,0);

// render ComplexSurface
glDrawArrays(GL_TRIANGLE_FAN,0,size);
glDisableVertexAttribArray(0);



在顶点着色器中

  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);
glUscProgram(0);

并使用投影矩阵中上面缓冲区中着色器中的位置,但这不是



因此,我现在不知道的是在哪里替换和在着色器中。我不知道在什么时候glMatrixMode发生和when用一些统一的矩阵(传递args作为统一不是这里的问题)。
我不能计算我已经读了多少教程,但我总是困惑所有混合版本。我总是很高兴一些代码示例,但请OpenGL 3或更高。



下一个将替代glTexCoord2f纹理,但是是一个不同的故事: / p>

解决方案

我发现当思考现代OpenGL时,最好忘记 glMatrixMode

考虑到这一点,让我们来看看最基本的绘制操作所需要的: gl_ModelViewProjectionMatrix

code>。因为它的名字意味着这是3个不同矩阵的组合:模型矩阵,视图矩阵和投影矩阵。



所以你需要在你的着色器以适应这是 mat4 类型的3个统一变量。你会这样使用:

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

布局(位置= 0)在vec3位置;

void main()
{
gl_Position = projMat * viewMat * modelMat * vec4(position,1.0);
}

此位的着色器代码执行与上面相同的功能。什么改变是内置的 gl_ModelViewProjectionMatrix 被3个统一的变量(可以组合为一个,如果你确保自己在C + )。并且内置 gl_Vertex 被替换为输入变量。



在C ++端,你需要做两件事。首先,您需要获取这些制服的位置:

  GLuint modelMatIdx = glGetUniformLocation(shaderProgId,modelMat) ; 
GLuint viewMatIdx = glGetUniformLocation(shaderProgId,viewMat);
GLuint projMatIdx = glGetUniformLocation(shaderProgId,projMat);

现在,您可以在绘制之前传递每个制服的值c $ c> glUniformMatrix4fv



一个特别的库让这个特别容易是glm 。例如,要获得与您的示例中相同的投影矩阵,您可以这样做:

  glm :: mat4 projMat = glm :: trunc (-RProjZ,+ RProjZ,-Aspect * RProjZ,+ Aspect * RProjZ,1.0,32768.0); 

,您可以这样传递:

  glUniformMatrix4fv(projMatIdx,1,GL_FALSE,glm :: value_ptr(projMat)); 

现在你知道了,我想解决when的问题。你说你不清楚矩阵模式的东西,让我回到我早先的说法忘记它。矩阵模式是这样,所以你可以告诉opengl其内置的应该受到OpenGL矩阵操作的调用,如glTranslate,glFrustum等等,但所有这一切都已经走了。你现在负责管理涉及的(可能许多)矩阵。所有你需要做的是在你画之前传递它们(如上所示),你会很好。



下面是一个工作示例(如果你被gl :: ...所惊讶,而不是gl ...这是因为我使用了一个由glLoadGen生成的opengl头,它将所有的opengl API函数放在gl命名空间中)。

  GLuint simpleProgramID; 
//加载着色器并使程序

GLuint modelMatIdx = gl :: GetUniformLocation(simpleProgramID,modelMat);
GLuint viewMatIdx = gl :: GetUniformLocation(simpleProgramID,viewMat);
GLuint projMatIdx = gl :: GetUniformLocation(simpleProgramID,projMat);

GLuint vaoID;
gl :: GenVertexArrays(1,& vaoID);
gl :: BindVertexArray(vaoID);

GLuint vertBufferID,indexBufferID;
gl :: GenBuffers(1,& vertBufferID);
gl :: GenBuffers(1,& indexBufferID);

struct Vec2 {float x,y; };
struct Vec3 {float x,y,z; };
struct Vert {Vec3 pos; Vec2 tex; };

std :: array< Vert,8> cubeVerts = {{
{{0.5f,0.5f,0.5f},{1.0f,0.0f}},{{0.5f,0.5f,-0.5f},{1.0f,1.0f}} ,{b0b} {{0.5f,-0.5f,-0.5f},{0.0f,1.0f}},{{0.5f,-0.5f,0.5f},{0.0f,0.0f}
{{-0.5f,0.5f,0.5f},{0.0f,0.0f}},{(-0.5f,0.5f,-0.5f},{0.0f,1.0f}},
{{-0.5f,-0.5f,-0.5f},{1.0f,1.0f}},{(-0.5f,-0.5f,0.5f},{1.0f,0.0f}}
}};

std :: array< unsigned int,36> cubeIdxs = {{
0,2,1,0,3,2,// Right
4,5,6,4,6,7,// Left
0, 3,0,4,7,// Top
1,6,2,1,5,6,// Bottom
0,5,1,0,4,5, b $ b 3,7,6,3,6,2 // Back
}};

//顶点缓冲区
gl :: BindBuffer(gl :: ARRAY_BUFFER,vertBufferID);
gl :: BufferData(gl :: ARRAY_BUFFER,sizeof(Vert)* cubeVerts.size(),cubeVerts.data(),gl :: STATIC_DRAW);
gl :: EnableVertexAttribArray(0); //匹配布局(位置= 0)
gl :: VertexAttribPointer(0,3,gl :: FLOAT,gl :: FALSE_,sizeof(Vert),0);
gl :: EnableVertexAttribArray(1); //匹配布局(位置= 1)
gl :: VertexAttribPointer(1,2,gl :: FLOAT,gl :: FALSE_,sizeof(Vert),(GLvoid *)sizeof(Vec3)

//索引缓冲区
gl :: BindBuffer(gl :: ELEMENT_ARRAY_BUFFER,indexBufferID);
gl :: BufferData(gl :: ELEMENT_ARRAY_BUFFER,sizeof(unsigned int)* cubeIdxs.size(),cubeIdxs.data(),gl :: STATIC_DRAW);
gl :: BindVertexArray(0);

glm :: mat4 projMat = glm :: perspective(56.25f,16.0f / 9.0f,0.1f,100.0f);
glm :: mat4 viewMat = glm :: lookAt(glm :: vec3(5,5,5),glm :: vec3(0,0,0),glm :: vec3(0,0,1) );
glm :: mat4 modelMat; // identity

while(!glfwWindowShouldClose(window))
{
gl :: Clear(gl :: COLOR_BUFFER_BIT | gl :: DEPTH_BUFFER_BIT);

gl :: UseProgram(simpleProgramID);
gl :: UniformMatrix 4fv(projMatIdx,1,gl :: FALSE_,glm :: value_ptr(projMat));
gl :: UniformMatrix 4fv(viewMatIdx,1,gl :: FALSE_,glm :: value_ptr(viewMat));
gl :: UniformMatrix4fv(modelMatIdx,1,gl :: FALSE_,glm :: value_ptr(modelMat));

gl :: BindVertexArray(vaoID);
gl :: DrawElements(gl :: TRIANGLES,36,gl :: UNSIGNED_INT,0);
gl :: BindVertexArray(0);

gl :: UseProgram(0);

glfwSwapBuffers(window);
glfwPollEvents();
}

关联顶点着色器:

  // [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:

  // [FRAGMENT SHADER] 
#version 430

in vec2 uv;

out vec4 color;

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

生成的图片是:



>


There are a couple of questions like this, but I still haven't really understood. I was coding with OpenGL over 10 years ago and noticed how difficult it is to get into modern OpenGL. The OpenGL.org page is a horrible mess when it comes to examples, you never know what version it is, any version seems to be mixed up in various code examples. Alright, I have an old code I want to update to OpenGL >3 at least. So first thing I did was to move on from glVertex3fv to finally make it with glVertexAttribPointer (over a step with glVertexPointer until I read this is deprecated now as well). This works out fine, but when trying to place textures I got stuck quickly and I assume it is because of wrong positioning and I wanted to get rid of c++ code :

glMatrixMode( GL_PROJECTION );
glLoadIdentity();
glFrustum( -RProjZ, +RProjZ, -Aspect*RProjZ, +Aspect*RProjZ, 1.0, 32768.0 );

and to draw it

// 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);

with in the vertexshader

gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; 

And everything is working magically. Now don't get me wrong, I'm a big fan of magic, but... Then I found a couple of matrix conversions which can be used to get a matrix to replace glFrustum, but whenever I try to replace it, it fails badly (although I think I understood the maths behind glFrustum and the conversion into the matrix).

What tried is something like

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

glUseProgram(g_program);
glUniformMatrix4fv(g_programFrustum, 1, GL_FALSE, g_ProjView );
glUseProgram(0);

and using the position in the shader from the buffer above with the projection matix, but this doesn't work out at all.

So what I plain don't get now is where to replace this and with what in the shader. I don't know at which point the glMatrixMode takes place and "when" to replace it with some uniform matrix (passing the args as uniform ain't the problem here). I can't count how many tutorials I read already, but I always get confused over all the mixed versions. I am always happy about some code examples, but please OpenGL 3 or higher.

The next would be a replacement for glTexCoord2f for texturing, but that's a different story :)

解决方案

I find that when thinking about modern OpenGL it is best to forget that glMatrixMode ever existed.

With that in mind, let's go over what you need for the most basic draw operation: a replacement for gl_ModelViewProjectionMatrix. As it's name implies this is a combination of 3 different matrices: the model matrix, the view matrix, and the projection matrix.

So what you'll need in your shader to accomodate this is 3 uniform variables of type mat4. Which you'll use like so:

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);
}

This bit of shader code performs the same function as the one you had above. What changed is the built-in gl_ModelViewProjectionMatrix was replaced by 3 uniform variables (which could be combined as one if you make sure to multiply them yourself on the C++ side before passing it in). And the builtin gl_Vertex was replaced by an input variable.

On the C++ side you will need to do 2 things. First you'll need to get the location for each of these uniforms:

GLuint modelMatIdx = glGetUniformLocation(shaderProgId, "modelMat");
GLuint viewMatIdx = glGetUniformLocation(shaderProgId, "viewMat");
GLuint projMatIdx = glGetUniformLocation(shaderProgId, "projMat");

And with this in hand you can now pass in the values for each uniform right before drawing using glUniformMatrix4fv.

One particular library which makes this particularly easy is glm. For example to get the same projection matrix as in your example you would do:

glm::mat4 projMat = glm::frustum(-RProjZ, +RProjZ, -Aspect*RProjZ, +Aspect*RProjZ, 1.0, 32768.0);

and you would pass it in like so:

glUniformMatrix4fv(projMatIdx, 1, GL_FALSE, glm::value_ptr(projMat));

Now that you know how, I'd like to address the issue of "when". You said you weren't clear about the matrix mode stuff and that brings me back to my earlier assertion of "forget about it". The matrix mode was there so that you could tell opengl which built in should be affected by calls to OpenGL matrix operations such as glTranslate, glFrustum and so on, but all of this is gone now. You are now in charge of managing the (possibly many) matrices involved. All you have to do is pass them in before you draw (as I've shown above) and you'll be fine. Just make sure the program is bound before you attempt to modify its uniforms.

Here's a working example (if you're suprised by gl::... instead of gl... it's because I'm using an opengl header generated by glLoadGen which puts all of the opengl API functions in the gl namespace).

GLuint simpleProgramID;
// load the shader and make the program

GLuint modelMatIdx = gl::GetUniformLocation(simpleProgramID, "modelMat");
GLuint viewMatIdx = gl::GetUniformLocation(simpleProgramID, "viewMat");
GLuint projMatIdx = gl::GetUniformLocation(simpleProgramID, "projMat");

GLuint vaoID;
gl::GenVertexArrays(1, &vaoID);
gl::BindVertexArray(vaoID);

GLuint vertBufferID, indexBufferID;
gl::GenBuffers(1, &vertBufferID);
gl::GenBuffers(1, &indexBufferID);

struct Vec2 { float x, y; };
struct Vec3 { float x, y, z; };
struct Vert { Vec3 pos; Vec2 tex; };

std::array<Vert, 8> cubeVerts = {{
    { {  0.5f,  0.5f,  0.5f }, { 1.0f, 0.0f } }, { {  0.5f,  0.5f, -0.5f }, { 1.0f, 1.0f } },
    { {  0.5f, -0.5f, -0.5f }, { 0.0f, 1.0f } }, { {  0.5f, -0.5f,  0.5f }, { 0.0f, 0.0f } },
    { { -0.5f,  0.5f,  0.5f }, { 0.0f, 0.0f } }, { { -0.5f,  0.5f, -0.5f }, { 0.0f, 1.0f } },
    { { -0.5f, -0.5f, -0.5f }, { 1.0f, 1.0f } }, { { -0.5f, -0.5f,  0.5f }, { 1.0f, 0.0f } }
}};

std::array<unsigned int, 36> cubeIdxs = {{ 
    0, 2, 1, 0, 3, 2, // Right
    4, 5, 6, 4, 6, 7, // Left
    0, 7, 3, 0, 4, 7, // Top
    1, 6, 2, 1, 5, 6, // Bottom
    0, 5, 1, 0, 4, 5, // Front
    3, 7, 6, 3, 6, 2  // Back
}};

// Vertex buffer
gl::BindBuffer(gl::ARRAY_BUFFER, vertBufferID);
gl::BufferData(gl::ARRAY_BUFFER, sizeof(Vert) * cubeVerts.size(), cubeVerts.data(), gl::STATIC_DRAW);
gl::EnableVertexAttribArray(0); // Matches layout (location = 0)
gl::VertexAttribPointer(0, 3, gl::FLOAT, gl::FALSE_, sizeof(Vert), 0);
gl::EnableVertexAttribArray(1); // Matches layout (location = 1)
gl::VertexAttribPointer(1, 2, gl::FLOAT, gl::FALSE_, sizeof(Vert), (GLvoid*)sizeof(Vec3));

// Index buffer
gl::BindBuffer(gl::ELEMENT_ARRAY_BUFFER, indexBufferID);
gl::BufferData(gl::ELEMENT_ARRAY_BUFFER, sizeof(unsigned int) * cubeIdxs.size(), cubeIdxs.data(), gl::STATIC_DRAW);
gl::BindVertexArray(0);

glm::mat4 projMat = glm::perspective(56.25f, 16.0f/9.0f, 0.1f, 100.0f);
glm::mat4 viewMat = glm::lookAt(glm::vec3(5, 5, 5), glm::vec3(0, 0, 0), glm::vec3(0, 0, 1));
glm::mat4 modelMat; // identity

while (!glfwWindowShouldClose(window))
{
    gl::Clear(gl::COLOR_BUFFER_BIT | gl::DEPTH_BUFFER_BIT);

    gl::UseProgram(simpleProgramID);
    gl::UniformMatrix4fv(projMatIdx, 1, gl::FALSE_, glm::value_ptr(projMat));
    gl::UniformMatrix4fv(viewMatIdx, 1, gl::FALSE_, glm::value_ptr(viewMat));
    gl::UniformMatrix4fv(modelMatIdx, 1, gl::FALSE_, glm::value_ptr(modelMat));

    gl::BindVertexArray(vaoID);
    gl::DrawElements(gl::TRIANGLES, 36, gl::UNSIGNED_INT, 0);
    gl::BindVertexArray(0);

    gl::UseProgram(0);

    glfwSwapBuffers(window);
    glfwPollEvents();
}

Associated Vertex Shader:

//[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;
}

And finally Fragment shader:

//[FRAGMENT SHADER]
#version 430

in vec2 uv;

out vec4 color;

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

The resulting image is:

这篇关于替换gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆