我有以下Rust代码来渲染带纹理的多维数据集。我正在使用piston2d-opengl_graphics
来加载纹理。
我的main.rs
extern crate sdl2;
extern crate glm;
extern crate gl;
extern crate libc;
extern crate num_traits;
extern crate opengl_graphics;
mod graphics;
use graphics::shader::Shader;
use sdl2::video::GLProfile;
use sdl2::event::Event;
use sdl2::keyboard::Keycode;
use std::ffi::CString;
use std::ptr;
use num_traits::identities::One;
use gl::types::*;
use std::mem;
use std::path::Path;
fn find_sdl_gl_driver() -> Option<u32> {
for (index, item) in sdl2::render::drivers().enumerate() {
if item.name == "opengl" {
return Some(index as u32);
}
}
None
}
fn main() {
let sdl_context = sdl2::init().unwrap();
let video_subsystem = sdl_context.video().unwrap();
let gl_attr = video_subsystem.gl_attr();
gl_attr.set_context_profile(GLProfile::Core);
gl_attr.set_context_flags().debug().set();
gl_attr.set_context_version(3, 3);
gl_attr.set_depth_size(24);
gl_attr.set_red_size(8);
gl_attr.set_green_size(8);
gl_attr.set_blue_size(8);
gl_attr.set_alpha_size(8);
gl_attr.set_stencil_size(8);
let window = video_subsystem.window("Renderer", 1024, 768,).opengl().build().unwrap();
let renderer = window.renderer().present_vsync().index(find_sdl_gl_driver().unwrap()).build().unwrap();
unsafe {
gl::load_with(|name| video_subsystem.gl_get_proc_address(name) as *const _);
renderer.window().unwrap().gl_set_context_to_current().unwrap();
gl::ClearColor(0.0, 0.0, 0.0, 1.0);
gl::Enable(gl::DEPTH_TEST);
gl::DepthFunc(gl::LESS);
}
let mut vao = 0;
unsafe {
gl::GenVertexArrays(1, &mut vao);
gl::BindVertexArray(vao);
}
let shader_program = Shader::new("shader.vert", "shader.frag").unwrap();
let mvp_location;
let texture_sampler_id;
unsafe {
mvp_location = gl::GetUniformLocation(shader_program.program, CString::new("MVP").unwrap().as_ptr());
texture_sampler_id = gl::GetUniformLocation(shader_program.program, CString::new("texture_sampler").unwrap().as_ptr());
}
let projection = glm::ext::perspective(45f32, 4f32 / 3f32, 0.1f32, 100f32);
let view = glm::ext::look_at(glm::Vec3::new(4f32, 3f32, 3f32),
glm::Vec3::new(0f32, 0f32, 0f32),
glm::Vec3::new(0f32, 1f32, 0f32));
let model_mat = glm::Matrix4::<f32>::one();
let mvp = projection * view * model_mat;
let mvp_array_vec4 = mvp.as_array();
let mut mvp_array: Vec<f32> = Vec::new();
for i in 0..mvp_array_vec4.len() {
for j in 0..4 {
mvp_array.push(mvp_array_vec4[i][j]);
}
}
let cube_vertices = vec![
-1.0f32,-1.0f32,-1.0f32,
-1.0f32,-1.0f32, 1.0f32,
-1.0f32, 1.0f32, 1.0f32,
1.0f32, 1.0f32,-1.0f32,
-1.0f32,-1.0f32,-1.0f32,
-1.0f32, 1.0f32,-1.0f32,
1.0f32,-1.0f32, 1.0f32,
-1.0f32,-1.0f32,-1.0f32,
1.0f32,-1.0f32,-1.0f32,
1.0f32, 1.0f32,-1.0f32,
1.0f32,-1.0f32,-1.0f32,
-1.0f32,-1.0f32,-1.0f32,
-1.0f32,-1.0f32,-1.0f32,
-1.0f32, 1.0f32, 1.0f32,
-1.0f32, 1.0f32,-1.0f32,
1.0f32,-1.0f32, 1.0f32,
-1.0f32,-1.0f32, 1.0f32,
-1.0f32,-1.0f32,-1.0f32,
-1.0f32, 1.0f32, 1.0f32,
-1.0f32,-1.0f32, 1.0f32,
1.0f32,-1.0f32, 1.0f32,
1.0f32, 1.0f32, 1.0f32,
1.0f32,-1.0f32,-1.0f32,
1.0f32, 1.0f32,-1.0f32,
1.0f32,-1.0f32,-1.0f32,
1.0f32, 1.0f32, 1.0f32,
1.0f32,-1.0f32, 1.0f32,
1.0f32, 1.0f32, 1.0f32,
1.0f32, 1.0f32,-1.0f32,
-1.0f32, 1.0f32,-1.0f32,
1.0f32, 1.0f32, 1.0f32,
-1.0f32, 1.0f32,-1.0f32,
-1.0f32, 1.0f32, 1.0f32,
1.0f32, 1.0f32, 1.0f32,
-1.0f32, 1.0f32, 1.0f32,
1.0f32,-1.0f32, 1.0f32
];
let cube_uv_coords: Vec<GLfloat> = vec![
0.000059, 1.0-0.000004,
0.000103, 1.0-0.336048,
0.335973, 1.0-0.335903,
1.000023, 1.0-0.000013,
0.667979, 1.0-0.335851,
0.999958, 1.0-0.336064,
0.667979, 1.0-0.335851,
0.336024, 1.0-0.671877,
0.667969, 1.0-0.671889,
1.000023, 1.0-0.000013,
0.668104, 1.0-0.000013,
0.667979, 1.0-0.335851,
0.000059, 1.0-0.000004,
0.335973, 1.0-0.335903,
0.336098, 1.0-0.000071,
0.667979, 1.0-0.335851,
0.335973, 1.0-0.335903,
0.336024, 1.0-0.671877,
1.000004, 1.0-0.671847,
0.999958, 1.0-0.336064,
0.667979, 1.0-0.335851,
0.668104, 1.0-0.000013,
0.335973, 1.0-0.335903,
0.667979, 1.0-0.335851,
0.335973, 1.0-0.335903,
0.668104, 1.0-0.000013,
0.336098, 1.0-0.000071,
0.000103, 1.0-0.336048,
0.000004, 1.0-0.671870,
0.336024, 1.0-0.671877,
0.000103, 1.0-0.336048,
0.336024, 1.0-0.671877,
0.335973, 1.0-0.335903,
0.667969, 1.0-0.671889,
1.000004, 1.0-0.671847,
0.667979, 1.0-0.335851
];
let texture = opengl_graphics::Texture::from_path(&Path::new("uvtemplate.jpg")).unwrap();
let mut vertex_buffer: GLuint = 0;
let mut uv_buffer: GLuint = 0;
unsafe {
// generate buffer for the cube vertices
gl::GenBuffers(1, &mut vertex_buffer);
gl::BindBuffer(gl::ARRAY_BUFFER, vertex_buffer);
gl::BufferData(gl::ARRAY_BUFFER, (cube_vertices.len() * mem::size_of::<f32>()) as GLsizeiptr,
mem::transmute(&cube_vertices[0]), gl::STATIC_DRAW);
// generate buffer for the uv coordinates
gl::GenBuffers(1, &mut uv_buffer);
gl::BindBuffer(gl::ARRAY_BUFFER, uv_buffer);
gl::BufferData(gl::ARRAY_BUFFER, (cube_uv_coords.len() * mem::size_of::<f32>()) as GLsizeiptr,
mem::transmute(&cube_uv_coords[0]), gl::STATIC_DRAW);
}
let mut event_pump = sdl_context.event_pump().unwrap();
'running: loop {
for event in event_pump.poll_iter() {
match event {
Event::Quit {..} | Event::KeyDown { keycode: Some(Keycode::Escape), .. } => {
break 'running
},
_ => {}
}
}
unsafe { gl::Clear(gl::COLOR_BUFFER_BIT | gl::DEPTH_BUFFER_BIT) };
shader_program.use_program();
unsafe {
gl::UniformMatrix4fv(mvp_location, 1, gl::FALSE, mvp_array.as_ptr());
// bind texture to texture unit 0 and tell sampler to use unit 0
gl::ActiveTexture(gl::TEXTURE0);
gl::BindTexture(gl::TEXTURE_2D, texture.get_id());
gl::Uniform1i(texture_sampler_id, 0);
// set vertex data
gl::EnableVertexAttribArray(0);
gl::BindBuffer(gl::ARRAY_BUFFER, vertex_buffer);
gl::VertexAttribPointer(0, 3, gl::FLOAT, gl::FALSE, 0, ptr::null_mut());
// set uv data
gl::EnableVertexAttribArray(1);
gl::BindBuffer(gl::ARRAY_BUFFER, uv_buffer);
gl::VertexAttribPointer(1, 2, gl::FLOAT, gl::FALSE, 0, ptr::null_mut());
gl::DrawArrays(gl::TRIANGLES, 0, 12 * 3);
gl::DisableVertexAttribArray(0);
gl::DisableVertexAttribArray(1);
}
renderer.window().unwrap().gl_swap_window();
}
}
我的shader.rs
:
extern crate glm;
extern crate gl;
use self::gl::types::*;
use std::fs::File;
use std::io::Read;
use std::io;
use std::fmt;
use std::error;
use std::ffi::CString;
use std::ptr;
use std::str;
#[derive(Debug)]
pub enum ShaderError {
IoError(io::Error),
CompilationError(String),
LinkError(String),
InfoLogError(str::Utf8Error)
}
impl fmt::Display for ShaderError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
ShaderError::IoError(ref error) => write!(f, "IO Error: {}", error),
ShaderError::CompilationError(ref error) => write!(f, "Shader compilation error: {}", error),
ShaderError::LinkError(ref error) => write!(f, "Linking error: {}", error),
ShaderError::InfoLogError(ref error) => write!(f, "InfoLog Error: {}", error),
}
}
}
impl error::Error for ShaderError {
fn description(&self) -> &str {
match *self {
ShaderError::IoError(ref err) => err.description(),
ShaderError::CompilationError(..) => "Error during shader compilation",
ShaderError::LinkError(..) => "Error during linking",
ShaderError::InfoLogError(ref err) => err.description(),
}
}
fn cause(&self) -> Option<&error::Error> {
match *self {
ShaderError::IoError(ref error) => Some(error),
ShaderError::InfoLogError(ref error) => Some(error),
_ => None
}
}
}
impl From<io::Error> for ShaderError {
fn from(err: io::Error) -> ShaderError {
ShaderError::IoError(err)
}
}
impl From<str::Utf8Error> for ShaderError {
fn from(err: str::Utf8Error) -> ShaderError {
ShaderError::InfoLogError(err)
}
}
pub struct Shader
{
pub vertex_path: String,
pub fragment_path: String,
pub program: GLuint
}
impl Shader
{
pub fn new(vert_path: &str, frag_path: &str) -> Result<Shader, ShaderError> {
let vertex_shader = try!(Shader::compile_shader(vert_path, gl::VERTEX_SHADER));
let fragment_shader = try!(Shader::compile_shader(frag_path, gl::FRAGMENT_SHADER));
let program = try!(Shader::link_program(vertex_shader, fragment_shader));
Ok(Shader {
vertex_path: vert_path.to_string(),
fragment_path: frag_path.to_string(),
program: program
})
}
fn compile_shader(path: &str, shader_type: GLenum) -> Result<GLuint, ShaderError> {
let mut shader_data = String::new();
let mut file = try!(File::open(path));
try!(file.read_to_string(&mut shader_data));
let shader;
unsafe {
shader = gl::CreateShader(shader_type);
let shader_src = CString::new(shader_data.as_bytes()).unwrap();
gl::ShaderSource(shader, 1, &shader_src.as_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::with_capacity(len as usize);
buf.set_len((len as usize) - 1); // subtract 1 to skip the trailing null character
gl::GetShaderInfoLog(shader, len, ptr::null_mut(), buf.as_mut_ptr() as *mut GLchar);
return match str::from_utf8(&buf) {
Ok(msg) => Err(ShaderError::CompilationError(msg.to_string())),
Err(err) => Err(ShaderError::InfoLogError(err))
}
}
}
Ok(shader)
}
fn link_program(vertex_shader: GLuint, fragment_shader: GLuint) -> Result<GLuint, ShaderError> {
unsafe {
let program = gl::CreateProgram();
gl::AttachShader(program, vertex_shader);
gl::AttachShader(program, fragment_shader);
gl::LinkProgram(program);
// get 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::with_capacity(len as usize);
buf.set_len((len as usize) - 1); // subtract 1 to skip the trailing null character
gl::GetProgramInfoLog(program, len, ptr::null_mut(), buf.as_mut_ptr() as *mut GLchar);
return match str::from_utf8(&buf) {
Ok(msg) => Err(ShaderError::LinkError(msg.to_string())),
Err(err) => Err(ShaderError::InfoLogError(err))
}
}
Ok(program)
}
}
pub fn use_program(&self) {
unsafe {
gl::UseProgram(self.program);
}
}
}
我的顶点着色器:
#version 330 core
layout(location = 0) in vec3 vertex_position_modelspace;
layout(location = 1) in vec2 vertex_uv;
out vec2 uv_coord;
uniform mat4 MVP;
void main()
{
gl_Position = MVP * vec4(vertex_position_modelspace, 1);
uv_coord = uv_coord;
}
我的片段着色器:
#version 330 core
in vec2 uv_coord;
out vec3 color;
uniform sampler2D texture_sampler;
void main()
{
color = texture(texture_sampler, uv_coord).rgb;
}
每当我尝试渲染立方体时,我总会得到像
这样的结果它总是闪烁,并没有显示出正确的结果:
我尝试使用glutin
作为窗口管理器,但这不起作用,所以我尝试切换到SDL2
,但这也不起作用。我也尝试使用BMP文件而不是JPEG,但我得到了相同的结果。但是,如果我在C ++中编写相同的代码,那么我会得到正确的结果。
这是我的C ++代码,它可以正确呈现多维数据集:
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <vector>
#include <iostream>
#include <fstream>
// Include GLEW
#include <GL/glew.h>
// Include GLFW
#include <glfw3.h>
GLFWwindow* window;
// Include GLM
#include <glm/glm.hpp>
#include <glm/ext.hpp>
using namespace glm;
GLuint LoadShader(const char * vertex_file_path, const char * fragment_file_path) {
// Create the shaders
GLuint VertexShaderID = glCreateShader(GL_VERTEX_SHADER);
GLuint FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
// Read the Vertex Shader code from the file
std::string VertexShaderCode;
std::ifstream VertexShaderStream(vertex_file_path, std::ios::in);
if (VertexShaderStream.is_open()) {
std::string Line = "";
while (getline(VertexShaderStream, Line))
VertexShaderCode += "\n" + Line;
VertexShaderStream.close();
}
else {
printf("Impossible to open %s. \n", vertex_file_path);
getchar();
return 0;
}
// Read the Fragment Shader code from the file
std::string FragmentShaderCode;
std::ifstream FragmentShaderStream(fragment_file_path, std::ios::in);
if (FragmentShaderStream.is_open()) {
std::string Line = "";
while (getline(FragmentShaderStream, Line))
FragmentShaderCode += "\n" + Line;
FragmentShaderStream.close();
}
GLint Result = GL_FALSE;
int InfoLogLength;
// Compile Vertex Shader
printf("Compiling shader : %s\n", vertex_file_path);
char const * VertexSourcePointer = VertexShaderCode.c_str();
glShaderSource(VertexShaderID, 1, &VertexSourcePointer, NULL);
glCompileShader(VertexShaderID);
// Check Vertex Shader
glGetShaderiv(VertexShaderID, GL_COMPILE_STATUS, &Result);
glGetShaderiv(VertexShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
if (InfoLogLength > 0) {
std::vector<char> VertexShaderErrorMessage(InfoLogLength + 1);
glGetShaderInfoLog(VertexShaderID, InfoLogLength, NULL, &VertexShaderErrorMessage[0]);
printf("%s\n", &VertexShaderErrorMessage[0]);
}
// Compile Fragment Shader
printf("Compiling shader : %s\n", fragment_file_path);
char const * FragmentSourcePointer = FragmentShaderCode.c_str();
glShaderSource(FragmentShaderID, 1, &FragmentSourcePointer, NULL);
glCompileShader(FragmentShaderID);
// Check Fragment Shader
glGetShaderiv(FragmentShaderID, GL_COMPILE_STATUS, &Result);
glGetShaderiv(FragmentShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
if (InfoLogLength > 0) {
std::vector<char> FragmentShaderErrorMessage(InfoLogLength + 1);
glGetShaderInfoLog(FragmentShaderID, InfoLogLength, NULL, &FragmentShaderErrorMessage[0]);
printf("%s\n", &FragmentShaderErrorMessage[0]);
}
// Link the program
printf("Linking program\n");
GLuint ProgramID = glCreateProgram();
glAttachShader(ProgramID, VertexShaderID);
glAttachShader(ProgramID, FragmentShaderID);
glLinkProgram(ProgramID);
// Check the program
glGetProgramiv(ProgramID, GL_LINK_STATUS, &Result);
glGetProgramiv(ProgramID, GL_INFO_LOG_LENGTH, &InfoLogLength);
if (InfoLogLength > 0) {
std::vector<char> ProgramErrorMessage(InfoLogLength + 1);
glGetProgramInfoLog(ProgramID, InfoLogLength, NULL, &ProgramErrorMessage[0]);
printf("%s\n", &ProgramErrorMessage[0]);
}
glDetachShader(ProgramID, VertexShaderID);
glDetachShader(ProgramID, FragmentShaderID);
glDeleteShader(VertexShaderID);
glDeleteShader(FragmentShaderID);
return ProgramID;
}
GLuint loadBMP(const char * imagepath) {
printf("Reading %s\n", imagepath);
// Data read from the header of the BMP file
unsigned char header[54];
unsigned int dataPos;
unsigned int imageSize;
unsigned int width, height;
// Actual RGB data
unsigned char * data;
// Open the file
FILE * file = fopen(imagepath, "rb");
if (!file)
{
printf("%s could not be opened.\n", imagepath);
getchar();
return 0;
}
// Read the header, i.e. the 54 first bytes
// If less than 54 bytes are read, problem
if (fread(header, 1, 54, file) != 54) {
printf("Not a correct BMP file\n");
return 0;
}
// A BMP files always begins with "BM"
if (header[0] != 'B' || header[1] != 'M') {
printf("Not a correct BMP file\n");
return 0;
}
// Make sure this is a 24bpp file
if (*(int*)&(header[0x1E]) != 0)
{
printf("Not a correct BMP file\n");
return 0;
}
if (*(int*)&(header[0x1C]) != 24)
{
printf("Not a correct BMP file\n");
return 0;
}
// Read the information about the image
dataPos = *(int*)&(header[0x0A]);
imageSize = *(int*)&(header[0x22]);
width = *(int*)&(header[0x12]);
height = *(int*)&(header[0x16]);
if (imageSize == 0) imageSize = width*height * 3;
if (dataPos == 0) dataPos = 54;
data = new unsigned char[imageSize];
// Read the actual data from the file into the buffer
fread(data, 1, imageSize, file);
fclose(file);
GLuint textureID;
glGenTextures(1, &textureID);
glBindTexture(GL_TEXTURE_2D, textureID);
// Give the image to OpenGL
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_BGR, GL_UNSIGNED_BYTE, data);
delete[] data;
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glGenerateMipmap(GL_TEXTURE_2D);
return textureID;
}
int main(void)
{
// Initialise GLFW
if (!glfwInit())
{
fprintf(stderr, "Failed to initialize GLFW\n");
return -1;
}
glfwWindowHint(GLFW_SAMPLES, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
window = glfwCreateWindow(1024, 768, "Tutorial 05 - Textured Cube", NULL, NULL);
if (window == NULL) {
fprintf(stderr, "Failed to open GLFW window. If you have an Intel GPU, they are not 3.3 compatible. Try the 2.1 version of the tutorials.\n");
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
// Initialize GLEW
glewExperimental = true;
if (glewInit() != GLEW_OK) {
fprintf(stderr, "Failed to initialize GLEW\n");
return -1;
}
glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
GLuint VertexArrayID;
glGenVertexArrays(1, &VertexArrayID);
glBindVertexArray(VertexArrayID);
GLuint programID = LoadShader("shader.vert", "shader.frag");
GLuint MatrixID = glGetUniformLocation(programID, "MVP");
glm::mat4 Projection = glm::perspective(45.0f, 4.0f / 3.0f, 0.1f, 100.0f);
glm::mat4 View = glm::lookAt(
glm::vec3(4, 3, 3),
glm::vec3(0, 0, 0),
glm::vec3(0, 1, 0)
);
glm::mat4 Model = glm::mat4(1.0f);
glm::mat4 MVP = Projection * View * Model;
GLuint Texture = loadBMP("uvtemplate.bmp");
// Get a handle for "textureSampler" uniform
GLuint TextureID = glGetUniformLocation(programID, "textureSampler");
static const GLfloat g_vertex_buffer_data[] = {
-1.0f,-1.0f,-1.0f,
-1.0f,-1.0f, 1.0f,
-1.0f, 1.0f, 1.0f,
1.0f, 1.0f,-1.0f,
-1.0f,-1.0f,-1.0f,
-1.0f, 1.0f,-1.0f,
1.0f,-1.0f, 1.0f,
-1.0f,-1.0f,-1.0f,
1.0f,-1.0f,-1.0f,
1.0f, 1.0f,-1.0f,
1.0f,-1.0f,-1.0f,
-1.0f,-1.0f,-1.0f,
-1.0f,-1.0f,-1.0f,
-1.0f, 1.0f, 1.0f,
-1.0f, 1.0f,-1.0f,
1.0f,-1.0f, 1.0f,
-1.0f,-1.0f, 1.0f,
-1.0f,-1.0f,-1.0f,
-1.0f, 1.0f, 1.0f,
-1.0f,-1.0f, 1.0f,
1.0f,-1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f,-1.0f,-1.0f,
1.0f, 1.0f,-1.0f,
1.0f,-1.0f,-1.0f,
1.0f, 1.0f, 1.0f,
1.0f,-1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f,-1.0f,
-1.0f, 1.0f,-1.0f,
1.0f, 1.0f, 1.0f,
-1.0f, 1.0f,-1.0f,
-1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
-1.0f, 1.0f, 1.0f,
1.0f,-1.0f, 1.0f
};
static const GLfloat g_uv_buffer_data[] = {
0.000059f, 1.0f - 0.000004f,
0.000103f, 1.0f - 0.336048f,
0.335973f, 1.0f - 0.335903f,
1.000023f, 1.0f - 0.000013f,
0.667979f, 1.0f - 0.335851f,
0.999958f, 1.0f - 0.336064f,
0.667979f, 1.0f - 0.335851f,
0.336024f, 1.0f - 0.671877f,
0.667969f, 1.0f - 0.671889f,
1.000023f, 1.0f - 0.000013f,
0.668104f, 1.0f - 0.000013f,
0.667979f, 1.0f - 0.335851f,
0.000059f, 1.0f - 0.000004f,
0.335973f, 1.0f - 0.335903f,
0.336098f, 1.0f - 0.000071f,
0.667979f, 1.0f - 0.335851f,
0.335973f, 1.0f - 0.335903f,
0.336024f, 1.0f - 0.671877f,
1.000004f, 1.0f - 0.671847f,
0.999958f, 1.0f - 0.336064f,
0.667979f, 1.0f - 0.335851f,
0.668104f, 1.0f - 0.000013f,
0.335973f, 1.0f - 0.335903f,
0.667979f, 1.0f - 0.335851f,
0.335973f, 1.0f - 0.335903f,
0.668104f, 1.0f - 0.000013f,
0.336098f, 1.0f - 0.000071f,
0.000103f, 1.0f - 0.336048f,
0.000004f, 1.0f - 0.671870f,
0.336024f, 1.0f - 0.671877f,
0.000103f, 1.0f - 0.336048f,
0.336024f, 1.0f - 0.671877f,
0.335973f, 1.0f - 0.335903f,
0.667969f, 1.0f - 0.671889f,
1.000004f, 1.0f - 0.671847f,
0.667979f, 1.0f - 0.335851f
};
GLuint vertexbuffer;
glGenBuffers(1, &vertexbuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data, GL_STATIC_DRAW);
GLuint uvbuffer;
glGenBuffers(1, &uvbuffer);
glBindBuffer(GL_ARRAY_BUFFER, uvbuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(g_uv_buffer_data), g_uv_buffer_data, GL_STATIC_DRAW);
do {
// Clear the screen
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(programID);
glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &MVP[0][0]);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, Texture);
glUniform1i(TextureID, 0);
// 1rst attribute buffer : vertices
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glVertexAttribPointer(
0,
3,
GL_FLOAT,
GL_FALSE,
0,
(void*)0
);
// 2nd attribute buffer : UVs
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, uvbuffer);
glVertexAttribPointer(
1,
2,
GL_FLOAT,
GL_FALSE,
0,
(void*)0
);
glDrawArrays(GL_TRIANGLES, 0, 12 * 3);
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
// Swap buffers
glfwSwapBuffers(window);
glfwPollEvents();
} // Check if the ESC key was pressed or the window was closed
while (glfwGetKey(window, GLFW_KEY_ESCAPE) != GLFW_PRESS &&
glfwWindowShouldClose(window) == 0);
// Cleanup VBO and shader
glDeleteBuffers(1, &vertexbuffer);
glDeleteBuffers(1, &uvbuffer);
glDeleteProgram(programID);
glDeleteTextures(1, &TextureID);
glDeleteVertexArrays(1, &VertexArrayID);
// Close OpenGL window and terminate GLFW
glfwTerminate();
return 0;
}