opengl 如何画旋转立方体胶质?

r3i60tvu  于 2023-02-22  发布在  其他
关注(0)|答案(1)|浏览(159)

为什么我的旋转立方体看起来不像旋转立方体?我需要移动相机吗?我不知道出了什么问题。我在rust中使用glium
24个顶点

const P: f32 = 0.5;
let vertex_buffer = glium::VertexBuffer::new(&display, &vec![
        // front 0-3
        Vertex { position: (-P, -P, 0.0) }, 
        Vertex { position: (P, P, 0.0) },
        Vertex { position: (P, -P, 0.0) },
        Vertex { position: (-P, P, 0.0) },
        // back 4-7
        Vertex { position: (-P, -P, 1.0) },
        Vertex { position: (P, P, 1.0) },
        Vertex { position: (P, -P, 1.0) },
        Vertex { position: (-P, P, 1.0) },
        // up 8-11
        Vertex { position: (-P, P, 0.0) }, 
        Vertex { position: (P, P, 0.0) },
        Vertex { position: (P, P, 1.0) },
        Vertex { position: (-P, P, 1.0) },
        // down 12-15
        Vertex { position: (-P, -P, 0.0) },
        Vertex { position: (P, -P, 0.0) },
        Vertex { position: (P, -P, 1.0) },
        Vertex { position: (-P, -P, 1.0) },
        // right 16-19
        Vertex { position: (P, -P, 0.0) }, 
        Vertex { position: (P, -P, 1.0) },
        Vertex { position: (P, P, 1.0) },
        Vertex { position: (P, P, 0.0) },
        // left 20-23
        Vertex { position: (-P, -P, 0.0) },
        Vertex { position: (-P, -P, 1.0) },
        Vertex { position: (-P, P, 1.0) },
        Vertex { position: (-P, P, 0.0) },
    ]
).unwrap();

生成立方体的6个面(每个面4个顶点,每个面2个三角形)的指数:

let indices = glium::IndexBuffer::new(&display, glium::index::PrimitiveType::TrianglesList,
&[
        // front
        0, 2, 1, 
        0, 3, 1,
        // back
        4, 6, 5,
        4, 7, 5,
        // up
        8, 9, 10,
        8, 11, 10,
        // down
        12, 13, 14,
        12, 15, 14,
        // right
        16, 17, 18,
        16, 19, 18,
        // left
        20, 21, 22,
        20, 23, 22u16,
    ]
).unwrap();

我正在使用 * Gouraud着色 *(来自glium教程)进行照明。
我在堆栈溢出中找到了cube的normals
Normals

let normals = glium::VertexBuffer::new(&display, &vec![
        // front
        Normal { normal: (1.0, 0.0, 0.0) }, 
        // back
        Normal { normal: (0.0, -1.0, 0.0) },
        // up
        Normal { normal: (1.0, 0.0, -1.0) },
        // down
        Normal { normal: (0.0, 0.0, 1.0) },
        // right
        Normal { normal: (1.0, 0.0, 0.0) },
        // left
        Normal { normal: (-1.0, 0.0, 0.0) },
    ]
).unwrap();

顶点着色器(glsl):

#version 150

in vec3 position;
in vec3 normal;
out vec3 v_normal;
uniform mat4 m;

void main() {
    v_normal = transpose(inverse(mat3(m))) * normal;
    gl_Position = m * vec4(position, 1.0);
}

片段着色器(glsl):

#version 150

in vec3 v_normal;
out vec4 color;
uniform vec3 u_light;

void main() {
    float brightness = dot(normalize(v_normal), normalize(u_light));
    vec3 dark_color = vec3(0.6, 0.0, 0.0);
    vec3 regular_color = vec3(1.0, 0.0, 0.0);
    color = vec4(mix(dark_color, regular_color, brightness), 1.0);
}

通过4x4矩阵进行旋转:

let mut t: f32 = 0.0;
let mut s: f32 = 0.002;

// ... loop.run

t += s;
if t > 180.0 || t < -180.0 {
    s = -s;
}

let m = [
    [1.0, 0.0, 0.0, 0.0],
    [0.0, t.cos(), -t.sin(), 0.0],
    [0.0, t.sin(), t.cos(), 0.0],
    [0.0, 0.0, 0.0, 1.0f32]
];

let light = [-1.0, -0.4, 0.9f32];

// params

target.draw((&vertex_buffer, &normals), &indices, &program, &uniform! { m: m, u_light: light }, &params).unwrap();

target.finish().unwrap();

有什么想法是错的吗?我很抱歉这么长的 * Q. * 有这么多的代码,但我不知道还有什么比这我可以提供。
下面是我的"旋转立方体"的一些图片:第一节第一节第一节第一节第二节第一节第三节第一节

mefy6pfw

mefy6pfw1#

你的旋转矩阵是绕X轴的旋转,并且你没有应用透视投影矩阵,所以你得到了默认的正交投影。你的图片或多或少是你在这种情况下得到的典型例子,尽管可能有更多的错误,也许在顶点数据中(我注意到了可见的对角线)。
顶点在YZ平面上绕X轴做圆周运动,你不能直接看到Z轴,所以只能看到它们在Y轴上上下运动。
为了得到一张看起来像旋转立方体的图片,你需要设置一个透视投影,可能还要设置一个正看着立方体的相机位置/旋转(视图矩阵)。
或者,您可以尝试将矩阵更改为绕Z轴旋转的矩阵:

let m = [
    [t.cos(), -t.sin(), 0.0, 0.0],
    [t.sin(), t.cos(), 0.0, 0.0],
    [0.0, 0.0, 1.0, 0.0],
    [0.0, 0.0, 0.0, 1.0f32]
];

这将是一个明显的轮换。
但总的来说,我强烈建议在程序中使用透视投影,这样可以显示Z轴上的运动(目前不可见),使图像对人类视觉更直观。添加更多对象和更复杂的对象,制作更完整的“场景”也很有用-然后如果你有代码错误,你可以看到它们是如何影响正在显示的“所有”几何图形的,而不是像你现在看到的那样,只看到一堆非常抽象的矩形。

相关问题