我正在制作游戏引擎,在那里我有一个加载OBJ模型的类。这个类本身运行得很完美,但是,我得到的问题是,当我使用纹理渲染任何模型时,我将始终得到错误(1282)无效操作。我在代码中尝试了不同的东西,我发现它特别是片段着色器中的texture()调用导致了这个问题。我有一个自定义类,根据打开的单位将纹理移动到纹理单元,这是类:
public class GLTextureHandler{
private static ConcurrentHashMap<Integer,Integer> texRef=new ConcurrentHashMap<Integer,Integer>();
public static final int texUnits=GL11.glGetInteger(GL20.GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS);
private static Integer[] inUse=new Integer[texUnits];
static{
for(int i=0;i<inUse.length;i++){
inUse[i]=0;
}
inUse[0]=1;
}
public static void registerTex(int tex){
texRef.put(tex,-1);
}
public static int useTex(int tex){
if(!texRef.containsKey(tex))
registerTex(tex);
int slot=texRef.get(tex);
if(slot!=-1)
return slot;
int cnt=0;
for(int u:inUse){
System.out.println("Checking CNT ("+cnt+"), u is "+u);
if(u==0){
glActiveTexture(GL_TEXTURE0+cnt);
glBindTexture(GL_TEXTURE_2D,tex);
inUse[u]=1;
texRef.put(tex,cnt);
System.out.println("putting in slot "+cnt);
return cnt;
}
cnt++;
}
glActiveTexture(GL_TEXTURE0+texUnits-1);
glBindTexture(GL_TEXTURE_2D,tex);
inUse[texUnits-1]=1;
texRef.put(tex,texUnits-1);
return texUnits-1;
}
public static void openSlot(int tex){
if(!texRef.containsKey(tex))
return;
int slot=texRef.get(tex);
if(slot!=-1)
inUse[slot]=0;
}
public static boolean hasTex(int tex){
return texRef.containsKey(tex);
}
}
当调用useTex()时,类将纹理放入一个槽中,并返回它放入的槽。我在我的DetailedVAO类中调用它,它只是在更新材料的制服后呈现VAO(模型视图矩阵是在模型类中处理)。它还告诉着色器纹理所在的纹理单元,据我所知,它可以直接绑定纹理。详细的VAO类是这样的:
class DetailedVAO{
private Material mtl;
private int vao,ksloc,kaloc,kdloc,texLoc,shinyLoc;
private int texRef;
public DetailedVAO(int vao,Material mtl,int ksloc,int kaloc,int kdloc,int texLoc,int shinyLoc){
this.vao=vao;
this.mtl=mtl;
this.kaloc=kaloc;
this.kdloc=kdloc;
this.ksloc=ksloc;
this.texLoc=texLoc;this.shinyLoc=shinyLoc;
texRef=(mtl.tex()==null?-1:mtl.tex().getTextureID());
GLTextureHandler.registerTex(texRef);
}
public void render(){
Vec3 Ks=(mtl.getKs()==null?new Vec3(1):mtl.getKs());
Vec3 Ka=(mtl.getKa()==null?new Vec3(.5f):mtl.getKa());
Vec3 Kd=(mtl.getKd()==null?new Vec3(1):mtl.getKd());
GL20.glUniform3f(ksloc,Ks.x,Ks.y,Ks.z);
GL20.glUniform3f(kaloc,Ka.x,Ka.y,Ka.z);
GL20.glUniform3f(kdloc,Kd.x,Kd.y,Kd.z);
GL20.glUniform1f(shinyLoc,mtl.getShiny());
int aSlot=GLTextureHandler.useTex(texRef);
GL20.glUniform1f(texLoc,aSlot);
glBindVertexArray(vao);
glDrawArrays(GL_TRIANGLES, 0, Model.fvaoSize/4);
}
}
顶点着色器:
#version 330
in vec4 position;
in vec3 normals;
in vec2 texCoords;
uniform mat4 view;
uniform mat4 projection;
uniform mat4 model;
uniform mat4 normal;
uniform vec3 u_lightPosition;
uniform vec3 u_cameraPosition;
uniform vec3 Ks;
uniform vec3 Ka;
uniform vec3 Kd;
out vec3 o_normal;
out vec3 o_toLight;
out vec3 o_toCamera;
out vec2 o_texcoords;
void main()
{
vec4 worldPosition=model*position;
o_normal = normalize(mat3(normal) * normals);
// direction to light
o_toLight = normalize(u_lightPosition - worldPosition.xyz);
// direction to camera
o_toCamera = normalize(u_cameraPosition - worldPosition.xyz);
// texture coordinates to fragment shader
o_texcoords = texCoords;
gl_Position=projection*view*worldPosition;
}
如果我只使用Blinn-Phong值,片段着色器可以工作:
#version 330
out vec4 outputColor;
uniform vec4 color;
uniform mat4 view;
uniform mat4 projection;
uniform mat4 model;
uniform vec3 u_lightAmbientIntensitys; // = vec3(0.6, 0.3, 0);
uniform vec3 u_lightDiffuseIntensitys; // = vec3(1, 0.5, 0);
uniform vec3 u_lightSpecularIntensitys; // = vec3(0, 1, 0);
// parameters of the material and possible values
uniform vec3 u_matAmbientReflectances; // = vec3(1, 1, 1);
uniform vec3 u_matDiffuseReflectances; // = vec3(1, 1, 1);
uniform vec3 u_matSpecularReflectances; // = vec3(1, 1, 1);
uniform float u_matShininess;
uniform sampler2D u_diffuseTexture;
uniform vec3 Ks;
uniform vec3 Ka;
uniform vec3 Kd;
in vec3 o_normal;
in vec3 o_toLight;
in vec3 o_toCamera;
in vec2 o_texcoords;
vec3 ambientLighting()
{
return Ka * u_lightAmbientIntensitys;
}
// returns intensity of diffuse reflection
vec3 diffuseLighting(in vec3 N, in vec3 L)
{
// calculation as for Lambertian reflection
float diffuseTerm = clamp(dot(N, L), 0, 1) ;
return Kd * u_lightDiffuseIntensitys * diffuseTerm;
}
// returns intensity of specular reflection
vec3 specularLighting(in vec3 N, in vec3 L, in vec3 V)
{
float specularTerm = 0;
// calculate specular reflection only if
// the surface is oriented to the light source
if(dot(N, L) > 0)
{
// half vector
vec3 H = normalize(L + V);
specularTerm = pow(dot(N, H), u_matShininess);
}
return Ks * u_lightSpecularIntensitys * specularTerm;
}
void main(void)
{
// normalize vectors after interpolation
vec3 L = normalize(o_toLight);
vec3 V = normalize(o_toCamera);
vec3 N = normalize(o_normal);
// get Blinn-Phong reflectance components
vec3 Iamb = ambientLighting();
vec3 Idif = diffuseLighting(N, L);
vec3 Ispe = specularLighting(N, L, V);
// diffuse color of the object from texture
vec3 diffuseColor = vec3(texture(u_diffuseTexture, o_texcoords.xy));
// combination of all components and diffuse color of the object
outputColor.xyz = diffuseColor*(Iamb+Ispe+Idif);
outputColor.a = 1;
}
答案 0 :(得分:1)
这可能是您遇到问题的根源:
GL20.glUniform1f(texLoc,aSlot);
应该是
GL20.glUniform1i(texLoc,aSlot); // i not f
编辑:我没有仔细阅读有关设置glActiveTexture的代码。我的评论是错误的。
您没有解开您的VAO:
glBindVertexArray(vao);
glDrawArrays(GL_TRIANGLES, 0, Model.fvaoSize/4);
glBindVertexArray( 0 ); // <- Probably want this