在OpenGL管道之前:我想为我渲染的某些对象使用特殊的顶点着色器。所以我想这个:OpenGL:为着色器创建代理用户
int currProgram = glGetInteger(GL_CURRENT_PROGRAM);
int currVertexShader = 0;
if (currProgram == 0) {
glUseProgram(programName);
} else {
currVertexShader = GLStatics.getShader(currProgram,
GL_VERTEX_SHADER);
if (currVertexShader != 0) {
glDetachShader(currProgram, currVertexShader); // <-- problem here
}
glAttachShader(currProgram, shaderName);
GLStatics.linkProgramSafe(currProgram);
}
// Actual render code
if (currProgram != 0) {
glDetachShader(currProgram, shaderName); // Can safely detach
if (currVertexShader != 0) {
glAttachShader(currProgram, currVertexShader);
}
GLStatics.linkProgramSafe(currProgram);
}
glUseProgram(currProgram);
所以我要静GLObjects:shaderName
,这是编译顶点着色器我想使用programName
这是我绑定,如果没有其他程序势必beforehands程序。
我以为这会运行良好时,真的有问题。在执行代码之前,在当前绑定程序的顶点着色器上调用glDeleteShader()时,着色器对象将被删除(在标记的行中),并且之后无法重新附加。
有没有一种简单的方法来解决这个问题(在高效的意义上容易)?
为了完整起见,GLStatics
类:
public class GLStatics {
public static ByteBuffer createDirectBuffer(int size) {
return ByteBuffer.allocateDirect(size);
}
public static int createProgramSafe() {
int programName = glCreateProgram();
if (programName == 0) {
throw new IllegalStateException(
"GL Error: Created Program is 0. Can't proceed.");
}
return programName;
}
public static int getShader(int program, int searchedType) {
int shaderCount = glGetProgrami(program, GL_ATTACHED_SHADERS);
IntBuffer attachedShaders = createDirectBuffer(shaderCount * 4)
.asIntBuffer();
IntBuffer count = createDirectBuffer(4).asIntBuffer();
glGetAttachedShaders(program, count, attachedShaders);
assert count.get() == shaderCount;
for (int i = 0; i < shaderCount; ++i) {
int shaderCandidate = attachedShaders.get();
if (searchedType == glGetShaderi(shaderCandidate, GL_SHADER_TYPE)) {
return shaderCandidate;
}
}
return 0;
}
public static void linkProgramSafe(int program) {
glLinkProgram(program);
if (glGetProgrami(program, GL_LINK_STATUS) == GL_FALSE) {
int errorLength = glGetProgrami(program, GL_INFO_LOG_LENGTH);
String error = glGetProgramInfoLog(program, errorLength);
throw new IllegalStateException(error);
}
}
}
附加着色器就够了,我没有链接它?你知道比没有它慢多少? – WorldSEnder
是的,附加就够了。我在答案中增加了一些更详细的说明。增加的开销应该是最小的。这不是你想要在一个紧密的循环中做的事情,但是你要用相同的代码连接一个着色器程序,这可能是数量级更昂贵的。 –