OpenGL- GLSL texture() 调用:1282 无效操作
OpenGL- GLSL texture() call: 1282 Invalid Operation
我正在制作一个游戏引擎,其中有一个 class 可以加载 OBJ 模型。 class 本身工作得很好,但是,我遇到的问题是,当我渲染任何带有纹理的模型时,我总是会收到错误 (1282) Invalid Operation。我在代码中尝试了不同的东西,我发现正是片段着色器中的 texture() 调用导致了这个问题。我有一个自定义 class 可以根据打开的单元将纹理移动到纹理单元中,这里是 class:
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() 时,class 将纹理放入一个槽中,returns 它被放入哪个槽中。我在我的 DetailedVAO class 中调用它,它只是在更新材质的制服后渲染 VAO(模型视图矩阵在模型内部处理 class)。它还告诉着色器纹理在哪个纹理单元中,据我所知它会直接绑定纹理。详细的VAOclass是这样的:
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;
}
这可能是您问题的根源:
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
我正在制作一个游戏引擎,其中有一个 class 可以加载 OBJ 模型。 class 本身工作得很好,但是,我遇到的问题是,当我渲染任何带有纹理的模型时,我总是会收到错误 (1282) Invalid Operation。我在代码中尝试了不同的东西,我发现正是片段着色器中的 texture() 调用导致了这个问题。我有一个自定义 class 可以根据打开的单元将纹理移动到纹理单元中,这里是 class:
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() 时,class 将纹理放入一个槽中,returns 它被放入哪个槽中。我在我的 DetailedVAO class 中调用它,它只是在更新材质的制服后渲染 VAO(模型视图矩阵在模型内部处理 class)。它还告诉着色器纹理在哪个纹理单元中,据我所知它会直接绑定纹理。详细的VAOclass是这样的:
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;
}
这可能是您问题的根源:
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