微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

openGL 4,翻译和缩放出错

如何解决openGL 4,翻译和缩放出错

我正在尝试在代表地图的平面上进行正射投影——想想“平面图”。我遇到了麻烦,因为 openGL 4 对我来说是新的(我上次使用的是 1.1,并且世界已经改变)并且因为我尝试做的与网上的常见示例不太一样。我的问题是缩放和转换。

描述地图的数据是一系列带有端点的线,我称之为“地牢坐标单位”。当我渲染图像时,我希望有一个固定的规则,即“1 个单位是 1 个像素”。

我的坐标都在第一象限,(0,0) 代表地图的左下角。我希望 (0,0) 显示在屏幕的左下方。

现在是棘手的部分。当我在片段着色器中渲染“地板”时,我得到了 gl_FragCoord,这是理想的。它实际上是一个像素位置,这意味着就我的目的而言,它相当于一个地牢坐标。我可以查找传递给着色器的所有信息(也在地牢坐标中)并找出如何绘制(或丢弃)该像素。它有效,除了……它绘制的 (0,0) 位于屏幕中央,而不是左下方。

更糟糕的是,有一些东西,比如线条(“墙”),我在第二遍中用地牢坐标中的细长三角形渲染。他们没有出现在我想要的地方。 (事实上​​,我很确定我用来平铺地板的三角形也是错误的,只是巧合地覆盖了屏幕。)

我真的,真的需要 openGL 来使用一个坐标系统,将 0,0 放在图像的左下角,并让我在我的单位中指定三角形顶点,这恰好直接映射到像素。

这似乎是一个简单的缩放和平移案例。但我显然应用了音阶并错误地翻译了。

顶点代码很简单:

#version 430
layout (location = 0) in vec3 Position;
uniform mat4 gWorld;
out vec4 Color; //unused; the fragment shader caslculates all colors

void main()
{
    gl_Position = gWorld * vec4(Position,1.0);
}

为地图地板构建 2 个三角形(现在是一个简单的矩形)似乎很简单:

Vector3f Vertices[4];
Vertices[0] = Vector3f(0.f,0.f,0.0f);
Vertices[1] = Vector3f(0.f,mapEdges.maxs.y,0.0f);
Vertices[2] = Vector3f(mapEdges.maxs.x,0.0f);
Vertices[3] = Vector3f(mapEdges.maxs.x,0.0f);
glGenBuffers(1,&VBO);
glBindBuffer(GL_ARRAY_BUFFER,VBO);
glBufferData(GL_ARRAY_BUFFER,sizeof(Vertices),Vertices,GL_STATIC_DRAW);
unsigned int Indices[] = { 0,1,2,3 };
glGenBuffers(1,&IBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,IBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER,sizeof(Indices),Indices,GL_STATIC_DRAW);

我为他们使用索引抽签。

C++ 代码(使用 glm)设置世界矩阵:

gluseProgram(ShaderProgram); //this selects the shader
gWorldLocation = glGetUniformlocation(ShaderProgram,"gWorld");
assert(gWorldLocation != 0xFFFFFFFF);

...并且在渲染时...

//try to fix openGL’s desire to think my buffer is -1 to 1 across
float scale = 1/1024.f; //test map is about 1024 units across
glm::mat4 sm = glm::scale(
    glm::mat4( 1.0f ),glm::vec3( scale,scale,1.0f )
    );
glm::mat4 ts = glm::translate(
    sm,glm::vec3( -512.0f,-512.0f,0.0f ) //shove left and down
    );

gluniformMatrix4fv(gWorldLocation,GL_TRUE,&ts[0][0]);

由于我的测试地图大约有 1024 个单位,我原以为这可以将东西推到位。但不是。地板(记住,它使用 gl_FragCoord 来决定绘制的位置和内容)是从屏幕中心向上和向右绘制的,尽管它看起来和我期望的一样。在地牢坐标中由细长三角形绘制的墙壁无处可见,可能在某处缩小到以太中。

基本上我不会让 openGL 相信我希望 x=0 是图像的左边缘,而且我的缩放显然是完全错误的。遗憾的是,我曾经有一个版本(错误地)在屏幕上画了一些墙,但我没有那个代码了。尽管如此,它告诉我我并没有完全放弃生成墙壁,只是将它们放下。

如何让 openGL 使用我的单位?

解决方法

当您设置矩阵统一时,您将转置矩阵。由于向量在着色器程序中从右侧乘以矩阵,因此这是错误的。见GLSL Programming/Vector and Matrix Operations

glUniformMatrix4fv(gWorldLocation,1,GL_TRUE,&ts[0][0]);

glUniformMatrix4fv(gWorldLocation,GL_FALSE,&ts[0][0]);

您可以使用矩阵 glm::ortho 设置正交投影,而不是缩放和平移顶点:

glm::mat4 projection = glm::ortho(0.0f,1024.0f,0.0f,-1.0f,1.0f);
glUniformMatrix4fv(gWorldLocation,glm::value_ptr(projection));

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?