我一直在尝试使用着色器存储缓冲区对象(SSBO)与opengl 4.3核心一段时间,但甚至不能让我的着色器程序链接
下面是我的顶点着色器的代码
# version 430 core
in vec3 vertex;
uniform mat4
perspectiveMatrix,
viewMatrix,
modelMatrix;
in vec3 normal;
out vec3 lightVectors[3];
out vec3 vertexNormal;
out vec3 cameraVector;
layout(std430,binding=1)buffer Lights
{
vec3 positions[3];
vec3 attenuations[3];
vec3 colors[3];
}buf1;
void main()
{
vec4 worldVertex=modelMatrix*vec4(vertex,1.0);
gl_Position=perspectiveMatrix*viewMatrix*worldVertex;
vertexNormal=(modelMatrix*vec4(normal,0)).xyz;
for(int i=0;i<3;i++){
lightVectors[i]=buf1.positions[i]-worldVertex.xyz;
}
cameraVector=(inverse(viewMatrix)*vec4(0,0,0,1)).xyz-worldVertex.xyz;
}
这是我的片段着色器的代码
# version 430 core
in vec3 vertexNormal;
in vec3 cameraVector;
in vec3 lightVectors[3];
out vec4 pixelColor;
layout(std430,binding=1)buffer Lights
{
vec3 positions[3];
vec3 attenuations[3];
vec3 colors[3];
}buf2;
uniform Material
{
vec3 diffuseMat;
vec3 specularMat;
float reflectivity;
float shininess;
};
float getAtten(int i)
{
float l=length(lightVectors[i]);
float atten=(buf2.attenuations[i].x*l)
+((buf2.attenuations[i].y)*(l*l))
+((buf2.attenuations[i].z)*(l*l*l));
return atten;
}
vec3 computeLightColor()
{
vec3 unitNormal=normalize(vertexNormal);
vec3 unitCam=normalize(cameraVector);
vec3 diffuse,specular,lightColor;
for(int i=0;i<3;i++)
{
vec3 unitLight=normalize(lightVectors[i]);
float atten=getAtten(i);
float nDiffuseDot=dot(unitLight,unitNormal);
float diffuseIntencity=max(0,nDiffuseDot);
diffuse+=(buf2.colors[i]*diffuseMat*diffuseIntencity)/atten;
vec3 reflectedLight=reflect(-unitLight,unitNormal);
float nSpecularDot=dot(reflectedLight,unitCam);
float specularIntencity=pow(max(0,nSpecularDot),reflectivity)*shininess;
specular+=(buf2.colors[i]*specularMat*specularIntencity)/atten;
}
lightColor=diffuse+specular;
return lightColor;
}
void main()
{
pixelColor=vec4(computeLightColor(),1)*0.7;
}
这两个着色器的通用代码是
layout(std430,binding=1)buffer Lights
{
vec3 positions[3];
vec3 attenuations[3];
vec3 colors[3];
};
这是我用于照明计算的SSBO
我需要在顶点着色器和片段着色器中使用这一个缓冲区,因为在我的顶点着色器中,这部分代码
lightVectors[i]=buf1.positions[i]-worldVertex.xyz;
使用SSBO中定义的灯光位置
在片段着色器中,
float getAtten(i) and
vec3 computeLight()
方法使用缓冲区颜色[3]和衰减[3]“阵列”来计算漫反射和镜面反射分量
但我无法使用上述SSBO定义链接顶点和碎片着色器,着色器信息日志为空,因此我也不知道错误
有没有办法在顶点着色器和碎片着色器中使用上面定义的SSBO,而不创建2个单独的SSBO,即一个用于顶点着色器,一个用于碎片着色器?
这是我的着色器类。我的所有着色器都扩展到此类以实现
public abstract class StaticShader extends Shader3D
{
private int
vertexShaderID=-1,
fragmentShaderID=-1;
private boolean alive=false;
private boolean isActive=false;
public StaticShader(Object vertexShader,Object fragmentShader)
{
programID=GL20.glCreateProgram();
vertexShaderID=loadShader(vertexShader,GL20.GL_VERTEX_SHADER);
fragmentShaderID=loadShader(fragmentShader,GL20.GL_FRAGMENT_SHADER);
GL20.glAttachShader(programID,vertexShaderID);
GL20.glAttachShader(programID,fragmentShaderID);
bindAttributes();
activateShader();
}
private int loadShader(Object src,int shaderType)
{
StringBuilder source=super.loadSource(src);
int shaderID=GL20.glCreateShader(shaderType);
GL20.glShaderSource(shaderID,source);
GL20.glCompileShader(shaderID);
if(GL20.glGetShaderi(shaderID,GL20.GL_COMPILE_STATUS)==GL11.GL_FALSE)
{
infoLogSize=GL20.glGetShaderi(shaderID,GL20.GL_INFO_LOG_LENGTH);
System.err.println(GL20.glGetShaderInfoLog(shaderID,infoLogSize));
System.err.println("COULD NOT COMPILE SHADER");
System.exit(-1);
}
return shaderID;
}
protected void activateShader()
{
GL20.glLinkProgram(programID);
if(GL20.glGetProgrami(programID,GL20.GL_LINK_STATUS)==GL11.GL_FALSE)
{
infoLogSize=GL20.glGetProgrami(programID,GL20.GL_INFO_LOG_LENGTH);
System.err.println(GL20.glGetProgramInfoLog(programID,infoLogSize));
System.err.println("COULD NOT LINK SHADER");
System.exit(-1);
}
GL20.glValidateProgram(programID);
if(GL20.glGetProgrami(programID,GL20.GL_VALIDATE_STATUS)==GL11.GL_FALSE)
{
infoLogSize=GL20.glGetProgrami(programID,GL20.GL_INFO_LOG_LENGTH);
System.err.println(GL20.glGetProgramInfoLog(programID,infoLogSize));
System.err.println("COULD NOT VALIDATE SHADER");
System.exit(-1);
}
}
public void dispose()
{
GL20.glUseProgram(0);
GL20.glDetachShader(programID,vertexShaderID);
GL20.glDetachShader(programID,fragmentShaderID);
GL20.glDeleteShader(vertexShaderID);
GL20.glDeleteShader(fragmentShaderID);
GL20.glDeleteProgram(programID);
}
}
我使用的是LWJGL 2.9.3 Java OpenGL版本
程序编译正常,但glLinkprogram()返回false且着色器信息日志为空
我甚至还没有创建任何类型的缓冲对象,我现在只是在学习语法
任何帮助都将不胜感激提前感谢你和那些在评论中帮助过我的人,但我现在非常沮丧
1条答案
按热度按时间cgvd09ve1#
在您的代码中,我得到了链接器错误:
错误:SSBO(名为灯光)的着色器之间的绑定不匹配
对于不同着色器阶段中的相同命名缓冲区对象,必须使用相同的绑定点。
在顶点着色器中:
Lights
是缓冲区的外部可见名称,buf1
是着色器内的块的名称。这意味着您必须在片段着色器中为缓冲区对象
Lights
使用相同的绑定点:另请参阅:
缓冲区限定符用于声明全局变量,这些变量的值存储在通过OpenGL API绑定的缓冲区对象的数据存储中。