简体   繁体   English

openGL 4,翻译和缩放出错

[英]openGL 4, translate and scale going wrong

I'm trying to do an ortho projection onto a plane, which represents a map – think “floor plan”.我正在尝试在代表 map 的平面上进行正交投影——想想“平面图”。 I'm running into trouble because openGL 4 is new to me (I last used 1.1, and the world has changed) and because what I'm trying to do isn't much like common examples online.我遇到了麻烦,因为 openGL 4 对我来说是新的(我上次使用的是 1.1,世界已经改变),而且因为我想要做的不像网上常见的例子。 My problem is scaling and translating.我的问题是缩放和翻译。

The data that describes the map is a series of lines with endpoints are in what I'll call “dungeon coordinates units”.描述 map 的数据是一系列带端点的线,我称之为“地牢坐标单位”。 When I render the image I want to have a fixed rule of “1 unit is 1 pixel”.当我渲染图像时,我希望有一个固定的规则“1 个单位是 1 个像素”。

My coordinates are all in the first quadrant, with (0,0) representing the lower left of the map.我的坐标都在第一象限,(0,0)代表map的左下角。 I'd like (0,0) to show up in the lower left of the screen.我希望 (0,0) 显示在屏幕的左下方。

Now for the tricky bits.现在是棘手的部分。 When I render the “floor” in the fragment shader, I'm being handed gl_FragCoord, which is ideal.当我在片段着色器中渲染“地板”时,我得到了 gl_FragCoord,这是理想的。 It's effectively a pixel location, which means for my purposes it is equivalent to a dungeon coordinate.它实际上是一个像素位置,这意味着就我的目的而言,它相当于一个地牢坐标。 I can look up all the information I passed to the shader (also in dungeon coordinates) and figure out how to paint (or discard) that pixel.我可以查看我传递给着色器的所有信息(也在地牢坐标中)并找出如何绘制(或丢弃)该像素。 It works, except… it draws (0,0) is in the center of the screen, not the low left.它可以工作,除了……它绘制的 (0,0) 位于屏幕的中心,而不是左下方。

Worse, There are some things, like lines (“walls”), that I render with skinny triangles in dungeon coordinates in a second pass.更糟糕的是,有一些东西,比如线条(“墙”),我在第二遍中用地牢坐标中的细三角形渲染。 They don't show up where I want them.他们没有出现在我想要的地方。 (In fact I'm pretty sure that the triangles I'm using to tile the floor are also wrong and are only covering the screen by coincidence.) (事实上,我很确定我用来平铺地板的三角形也是错误的,只是巧合地覆盖了屏幕。)

I really, really need openGL to use a coordinate system that puts 0,0 at the lower left of the image and lets me specify triangle vertices in my units, which happen to map straight to pixels.我真的,真的需要 openGL 使用坐标系,将 0,0 放在图像的左下角,并让我在我的单位中指定三角形顶点,这发生在 map 直接到像素。

This seems like a simple case of scaling and translating.这似乎是一个简单的缩放和翻译案例。 But I'm obviously applying the scale and translate incorrectly.但我显然应用了比例并且翻译不正确。

The vertex code is simple:顶点代码很简单:

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

Building the 2 triangles for the map floor (a simple rectangle for now) seems simple:为 map 地板(现在是一个简单的矩形)构建 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.f, 0.0f);
Vertices[3] = Vector3f(mapEdges.maxs.x, mapEdges.maxs.y, 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,
                        1, 2, 3 };
glGenBuffers(1, &IBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(Indices), Indices, GL_STATIC_DRAW);

and I use an indexed draw for them.我为他们使用索引绘制。

The C++ code (using glm) sets up the world matrix: C++ 代码(使用 glm)设置世界矩阵:

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

...and when rendering… ...在渲染时...

//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, 1, GL_TRUE, &ts[0][0]);

Since my test map is about 1024 units across, I'd have thought this would have shoved things into position.由于我的测试 map 大约有 1024 个单位,我原以为这会将东西推到 position 中。 But no.但不是。 The floor (which, remember, is using gl_FragCoord to decide where and what to draw) is painted from screen center and up and right, though it otherwise looks as I'd expect.地板(记住,它使用 gl_FragCoord 来决定在哪里绘制什么内容)是从屏幕中心向上和向右绘制的,尽管它看起来像我预期的那样。 The walls, which are painted by skinny triangles in dungeon coordinates, are nowhere to be seen, probably scaled off into the aether somewhere.墙壁在地牢坐标中由细三角形绘制,无处可见,可能在某处缩放到以太中。

Basically I'm not convincing openGL that I want x=0 to be the left edge of the image and my scaling is obviously completely wrong.基本上我不能说服 openGL 我希望 x=0 成为图像的左边缘,而我的缩放显然是完全错误的。 Sadly I had one version that (incorrectly) drew some walls on the screen at one point, but I don't have that code anymore.可悲的是,我有一个版本(错误地)在屏幕上画了一些墙,但我不再有那个代码了。 Still, it tells me that I'm not completely off in generating the walls, just laying them down.尽管如此,它告诉我,我并没有完全放弃生成墙壁,只是将它们放下。

How do I get openGL to use my units?如何让 openGL 使用我的设备?

You transpose the matrix when you set the matrix uniform.当您设置矩阵统一时,您转置矩阵。 Since the vector is multiplied to the matrix from the right in your shader program, this is wrong.由于向量在着色器程序中从右侧乘以矩阵,因此这是错误的。 See GLSL Programming/Vector and Matrix Operations请参阅GLSL 编程/向量和矩阵运算

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

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

Instead of scaling and translating the vertices you can set an orthographic projection with matrix with glm::ortho :您可以使用glm::ortho使用矩阵设置正交投影,而不是缩放和平移顶点:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM