#include #include #include #include #include #define STB_IMAGE_IMPLEMENTATION #include #include #include #include #include GLuint shader; //standard shader program used for all elements GLuint transUniform; //location of the "transMatrix" transformation matrix uniform in the shader //parts of the model (see modelpart.hpp) ModelPart parts[3]; void display () { glClear(GL_COLOR_BUFFER_BIT); for (int i = 0; i < sizeof(parts)/sizeof(ModelPart); i++) { parts[i].bindAndDraw(); } glutSwapBuffers(); } void initBuffers (GLuint* vaoNum) { //TODO: put quad stuff in header file or something GLfloat quad[] = { //vertex UV/texcoord 0.5f, 0.5f, 1.0f, 0.0f, 0.5f, -0.5f, 1.0f, 1.0f, -0.5f, -0.5f, 0.0f, 1.0f, -0.5f, 0.5f, 0.0f, 0.0f, }; GLuint quadElements[] = { 0, 1, 2, 2, 3, 0 }; glGenVertexArrays(1, vaoNum); glBindVertexArray(*vaoNum); GLuint vbo; //vertex buffer glGenBuffers(1, &vbo); glBindBuffer(GL_ARRAY_BUFFER, vbo); //change to GL_DYNAMIC_DRAW when using deformable meshes glBufferData(GL_ARRAY_BUFFER, sizeof(quad), quad, GL_STATIC_DRAW); GLuint ebo; //element buffer glGenBuffers(1, &ebo); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(quadElements), quadElements, GL_STATIC_DRAW); //tell OpenGL what to put in the input vars GLuint posAttr = glGetAttribLocation(shader, "position"); glVertexAttribPointer(posAttr, 2, GL_FLOAT, GL_FALSE, 4*sizeof(GLfloat), 0); glEnableVertexAttribArray(posAttr); GLuint uvAttr = glGetAttribLocation(shader, "texcoord"); glVertexAttribPointer(uvAttr, 2, GL_FLOAT, GL_FALSE, 4*sizeof(GLfloat), (void*)(2*sizeof(GLfloat))); glEnableVertexAttribArray(uvAttr); } void initGraphics () { int argc = 1; char *argv[1] = {(char*)"fc2d"}; glutInit(&argc, argv); glutCreateWindow("FaceCam2D"); glutInitWindowSize(512, 512); glewExperimental = GL_TRUE; glewInit(); initShader(); parts[0] = ModelPart(resolvePath("models/test/head-base.png").c_str(), transUniform); parts[1] = ModelPart(resolvePath("models/test/face-eyes.png").c_str(), transUniform); parts[2] = ModelPart(resolvePath("models/test/face-mouth-closed.png").c_str(), transUniform); parts[2].addTexture(resolvePath("models/test/face-mouth-open.png").c_str(), 1); //enable blending for alpha textures glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); //set background color glClearColor(0.5f, 0.5f, 0.5f, 1.0f); glutDisplayFunc(display); std::cout << "graphics init complete" << std::endl; } void initTexture (GLuint* texNum, const char* path) { glGenTextures(1, texNum); glBindTexture(GL_TEXTURE_2D, *texNum); int x, y, channels; GLubyte* pixels = stbi_load(path, &x, &y, &channels, 4); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, x, y, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); } void initShader() { const char* vsSrc = "#version 120\n" "attribute vec2 position;" "attribute vec2 texcoord;" "varying vec2 uv;" "uniform mat4 transMatrix;" "void main () {" "gl_Position = transMatrix * vec4(position, 0.0, 1.0);" "uv = texcoord;" "}"; const char* fsSrc = "#version 120\n" "varying vec2 uv;" "uniform sampler2D tex;" "void main () {" "gl_FragColor = texture2D(tex, uv);" "}"; //compile vert shader GLuint vs = glCreateShader(GL_VERTEX_SHADER); glShaderSource(vs, 1, &vsSrc, NULL); glCompileShader(vs); GLint status; glGetShaderiv(vs, GL_COMPILE_STATUS, &status); if (status != GL_TRUE) { std::cout << "vertex shader borked" << std::endl; printShaderCompileLog(vs); } //compile frag shader GLuint fs = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(fs, 1, &fsSrc, NULL); glCompileShader(fs); glGetShaderiv(fs, GL_COMPILE_STATUS, &status); if (status != GL_TRUE) { std::cout << "fragment shader borked" << std::endl; printShaderCompileLog(vs); } //link shaders into a shader program shader = glCreateProgram(); glAttachShader(shader, vs); glAttachShader(shader, fs); //glBindFragDataLocation(shader, 0, "color"); glLinkProgram(shader); glUseProgram(shader); //set an identity ("do nothing") transformation matrix as default transUniform = glGetUniformLocation(shader, "transMatrix"); glUniformMatrix4fv(transUniform, 1, GL_FALSE, glm::value_ptr(glm::mat4(1.0f))); } void graphicsFrame () { glutMainLoopEvent(); } void printShaderCompileLog(GLuint shader) { char logBuffer[1024]; glGetShaderInfoLog(shader, 1024, NULL, logBuffer); std::cout << "Compile log for shader " << shader << std::endl; std::cout << logBuffer << std::endl; } void initModel () { } void updateModel(glm::vec2 headPos, glm::vec2 facePos, float rotation, float scale, bool mouthOpen) { //calculate transforms parts[0].setTransform(headPos, rotation, scale); parts[1].setTransform(facePos, rotation, scale); parts[2].setTransform(facePos, rotation, scale); //set mouth texture to open or closed parts[2].selectTexture(mouthOpen ? 1 : 0); //tell FreeGLUT to schedule a screen update glutPostRedisplay(); }