今天我想我修改了一个如何使用gl-rs(Rust的OpenGL绑定)添加颜色数组并绘制一些点而不是三角形的小例子。琐碎,我以为......
然而,我的COLOUR_DATA
似乎以某种方式用于顶点位置。
鉴于
static VERTEX_DATA: [GLfloat, ..6] = [
0.2, 0.0,
0.0, 0.2,
0.0, 0.0];
static COLOUR_DATA: [GLfloat, ..12] = [
0.0, 0.5, 0.0, 1.0,
0.5, 0.0, 0.0, 1.0,
0.0, 0.0, 5.0, 1.0];
很明显,下面的屏幕截图中的点是COLOUR_DATA
的前6个值,而不是VERTEX_DATA
。问题'当我注释掉与我的颜色缓冲区对象相关的BindBuffer
和BufferData
调用时,它会消失。
源代码位于屏幕截图下方,当然删除BindBuffer
/ BufferData
也意味着删除EnableVertexAttribArray
和VertexAttribPointer
类以进行编译,但它们没有对现有情况的影响)。
为什么会发生这种情况,我该如何避免呢?我只是错过了一些明显的东西吗?或者我在这里处理更深层次的事情(例如gl-rs中的错误)?
#![feature(globs)]
extern crate gl;
extern crate glfw;
extern crate native;
use gl::types::*;
use glfw::Context;
use std::mem;
use std::ptr;
use std::str;
// Vertex data
static VERTEX_DATA: [GLfloat, ..6] = [
0.2, 0.0,
0.0, 0.2,
0.0, 0.0];
static COLOUR_DATA: [GLfloat, ..12] = [
0.0, 0.5, 0.0, 1.0,
0.5, 0.0, 0.0, 1.0,
0.0, 0.0, 5.0, 1.0];
// Shader sources
static VS_SRC: &'static str =
"#version 150\n\
in vec2 position;\n\
in vec4 vertexColor;\n\
out vec4 fragmentColor;\n\
void main() {\n\
gl_Position = vec4(position, 0.0, 1.0);\n\
fragmentColor = vertexColor;\n\
}";
static FS_SRC: &'static str =
"#version 150\n\
in vec4 fragmentColor;\n\
out vec4 out_color;\n\
void main() {\n\
out_color = vec4(1.0, 0.0, 0.0, 1.0);\n\
}";
//out_color = fragmentColor;\n\
// the above line removed from shader string for debugging this
fn compile_shader(src: &str, ty: GLenum) -> GLuint {
let shader;
unsafe {
shader = gl::CreateShader(ty);
// Attempt to compile the shader
src.with_c_str(|ptr| gl::ShaderSource(shader, 1, &ptr, ptr::null()));
gl::CompileShader(shader);
// Get the compile status
let mut status = gl::FALSE as GLint;
gl::GetShaderiv(shader, gl::COMPILE_STATUS, &mut status);
// Fail on error
if status != (gl::TRUE as GLint) {
let mut len = 0;
gl::GetShaderiv(shader, gl::INFO_LOG_LENGTH, &mut len);
let mut buf = Vec::from_elem(len as uint - 1, 0u8); // subtract 1 to skip the trailing null character
gl::GetShaderInfoLog(shader, len, ptr::null_mut(), buf.as_mut_ptr() as *mut GLchar);
panic!("{}", str::from_utf8(buf.as_slice()).expect("ShaderInfoLog not valid utf8"));
}
}
shader
}
fn link_program(vs: GLuint, fs: GLuint) -> GLuint {
unsafe {
let program = gl::CreateProgram();
gl::AttachShader(program, vs);
gl::AttachShader(program, fs);
gl::LinkProgram(program);
// Get the link status
let mut status = gl::FALSE as GLint;
gl::GetProgramiv(program, gl::LINK_STATUS, &mut status);
// Fail on error
if status != (gl::TRUE as GLint) {
let mut len: GLint = 0;
gl::GetProgramiv(program, gl::INFO_LOG_LENGTH, &mut len);
let mut buf = Vec::from_elem(len as uint - 1, 0u8); // subtract 1 to skip the trailing null character
gl::GetProgramInfoLog(program, len, ptr::null_mut(), buf.as_mut_ptr() as *mut GLchar);
panic!("{}", str::from_utf8(buf.as_slice()).expect("ProgramInfoLog not valid utf8"));
}
program
}
}
#[start]
fn start(argc: int, argv: *const *const u8) -> int {
native::start(argc, argv, main)
}
fn main() {
let glfw = glfw::init(glfw::FAIL_ON_ERRORS).unwrap();
// Choose a GL profile that is compatible with OS X 10.7+
glfw.window_hint(glfw::ContextVersion(3, 2));
glfw.window_hint(glfw::OpenglForwardCompat(true));
glfw.window_hint(glfw::OpenglProfile(glfw::OpenGlCoreProfile));
let (window, _) = glfw.create_window(800, 600, "OpenGL", glfw::Windowed)
.expect("Failed to create GLFW window.");
// It is essential to make the context current before calling `gl::load_with`.
window.make_current();
// Load the OpenGL function pointers
gl::load_with(|s| window.get_proc_address(s));
// Create GLSL shaders
let vs = compile_shader(VS_SRC, gl::VERTEX_SHADER);
let fs = compile_shader(FS_SRC, gl::FRAGMENT_SHADER);
let program = link_program(vs, fs);
let mut vao = 0;
let mut vbo = 0;
let mut cbo = 0;
unsafe {
// Create Vertex Array Object
gl::GenVertexArrays(1, &mut vao);
gl::BindVertexArray(vao);
// Set up vertex buffer object
gl::GenBuffers(1, &mut vbo);
gl::BindBuffer(gl::ARRAY_BUFFER, vbo);
gl::BufferData(gl::ARRAY_BUFFER,
(VERTEX_DATA.len() * mem::size_of::<GLfloat>()) as GLsizeiptr,
mem::transmute(&VERTEX_DATA[0]),
gl::STATIC_DRAW);
// Set up colour buffer object
gl::GenBuffers(1, &mut cbo);
gl::BindBuffer(gl::ARRAY_BUFFER, cbo);
gl::BufferData(gl::ARRAY_BUFFER,
(COLOUR_DATA.len() * mem::size_of::<GLfloat>()) as GLsizeiptr,
mem::transmute(&COLOUR_DATA[0]),
gl::STATIC_DRAW);
gl::UseProgram(program);
// Bind fragment shader
"out_color".with_c_str(|ptr| gl::BindFragDataLocation(program, 0, ptr));
// Configure vertex buffer
let pos_attr = "position".with_c_str(|ptr| gl::GetAttribLocation(program, ptr));
println!("{}", pos_attr);
gl::EnableVertexAttribArray(pos_attr as GLuint);
gl::VertexAttribPointer(pos_attr as GLuint, 2, gl::FLOAT,
gl::FALSE as GLboolean, 0, ptr::null());
gl::PointSize(10.0);
// Configure colour buffer
let col_attr = "vertexColor".with_c_str(|ptr| gl::GetAttribLocation(program, ptr));
println!("{}", col_attr);
gl::EnableVertexAttribArray(col_attr as GLuint);
gl::VertexAttribPointer(col_attr as GLuint, 4, gl::FLOAT,
gl::FALSE as GLboolean, 0, ptr::null());
}
while !window.should_close() {
glfw.poll_events();
unsafe {
gl::ClearColor(0.3, 0.3, 0.3, 1.0);
gl::Clear(gl::COLOR_BUFFER_BIT);
gl::DrawArrays(gl::POINTS, 0, 3);
}
window.swap_buffers();
}
unsafe {
gl::DeleteProgram(program);
gl::DeleteShader(fs);
gl::DeleteShader(vs);
gl::DeleteBuffers(1, &cbo);
gl::DeleteBuffers(1, &vbo);
gl::DeleteVertexArrays(1, &vao);
}
}
注意:代码取决于gl-rs和glfw-rs。每晚运行Windows 8.1和Rust 0.13 40fb87d40)。 gl-rs在问题跟踪器中似乎没有这样的东西。
答案 0 :(得分:6)
因为在调用BindBuffer
之前需要绑定正确的缓冲区(VertexAttribPointer
)。
// Configure vertex buffer
let pos_attr = "position".with_c_str(|ptr| gl::GetAttribLocation(program, ptr));
println!("{}", pos_attr);
gl::EnableVertexAttribArray(pos_attr as GLuint);
gl::BindBuffer(gl::ARRAY_BUFFER, vbo);
gl::VertexAttribPointer(pos_attr as GLuint, 2, gl::FLOAT,
gl::FALSE as GLboolean, 0, ptr::null());
gl::PointSize(10.0);
// Configure colour buffer
let col_attr = "vertexColor".with_c_str(|ptr| gl::GetAttribLocation(program, ptr));
println!("{}", col_attr);
gl::EnableVertexAttribArray(col_attr as GLuint);
gl::BindBuffer(gl::ARRAY_BUFFER, cbo);
gl::VertexAttribPointer(col_attr as GLuint, 4, gl::FLOAT,
gl::FALSE as GLboolean, 0, ptr::null());
没有缓冲区绑定,VertexAttribPointer
的最后一个参数是指向系统内存的指针。对于顶点缓冲区对象,它将成为当前绑定缓冲区的偏移量。在您的情况下,颜色缓冲区是在初始化期间最后绑定的颜色缓冲区,并且用于两个顶点属性。