开发者

What is the proper way to draw my 3D objects with shaders?

I have an OBJ & MTL file exported from 3DS Max that is a complete chess set. In my end result, I would like to be able to select a game piece & then select a square to move it too. The elements I am having problems tying together are:

  • Object selection
  • Shaders

I have my object importer working in two ways.

1) Group everything together with like materials into a struct called Mesh and loop through all the model.meshes drawing each frame.

2) Identify the board, each square, & each game piece and place the relevant vertices, material, etc into a struct called GroupObject. They are placed in model.objects which I loop through drawing each frame.

Here is a screenshot of what each option described in #1 and #2 look like. In the top 1/2 of the SS, I just draw out the meshes and all the shading looks right, but nothing is selectable. In the bottom 1/2, I can select a game piece or a square just fine, but the model looks like crap.

http://img815.imageshack.us/img815/2158/chesst.png

Additionally, if I use the shader with the code from #2, panning & zooming slows down to a crawl. It is almost completely unresponsive.

Here is the method called to draw the objects every frame. The first 2 commented lines is where I try option 1, and just draw my struct Mesh's and it looks good. Rotating & Zooming are smooth as well, but I cannot select an object b/c I can't do the glPushName of a Mesh. Right now, the code is setup looping through each model.objects so I can run the glPushName( (int)object ); which is necessary for the picking/selection of a game piece or square. The commented out section is where I try and apply the shader that is very slow when looping through model.objects (no slow down when looping model.mesh's )

 glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

//for (int i = 0; i < model.getNumberOfMeshes(); ++i)
//{
for ( int i = 0; i < (int)model.objects.size(); i++ )
{
    ModelOBJ::GroupObject *object = model.objects[i];

    glPushName( (int)object );

    int faceSize = (int)object->faces.size();

    for ( int j = 0; j < faceSize; j++ )
    {

        ModelOBJ::Face *face = object->faces[j];
        pMaterial = &model.getMaterial( face->materialId );


        glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (GLfloat *)pMaterial->ambient);
        glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (GLfloat *)pMaterial->diffuse);
        glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (GLfloat *)pMaterial->specular);
        glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, pMaterial->shininess * 128.0f);

        glDisable(GL_TEXTURE_2D);
        drawFace( *face );

        //if (pMaterial->bumpMapFilename.empty())
        //{
            // Per fragment Blinn-Phong code path.

        //  glUseProgram(blinnPhongShader);

        //  // Bind the color map texture.

        //  texture = nullTexture;

        //  if (enableTextures)
        //  {
        //      iter = modelTextures.find(pMaterial->colorMapFilename);

        //      if (iter != modelTextures.end())
        //          texture = iter->second;
        //  }

        //  glActiveTexture(GL_TEXTURE0);
        //  glEnable(GL_TEXTURE_2D);
        //  glBindTexture(GL_TEXTURE_2D, texture);

        //  // Update shader parameters.

        //  glUniform1i(glGetUniformLocation(
        //      blinnPhongShader, "colorMap"), 0);
        //  glUniform1f(glGetUniformLocation(
        //      blinnPhongShader, "materialAlpha"), pMaterial->alpha);
        //}        
    }
    glPopName();
}

glBindTexture(GL_TEXTURE_2D, 0);
glUseProgram(0);
glDisable(GL_BLEND);

Here is the drawFace method in case it's relevant

void GLEngine::drawFace(ModelOBJ::Face &face)
{
if ( (int)face.numVertices <= 3 )
    glBegin(GL_TRIANGLES);
else 
    glBegin(GL_POLYGON);

for ( int v = 0; v < (int)face.numVertices; v++ )
{
    if ( (int)face.numUVWs > v && face.UVWs != NULL )
        glTexCoord2f(face.UVWs[v]->x, face.UVWs[v]->y);

    if ( (int)face.numNormals > v && face.normals != NULL )
        glT开发者_JS百科exCoord3d(face.normals[v]->x, face.normals[v]->y, face.normals[v]->z);

    if ( (int)face.numVertices > v && face.vertices != NULL )
        glVertex3f(face.vertices[v]->x, face.vertices[v]->y, face.vertices[v]->z);
}
glEnd();
}

And here is the shader I am using

Per-fragment Blinn-Phong shader for a single directional light source.

[vert]


varying vec3 normal;

void main()
{
    normal = normalize(gl_NormalMatrix * gl_Normal);

    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
    gl_TexCoord[0] = gl_MultiTexCoord0;    
}

[frag]


uniform sampler2D colorMap;
uniform float materialAlpha;

varying vec3 normal;

void main()
{   
    vec3 n = normalize(normal);

    float nDotL = max(0.0, dot(n, gl_LightSource[0].position.xyz));
    float nDotH = max(0.0, dot(normal, vec3(gl_LightSource[0].halfVector)));
    float power = (nDotL == 0.0) ? 0.0 : pow(nDotH, gl_FrontMaterial.shininess);

    vec4 ambient = gl_FrontLightProduct[0].ambient;
    vec4 diffuse = gl_FrontLightProduct[0].diffuse * nDotL;
    vec4 specular = gl_FrontLightProduct[0].specular * power;
    vec4 color = gl_FrontLightModelProduct.sceneColor + ambient + diffuse + specular;

    gl_FragColor = color * texture2D(colorMap, gl_TexCoord[0].st);
    gl_FragColor.a = materialAlpha;
}

How would you merge all of these functions together? My first thought is to draw all the model.objects with none of the material information and make them transparent. Then run through a second loop and draw all the model.meshes complete with material & using the shader. But then I thought when I start moving game pieces to a new square, how will I make sure the proper shading is applied to the piece's new position. When I select the transparent GroupObject and it translate's to a new square, will the piece still have the proper shading?

What is the best way to fix the problem I am having?


Why do you send your normal as a texture coordinate in GLEngine::drawFace:

glTexCoord3d(face.normals[v]->x, face.normals[v]->y, face.normals[v]->z);

You shader expect it to be as a glNormal3d, as you can see here:

normal = normalize(gl_NormalMatrix * gl_Normal);
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜