glVertexAttrib4fv不会传递到位置0的着色器输入

时间:2015-11-04 20:55:27

标签: opengl glsl rust

我试图同时学习OpenGL和Rust。我正在使用OpenGL Superbible第六版,并陷入第3章,它引入了函数glVertexAttrib4fv来抵消三角形的位置。当我在C ++中使用它时,它工作得很好,但当我尝试将其转换为Rust时,三角形消失了。我已尝试尽可能地将示例缩减为以下代码(货物依赖项为glutin = "*"gl = "*"):

main.rs

extern crate glutin;
extern crate gl;

use std::io::Read;

fn main() {
    unsafe {
        let win = glutin::Window::new().unwrap();
        win.make_current().unwrap();
        gl::load_with(|s| win.get_proc_address(s));

        let program = build_shader_program();
        gl::UseProgram(program);

        let mut vao = std::mem::uninitialized();
        gl::GenVertexArrays(1, &mut vao);
        gl::BindVertexArray(vao);

        let red = [1.0, 0.0, 0.0, 1.0];

        let mut running = true;
        while running {
            for event in win.poll_events() {
                if let glutin::Event::Closed = event {
                    running = false;
                }
            }

            win.swap_buffers().unwrap();
            gl::ClearBufferfv(gl::COLOR, 0, &red[0]);

            let attrib = [0.5, 0.0, 0.0, 0.0];
            panic_if_error("before VertexAttrib4fv");
            gl::VertexAttrib4fv(0, &attrib[0]);
            panic_if_error("after VertexAttrib4fv");

            gl::DrawArrays(gl::TRIANGLES, 0, 3);
        }
    }
}

fn panic_if_error(message: &str) {
    unsafe {
        match gl::GetError() {
            gl::NO_ERROR => (),
            _ => panic!("{}", message),
        }
    }
}

fn load_file_as_cstring(path: &str) -> std::ffi::CString {
    let mut contents = Vec::new();
    let mut file = std::fs::File::open(path).unwrap();
    file.read_to_end(&mut contents).unwrap();
    std::ffi::CString::new(contents).unwrap()
}

fn load_and_compile_shader(path: &str, shader_type: u32) -> u32 {
    let contents = load_file_as_cstring(path);
    unsafe {
        let shader_id = gl::CreateShader(shader_type);

        let source_ptr = contents.as_ptr();
        gl::ShaderSource(shader_id, 1, &source_ptr, std::ptr::null());
        gl::CompileShader(shader_id);

        let mut result = std::mem::uninitialized();
        gl::GetShaderiv(shader_id, gl::COMPILE_STATUS, &mut result);
        assert_eq!(result, gl::TRUE as i32);

        shader_id
    }
}

fn build_shader_program() -> u32 {
    let vert = load_and_compile_shader("a.vert", gl::VERTEX_SHADER);
    let frag = load_and_compile_shader("a.frag", gl::FRAGMENT_SHADER);

    unsafe {
        let program_id = gl::CreateProgram();
        gl::AttachShader(program_id, vert);
        gl::AttachShader(program_id, frag);
        gl::LinkProgram(program_id);

        let mut result = std::mem::uninitialized();
        gl::GetProgramiv(program_id, gl::LINK_STATUS, &mut result);
        assert_eq!(result, gl::TRUE as i32);

        program_id
    }
}

a.frag

#version 430 core
out vec4 color;
void main() {
    color = vec4(1.0, 1.0, 1.0, 1.0);
}

a.vert

#version 430 core
layout (location = 0) in vec4 offset;
void main() {
    const vec4 vertices[3] =
        vec4[3](vec4( 0.25, -0.25, 0.5, 1.0),
                vec4(-0.25, -0.25, 0.5, 1.0),
                vec4( 0.25,  0.25, 0.5, 1.0));

    gl_Position = vertices[gl_VertexID];             // LINE 1
    // gl_Position = vertices[gl_VertexID] + offset; // LINE 2
}

此代码按原样在红色窗口的中间生成一个白色三角形。

enter image description here

现在,我的期望是,当我在顶点着色器中注释LINE 1并取消注释LINE 2时,三角形应向右移动四分之一的屏幕,因为此代码在& #34; main.rs":

let attrib = [0.5, 0.0, 0.0, 0.0];
panic_if_error("before VertexAttrib4fv");
gl::VertexAttrib4fv(0, &attrib[0]);
panic_if_error("after VertexAttrib4fv");

但相反,三角形完全消失了。 panic_if_error之前和之后的gl::VertexAttrib4fv来电确保gl::GetError返回gl::NO_ERROR

问题:有人知道为什么会这样吗?

其他注意事项。当我在寻找答案的时候,我遇到了this question,用户遇到了类似的问题(除了C ++,我没有问题)。无论如何,其中一条评论偶然导致我尝试将位置从0更改为1,如下所示:

layout (location = 1) in vec4 offset;

用于顶点着色器,这用于调用gl::VertexAttrib4fv

gl::VertexAttrib4fv(1, &attrib[0]);

嗯,这有用,但我不知道为什么,并且仍然想知道在那里使用位置0的问题是什么(因为那是本书所展示的,并且它在C ++中运行良好)。

1 个答案:

答案 0 :(得分:2)

您需要确保拥有Core Profile上下文。如果未指定此选项,则可能正在创建兼容性配置文件上下文。在兼容性配置文件中,顶点属性0具有特殊含义。从OpenGL 3.2兼容性配置文件规范:

  

设置通用顶点属性零指定顶点;四个顶点坐标取自属性零的值。 Vertex2,Vertex3或Vertex4命令完全等效于索引为零的相应VertexAttrib *命令。设置任何其他通用顶点属性会更新属性的当前值。顶点属性零没有当前值。

换句话说,顶点属性0是兼容性配置文件中固定功能顶点位置的别名。

以上内容不适用于Core Profile。顶点属性0没有特殊含义,可以像任何其他顶点属性一样使用。

根据您已找到的内容,您需要使用带有参数{[response, { "id": "KMKE", "loc": { "long": -87.9, "lat": 42.95 }, "place": { "name": "milwaukee", "state": "wi", "country": "us" }, "profile": { "tz": "America/Chicago", "elevM": 206, "elevFT": 676 }, "obTimestamp": 1446677520, "obDateTime": "2015-11-04T16:52:00-06:00", "ob": { "timestamp": 1446677520, "dateTimeISO": "2015-11-04T16:52:00-06:00", "tempC": 19, "tempF": 66, "dewpointC": 14, "dewpointF": 57, "humidity": 73, "pressureMB": 1016, "pressureIN": 30, "spressureMB": 992, "spressureIN": 29.29, "altimeterMB": 1017, "altimeterIN": 30.03, "windKTS": 8, "windKPH": 15, "windMPH": 9, "windSpeedKTS": 8, "windSpeedKPH": 15, "windSpeedMPH": 9, "windDirDEG": 200, "windDir": "SSW", "windGustKTS": null, "windGustKPH": null, "windGustMPH": null, "flightRule": "LIFR", "visibilityKM": 16.09344, "visibilityMI": 10, "weather": "Clear", "weatherShort": "Clear", "weatherCoded": "::CL", "weatherPrimary": "Clear", "weatherPrimaryCoded": "::CL", "cloudsCoded": "CL", "icon": "clearn.png", "heatindexC": 19, "heatindexF": 66, "windchillC": 19, "windchillF": 66, "feelslikeC": 19, "feelslikeF": 66, "isDay": false, "sunrise": 1446640242, "sunriseISO": "2015-11-04T06:30:42-06:00", "sunset": 1446676779, "sunsetISO": "2015-11-04T16:39:39-06:00", "snowDepthCM": null, "snowDepthIN": null, "precipMM": 0, "precipIN": 0, "solradWM2": null, "light": 0, "sky": 0 }, "raw": "KMKE 042252Z 20008KT 10SM CLR 19/14 A3003 RMK AO2 SLP169 T01890139", "relativeTo": { "lat": 43.0389, "long": -87.90647, "bearing": 177, "bearingENG": "S", "distanceKM": 9.899, "distanceMI": 6.151 } }]} 的{​​{3}}来指定您在创建窗口时使用核心配置文件。