我想在我的程序中设置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
平面图片:
流畅的图像: