我已经设法将Nehe's Cel-Shading渲染与我的模型加载器进行整合,并使用Toon遮罩和同时勾勒出它们的原始纹理。结果实际上是一个非常漂亮的模型纹理Cel Shading效果,但是它提高了程序的速度,即使屏幕上只有3个模型也是非常慢的...卡通着色器与纹理。这可以优化吗?
由于结果是有点被黑在一起,我在想,也许我正在执行一些额外的步骤或额外的渲染任务,可能是不需要的,并且正在减慢游戏速度? 你可能会发现一些不必要的东西吗?
两个MD2和3DS装载机曾呼吁建立一个InitToon()函数来加载着色器
initToon(){
int i; // Looping Variable (NEW)
char Line[255]; // Storage For 255 Characters (NEW)
float shaderData[32][3]; // Storate For The 96 Shader Values (NEW)
FILE *In = fopen ("Shader.txt", "r"); // Open The Shader File (NEW)
if (In) // Check To See If The File Opened (NEW)
{
for (i = 0; i < 32; i++) // Loop Though The 32 Greyscale Values (NEW)
{
if (feof (In)) // Check For The End Of The File (NEW)
break;
fgets (Line, 255, In); // Get The Current Line (NEW)
shaderData[i][0] = shaderData[i][1] = shaderData[i][2] = float(atof (Line)); // Copy Over The Value (NEW)
}
fclose (In); // Close The File (NEW)
}
else
return false; // It Went Horribly Horribly Wrong (NEW)
glGenTextures (1, &shaderTexture[0]); // Get A Free Texture ID (NEW)
glBindTexture (GL_TEXTURE_1D, shaderTexture[0]); // Bind This Texture. From Now On It Will Be 1D (NEW)
// For Crying Out Loud Don't Let OpenGL Use Bi/Trilinear Filtering! (NEW)
glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexImage1D (GL_TEXTURE_1D, 0, GL_RGB, 32, 0, GL_RGB , GL_FLOAT, shaderData); // Upload (NEW)
}
这是动画MD2模型图纸:
void MD2Model::drawToon() {
float outlineWidth = 3.0f; // Width Of The Lines (NEW)
float outlineColor[3] = { 0.0f, 0.0f, 0.0f }; // Color Of The Lines (NEW)
// ORIGINAL PART OF THE FUNCTION
//Figure out the two frames between which we are interpolating
int frameIndex1 = (int)(time * (endFrame - startFrame + 1)) + startFrame;
if (frameIndex1 > endFrame) {
frameIndex1 = startFrame;
}
int frameIndex2;
if (frameIndex1 < endFrame) {
frameIndex2 = frameIndex1 + 1;
}
else {
frameIndex2 = startFrame;
}
MD2Frame* frame1 = frames + frameIndex1;
MD2Frame* frame2 = frames + frameIndex2;
//Figure out the fraction that we are between the two frames
float frac =
(time - (float)(frameIndex1 - startFrame)/
(float)(endFrame - startFrame + 1)) * (endFrame - startFrame + 1);
// I ADDED THESE FROM NEHE'S TUTORIAL FOR FIRST PASS (TOON SHADE)
glHint (GL_LINE_SMOOTH_HINT, GL_NICEST); // Use The Good Calculations (NEW)
glEnable (GL_LINE_SMOOTH);
// Cel-Shading Code //
glEnable (GL_TEXTURE_1D); // Enable 1D Texturing (NEW)
glBindTexture (GL_TEXTURE_1D, shaderTexture[0]); // Bind Our Texture (NEW)
glColor3f (1.0f, 1.0f, 1.0f); // Set The Color Of The Model (NEW)
// ORIGINAL DRAWING CODE
//Draw the model as an interpolation between the two frames
glBegin(GL_TRIANGLES);
for(int i = 0; i < numTriangles; i++) {
MD2Triangle* triangle = triangles + i;
for(int j = 0; j < 3; j++) {
MD2Vertex* v1 = frame1->vertices + triangle->vertices[j];
MD2Vertex* v2 = frame2->vertices + triangle->vertices[j];
Vec3f pos = v1->pos * (1 - frac) + v2->pos * frac;
Vec3f normal = v1->normal * (1 - frac) + v2->normal * frac;
if (normal[0] == 0 && normal[1] == 0 && normal[2] == 0) {
normal = Vec3f(0, 0, 1);
}
glNormal3f(normal[0], normal[1], normal[2]);
MD2TexCoord* texCoord = texCoords + triangle->texCoords[j];
glTexCoord2f(texCoord->texCoordX, texCoord->texCoordY);
glVertex3f(pos[0], pos[1], pos[2]);
}
}
glEnd();
// ADDED THESE FROM NEHE'S FOR SECOND PASS (OUTLINE)
glDisable (GL_TEXTURE_1D); // Disable 1D Textures (NEW)
glEnable (GL_BLEND); // Enable Blending (NEW)
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); // Set The Blend Mode (NEW)
glPolygonMode (GL_BACK, GL_LINE); // Draw Backfacing Polygons As Wireframes (NEW)
glLineWidth (outlineWidth); // Set The Line Width (NEW)
glCullFace (GL_FRONT); // Don't Draw Any Front-Facing Polygons (NEW)
glDepthFunc (GL_LEQUAL); // Change The Depth Mode (NEW)
glColor3fv (&outlineColor[0]); // Set The Outline Color (NEW)
// HERE I AM PARSING THE VERTICES AGAIN (NOT IN THE ORIGINAL FUNCTION) FOR THE OUTLINE AS PER NEHE'S TUT
glBegin (GL_TRIANGLES); // Tell OpenGL What We Want To Draw
for(int i = 0; i < numTriangles; i++) {
MD2Triangle* triangle = triangles + i;
for(int j = 0; j < 3; j++) {
MD2Vertex* v1 = frame1->vertices + triangle->vertices[j];
MD2Vertex* v2 = frame2->vertices + triangle->vertices[j];
Vec3f pos = v1->pos * (1 - frac) + v2->pos * frac;
Vec3f normal = v1->normal * (1 - frac) + v2->normal * frac;
if (normal[0] == 0 && normal[1] == 0 && normal[2] == 0) {
normal = Vec3f(0, 0, 1);
}
glNormal3f(normal[0], normal[1], normal[2]);
MD2TexCoord* texCoord = texCoords + triangle->texCoords[j];
glTexCoord2f(texCoord->texCoordX, texCoord->texCoordY);
glVertex3f(pos[0], pos[1], pos[2]);
}
}
glEnd(); // Tell OpenGL We've Finished
glDepthFunc (GL_LESS); // Reset The Depth-Testing Mode (NEW)
glCullFace (GL_BACK); // Reset The Face To Be Culled (NEW)
glPolygonMode (GL_BACK, GL_FILL); // Reset Back-Facing Polygon Drawing Mode (NEW)
glDisable (GL_BLEND);
}
而这是在3DS加载器中的drawToon函数
void Model_3DS::drawToon()
{
float outlineWidth = 3.0f; // Width Of The Lines (NEW)
float outlineColor[3] = { 0.0f, 0.0f, 0.0f }; // Color Of The Lines (NEW)
//ORIGINAL CODE
if (visible)
{
glPushMatrix();
// Move the model
glTranslatef(pos.x, pos.y, pos.z);
// Rotate the model
glRotatef(rot.x, 1.0f, 0.0f, 0.0f);
glRotatef(rot.y, 0.0f, 1.0f, 0.0f);
glRotatef(rot.z, 0.0f, 0.0f, 1.0f);
glScalef(scale, scale, scale);
// Loop through the objects
for (int i = 0; i < numObjects; i++)
{
// Enable texture coordiantes, normals, and vertices arrays
if (Objects[i].textured)
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
if (lit)
glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);
// Point them to the objects arrays
if (Objects[i].textured)
glTexCoordPointer(2, GL_FLOAT, 0, Objects[i].TexCoords);
if (lit)
glNormalPointer(GL_FLOAT, 0, Objects[i].Normals);
glVertexPointer(3, GL_FLOAT, 0, Objects[i].Vertexes);
// Loop through the faces as sorted by material and draw them
for (int j = 0; j < Objects[i].numMatFaces; j ++)
{
// Use the material's texture
Materials[Objects[i].MatFaces[j].MatIndex].tex.Use();
// AFTER THE TEXTURE IS APPLIED I INSERT THE TOON FUNCTIONS HERE (FIRST PASS)
glHint (GL_LINE_SMOOTH_HINT, GL_NICEST); // Use The Good Calculations (NEW)
glEnable (GL_LINE_SMOOTH);
// Cel-Shading Code //
glEnable (GL_TEXTURE_1D); // Enable 1D Texturing (NEW)
glBindTexture (GL_TEXTURE_1D, shaderTexture[0]); // Bind Our Texture (NEW)
glColor3f (1.0f, 1.0f, 1.0f); // Set The Color Of The Model (NEW)
glPushMatrix();
// Move the model
glTranslatef(Objects[i].pos.x, Objects[i].pos.y, Objects[i].pos.z);
// Rotate the model
glRotatef(Objects[i].rot.z, 0.0f, 0.0f, 1.0f);
glRotatef(Objects[i].rot.y, 0.0f, 1.0f, 0.0f);
glRotatef(Objects[i].rot.x, 1.0f, 0.0f, 0.0f);
// Draw the faces using an index to the vertex array
glDrawElements(GL_TRIANGLES, Objects[i].MatFaces[j].numSubFaces, GL_UNSIGNED_SHORT, Objects[i].MatFaces[j].subFaces);
glPopMatrix();
}
glDisable (GL_TEXTURE_1D); // Disable 1D Textures (NEW)
// THIS IS AN ADDED SECOND PASS AT THE VERTICES FOR THE OUTLINE
glEnable (GL_BLEND); // Enable Blending (NEW)
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); // Set The Blend Mode (NEW)
glPolygonMode (GL_BACK, GL_LINE); // Draw Backfacing Polygons As Wireframes (NEW)
glLineWidth (outlineWidth); // Set The Line Width (NEW)
glCullFace (GL_FRONT); // Don't Draw Any Front-Facing Polygons (NEW)
glDepthFunc (GL_LEQUAL); // Change The Depth Mode (NEW)
glColor3fv (&outlineColor[0]); // Set The Outline Color (NEW)
for (int j = 0; j < Objects[i].numMatFaces; j ++)
{
glPushMatrix();
// Move the model
glTranslatef(Objects[i].pos.x, Objects[i].pos.y, Objects[i].pos.z);
// Rotate the model
glRotatef(Objects[i].rot.z, 0.0f, 0.0f, 1.0f);
glRotatef(Objects[i].rot.y, 0.0f, 1.0f, 0.0f);
glRotatef(Objects[i].rot.x, 1.0f, 0.0f, 0.0f);
// Draw the faces using an index to the vertex array
glDrawElements(GL_TRIANGLES, Objects[i].MatFaces[j].numSubFaces, GL_UNSIGNED_SHORT, Objects[i].MatFaces[j].subFaces);
glPopMatrix();
}
glDepthFunc (GL_LESS); // Reset The Depth-Testing Mode (NEW)
glCullFace (GL_BACK); // Reset The Face To Be Culled (NEW)
glPolygonMode (GL_BACK, GL_FILL); // Reset Back-Facing Polygon Drawing Mode (NEW)
glDisable (GL_BLEND);
glPopMatrix();
}
最后这是tex.Use()函数t加载BMP纹理,并以某种方式与Toon着色完美融合
void GLTexture::Use()
{
glEnable(GL_TEXTURE_2D); // Enable texture mapping
glBindTexture(GL_TEXTURE_2D, texture[0]); // Bind the texture as the current one
}
编辑---------------------------- ------------------------------------------------
谢谢大家的建议。遵循Kos的建议,我重新考虑了该函数以便不使用glBegin/End ....因此,我在将std :: vectors存储在std :: vectors中,然后使用glDrawArrays从vector中读取。 ....这在理论上意味着更快,但它给我一个比以前更低的帧率......这是否正确实施?
for(int i = 0; i < numTriangles; i++) {
MD2Triangle* triangle = triangles + i;
for(int j = 0; j < 3; j++) {
MD2Vertex* v1 = frame1->vertices + triangle->vertices[j];
MD2Vertex* v2 = frame2->vertices + triangle->vertices[j];
Vec3f pos = v1->pos * (1 - frac) + v2->pos * frac;
Vec3f normal = v1->normal * (1 - frac) + v2->normal * frac;
if (normal[0] == 0 && normal[1] == 0 && normal[2] == 0) {
normal = Vec3f(0, 0, 1);
}
normals.push_back(normal[0]);
normals.push_back(normal[1]);
normals.push_back(normal[2]);
MD2TexCoord* texCoord = texCoords + triangle->texCoords[j];
textCoords.push_back(texCoord->texCoordX);
textCoords.push_back(texCoord->texCoordY);
vertices.push_back(pos[0]);
vertices.push_back(pos[1]);
vertices.push_back(pos[2]);
}
}
glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);
glNormalPointer(GL_FLOAT, 0, &normals[0]);
glTexCoordPointer(2, GL_FLOAT, 0, &textCoords[0]);
glVertexPointer(3, GL_FLOAT, 0, &vertices[0]);
glDrawArrays(GL_TRIANGLES, 0, vertices.size()/3);
glDisableClientState(GL_VERTEX_ARRAY); // disable vertex arrays
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
vertices.clear();
textCoords.clear();
normals.clear();
您应该访问http://codereview.stackexchange.com。这个网站是针对特定的编程问题。 – Constantinius