GLSL 着色器未编译,没有错误消息
Posted
技术标签:
【中文标题】GLSL 着色器未编译,没有错误消息【英文标题】:GLSL Shader not Compiling, no Error Message 【发布时间】:2015-02-11 22:17:03 【问题描述】:我正在尝试使用我从 LWJGL 编写的 GLSL 着色器。它只是一个简单的基于片段的 phong 着色器。着色器过去运行良好,即使在这台计算机上也是如此。前几天,突然间,它无缘无故地停止了编译。当我尝试编译它并检查信息日志时,我收到以下消息:
Exception in thread "Thread-1" org.lwjgl.opengl.OpenGLException: Invalid value (1281)
at org.lwjgl.opengl.Util.checkGLError(Util.java:59)
at org.lwjgl.opengl.GL20.glGetShaderi(GL20.java:542)
at aspect.render.shader.ShaderProgram.getLogInfo(ShaderProgram.java:161)
at aspect.render.shader.ShaderProgram.<init>(ShaderProgram.java:69)
at aspect.render.shader.ShaderProgram.loadPrebuilt(ShaderProgram.java:168)
at aspect.core.AspectLauncher$1.run(AspectLauncher.java:143)
我的 OpenGL 信息:
GL VENDOR: Intel
GL RENDERER: Intel(R) HD Graphics 3000
GL VERSION: 3.1.0 - Build 9.17.10.3347
GLSL VERSION: 1.40 - Intel Build 9.17.10.3347
这是着色器本身:
顶点:
#version 140
uniform int numLights;
uniform bool useLighting;
varying vec3 normal;
varying vec3 ambient;
varying vec3 color;
varying vec3 diffuse[8];
varying vec3 lightDir[8];
varying vec3 dist[8];
varying vec2 texCoord;
void main()
vec4 position = gl_ModelViewMatrix * gl_Vertex;
gl_Position = gl_ProjectionMatrix * position;
normal = normalize(gl_NormalMatrix * gl_Normal);
texCoord = gl_MultiTexCoord0.st;
color = gl_Color.rgb;
ambient = gl_FrontMaterial.emission.rgb + gl_LightModel.ambient.rgb * gl_FrontMaterial.ambient.rgb;
if (useLighting)
for (int i = 0; i < numLights; i++)
float diffuseIntensity;
if (gl_LightSource[i].position.w != 0.0)
vec3 toLight = (gl_LightSource[i].position - position).xyz;
dist[i] = toLight;
lightDir[i] = normalize(toLight);
diffuseIntensity = dot(normalize(toLight), normal);
else
lightDir[i] = normalize(gl_LightSource[i].position.xyz);
diffuseIntensity = dot(normalize(gl_LightSource[i].position.xyz), normal);
diffuseIntensity = max(diffuseIntensity, 0.0);
diffuse[i] = gl_FrontMaterial.diffuse.rgb * gl_LightSource[i].diffuse.rgb * diffuseIntensity;
片段:
#version 140
uniform bool useTexture;
uniform bool useLighting;
uniform sampler2D tex;
uniform int numLights;
varying vec3 normal;
varying vec3 ambient;
varying vec3 color;
varying vec3 diffuse[8];
varying vec3 lightDir[8];
varying vec3 dist[8];
varying vec2 texCoord;
void main()
vec4 texColor;
if (useTexture)
texColor = texture2D(tex, texCoord);
else
texColor = vec4(1.0);
if (texColor.a == 0.0)
discard;
else
texColor.a = 1.0;
vec3 lightColor;
if (useLighting)
lightColor = ambient;
for (int i = 0; i < numLights; i++)
float specularIntensity;
float att = 1.0;
if (gl_LightSource[i].position.w != 0.0)
float dist = length(dist[i]);
att = 1.0 / (gl_LightSource[i].constantAttenuation +
gl_LightSource[i].linearAttenuation * dist +
gl_LightSource[i].quadraticAttenuation * dist * dist);
vec3 halfVector = normalize(lightDir[i]) + vec3(0.0, 0.0, 1.0);
specularIntensity = dot(normalize(halfVector), normalize(normal));
else
vec3 halfVector = normalize(lightDir[i]) + vec3(0.0, 0.0, 1.0);
specularIntensity = dot(normalize(halfVector), normalize(normal));
specularIntensity = max(specularIntensity, 0.0);
lightColor += diffuse[i] * att;
lightColor += gl_FrontMaterial.specular.rgb * gl_LightSource[i].specular.rgb * pow(specularIntensity, gl_FrontMaterial.shininess) * att;
else
lightColor = color;
gl_FragColor = texColor * vec4(lightColor, 1.0);
最后,我加载着色器的代码:
public class ShaderProgram
private final int programID;
public ShaderProgram(int programID)
this.programID = programID;
public ShaderProgram(Shader... shaders)
int id;
try
id = glCreateProgram();
catch (Exception ex)
Logger.getLogger(ShaderProgram.class.getName()).log(Level.SEVERE, null, ex);
programID = 0;
return;
for (Shader shader : shaders)
glAttachShader(id, shader.id);
glLinkProgram(id);
if (glGetProgrami(id, GL_LINK_STATUS) == GL_FALSE)
System.err.println(getLogInfo(id)); // This is the line that causes the error. It actually throws an exception (doesn't just print error info)
programID = 0;
return;
glValidateProgram(id);
if (glGetProgrami(id, GL_VALIDATE_STATUS) == GL_FALSE)
System.err.println(getLogInfo(id));
programID = 0;
return;
programID = id;
public static String getLogInfo(int obj)
return glGetShaderInfoLog(obj, glGetShaderi(obj, GL_INFO_LOG_LENGTH));
public static ShaderProgram loadPrebuilt(String name)
Shader vert = Shader.loadPrebuilt(name + ".vert", Shader.Type.VERTEX);
Shader frag = Shader.loadPrebuilt(name + ".frag", Shader.Type.FRAGMENT);
return new ShaderProgram(vert, frag);
这是单个着色器文件(片段或顶点)的类
public class Shader
public final int id;
public Shader(int id)
this.id = id;
public Shader(File file, Shader.Type type)
int shader = 0;
try
shader = create(readIntoString(new FileInputStream(file)), type);
catch (IOException ex)
Logger.getLogger(Shader.class.getName()).log(Level.SEVERE, null, ex);
id = shader;
public Shader (String program, Shader.Type type)
id = create(program, type);
public static Shader loadPrebuilt(String name, Shader.Type type)
try
return new Shader(readIntoString(name), type);
catch (IOException | URISyntaxException ex)
Logger.getLogger(ShaderProgram.class.getName()).log(Level.SEVERE, null, ex);
return new Shader(0);
private int create(String program, Type type)
int shader = 0;
try
shader = glCreateShader(type.glType);
glShaderSource(shader, program);
glCompileShader(shader);
if (glGetShaderi(shader, GL_COMPILE_STATUS) == GL_FALSE)
System.err.println("Error creating shader (" + type.name() + "): " + getLogInfo(shader));
catch (Exception ex)
glDeleteShader(shader);
Logger.getLogger(ShaderProgram.class.getName()).log(Level.SEVERE, null, ex);
shader = 0;
return shader;
private static String readIntoString(String filename) throws IOException, URISyntaxException
InputStream stream = Shader.class.getResourceAsStream(filename);
return readIntoString(stream);
private static String readIntoString(InputStream stream) throws IOException
String version = glGetString(GL_SHADING_LANGUAGE_VERSION);
version = version.substring(0, version.indexOf(" ")).replaceFirst("\\.", "");
return "#version " + version + "\n\n" + loadTextFile(stream);
失败的行是这样的:
ShaderProgram.loadPrebuilt("phong");
文件加载得很好。如果我打印它,它会打印出我想要的内容,并且在我尝试获取 ShaderProgram.java 中的日志信息之前它不会失败
【问题讨论】:
我敢打赌,问题不是与您的着色器有关,但这恰好是您下次检查 GL 错误时。 @immibis 如果我尝试更早地获取日志信息,那么无论如何它都会失败。我的其他着色器编译得很好,只是这个没有。此行仅在 glGetProgrami(id, GL_LINK_STATUS) == GL_FALSE 时运行,因此发生异常时程序已经编译失败。异常本身似乎是由于从无效着色器程序获取日志引起的,因为由于某种原因 glLinkProgram(id) 无法正常工作。 【参考方案1】:在ShaderProgram
构造函数中的这段代码序列中:
if (glGetProgrami(id, GL_LINK_STATUS) == GL_FALSE)
System.err.println(getLogInfo(id));
id
是一个程序 id。你将它传递给getLogInfo()
方法:
public static String getLogInfo(int obj)
return glGetShaderInfoLog(obj, glGetShaderi(obj, GL_INFO_LOG_LENGTH));
glGetShaderInfoLog()
和 glGetShaderi()
都期望 shader id 作为第一个参数。要获取有关程序的信息,您需要使用相应的程序调用:
public static String getLogInfo(int obj)
return glGetProgramInfoLog(obj, glGetProgrami(obj, GL_INFO_LOG_LENGTH));
【讨论】:
哇,有道理。就像你说的那样,我在 ShaderProgram 类中更改了我的 getLogInfo 方法(并为 Shader 创建了一个新方法)。现在我实际上可以看到我的着色器出了什么问题(它说没有足够的空间来定义变量)所以我想我现在会查一下。以上是关于GLSL 着色器未编译,没有错误消息的主要内容,如果未能解决你的问题,请参考以下文章
从 C++ 运行 GLSL 着色器(尚未编译)的最快捷方式是啥?
Xcode 7 / iOS 9:在 SKNode 中使用 OpenGL 片段着色器未编译