簡體   English   中英

OpenGL VAO多個VBO綁定問題

[英]OpenGL VAO multiple VBO binding issue

我正在編寫現代的openGL模型加載器,並且使用非0的着色器屬性位置遇到了一些問題。我可以將位置屬性添加到着色器中,但不能獲取Blinn-Phong着色所需的值(在程序中綁定到位置:Ks-3,Ka-4,Kd-5)。 這是我用來加載和渲染OBJ模型的代碼:

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為(.64,.64,.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);
    }

}

我找不到問題,但是如果有人可以,那將是很大的幫助。 謝謝!

我沒有詳細介紹您的代碼,但似乎對頂點屬性的工作原理存在基本的誤解。 在頂點着色器中,您具有以下看起來不錯的屬性:

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()類的調用的位置與着色器程序中的屬性位置相匹配。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM