[英]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.