InfinityCity
InfinityCity

Reputation: 33

Rust, OpenGL - Distance is equal in code, but not after drawing

Using rust with glfw and gl bindings.

I have created an array of vertices for usage in vbo:

let x = 2.0 / ((HORIZONTAL_BOOK_AMOUNT * 2) + HORIZONTAL_BOOK_AMOUNT + 1) as f32; 
// x is the desired distance based on width of NDC divided by amount of horizontal objects to draw
// in the case of attached picture the HORIZONTAL_BOOK_AMOUNT would be 4

let mut vbo = 0;

let side = x * IMAGE_HEIGHT_MULTIPLIER; 
// here x is multiplied by constant, equaling to desired height of object

let vertices: Vec<f32> = vec![
-1.0 + x, 1.0 - x, 0.0, 1.0, //top left
-1.0 + 3.0 * x, 1.0 - x, 1.0, 1.0, // top right
-1.0 + 3.0 * x, 1.0 - x - (2.0 * side), 1.0, 0.0, //bottom right
-1.0 + 3.0 * x, 1.0 - x - (2.0 * side), 1.0, 0.0, //bottom right
-1.0 + x, 1.0 - x - (2.0 * side), 0.0, 0.0, //bottom left
-1.0 + x, 1.0 - x, 0.0, 1.0]; //top left 

gl::GenBuffers(1, &mut vbo);

gl::BindBuffer(gl::ARRAY_BUFFER, vbo);

gl::BufferData(gl::ARRAY_BUFFER, (vertices.len() * std::mem::size_of::<GLfloat>()) as GLsizeiptr, &vertices[0] as *const f32 as *const std::ffi::c_void, gl::STATIC_DRAW);

The problem is that after drawing the distance between top left vertex and top border should be equal to distance between top left vertex and left border.

The achieved effect, distances are not equal and are forming a rectangle:

Achieved effect

I tried recreating the issue with shorter example but it yielded similar results. Possibly it could be window size issue, but it is just my guess

The desired effect, which forms a square:

Desired effect

VAO code:

let mut VAO = 0;
gl::GenVertexArrays(1, &mut VAO);

gl::BindVertexArray(VAO);

let stride = 4 * std::mem::size_of::<GLfloat>() as GLsizei;

gl::VertexAttribPointer(0, 2, gl::FLOAT, gl::FALSE, stride, std::ptr::null());

gl::EnableVertexAttribArray(0);

gl::VertexAttribPointer(1, 2, gl::FLOAT, gl::FALSE, stride, (2 * std::mem::size_of::<GLfloat>()) as *const std::ffi::c_void);

gl::EnableVertexAttribArray(1);

Vertex shader:

#version 430 core
layout (location = 0) in vec2 aPos;

layout (location = 1) in vec2 aTexCoord;

out vec2 TexCoord;

uniform mat4 translatematrix; 
// this matrix is used for drawing objects by iterating through array // of (in this case:) books based on amount of them and horizontal // // amount

void main()
{

gl_Position = translatematrix * vec4(aPos, 0.0, 1.0);
TexCoord = aTexCoord;

}

Frag shader:

#version 430 core

out vec4 FragColor;

in vec2 TexCoord;

uniform sampler2D tex1;

void main()
{
FragColor = texture(tex1, TexCoord);
}

glViewport is set using glfw window event:

for (_, event) in glfw::flush_messages(&events) {

...

match event {

glfw::WindowEvent::FramebufferSize(width, height) => {
      gl::Viewport(0, 0, width, height); },

Upvotes: 2

Views: 163

Answers (2)

Rabbid76
Rabbid76

Reputation: 210908

You need to scale the position along the Y axis with the inverse aspect ratio:

y = x * width / height

Upvotes: 0

Yakov Galka
Yakov Galka

Reputation: 72479

You calculate the vertices in NDC (normalized device coordinates), which range through [-1, 1] within the viewport. The top-left vertex is x NDC units away from the corner both horizontally and vertically. However, for a non-square viewport, that would be a different amount of pixels.

Instead you should calculate all vertex coordinates in pixels, and incorporate a projection matrix into the translatematrix to convert pixels to NDC in the vertex shader.

Upvotes: 2

Related Questions