试图在桌面的jogl中绘制带有Gouraud阴影的模型,但它是平的

时间:2017-03-14 01:04:41

标签: java opengl jogl

我已经有一个绘制的模型,但它有平面阴影(据我所知它默认应该是平滑的......)

这是初始配置:

private void SetLightningAndMaterials(){
    //float[] lightPos = {1, 1, 1, 0};
    float[] lightPos = {0, 0, 1, 0};
    float[] lightColorDiffuse = {1, 1, 1, 1};    
    float[] lightColorAmbient = {0.2f, 0.2f, 0.2f, 1};     

    gl.glShadeModel(GL.GL_SMOOTH); 

    gl.glLightfv(GL.GL_LIGHT1, GL.GL_POSITION, lightPos, 0);
    gl.glLightfv(GL.GL_LIGHT1, GL.GL_DIFFUSE, lightColorDiffuse, 0);
    gl.glLightfv(GL.GL_LIGHT1, GL.GL_AMBIENT, lightColorAmbient, 0);        

    gl.glEnable(GL.GL_LIGHT1);
    gl.glEnable(GL.GL_LIGHTING);

    gl.glMaterialfv(GL.GL_FRONT, GL.GL_AMBIENT, ambientColour, 0);   
    gl.glMaterialfv(GL.GL_FRONT, GL.GL_DIFFUSE, mesh.colour, 0);

    gl.glEnable(GL.GL_LIGHTING);   
    gl.glEnable(GL.GL_LIGHT0);
    float[] noAmbient =
    { 0.1f, 0.1f, 0.1f, 1f }; // low ambient light
    float[] spec =
    { 1f, 0.6f, 0f, 1f }; // low ambient light
    float[] diffuse =
    { 0.5f, 0.5f, 0.5f, 1f };
    gl.glLightfv(GL.GL_LIGHT0, GL.GL_AMBIENT, noAmbient, 0);  
    gl.glLightfv(GL.GL_LIGHT0, GL.GL_SPECULAR, spec, 0);  
    gl.glLightfv(GL.GL_LIGHT0, GL.GL_DIFFUSE, diffuse, 0);  
    gl.glLightfv(GL.GL_LIGHT0, GL.GL_POSITION, new float[]{0,0,10,1}, 0);
}

这就是我绘制模型的方式:

public void Draw(GL gl, GLU glu){      
Vec3d normal;
MassPoint vertex1, vertex2, vertex3;
int faceIndex=0;
Face surfaceFace;

for (faceIndex=0; faceIndex<surfaceFaces.size();faceIndex++){
    surfaceFace = surfaceFaces.get(faceIndex);
    surfaceFace.recalculateNormal();
    vertex1 = surfaceFace.vertex1;            
    vertex2 = surfaceFace.vertex2;            
    vertex3 = surfaceFace.vertex3;
    normal = surfaceFace.normal;   

    gl.glBegin(gl.GL_TRIANGLES); 
        gl.glNormal3d(normal.x, normal.y, normal.z);  

        gl.glMaterialfv(GL.GL_FRONT, GL.GL_DIFFUSE, colour, 0);
        gl.glVertex3d(vertex1.position.x, vertex1.position.y, vertex1.position.z);  

        gl.glVertex3d(vertex2.position.x, vertex2.position.y, vertex2.position.z);

        gl.glVertex3d(vertex3.position.x, vertex3.position.y, vertex3.position.z);

    gl.glEnd();               
}   
}   

我想相信有一种简单的方法可以解决这个问题,而无需创建着色器(我不知道如何在Java中设置这些)。 我顺便使用JOGL 1,可能是旧版本(导入类似于javax.media.opengl。*)。

1 个答案:

答案 0 :(得分:0)

我设法解决了这个问题。为了平滑工作,绘图需要3个法线(每个顶点一个),我只传递1个法线(每个面一个)。

以下是绘图的新代码:

public void Draw(GL gl, GLU glu) {      
    Vec3d[] normalsPerVertex = new Vec3d[3];
    MassPoint vertex1, vertex2, vertex3;

    int faceIndex=0;
    Face surfaceFace;
    for (faceIndex=0; faceIndex<surfaceFaces.size();faceIndex++){
        surfaceFace = surfaceFaces.get(faceIndex);
            vertex1=surfaceFace.vertex1;   
            normalsPerVertex[0] = vertex1.CalcNormal();
            vertex2=surfaceFace.vertex2;   
            normalsPerVertex[1] = vertex2.CalcNormal();         
            vertex3=surfaceFace.vertex3;
            normalsPerVertex[2] = vertex3.CalcNormal();

            gl.glBegin(GL.GL_TRIANGLES);  
                gl.glNormal3d(normalsPerVertex[0].x, normalsPerVertex[0].y, normalsPerVertex[0].z);  
                gl.glVertex3d(vertex1.position.x, vertex1.position.y, vertex1.position.z);  

                gl.glNormal3d(normalsPerVertex[1].x, normalsPerVertex[1].y, normalsPerVertex[1].z);  
                gl.glVertex3d(vertex2.position.x, vertex2.position.y, vertex2.position.z);

                gl.glNormal3d(normalsPerVertex[2].x, normalsPerVertex[2].y, normalsPerVertex[2].z);  
                gl.glVertex3d(vertex3.position.x, vertex3.position.y, vertex3.position.z);

            gl.glEnd();  
    }   
} 

每个顶点的计算法线是连接到该顶点的所有面的媒体。这是代码:

public Vec3d CalcNormal() {
    Vec3d normalMedia = new Vec3d();
    for (Face face : facesRelated) {
        face.recalculateNormal();
        normalMedia.add(face.normal);
    }
    normalMedia.mul(1d/facesRelated.size());
    return normalMedia;
}

希望这有助于其他人。