2015-09-24 2 views
0

Я пишу современный загрузчик модели openGL и сталкиваюсь с некоторыми проблемами, используя расположение атрибутов шейдера, отличных от 0. Я могу получить атрибут position в шейдере, но не значения, необходимые для Blinn- Фонг-затенение (привязано в программе к местоположениям: 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-ВБО, чтобы в нужном месте, но затенение делает их черным , Вот код вершинного шейдера:

#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; 
} 

пиксельный шейдер выводит черный цвет, если Кд имеет значение (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

Смежные вопросы