无法在opengl中使用.obj模型(使用glm.h)进行phong着色

时间:2016-10-19 13:06:21

标签: c++ opengl glsl wavefront

我想在我的程序中设置phong着色,我使用" glm.h"帮助我阅读和绘制.obj模型。因为并非所有模型都有文件中的顶点法线数据,所以我自己算一下,然后检查它是对的。 但是当我使用" glmDraw(myObj,GLM_FLAT)"时,着色器可以在平面着色器中校正。 ,它会使用face normal来计算它。当我使用" glmDraw(myObj,GLM_SMOOTH)"时,我无法获得正确的效果。使用顶点法线计数。我的代码有什么问题?这是我的主要程序错了吗?还是我的shder程序?

我的主要代码:

#define GLEW_STATIC

#include <Windows.h>    // for solving the Code::Blocks errors
#include <stdlib.h>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <vector>

#include <GL/glew.h>
#include <GL/glut.h>

#include "textfile.h"
#include "glm.h"

#define PI 3.1415926535897

using namespace std;

GLMmodel *myObj = NULL;
GLMmodel *myObj_inner = NULL;

int width, height;
int start_x, start_y;
GLdouble theta = -PI/2, phi = PI / 2;
GLdouble eye_x = 0.0, eye_y = 0.0, eye_z = 0.0,
         center_x = eye_x + sin(phi) * cos(theta), center_y = eye_y + cos(phi), center_z = 4*sin(phi) * sin(theta),
         up_x = 0.0, up_y = 1.0, up_z = 0.0;

bool ridingMode = false;
float delta_x = 0.0, delta_y = 0.0, delta_z = 0.0;
float angle=0;

GLfloat vertices[][3] =
    {{-0.5,-0.5,-0.5},
    {0.5,-0.5,-0.5},
    {0.5,0.5,-0.5},
    {-0.5,0.5,-0.5},
    {-0.5,-0.5,0.5},
    {0.5,-0.5,0.5},
    {0.5,0.5,0.5},
    {-0.5,0.5,0.5}};

GLdouble lightTheta = 10.0;
GLfloat light0_ambient[] = {0.9, 0.9, 0.9, 1.0};
GLfloat light0_diffuse[] = {0.7, 0.7, 0.7, 1.0};
GLfloat light0_specular[] = {0.7, 0.7, 0.7, 1.0};
GLfloat light0_pos[]={0.0, 0.0, 0.0, 1.0};
GLfloat light0_shininess = 50;

GLfloat min_x, max_x, min_y, max_y, min_z, max_z;
GLfloat bound_size[3];
GLfloat bound_center[3];

vector<int> *point_tri = NULL;

bool show = true;

void polygon(int a, int b, int c , int d)
{
/* draw a polygon via list of vertices */
    glBegin(GL_POLYGON);
        glVertex3fv(vertices[a]);
        glVertex3fv(vertices[b]);
        glVertex3fv(vertices[c]);
        glVertex3fv(vertices[d]);
    glEnd();
}

void cube(void)
{
/* map vertices to faces */

    polygon(0,3,2,1);
    polygon(2,3,7,6);
    polygon(0,4,7,3);
    polygon(1,2,6,5);
    polygon(4,5,6,7);
    polygon(0,1,5,4);
}

void draw_bounding_box()
{
    glScalef(bound_size[0],bound_size[1],bound_size[2]);
    glPolygonMode(GL_FRONT, GL_LINE);
    glPolygonMode(GL_BACK, GL_LINE);
    cube();
    glPolygonMode(GL_FRONT, GL_FILL);
    glPolygonMode(GL_BACK, GL_FILL);
    glScalef(1/bound_size[0],1/bound_size[1],1/bound_size[2]);
}



void setShaders()
{
    GLhandleARB v = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB),
                f = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB),
                p;

    char *vs = NULL, *fs = NULL;

    vs = textFileRead("myshader.vert");
    fs = textFileRead("myshader.frag");

    const char * vv = vs;
    const char * ff = fs;

    glShaderSourceARB(v, 1, &vv, NULL);
    glShaderSourceARB(f, 1, &ff, NULL);

    free(vs);free(fs);

    glCompileShaderARB(v);
    glCompileShaderARB(f);

    p = glCreateProgramObjectARB();
    glAttachObjectARB(p,v);
    glAttachObjectARB(p,f);

    glLinkProgramARB(p);
    glUseProgramObjectARB(p);

    glUniform1iARB(glGetUniformLocationARB(p, "texture"), 0);
    glUniform3fARB(glGetUniformLocationARB(p, "light"), light0_pos[0], light0_pos[1], light0_pos[2]);

    glUniform4fARB(glGetUniformLocationARB(p, "l_ambient"), light0_ambient[0], light0_ambient[1], light0_ambient[2], light0_ambient[3] );
    glUniform4fARB(glGetUniformLocationARB(p, "l_diffuse"), light0_diffuse[0], light0_diffuse[1], light0_diffuse[2], light0_diffuse[3] );
    glUniform4fARB(glGetUniformLocationARB(p, "l_specular"), light0_specular[0], light0_specular[1], light0_specular[2], light0_specular[3] );
    glUniform1fARB(glGetUniformLocationARB(p, "l_shininess"), light0_shininess );

}

void display(void)
{
    /* display callback, clear frame buffer and z buffer,
        rotate cube and draw, swap buffers */
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    gluLookAt(eye_x, eye_y, eye_z, center_x, center_y, center_z, up_x, up_y, up_z);

    //lighting
    glEnable(GL_LIGHTING);
    glEnable(GL_LIGHT0);


    glLightfv(GL_LIGHT0, GL_AMBIENT, light0_ambient);
    glLightfv(GL_LIGHT0, GL_DIFFUSE, light0_diffuse);
    glLightfv(GL_LIGHT0, GL_SPECULAR, light0_specular);
    glLightfv(GL_LIGHT0, GL_POSITION, light0_pos);

    setShaders();

    glPushMatrix();

    glTranslatef(-bound_center[0], -bound_center[1], -bound_center[2]);

    if(show){
//        glPolygonMode(GL_FRONT, GL_LINE);
//        glPolygonMode(GL_BACK, GL_LINE);
//        glmDraw(myObj, GLM_FLAT);
        glmDraw(myObj,GLM_SMOOTH);
//        glmDraw(myObj,GLM_NONE);
//        glPolygonMode(GL_FRONT, GL_FILL);
//        glPolygonMode(GL_BACK, GL_FILL);
    }

    glPopMatrix();

    draw_bounding_box();

    glutSwapBuffers();
    glutPostRedisplay();
}

void mouse(int btn, int state, int x, int y)
{
    if(state == GLUT_DOWN)
    {
        start_x = x;
        start_y = y;
    }
}

void mouseMotion(int x, int y)
{
    theta += 2 * static_cast<double> (x - start_x) / width;
    if(theta > 2 * PI) theta -= 2 * PI;
    if(theta < -2 * PI) theta += 2 * PI;
    GLdouble tmp = phi;
    phi += 2 * static_cast<double> (y - start_y) / height;
    if(phi > 0 && phi < PI)
        center_y = eye_y  + bound_size[1] * cos(phi);
    else
        phi = tmp;
    center_x = eye_x + bound_size[0] * sin(phi) * cos(theta);
    center_z = eye_z + bound_size[2] * sin(phi) * sin(theta);
    start_x = x;
    start_y = y;
}

void keyboard(unsigned char key,int x,int y)
{
    //²¾°Ê
    if(key == 'q' || key == 'Q') //quit
    {
        glmDelete(myObj);
        delete point_tri;
        exit(0);
    }
    if(key == 'w' || key == 'W') //move forward
    {
        eye_x += 0.1 * bound_size[0] * sin(phi) * cos(theta);
        eye_y += 0.1 * bound_size[1] * cos(phi);
        eye_z += 0.1 * bound_size[2] * sin(phi) * sin(theta);
        center_x += 0.1 * bound_size[0] * sin(phi) * cos(theta);
        center_y += 0.1 * bound_size[1] * cos(phi);
        center_z += 0.1 * bound_size[2] * sin(phi) * sin(theta);
    }
    if(key == 's' || key == 'S') //move backward
    {
        eye_x -= 0.1 * bound_size[0] * sin(phi) * cos(theta);
        eye_y -= 0.1 * bound_size[1] * cos(phi);
        eye_z -= 0.1 * bound_size[2] * sin(phi) * sin(theta);
        center_x -= 0.1 * bound_size[0] * sin(phi) * cos(theta);
        center_y -= 0.1 * bound_size[1] * cos(phi);
        center_z -= 0.1 * bound_size[2] * sin(phi) * sin(theta);
     }
    if(key == 'a' || key == 'A') //move left
    {
        eye_x += 0.1 * bound_size[0] * sin(phi) * sin(theta);
        eye_z += -0.1 * bound_size[2] * sin(phi) * cos(theta);
        center_x += 0.1 * bound_size[0] * sin(phi) * sin(theta);
        center_z += -0.1 * bound_size[2] * sin(phi) * cos(theta);
    }
    if(key == 'd' || key == 'D') //move right
    {
        eye_x += -0.1 * bound_size[0] * sin(phi) * sin(theta);
        eye_z += 0.1 * bound_size[2] * sin(phi) * cos(theta);
        center_x += -0.1 * bound_size[0] * sin(phi) * sin(theta);
        center_z += 0.1 * bound_size[2] * sin(phi) * cos(theta);
    }
    if(key == 'r' || key == 'R') // up
    {
        eye_y += 0.1 * bound_size[1];
        center_y += 0.1 * bound_size[1];
    }
    if(key == 'f' || key == 'F') // down
    {
        eye_y -= 0.1 * bound_size[1];
        center_y -= 0.1 * bound_size[1];
    }

    if(key == 'z' || key == 'Z')
    {
        theta = -PI/2, phi = PI / 2;
        eye_x = 0.0, eye_y = 0.0, eye_z = 0.0 + 2.0 * bound_size[2],
        center_x = eye_x + sin(phi) * cos(theta), center_y = eye_y + cos(phi), center_z = 4*sin(phi) * sin(theta);
    }

    if(key == 'b' || key == 'B') // down
    {
        show = !show;
    }

    if(key=='+')
    {
        lightTheta += 10.0;
    }
    else if(key=='-')
    {
        lightTheta -= 10.0;
    }


    if(key==27)
    {
        exit(0);
    }
}

void special(int key, int x, int y)
{
    if(key == GLUT_KEY_UP) // look up
        if(phi - 0.02 > 0) phi -= 0.02;
    if(key == GLUT_KEY_DOWN) // look down
        if(phi + 0.02 < PI) phi += 0.02;
    if(key == GLUT_KEY_LEFT) // turn left
    {
        theta -= 0.1;
        if(theta <= -2 * PI) theta += 2 * PI;
    }
    if(key == GLUT_KEY_RIGHT) // turn right
    {
        theta += 0.1;
        if(theta >= 2 * PI) theta -= 2 * PI;
    }
    center_x = eye_x + bound_size[0] * sin(phi) * cos(theta);
    center_y = eye_y + bound_size[1] * cos(phi);
    center_z = eye_z + bound_size[2] * sin(phi) * sin(theta);
}

void myReshape(int w, int h)
{
    width = w;
    height = h;
    float ratio = w * 1.0 / h;
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glViewport(0, 0, w, h);
    gluPerspective(50.0, ratio, 0.1, 100000.0);
    glMatrixMode(GL_MODELVIEW);
}

void bounding_box()
{
    //cout << myObj->vertices[3 * 1 + 0] << " " << myObj->vertices[3 * 1 + 1] << " " << myObj->vertices[3 * 1 + 2] << endl;
    min_x = max_x = myObj->vertices[3 * 1 + 0];
    min_y = max_y = myObj->vertices[3 * 1 + 1];
    min_z = max_z = myObj->vertices[3 * 1 + 2];

    for(int i = 1 ; i <= myObj->numvertices ; i += 1)
    {
        if (myObj->vertices[3 * i + 0] < min_x) min_x = myObj->vertices[3 * i + 0];
        if (myObj->vertices[3 * i + 0] > max_x) max_x = myObj->vertices[3 * i + 0];
        if (myObj->vertices[3 * i + 1] < min_y) min_y = myObj->vertices[3 * i + 1];
        if (myObj->vertices[3 * i + 1] > max_y) max_y = myObj->vertices[3 * i + 1];
        if (myObj->vertices[3 * i + 2] < min_z) min_z = myObj->vertices[3 * i + 2];
        if (myObj->vertices[3 * i + 2] > max_z) max_z = myObj->vertices[3 * i + 2];
    }

    bound_size[0] = max_x - min_x;
    bound_size[1] = max_y - min_y;
    bound_size[2] = max_z - min_z;

    bound_center[0] = (max_x + min_x)/2.0;
    bound_center[1] = (max_y + min_y)/2.0;
    bound_center[2] = (max_z + min_z)/2.0;

    eye_z = eye_z + 2.0 * bound_size[2];

    light0_pos[0] += 1.25 * bound_size[0];
    light0_pos[1] += 1.25 * bound_size[1];
    light0_pos[2] += 1.25 * bound_size[2];
}

void recount_normal()
{
    point_tri = new vector<int>[myObj->numvertices + 1];

    for(int i = 0 ; i < myObj->numtriangles ; i += 1)
    {
        for(int j = 0 ; j < 3 ; j += 1)
        {
            bool add = true;
            for(int k = 0 ; k < point_tri[myObj->triangles[i].vindices[j]].size() ; k += 1)
            {
                GLfloat *temp = &myObj->facetnorms[3 * point_tri[myObj->triangles[i].vindices[j]][k]];
                if(*temp == myObj->facetnorms[3 * (i+1) + 0] && *(temp + 1) == myObj->facetnorms[3 * (i+1) + 1] && *(temp + 2) == myObj->facetnorms[3 * (i+1) + 2])
                {
                    add = false;
                    break;
                }
            }
            if(add)
                point_tri[myObj->triangles[i].vindices[j]].push_back(i + 1);
        }
    }

    for(int i = 1 ; i <= myObj->numvertices ; i += 1)
    {
        sort(point_tri[i].begin(),point_tri[i].begin() + point_tri[i].size());
    }

    myObj->numnormals = myObj->numvertices;
    myObj->normals = new GLfloat[3 * (myObj->numnormals + 1)];
    for(int i = 1 ; i <= myObj->numnormals ; i += 1)
    {
        GLfloat temp[3] = {0.0 , 0.0 , 0.0};
        for(int j = 0 ; j < point_tri[i].size() ; j += 1)
        {
            temp[0] += myObj->facetnorms[3 * point_tri[i][j] + 0];
            temp[1] += myObj->facetnorms[3 * point_tri[i][j] + 1];
            temp[2] += myObj->facetnorms[3 * point_tri[i][j] + 2];
        }
        GLfloat normal_length = sqrt(pow(temp[0],2) + pow(temp[1],2) + pow(temp[2],2));
        temp[0] /= normal_length;
        temp[1] /= normal_length;
        temp[2] /= normal_length;

        myObj->normals[3 * i + 0] = temp[0];
        myObj->normals[3 * i + 1] = temp[1];
        myObj->normals[3 * i + 2] = temp[2];

    }

    myObj_inner->numnormals = myObj_inner->numvertices;
    myObj_inner->normals = new GLfloat[3 * (myObj_inner->numnormals + 1)];
}

void init()
{
    bounding_box();
    recount_normal();
}

int main(int argc, char **argv)
{
    myObj = glmReadOBJ("test_model/cube.obj");
    myObj_inner = glmReadOBJ("test_model/cube.obj");

    glmFacetNormals(myObj);

    init();

    glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
    glutInitWindowSize(1000,1000);

    glutCreateWindow("Zometool");
    glutDisplayFunc(display);
    glutReshapeFunc(myReshape);
    glutMouseFunc(mouse);
    glutMotionFunc(mouseMotion);
    glutKeyboardFunc(keyboard);
    glutSpecialFunc(special);
    glEnable(GL_DEPTH_TEST); /* Enable hidden--surface--removal */

    glewInit();

    glutMainLoop();
    return 0;
}

我的顶点着色器:

varying vec3 N;
varying vec3 v;

void main(void)
{
   v = vec3(gl_ModelViewMatrix * gl_Vertex);
   N = normalize(gl_ModelViewMatrix * gl_Normal);
   gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}

我的片段着色器:

uniform vec4 l_ambient;
uniform vec4 l_diffuse;
uniform vec4 l_specular;
uniform vec3 light;
uniform float l_shininess;

varying vec3 N;
varying vec3 v;

void main (void)
{
    vec3 lightWeighting;
    vec3 lightDirection = normalize(light.xyz - v);
    vec3 normal = N;

    float specularLightWeighting = 0.0;

    vec3 eyeDirection = normalize(-v);
    vec3 reflectionDirection = normalize(-reflect(L,N));

    specularLightWeighting = pow(max(dot(reflectionDirection, eyeDirection), 0.0), l_shininess);

    float diffuseLightWeighting = max(dot(normal, lightDirection), 0.0);
     lightWeighting = l_ambient
        + l_specular * specularLightWeighting
        + l_diffuse * diffuseLightWeighting;

    gl_FragColor = gl_FrontLightModelProduct.sceneColor + lightWeighting;
}

我的cube.obj:

# Blender v2.62 (sub 0) OBJ File: ''
# www.blender.org
mtllib cube.mtl
o Cube
v 1.000000 -1.000000 -1.000000
v 1.000000 -1.000000 1.000000
v -1.000000 -1.000000 1.000000
v -1.000000 -1.000000 -1.000000
v 1.000000 1.000000 -1.000000
v 1.000000 1.000000 1.000000
v -1.000000 1.000000 1.000000
v -1.000000 1.000000 -1.000000
usemtl Material
s off
f 1 2 3 4
f 5 8 7 6
f 1 5 6 2
f 2 6 7 3
f 3 7 8 4
f 5 1 4 8

我的cube.mtl:

# Blender MTL File: ''
# Material Count: 1
newmtl Material
Ns 96.078431
Ka 0.000000 0.000000 0.000000
Kd 0.640000 0.640000 0.640000
Ks 0.500000 0.500000 0.500000
Ni 1.000000
d 1.000000
illum 2

平面图片:

flat image

流畅的图像:

smooth image

0 个答案:

没有答案