I’ve written some code to load up models from obj files and display them. I’ve written 2 versions of this one using the old fixed function pipeline and another using shaders with my own implementation of the phong lighting model. The code works as expected when I run it on my Mac setup (yosemite, opengl version 2.1 INTEL-10.6.20). below is the result
[ATTACH=CONFIG]1187[/ATTACH][ATTACH=CONFIG]1188[/ATTACH]
But this is not the case on my windows machine spec:
Windows 7
GLEW 1.12.0
GeForce GTX 970 Nivida
opengl version 4.5.0
GLSL: 4.50 NVIDA
Here is the result:
[ATTACH=CONFIG]1189[/ATTACH]
The image on the left is the one using the shader and the image on the right is the one using fixed function pipeline.
shader based code:
#include <cassert>
#include <gl/glew.h>
#include <gl/freeglut.h>
#include <gl/glext.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/matrix_inverse.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <jutil/time.h>
#include <jutil/GLSLShader.h>
#include <tinyobj/tiny_obj_loader.h>
#include <vector>
#include <iostream>
#include <stdexcept>
#include <algorithm>
#include <thread>
#include <future>
#pragma comment(lib, "glew32.lib")
#define GL_CHECK_ERRORS assert(glGetError() == GL_NO_ERROR);
using namespace std;
using namespace jutil;
using namespace tinyobj;
using namespace glm;
struct lightSource_t {
vec4 pos;
vec4 amb;
vec4 dif;
vec4 spec;
vec4 spotDirection;
float spotAngle;
float spotExponent;
float kc;
float ki;
float kq;
bool transform;
};
struct material_s {
vec4 emit;
vec4 amb;
vec4 dif;
vec4 spec;
float shine;
};
float g = 168.0 / 256;
vec4 globalAmb = vec4(0.2, 0.2, 0.2, 1.0);
material_s material;
lightSource_t light;
//const char* objPath = "Female Cyborg.obj";
//const char* objPath = "D:\\Users\\Josiah\\3d\\3d Models\\Robot_IVO\\Ivo.obj";
// const char* objPath = "D:\\Users\\Josiah\\3d\\3d Models\\Werewolf Game Model\\werewolf.obj"; // "Female Cyborg.obj";
//const char* objPath = "D:\\Users\\Josiah\\3d Models\\robots\\robot char\\robot.obj";
//const char* objPath = "D:\\Users\\Josiah\\3d Models\\Office Interior Reception 2\\office.obj";
const char* objPath = "D:\\Users\\Josiah\\3d\\3d Models\\Nissan FairladyZ 2009\\basemeshobj.obj";
const char* vertexShaderPath = "cyborg.vert";
const char* fragmentShaderPath = "cyborg.frag";
mat4 Model = mat4(1);
mat4 View = mat4(1);
mat4 Projection = mat4(1);
GLSLShader shader;
vector<shape_t> shapes;
vector<material_t> materials;
vector<vector<vec3>> colors;
vector<GLuint> vaos;
vector<GLuint> vbos;
template <typename T>
GLulong sizeOfBuf(const vector<T>& buff) {
return sizeof(buff[0]) * buff.size();
}
void initalizeShaders() {
shader.loadFromFile(GL_VERTEX_SHADER, vertexShaderPath);
shader.loadFromFile(GL_FRAGMENT_SHADER, fragmentShaderPath);
shader.createAndLinkProgram();
shader.use();
shader.addAttribute("aVertex", 0);
shader.addAttribute("aNormal", 1);
shader.addAttribute("aTexCoord", 2);
shader.unUse();
light.amb = vec4(0, 0, 0, 1);
light.dif = vec4(1, 1, 1, 1);
light.spec = vec4(1, 1, 1, 1);
light.pos = vec4(0.0, -5, -5, 1);
light.spotDirection = light.pos;
light.spotAngle = 180.0f; // not a spot light
light.spotExponent = 1;
light.kc = 1;
light.ki = 0;
light.kq = 0;
light.transform = false;
material.amb = vec4(0.2, 0.2, 0.2, 1.0);
material.dif = vec4(0.5, 0.5, 0.5, 1.0);
material.spec = vec4(0.5, 0.5, 0.5, 1);
material.shine = 0.6;
material.emit = vec4(0, 0, 0, 0);
}
void loadModel() {
string result = LoadObj(shapes, materials, objPath);
if (!shapes.empty() || result.empty()) {
/* for_each(shapes.begin(), shapes.end(), [](shape_t s) {
vector<vec3> color;
int size = s.mesh.positions.size() / 3;
for (int i = 0; i < size; i++) {
color.push_back(vec3(0, 0, 1));
}
colors.emplace_back(color);
});*/
cout << "model successfully loaded" << endl;
}
else {
throw runtime_error("unable to load model");
}
}
GLuint getNoOfBuffers() {
int res = 0;
mesh_t mesh = shapes.front().mesh;
if (!mesh.positions.empty()) res++;
if (!mesh.normals.empty()) res++;
if (!mesh.texcoords.empty()) res++;
if (!mesh.indices.empty()) res++;
return res;
}
int bufferedShapdes = 0;
void intializeBuffers() {
GLuint no_of_buffers = 4;
const unsigned long no_of_shapes = shapes.size();
vaos = vector<GLuint>(no_of_shapes);
vbos = vector<GLuint>(no_of_shapes * no_of_buffers); // position, normals, texCoords and indices VBOs
glGenVertexArrays(no_of_shapes, &vaos[0]);
glGenBuffers(no_of_shapes * no_of_buffers, &vbos[0]);
for (int i = 0; i < no_of_shapes; i++){
shape_t shape = shapes[i];
cout << "intializing buffers for: " << shape.name << endl;
mesh_t mesh = shape.mesh;
glBindVertexArray(vaos[i]);
glBindBuffer(GL_ARRAY_BUFFER, vbos[i * no_of_buffers]);
glBufferData(GL_ARRAY_BUFFER, sizeOfBuf(mesh.positions), &mesh.positions[0], GL_STATIC_DRAW);
glEnableVertexAttribArray(shader["aVertex"]);
glVertexAttribPointer(shader["aVertex"], 3, GL_FLOAT, GL_FALSE, 0, 0);
int err = glGetError();
if (err != GL_NO_ERROR) {
cerr << "error wille generating vertex buffer , err: " << err << endl;
throw runtime_error("");
}
if (!mesh.normals.empty()) {
glBindBuffer(GL_ARRAY_BUFFER, vbos[i * no_of_buffers + 1]);
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * mesh.normals.size(), &mesh.normals[0], GL_STATIC_DRAW);
glEnableVertexAttribArray(shader["aNormal"]);
glVertexAttribPointer(shader["aNormal"], 3, GL_FLOAT, GL_FALSE, 0, 0);
}
err = glGetError();
if (err != GL_NO_ERROR) {
cerr << "error wille generating Normal buffer , err: " << err << endl;
throw runtime_error("");
}
if (!mesh.texcoords.empty()) {
glBindBuffer(GL_ARRAY_BUFFER, vbos[i * no_of_buffers + 2]);
glBufferData(GL_ARRAY_BUFFER, sizeOfBuf(mesh.texcoords), &mesh.texcoords[0], GL_STATIC_DRAW);
glEnableVertexAttribArray(shader["aTexCoord"]);
glVertexAttribPointer(shader["aTexCoord"], 2, GL_FLOAT, GL_FALSE, 0, 0);
}
GL_CHECK_ERRORS
err = glGetError();
if (err != GL_NO_ERROR) {
cerr << "error wille generating buffer, err: " << err << endl;
throw runtime_error("");
}
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbos[i * no_of_buffers + 3]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeOfBuf(mesh.indices), &mesh.indices[0], GL_STATIC_DRAW);
glBindVertexArray(0);
err = glGetError();
if (err != GL_NO_ERROR) {
cerr << "error wille generating index buffer, err: " << err << endl;
throw runtime_error("");
}
};
cout << "buffer initalization complete" << endl;
}
atomic_bool ready = false;
void init() {
float g = 32.f / 256.f;
glClearColor(g, g, g, 1.0);
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
initalizeShaders();
loadModel();
intializeBuffers();
}
Time t;
float ang = 0;
float speed = 0.1;
void display() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
View = mat4(1);
View = translate(View, vec3(0, -0, -35));
View = rotate(View, ang, vec3(0, 1, 0));
//View = scale(View, vec3(0.5, 0.5, 0.5));
shader.use();
for (int i = 1; i <= shapes.size(); i++) {
Model = mat4(1);
mat3 normalMatrix = inverseTranspose(mat3(View * Model));
GLuint vaoId = i ;
vector<GLuint> indices = shapes[vaoId - 1].mesh.indices;
glBindVertexArray(vaoId);
shader.sendUniformMatrix4fv("MVP", 1, GL_FALSE, glm::value_ptr(Projection * View * Model));
shader.sendUniformMatrix4fv("MV", 1, GL_FALSE, glm::value_ptr(View * Model));
shader.sendUniformMatrix3fv("normalMatrix", 1, GL_FALSE, glm::value_ptr(normalMatrix));
shader.sendUniform4fv("light0.pos", 1, &light.pos[0]);
shader.sendUniform4fv("light0.amb", 1, &light.amb[0]);
shader.sendUniform4fv("light0.dif", 1, &light.dif[0]);
shader.sendUniform4fv("light0.spec", 1, &light.spec[0]);
shader.sendUniform4fv("light0.spotDirection", 1, &light.spotDirection[0]);
shader.sendUniform1f("light0.spotAngle", light.spotAngle);
shader.sendUniform1f("light0.spotExponent", light.spotExponent);
shader.sendUniform1f("light0.kc", light.kc);
shader.sendUniform1f("light0.ki", light.ki);
shader.sendUniform1f("light0.kq", light.kq);
shader.sendUniform4fv("m.amb", 1, &material.amb[0]);
shader.sendUniform4fv("m.dif", 1, &material.dif[0]);
shader.sendUniform4fv("m.spec", 1, &material.spec[0]);
shader.sendUniform4fv("m.emit", 1, &material.emit[0]);
shader.sendUniform1f("m.shine", material.shine);
shader.sendUniform4fv("globalAmb", 1, &globalAmb[0]);
glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, 0);
}
shader.unUse();
glutSwapBuffers();
}
void resize(int w, int h) {
glViewport(0, 0, w, h);
Projection = perspective(90.0f, float(w) / h, 5.0f, 300.f);
}
void update() {
ang += speed * t;
glutPostRedisplay();
}
void shutdown() {
const unsigned long no_of_shapes = shapes.size();
glDeleteBuffers(no_of_shapes * 4, &vbos[0]);
glDeleteVertexArrays(no_of_shapes, &vaos[0]);
}
const int WIDTH = 1024;
const int HEIGHT = 768;
int main(int argc, char** argv) {
;
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
glutInitContextVersion(4, 5);
glutInitContextFlags(GLUT_CORE_PROFILE | GLUT_DEBUG);
glutInitWindowSize(WIDTH, HEIGHT);
glutCreateWindow("Female Cyborg - OpenGL 4.5");
//glew initialization
glewExperimental = GL_TRUE;
GLenum err = glewInit();
if (GLEW_OK != err) {
cerr << "Error: " << glewGetErrorString(err) << endl;
}
else {
if (GLEW_VERSION_4_5)
{
cout << "Driver supports OpenGL 4.3
Details:" << endl;
}
}
err = glGetError(); //this is to ignore INVALID ENUM error 1282
GL_CHECK_ERRORS
//print information on screen
cout << " Using GLEW " << glewGetString(GLEW_VERSION) << endl;
cout << " Vendor: " << glGetString(GL_VENDOR) << endl;
cout << " Renderer: " << glGetString(GL_RENDERER) << endl;
cout << " Version: " << glGetString(GL_VERSION) << endl;
cout << " GLSL: " << glGetString(GL_SHADING_LANGUAGE_VERSION) << endl;
GL_CHECK_ERRORS
//opengl initialization
init();
//callback hooks
glutCloseFunc(shutdown);
glutDisplayFunc(display);
glutReshapeFunc(resize);
glutIdleFunc(update);
//main loop call
glutMainLoop();
cin.get();
return 0;
}
shaders
// vertex shader
#version 450
#pragma debug(on)
#pragma optimise(off)
struct lightSource_t{
vec4 pos;
vec4 amb;
vec4 dif;
vec4 spec;
vec4 spotDirection;
float spotAngle;
float spotExponent;
float kc;
float ki;
float kq;
bool transform;
};
struct material_t{
vec4 emit;
vec4 amb;
vec4 dif;
vec4 spec;
float shine;
};
uniform lightSource_t light0;
uniform material_t m;
uniform mat4 MV;
uniform mat4 MVP;
uniform vec4 globalAmb;
layout(location=0) in vec3 aVertex;
layout(location=1) in vec3 aNormal;
layout(location=2) in vec4 aColor;
smooth out vec4 interpolatedColor;
vec3 lightDirection(vec4 pos, lightSource_t light);
float daf(float dist, lightSource_t light);
float saf(lightSource_t light, vec3 lightDirection);
void main()
{
mat3 normalMatrix = transpose(inverse(mat3(MV)));
vec3 N = normalize(normalMatrix * aNormal);
vec4 pos = MV * vec4(aVertex, 1);
vec3 L = lightDirection(pos, light0);
vec4 gAmb = m.emit + globalAmb * m.amb;
float _daf = daf(length(L), light0);
float _saf = saf(light0, L);
vec4 amb = light0.amb * m.amb;
vec4 dif = max(dot(L, N), 0) * light0.dif * m.dif;
vec3 E = normalize(-pos.xyz); // position of eyes;
vec3 S = normalize(L + E); // half way vector between light direction and eyes
vec4 spec = pow(max(dot(S, N), 0), m.shine) * light0.spec * m.spec;
vec4 finalColor = gAmb + _daf * _saf * (amb + dif + spec);
interpolatedColor = finalColor;
gl_Position = MVP * vec4(aVertex, 1);
}
vec3 lightDirection(vec4 pos, lightSource_t light){
if(light.pos.w == 0){ // directional light
if(light.transform){
return normalize(MV * light.pos).xyz;
}else{
return normalize(light.pos).xyz;
}
}else{ // positional light
vec3 lightPos = vec3(light.pos/light.pos.w);
return normalize(vec4(lightPos, 1) - pos).xyz;
}
}
float daf(float dist, lightSource_t light){
return 1.0 / (light.kc + light.ki * dist + light.kq * dist * dist);
}
float saf(lightSource_t light, vec3 lightDirection){
vec3 l = normalize(lightDirection);
vec3 d = normalize(light.spotDirection).xyz;
float h = light.spotExponent;
if(light.spotAngle >= 180) return 1.0;
float _LdotD = dot(-l, d);
float cos_spotAngle = cos(light.spotAngle);
if(_LdotD < cos_spotAngle) return 0.0;
return pow(_LdotD, h);
}
// fragment shader
#version 450
#pragma debug(on)
#pragma optimise(off)
in vec4 interpolatedColor;
out vec4 fragColor;
void main()
{
fragColor = interpolatedColor;
}
And here is the fixed function pipeline version
#include <cassert>
#include <gl/glew.h>
#include <gl/freeglut.h>
#include <gl/glext.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/matrix_inverse.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <jutil/time.h>
#include <jutil/GLSLShader.h>
#include <tinyobj/tiny_obj_loader.h>
#include <vector>
#include <iostream>
#include <stdexcept>
#include <algorithm>
#include <thread>
#include <future>
#pragma comment(lib, "glew32.lib")
using namespace std;
using namespace tinyobj;
using namespace jutil;
enum BufferIds { VECTOR_ID, NORMAL_ID, COLOR_ID, TEX_COOD_ID, INDEX_ID, BUFFER_SIZE };
GLuint buffers[BUFFER_SIZE];
GLuint vaoID;
GLSLShader shader;
vector<GLuint> vaos;
vector<GLuint> vbos;
float white[] = { 1, 0, 0, 1 };
float g = 200 / 256;
float matAmbAndDif1[] = { 0.5, 0.5, 0.5, 1.0 };
float matAmbAndDif2[] = { 0.9, 0.9, 0.9, 1.0 };
float matSpec[] = { 1.0, 1.0, 1.0, 1.0 };
float matShine[] = { 120.0 };
struct vec3 {
float x, y, z;
vec3(float x, float y, float z) :x{ x }, y{ y }, z{ z } {
}
};
//const char* filename = "/Users/jay/Downloads/Robot_IVO/ivo.obj";
const char* filename = "D:\\Users\\Josiah\\3d\\3d Models\\Nissan FairladyZ 2009\\basemeshobj.obj";
//const char* filename = "D:\\Users\\Josiah\\3d\\3d Models\\Werewolf Game Model\\werewolf.obj";
//const char* filename = "D:\\Users\\Josiah\\3d\\3d Models\\Robot Character\\robot.obj";
//const char* filename = "D:\\Users\\Josiah\\3d\\3d Models\\Female Cyborg\\Female Cyborg(obj)\\Female Cyborg.obj";
vector<shape_t> shapes;
vector<vector<vec3>> colors;
vector<material_t> materials;
Time t;
float angle = 0;
float speed = 5;
template<typename T>
unsigned long sizeofV(vector<T> v) {
return sizeof(v[0]) * v.size();
}
void createAndBindBuffers() {
GLsizei no_of_shapes = (GLuint)shapes.size();
vaos = vector<GLuint>(no_of_shapes);
glGenVertexArrays(no_of_shapes, &vaos[0]);
for (int i = 0; i < no_of_shapes; i++) {
mesh_t mesh = shapes[i].mesh;
glBindVertexArray(vaos[i]);
glGenBuffers(BUFFER_SIZE, buffers);
glBindBuffer(GL_ARRAY_BUFFER, buffers[VECTOR_ID]);
glBufferData(GL_ARRAY_BUFFER, sizeofV(mesh.positions), &mesh.positions[0], GL_STATIC_DRAW);
glVertexPointer(3, GL_FLOAT, 0, 0);
glEnableClientState(GL_VERTEX_ARRAY);
if (!mesh.normals.empty()) {
glBindBuffer(GL_ARRAY_BUFFER, buffers[NORMAL_ID]);
glBufferData(GL_ARRAY_BUFFER, sizeofV(mesh.normals), &mesh.normals[0], GL_STATIC_DRAW);
glNormalPointer(GL_FLOAT, 0, 0);
glEnableClientState(GL_NORMAL_ARRAY);
}
glBindBuffer(GL_ARRAY_BUFFER, buffers[COLOR_ID]);
glBufferData(GL_ARRAY_BUFFER, sizeofV(colors[i]), &colors[i][0], GL_STATIC_DRAW);
glColorPointer(3, GL_FLOAT, 0, 0);
glEnableClientState(GL_COLOR_ARRAY);
if (!mesh.texcoords.empty()) {
glBindBuffer(GL_ARRAY_BUFFER, buffers[TEX_COOD_ID]);
glBufferData(GL_ARRAY_BUFFER, sizeofV(mesh.texcoords), &mesh.texcoords[0], GL_STATIC_DRAW);
}
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[INDEX_ID]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeofV(mesh.indices), &mesh.indices[0], GL_STATIC_DRAW);
glBindVertexArray(0);
}
}
void loadAndBindTextures() {
// TODO load textures from file and bind
}
void logShapes() {
cout << shapes.size() << " shapes loadeded from " << filename;
cout << "Shape names: " << endl;
for_each(shapes.begin(), shapes.end(), [](shape_t shape) {
vector<vec3> color;
for (int i = 0; i < shape.mesh.positions.size(); i++) {
color.push_back(vec3(g, g, g));
}
colors.push_back(color);
cout << shape.name << endl;
});
}
void initializeShaders() {
/*shader.loadFromFile(GL_VERTEX_SHADER, "/Users/jay/projects/model/model/shader.vert");
shader.loadFromFile(GL_FRAGMENT_SHADER, "/Users/jay/projects/model/model/shader.frag");
shader.createAndLinkProgram();
shader.use();
shader.addAttribute("aVertex", 0);
shader.addUniform("color");
glUniform4fv(shader["color"], 1, white);
shader.unUse();*/
}
void createLight() {
glEnable(GL_LIGHTING);
//glEnable(GL_COLOR_MATERIAL);
//glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
// Light property vectors.
float lightAmb[] = { 0.0, 0.0, 0.0, 1.0 };
float lightDifAndSpec[] = { 1.0, 1.0, 1.0, 1.0 };
float lightPos[] = { 0.0, -5, -5, 1 };
//float lightPos[] = {0.0, -10, -40, 1};
float globAmb[] = { 0.2, 0.2, 0.2, 1.0 };
// Light properties.
glLightfv(GL_LIGHT0, GL_AMBIENT, lightAmb);
glLightfv(GL_LIGHT0, GL_DIFFUSE, lightDifAndSpec);
glLightfv(GL_LIGHT0, GL_SPECULAR, lightDifAndSpec);
glLightfv(GL_LIGHT0, GL_POSITION, lightPos);
glEnable(GL_LIGHT0); // Enable particular light source.
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, globAmb); // Global ambient light.
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE); // Enable two-sided lighting.
glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE); // Enable local viewpoint.
//glShadeModel(GL_FLAT);
}
void init() {
initializeShaders();
LoadObj(shapes, materials, filename);
logShapes();
createAndBindBuffers();
loadAndBindTextures();
createLight();
float g = 32.f / 256.f;
glClearColor(g, g, g, 1.0);
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
cout << "loading done" << endl;
}
void display() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// glColorMask(GL_FALSE, GL_TRUE, GL_FALSE, GL_TRUE);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glPushMatrix();
//glTranslatef(0, -40, -50);
glTranslatef(0, 0, -50);
glRotatef(angle, 0, 1, 0);
// createLight();
// glPointSize(3.0);
// glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
/*
glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, matSpec);
glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, matShine);*/
float matAmb[] = { 0.2, 0.2, 0.2, 1.0 };
float matDiff[] = { 0.5, 0.5, 0.5, 1.0 };
float matSpec[] = { 0.5, 0.5, 0.5, 1.0 };
float matShine[] = { 0.6 };
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, matAmb);
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, matDiff);
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, matSpec);
glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, matShine);
int no_of_shapes = (int)shapes.size();
for (int i = 0; i < no_of_shapes; i++) {
GLsizei count = (GLsizei)shapes[i].mesh.indices.size();
glBindVertexArray(vaos[i]);
glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_INT, 0);
}
glPopMatrix();
glutSwapBuffers();
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
}
void update() {
angle += speed * t;
glutPostRedisplay();
}
void resize(int w, int h) {
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(90, float(w) / h, 5, 300);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
int main(int argc, char * argv[]) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
glutInitWindowSize(1024, 768);
glutInitWindowPosition(50, 50);
glutCreateWindow("Were wolf");
glutDisplayFunc(display);
glutReshapeFunc(resize);
glutIdleFunc(update);
glewExperimental = GL_TRUE;
glewInit();
init();
const GLubyte* version = glGetString(GL_VERSION);
const GLubyte* vendor = glGetString(GL_VENDOR);
const GLubyte* extensions = glGetString(GL_EXTENSIONS);
cout << "Opengl version: " << version << endl;
cout << "Opengl vendor: " << vendor << endl;
// cout << "supported extensions: " << extensions << endl;
glutMainLoop();
init();
//PrintInfo(shapes, materials);
return 0;
}