commit
d321ff095f
@ -0,0 +1,222 @@ |
||||
#ifdef __APPLE__ |
||||
#define glGenVertexArrays glGenVertexArraysAPPLE |
||||
#define glBindVertexArray glBindVertexArrayAPPLE |
||||
#endif |
||||
|
||||
#define GL_GLEXT_PROTOTYPES // for Linux
|
||||
|
||||
#include <GL/glfw.h> |
||||
#include <iostream> |
||||
#include <fstream> |
||||
#include <stdint.h> |
||||
#include <stdlib.h> |
||||
#include <vector> |
||||
#include <assert.h> |
||||
#include <string> |
||||
#include <string.h> |
||||
#include <cmath> |
||||
|
||||
typedef struct { |
||||
float pos[3]; |
||||
} Vertex; |
||||
|
||||
typedef struct { |
||||
uint32_t vbo_id; |
||||
uint32_t ibo_id; |
||||
uint32_t vao_id; |
||||
uint32_t num_poly; |
||||
} Mesh; |
||||
|
||||
typedef struct { |
||||
uint32_t prog_id; |
||||
uint32_t vert_id; |
||||
uint32_t frag_id; |
||||
} Shader; |
||||
|
||||
Shader shaders[1]; |
||||
Mesh popcan; |
||||
|
||||
char basic_vert_shader[] = |
||||
"varying vec4 color;" |
||||
"void main () {" |
||||
" color = vec4(clamp(gl_Vertex.y,0.0,0.7)+0.3,0.0,0.0,1.0);" |
||||
" gl_Position = gl_ModelViewProjectionMatrix*gl_Vertex;" |
||||
"}"; |
||||
|
||||
char basic_frag_shader[] = |
||||
"varying vec4 color;" |
||||
"void main () {" |
||||
" gl_FragColor = color;" |
||||
"}"; |
||||
|
||||
void render () { |
||||
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); |
||||
glLoadIdentity (); |
||||
glUseProgram (shaders[0].prog_id |
||||
); |
||||
static float x = 0; |
||||
glTranslatef (-8,0,-20); |
||||
glRotatef (x+=1.0, 0,1,0); |
||||
glRotatef (30.0, 1.0,0,0); |
||||
|
||||
glBindVertexArray (popcan.vao_id); |
||||
glDrawElements(GL_TRIANGLES, popcan.num_poly, GL_UNSIGNED_INT, 0); |
||||
} |
||||
|
||||
void print_shader_error (uint32_t id, uint32_t type) { |
||||
char *log; |
||||
GLint length=0, result; |
||||
if (type == GL_COMPILE_STATUS) glGetShaderiv(id, GL_INFO_LOG_LENGTH, &length); |
||||
else glGetProgramiv (id, GL_INFO_LOG_LENGTH, &length); |
||||
if (length == 0) { |
||||
std::cerr << "Unknown error.\n"; |
||||
return; |
||||
} |
||||
log = new char[length]; |
||||
if (type == GL_COMPILE_STATUS) glGetShaderInfoLog(id, length, &result, log); |
||||
else glGetProgramInfoLog(id, length, &result, log); |
||||
std::cerr << log << "\n"; |
||||
delete[] log; |
||||
} |
||||
|
||||
Mesh load_mesh (std::string filename) { |
||||
Mesh m; |
||||
|
||||
std::ifstream fin (filename.c_str ()); |
||||
if (!fin.good ()) { std::cerr << "Couldn't open " << filename << "\n"; exit(1); } |
||||
std::vector<Vertex> vert_data; |
||||
std::vector<uint32_t> index_data; |
||||
while (!fin.eof ()) { |
||||
char line[128]; |
||||
fin.getline(line, 128); |
||||
if (line[0] == 'v') { |
||||
Vertex v; |
||||
char *fstr = strtok(&(line[1]), " "); |
||||
v.pos[0] = atof(fstr); |
||||
fstr = strtok(NULL, " "); |
||||
v.pos[1] = atof(fstr); |
||||
fstr = strtok(NULL, " "); |
||||
v.pos[2] = atof(fstr); |
||||
assert (strtok (NULL, " ") == NULL); |
||||
vert_data.push_back(v); |
||||
} else if (line[0] == 'f') { |
||||
char *intstr = strtok(&(line[1]), " "); |
||||
index_data.push_back(atoi (intstr) - 1); |
||||
intstr = strtok(NULL, " "); |
||||
index_data.push_back(atoi (intstr) - 1); |
||||
intstr = strtok(NULL, " "); |
||||
index_data.push_back(atoi (intstr) - 1); |
||||
if (strtok(NULL, " ") != NULL) { std::cerr << "You got some quads bro.\n"; exit (1); } |
||||
} |
||||
} |
||||
glGenVertexArrays (1, &(m.vao_id)); |
||||
glBindVertexArray (m.vao_id); |
||||
|
||||
glGenBuffers(2, &m.vbo_id); |
||||
glBindBuffer(GL_ARRAY_BUFFER, m.vbo_id); |
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m.ibo_id); |
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex)*vert_data.size (), &(vert_data[0]), GL_STATIC_DRAW); |
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(uint32_t)*index_data.size (), &(index_data[0]), GL_STATIC_DRAW); |
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0); |
||||
glEnableVertexAttribArray(0); |
||||
glBindVertexArray (0); |
||||
m.num_poly = (uint32_t)index_data.size () / 3; |
||||
std::cerr << "Loaded " << filename << "\n"; |
||||
return m; |
||||
} |
||||
|
||||
uint32_t compile_individual_shader (const char *src, uint32_t len, uint32_t type) { |
||||
uint32_t id = glCreateShader (type); |
||||
glShaderSource (id, 1, &src, NULL); |
||||
glCompileShader (id); |
||||
|
||||
GLint compiled; |
||||
glGetShaderiv (id, GL_COMPILE_STATUS, &compiled); |
||||
if (compiled == GL_FALSE) { |
||||
std::cerr << "Error compiling shader: "; |
||||
print_shader_error(id, GL_COMPILE_STATUS); |
||||
exit (1); |
||||
} |
||||
return id; |
||||
} |
||||
|
||||
Shader make_shader (char* vert_src, uint32_t vert_len, char* frag_src, uint32_t frag_len) { |
||||
Shader s; |
||||
s.vert_id = compile_individual_shader (vert_src, vert_len, GL_VERTEX_SHADER); |
||||
s.frag_id = compile_individual_shader (frag_src, frag_len, GL_FRAGMENT_SHADER); |
||||
s.prog_id = glCreateProgram (); |
||||
glAttachShader (s.prog_id, s.frag_id); |
||||
glAttachShader (s.prog_id, s.vert_id); |
||||
glLinkProgram (s.prog_id); |
||||
GLint linked; |
||||
glGetProgramiv(s.prog_id, GL_LINK_STATUS, &linked); |
||||
if (linked == GL_FALSE) { |
||||
std::cerr << "Error linking shader: "; |
||||
print_shader_error (s.prog_id, GL_COMPILE_STATUS); |
||||
exit (1); |
||||
} |
||||
return s; |
||||
} |
||||
|
||||
|
||||
|
||||
void GL_init (float w, float h) { |
||||
glShadeModel (GL_SMOOTH); |
||||
glEnable (GL_DEPTH_TEST); |
||||
glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); |
||||
// TODO: blender is apparently a dick and doesn't export to .obj with a consistent poly orientation.
|
||||
// Fix it manually during a load or something to get this culling.
|
||||
// glFrontFace (GL_CCW);
|
||||
// glCullFace (GL_BACK);
|
||||
// glEnable (GL_CULL_FACE);
|
||||
|
||||
glClearColor (0,0,0,0); |
||||
glEnable (GL_TEXTURE_2D); |
||||
|
||||
glViewport (0, 0, w, h); |
||||
|
||||
// TODO: This code is old and bad, needs to go
|
||||
glMatrixMode (GL_PROJECTION); |
||||
glLoadIdentity(); |
||||
float near = 0.001; |
||||
float far = 1000.0; |
||||
float fH = tan(45.0/360.0*M_PI)*near; |
||||
float fW = fH*w/h; |
||||
glFrustum(-fW, fW, -fH, fH, near, far); |
||||
glMatrixMode (GL_MODELVIEW); |
||||
// TODO: replace above
|
||||
|
||||
popcan = load_mesh ("can.obj"); |
||||
shaders[0] = make_shader (basic_vert_shader, sizeof (basic_vert_shader), basic_frag_shader, sizeof (basic_frag_shader)); |
||||
} |
||||
|
||||
int main () { |
||||
float w = 480; |
||||
float h = 272; |
||||
if (!glfwInit () || !glfwOpenWindow (w, h, 8,8,8,0,32,0,GLFW_WINDOW)) { |
||||
std::cerr << "Something GLFW failed.\n"; |
||||
return 1; |
||||
} |
||||
GL_init (w, h); |
||||
|
||||
int running = 1; |
||||
|
||||
float t0 = glfwGetTime (); |
||||
uint32_t frames = 0; |
||||
// glfwSwapInterval (0); // Uncomment this to test FPS without vsync
|
||||
while (running) { |
||||
float t = glfwGetTime (); |
||||
if (t-t0 >= 5.0) { |
||||
std::cerr << (float)frames/5.0 << " FPS\n"; |
||||
t0 = t; |
||||
frames = 0; |
||||
} |
||||
render (); |
||||
frames++; |
||||
glfwSwapBuffers (); |
||||
running = glfwGetWindowParam (GLFW_OPENED); |
||||
} |
||||
|
||||
glfwTerminate (); |
||||
} |
||||
|
Binary file not shown.
Binary file not shown.
After Width: | Height: | Size: 56 KiB |
After Width: | Height: | Size: 1.2 MiB |
Binary file not shown.
Loading…
Reference in new issue