我正在使用OpenGL SuperBible第6版,并了解曲面细分着色器。我从INVALID_OPERATION
收到gl::DrawArrays
错误。这是我的代码:
extern crate libc;
extern crate glutin;
extern crate gl;
use std::io::Read;
fn main() {
unsafe {
let win = glutin::WindowBuilder::new()
.with_gl_profile(glutin::GlProfile::Core)
.build_strict()
.unwrap();
win.make_current().unwrap();
gl::load_with(|s| win.get_proc_address(s));
gl::DebugMessageCallback(
std::mem::transmute(gl_debug_message),
std::ptr::null_mut());
let program = build_shader_program();
gl::UseProgram(program);
let mut vao = std::mem::uninitialized();
gl::GenVertexArrays(1, &mut vao);
gl::BindVertexArray(vao);
gl::PolygonMode(gl::FRONT_AND_BACK, gl::LINE);
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]);
gl::DrawArrays(gl::TRIANGLES, 0, 3);
}
}
}
extern "system"
fn gl_debug_message(_source: u32, _type: u32, _id: u32, _sev: u32,
_len: i32, message: *const libc::c_char,
_param: *mut libc::c_void)
{
unsafe {
let s = cstring_to_string(message);
panic!("OpenGL Debug message: {}", s);
}
}
fn build_shader_program() -> u32 {
let vert = load_and_compile_shader("a.vert", gl::VERTEX_SHADER);
let tesc = load_and_compile_shader("a.tesc", gl::TESS_CONTROL_SHADER);
let tese = load_and_compile_shader("a.tese", gl::TESS_EVALUATION_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, tesc);
gl::AttachShader(program_id, tese);
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
}
}
unsafe fn cstring_to_string(mut cs: *const libc::c_char) -> String {
let mut v : Vec<u8> = Vec::new();
while *cs != 0 {
v.push(*cs as u8);
cs = cs.offset(1);
}
String::from_utf8(v).expect("c-string not utf8")
}
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
}
}
运行此程序会导致调试消息:
OpenGL Debug message: glDrawArrays has generated an error (GL_INVALID_OPERATION)
我省略了着色器(顶点着色器,片段着色器,曲面细分控制着色器和曲面细分评估着色器),但如果有必要,我可以显示它们。它们非常基础,我只是不想弄乱这个问题。实际上它们是来自sb6 git存储库的this example program中的那些。他们编译和链接没有错误。
如果我删除了两个曲面细分着色器的gl::AttachShader
调用,则没有错误,并绘制一个简单的线框三角形。使用曲面细分着色器时,应该绘制相同的三角形,只需切割成较小的三角形。
我查看了glDrawArrays
on this site的文档,我的代码似乎没有做任何导致INVALID_OPERATION
错误的事情, AFAICT。
答案 0 :(得分:1)
曲面细分着色器不渲染图元,而是渲染补丁。图元是在细分期间创建的。见Tessellation。
您必须使用 Primitive 类型 gl::PATCHES
而不是 gl::TRIANGLES
。此外,您必须通过将参数 gl::PATCH VERTICES
设置为 gl::PatchParameteri
来指定单个补丁的大小:
gl::DrawArrays(gl::TRIANGLES, 0, 3);
gl::PatchParameteri(gl::PATCH_VERTICES, 3);
gl::DrawArrays(gl::PATCHES, 0, 3);