2015-09-24 80 views
0

我正在寫一個現代化的openGL模型加載器,並且正在使用除0以外的着色器屬性位置運行一些問題。我可以將位置屬性置入着色器中,但不能獲得Blinn- Phong陰影(在程序中綁定到位置:Ks-3,Ka-4,Kd-5)。下面是我使用的加載和渲染OBJ機型代碼:OpenGL VAO多個VBO綁定問題

public class Model{ 
private List<Vector3f> vertices=new ArrayList<>(); 
private List<Vector3f> normals=new ArrayList<>(); 

private ArrayList<Integer> vaos=new ArrayList<>(); 
private float[] faces=new float[fvaoSize]; 
private float[] ks=new float[kvaoSize]; 
private float[] ka=new float[kvaoSize]; 
private float[] kd=new float[kvaoSize]; 
private int currentPlace=0,kcurrentPlace=0; 
private static final int fvaoSize=glGetInteger(GL12.GL_MAX_ELEMENTS_VERTICES)-(glGetInteger(GL12.GL_MAX_ELEMENTS_VERTICES)%12); 
private static final int kvaoSize=(fvaoSize/4)*3; 
private int facesd=0; 
private HashMap<String,Material> materials=new HashMap<>(); 

@SuppressWarnings("unused") 
private int plainFaceVAO=0,texFaceVAO=0,normalsFaceVAO=0,normalsTexVAO=0; 
@SuppressWarnings("unused") 
private int faceOffset=0, 
     texOffset=0,texTexture=0,texCoords=0, 
     normalOffset=0,normalCoords=0, 
     normalTexOffset=0,normalTexNormalCoords,normalTexTexCoords,normalTexTexture=0; 
@SuppressWarnings("unused") 
private Shader faceShader=null,texShader=null,normalsShader=null,normalTexShader=null; 
private Material currMtl=null; 

public Model(File f,Shader faceShader,Shader texShader,Shader normalsShader,Shader normalTexShader){ 
    loadModelData(f); 
    this.faceShader=faceShader; 
    this.texShader=texShader; 
    this.normalsShader=normalsShader; 
    this.normalTexShader=normalTexShader; 
    faceOffset=glGetUniformLocation(faceShader.getID(),"trans"); 
    texOffset=glGetUniformLocation(texShader.getID(),"trans"); 
    texTexture=glGetAttribLocation(texShader.getID(),"tex"); 
    texCoords=glGetAttribLocation(texShader.getID(),"texCoords"); 
    normalOffset=glGetUniformLocation(normalsShader.getID(),"trans"); 
    normalCoords=glGetAttribLocation(normalsShader.getID(),"normalsCoords"); 
} 
@SuppressWarnings("null") 
private void loadModelData(File f){ 
    try(BufferedReader br=new BufferedReader(new FileReader(f))){ 
     String line=""; 
     while((line=br.readLine())!=null){ 
      String[] words=line.split(" "); 
      //System.out.println(line); 
      if(line.startsWith("#")) 
       continue; 
      switch(words[0]){ 
       case OBJ_VERTEX: 
        vertices.add(new Vector3f(parseFloat(words[1]),parseFloat(words[2]),-parseFloat(words[3]))); 
        break; 
       case OBJ_VERTEX_NORMAL: 
        normals.add(new Vector3f(parseFloat(words[1]),parseFloat(words[2]),-parseFloat(words[3]))); 
        break; 
       case OBJ_FACE: 
        facesd++; 
        FaceType cft=null; 
        int slashCount=0; 
        for(char c:words[1].toCharArray()){ 
         if(c=='/') 
          slashCount++; 
        } 

        if(slashCount==0){ 
         cft=FaceType.COORDSONLY; 
        }else if(slashCount==1){ 
         cft=FaceType.TEXTURE; 
        }else if(slashCount==2){ 
         if(words[0].contains("//")){ 
          cft=FaceType.NORMALS; 
         }else{ 
          cft=FaceType.NORMALS_AND_TEXTURE; 
         } 
        } 
        switch(cft){ 
         case COORDSONLY: 
          Vector3f pos1=vertices.get(Integer.parseInt(words[1])-1); 
          Vector3f pos2=vertices.get(Integer.parseInt(words[2])-1); 
          Vector3f pos3=vertices.get(Integer.parseInt(words[3])-1); 
          Vec3 Ks=(currMtl.getKs()!=null?currMtl.getKs():new Vec3(1)); 
          Vec3 Ka=(currMtl.getKa()!=null?currMtl.getKa():new Vec3(1)); 
          Vec3 Kd=(currMtl.getKd()!=null?currMtl.getKd():new Vec3(1)); 
          float[] temp=new float[] 
           { 
            pos1.x,pos1.y,pos1.z,1.0f, 
            pos2.x,pos2.y,pos2.z,1.0f, 
            pos3.x,pos3.y,pos3.z,1.0f 
           }; 
          for(int i=0;i<12;i++){ 
           faces[currentPlace+i]=temp[i]; 
          } 
          float[] ktemp=new float[] 
           { 
            Ks.x,Ks.y,Ks.z, 
            Ks.x,Ks.y,Ks.z, 
            Ks.x,Ks.y,Ks.z 
           }; 
          for(int i=0;i<9;i++){ 
           ks[kcurrentPlace+i]=ktemp[i]; 
          } 
          ktemp=new float[] 
           { 
            Ka.x,Ka.y,Ka.z, 
            Ka.x,Ka.y,Ka.z, 
            Ka.x,Ka.y,Ka.z 
           }; 
          for(int i=0;i<9;i++){ 
           ka[kcurrentPlace+i]=ktemp[i]; 
          } 
          ktemp=new float[] 
           { 
            Kd.x,Kd.y,Kd.z, 
            Kd.x,Kd.y,Kd.z, 
            Kd.x,Kd.y,Kd.z 
           }; 
          for(int i=0;i<9;i++){ 
           kd[kcurrentPlace+i]=ktemp[i]; 
          } 
          kcurrentPlace+=9; 
          currentPlace+=12; 
          if(currentPlace==fvaoSize){ 


           int fvbo=glGenBuffers(); 
           FloatBuffer vertexPositionsBuffer=BufferUtils.createFloatBuffer(fvaoSize); 
           vertexPositionsBuffer.put(faces); 
           vertexPositionsBuffer.flip(); 
           glBindBuffer(GL_ARRAY_BUFFER, fvbo); 
           glBufferData(GL_ARRAY_BUFFER, vertexPositionsBuffer, GL_STATIC_DRAW); 

           int ksvbo=glGenBuffers(); 
           FloatBuffer ksBuffer=BufferUtils.createFloatBuffer(kvaoSize); 
           ksBuffer.put(ks); 
           ksBuffer.flip(); 
           glBindBuffer(GL_ARRAY_BUFFER, ksvbo); 
           glBufferData(GL_ARRAY_BUFFER, ksBuffer, GL_STATIC_DRAW); 

           int kavbo=glGenBuffers(); 
           FloatBuffer kaBuffer=BufferUtils.createFloatBuffer(kvaoSize); 
           kaBuffer.put(ka); 
           kaBuffer.flip(); 
           glBindBuffer(GL_ARRAY_BUFFER, kavbo); 
           glBufferData(GL_ARRAY_BUFFER, kaBuffer, GL_STATIC_DRAW); 

           int kdvbo=glGenBuffers(); 
           FloatBuffer kdBuffer=BufferUtils.createFloatBuffer(kvaoSize); 
           kdBuffer.put(kd); 
           kdBuffer.flip(); 
           glBindBuffer(GL_ARRAY_BUFFER, kdvbo); 
           glBufferData(GL_ARRAY_BUFFER, kdBuffer, GL_STATIC_DRAW); 

           int vao = glGenVertexArrays(); 
           glBindVertexArray(vao); 

           glBindBuffer(GL_ARRAY_BUFFER, fvbo); 
           glVertexAttribPointer(0, 4, GL_FLOAT, false, 0, 0); 

           glBindBuffer(GL_ARRAY_BUFFER, ksvbo); 
           glVertexAttribPointer(3, 3, GL_FLOAT, false, 0, 0); 

           glBindBuffer(GL_ARRAY_BUFFER, kavbo); 
           glVertexAttribPointer(4, 3, GL_FLOAT, false, 0, 0); 

           glBindBuffer(GL_ARRAY_BUFFER, kdvbo); 
           glVertexAttribPointer(5, 3, GL_FLOAT, false, 0, 0); 

           glEnableVertexAttribArray(0); 
           glEnableVertexAttribArray(3); 
           glEnableVertexAttribArray(4); 
           glEnableVertexAttribArray(5); 

           glBindVertexArray(0); 

           glDeleteBuffers(fvbo); 
           glDeleteBuffers(ksvbo); 
           glDeleteBuffers(kavbo); 
           glDeleteBuffers(kdvbo); 
           ksBuffer=null; 
           kaBuffer=null; 
           kdBuffer=null; 
           vertexPositionsBuffer=null; 
           vaos.add(vao); 

           glBindBuffer(GL_ARRAY_BUFFER, 0); 
           currentPlace=0; 
           kcurrentPlace=0; 
           faces=new float[fvaoSize]; 
           ks=new float[kvaoSize]; 
           ka=new float[kvaoSize]; 
           kd=new float[kvaoSize]; 
          } 
          break; 
         case NORMALS: 
          throw new RuntimeException("File is unsupported."); 
         case NORMALS_AND_TEXTURE: 
          throw new RuntimeException("File is unsupported."); 
         case TEXTURE: 
          throw new RuntimeException("File is unsupported."); 
         default: 
          throw new RuntimeException("File is unsupported."); 
        } 

        break; 
       case OBJ_MTLLIB: 
        materials=MTLLibLoader.loadMTLLib(f.toPath().getParent()+"/"+words[1]); 
        break; 
       case OBJ_USEMTL: 
        System.out.println("Using Material "+words[1]+": Exists in hmap: "+materials.containsKey(words[1])); 
        currMtl=materials.get(words[1]); 
        break; 
       default: 
        break; 
      } 
     } 
     int fvbo=glGenBuffers(); 
     FloatBuffer vertexPositionsBuffer=BufferUtils.createFloatBuffer(fvaoSize); 
     vertexPositionsBuffer.put(faces); 
     vertexPositionsBuffer.flip(); 
     glBindBuffer(GL_ARRAY_BUFFER, fvbo); 
     glBufferData(GL_ARRAY_BUFFER, vertexPositionsBuffer, GL_STATIC_DRAW); 

     int ksvbo=glGenBuffers(); 
     FloatBuffer ksBuffer=BufferUtils.createFloatBuffer(kvaoSize); 
     ksBuffer.put(ks); 
     ksBuffer.flip(); 
     glBindBuffer(GL_ARRAY_BUFFER, ksvbo); 
     glBufferData(GL_ARRAY_BUFFER, ksBuffer, GL_STATIC_DRAW); 

     int kavbo=glGenBuffers(); 
     FloatBuffer kaBuffer=BufferUtils.createFloatBuffer(kvaoSize); 
     kaBuffer.put(ka); 
     kaBuffer.flip(); 
     glBindBuffer(GL_ARRAY_BUFFER, kavbo); 
     glBufferData(GL_ARRAY_BUFFER, kaBuffer, GL_STATIC_DRAW); 

     int kdvbo=glGenBuffers(); 
     FloatBuffer kdBuffer=BufferUtils.createFloatBuffer(kvaoSize); 
     kdBuffer.put(kd); 
     kdBuffer.flip(); 
     glBindBuffer(GL_ARRAY_BUFFER, kdvbo); 
     glBufferData(GL_ARRAY_BUFFER, kdBuffer, GL_STATIC_DRAW); 

     int vao = glGenVertexArrays(); 
     glBindVertexArray(vao); 

     glBindBuffer(GL_ARRAY_BUFFER, fvbo); 
     glVertexAttribPointer(0, 4, GL_FLOAT, false, 0, 0); 

     glBindBuffer(GL_ARRAY_BUFFER, ksvbo); 
     glVertexAttribPointer(3, 3, GL_FLOAT, false, 0, 0); 

     glBindBuffer(GL_ARRAY_BUFFER, kavbo); 
     glVertexAttribPointer(4, 3, GL_FLOAT, false, 0, 0); 

     glBindBuffer(GL_ARRAY_BUFFER, kdvbo); 
     glVertexAttribPointer(5, 3, GL_FLOAT, false, 0, 0); 

     glEnableVertexAttribArray(0); 
     glEnableVertexAttribArray(3); 
     glEnableVertexAttribArray(4); 
     glEnableVertexAttribArray(5); 

     glBindVertexArray(0); 

     glDeleteBuffers(fvbo); 
     glDeleteBuffers(ksvbo); 
     glDeleteBuffers(kavbo); 
     glDeleteBuffers(kdvbo); 
     ksBuffer=null; 
     kaBuffer=null; 
     kdBuffer=null; 
     vertexPositionsBuffer=null; 
     vaos.add(vao); 

     glBindBuffer(GL_ARRAY_BUFFER, 0); 
    }catch(FileNotFoundException e){ 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    }catch(IOException e){ 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 
    System.out.println("Object \""+f.getName().substring(0,f.getName().lastIndexOf("."))+"\" loaded, has "+facesd+" faces"); 
} 
public void drawModel(Camera c,Vec3 offset){ 
    //System.err.format("rendering model, %d vaos\n",vaos.size()); 
    //Matrix4f modelMat=RenderMatrixHelper.getModelMatrix(offset,new Vec3(0)); 

    faceShader.useShader(); 
    c.useCameraView(); 
    glUniform4f(faceOffset,offset.x,offset.y,offset.z,0f); 
    for(Integer i:vaos){ 
     glBindVertexArray(i); 
     glDrawArrays(GL_TRIANGLES, 0, fvaoSize/4); 
    } 
    Shader.stopShader(); 
    glBindVertexArray(0); 
} 
public int getNumFaces(){ 
    return facesd; 
} 
private enum FaceType{ 
    COORDSONLY, 
    TEXTURE, 
    NORMALS, 
    NORMALS_AND_TEXTURE, 
} 

}

我想我已經正確綁定的K-VBO的正確的位置,但着色器渲染他們爲黑色。這裏是頂點着色器代碼:

#version 330 

in vec4 position; 
in vec3 normals; 
in vec2 texCoords; 


uniform vec4 trans; 

uniform mat4 view; 
uniform mat4 projection; 
uniform mat4 model; 

void main() 
{ 
    gl_Position = projection*view* (position+trans);//-camera_position; 
} 

如果Kd的值爲(0,0,0),則片段着色器輸出黑色,否則輸出白色。在我的代碼,我已經確認並知道Kd爲(0.64,0.64,0.64) 而片段着色器:

#version 330 
out vec4 outputColor; 

in vec3 Ks; 
in vec3 Ka; 
in vec3 Kd; 

uniform mat4 view; 
uniform mat4 projection; 

void main() 
{ 
    if(Kd==vec3(0f)){ 
     outputColor=vec4(0f); 
    }else{ 
     outputColor=vec4(1f); 
    } 

} 

我無法找到問題,但如果任何人都可以這將是非常有幫助。謝謝!

回答

4

我沒有仔細看過你的代碼,但似乎有一個關於頂點屬性如何工作的基本誤解。在頂點着色器,你有這些屬性,這看起來不錯:

in vec4 position; 
in vec3 normals; 
in vec2 texCoords; 

但隨後在片段着色器,你有這些定義:

in vec3 Ks; 
in vec3 Ka; 
in vec3 Kd; 

基於代碼,它看起來像你」重新計劃將它們用作頂點屬性。這不起作用。您不能將頂點屬性直接送入片段着色器。它們需要在頂點着色器中爲in變量。如果需要片段着色器中的(插值)值,則需要使用頂點着色器中的out變量和片段着色器中的in變量將它們從頂點着色器傳遞到片段着色器。

如果你做錯誤檢查,我很驚訝你的着色器程序甚至鏈接。片段着色器中的in變量(至少與代碼中使用的變量一樣)需要在頂點着色器中具有匹配的out變量。爲Kd

當然,如果你的材質屬性至少對於單個對象是恆定的,你也可以讓它們制服而不是屬性。

一旦您遇到更基本的問題,另一個需要注意的方面是屬性的位置。對於材質屬性,您的值爲3,4和5。您將需要在着色器代碼中使用諸如glGetAttribLocation()glSetAttribLocation()location限定符之類的調用,以確保用於諸如glVertexAttribPointer()等調用的位置與着色器程序中的屬性位置相匹配。

+0

儘管問題實際上是**編譯器將它們優化出來**,但我仍然學到了一些東西,並且我相信其他人可以從中受益。 +1,謝謝! – johnnic431