有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java试图在jogl中为桌面绘制一个带有Gouraud着色的模型,但它是平面的

我已经绘制了一个模型,但它有平面着色(据我所知,默认情况下应该是平滑的…)

这是初始配置:

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) 个答案

  1. # 1 楼答案

    我设法解决了这个问题。为了使平滑度发挥作用,绘图需要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;
    }
    

    希望这对其他人有帮助