【问题标题】:OpenGL- GLSL texture() call: 1282 Invalid OperationOpenGL-GLSL 纹理()调用:1282 无效操作
【发布时间】:2015-10-27 23:23:57
【问题描述】:

我正在制作一个游戏引擎,其中我有一个加载 OBJ 模型的类。该类本身运行良好,但是,我遇到的问题是,当我使用纹理渲染任何模型时,我总是会收到错误 (1282) Invalid Operation。我在代码中尝试了不同的东西,我发现正是片段着色器中的 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;
}

【问题讨论】:

  • 你从哪里得到INVALID_OPERATION - 你有没有移动你的glGetError?有点奇怪。关于片段着色器,我得到的唯一想法是像这样替换纹理查找:vec3 diffuseColor = texture(u_diffuseTexture, o_texcoords.xy).rgb;
  • 是的,请在每个 opengl调用后检查glGetError(如果需要,请将其放在#ifdef _DEBUG括号中)。
  • 我启用了调试选项,所以每次调用后都会调用它。就像我在帖子中所说的那样,删除 texture() 可以解决问题。 @St0fF,我也试过了,同样的错误。感谢您的关注!
  • 好吧,我不知道这个组合。对我来说,普通的 OpenGL 是 C/C++。您必须在那里拨打glGetError 电话。特别是我很困惑,您可以将错误处理到片段着色器中。所以现在我只假设glDrawArrays 抛出了错误。它不会在没有纹理的情况下出现 - 您是否正确设置了所有必要的纹理参数? GL_MIN_FILTERGL_MAG_FILTERGL_TEXTURE_WRAP_SGL_TEXTURE_WRAP_T?
  • 如果您使用某种调试选项,它应该真正告诉您哪个 OpenGL 调用触发了错误。否则它将毫无用处,您最好自己拨打glGetError()。缩小错误的来源真的很容易。一旦你这样做了,就会很明显是什么原因造成的。

标签: java opengl glsl textures lwjgl


【解决方案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
    

【讨论】:

  • 如果你仔细看代码,你会发现使用最后一个纹理槽是为了当所有其他纹理单元都被填充时。不过关闭。
猜你喜欢
  • 2015-09-28
  • 1970-01-01
  • 1970-01-01
  • 2018-08-24
  • 2015-03-20
  • 2013-10-05
  • 1970-01-01
  • 2019-12-10
  • 1970-01-01
相关资源
最近更新 更多