Opengl 4.3:在顶点和顶点使用一个SSBO对象片段着色器

时间:2017-12-02 12:37:36

标签: opengl

我一直在尝试使用带有opengl 4.3内核的着色器存储缓冲区对象(SSBO)一段时间,但是甚至无法将我的着色器程序链接到

这是我的顶点着色器代码

# 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

我需要在Vertex和amp;中使用这一个缓冲区。片段着色器,因为在我的顶点着色器中这部分代码

lightVectors[i]=buf1.positions[i]-worldVertex.xyz;

使用SSBO中定义的灯光位置

在Fragment Shader中

float getAtten(i) and
vec3 computeLight()

方法使用缓冲区颜色[3]和衰减[3]“数组”来计算漫反射和镜面反射分量

但我不能链接顶点和放大器使用上述SSBO定义的Fragement着色器 并且着色器信息日志为空所以我不知道错误

是否有一种方法可以在顶点和Fragement着色器中使用上面定义的SSBO而不创建2个单独的SSBO,即一个用于顶点着色器,一个用于fragement Shader?

这是我的着色器类。我的所有着色器都延伸到此类进行实施

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 个答案:

答案 0 :(得分:2)

在你的代码中,我收到链接器错误:

  

错误:SSBO(名为Lights)的着色器之间的绑定不匹配

您必须在不同的着色器阶段为相同的命名缓冲区对象使用相同的绑定点。

在你的顶点着色器中:

layout(std430, binding=1) buffer Lights
{
  vec3 positions[3];
  vec3 attenuations[3];
  vec3 colors[3];
} buf1;

Lights是缓冲区的外部可见名称,buf1是着色器中块的名称。

这意味着您必须在片段着色器中对缓冲区对象Lights使用相同的绑定点:

layout(std430,binding=1) buffer Lights // <---- binding=1 instead of binding=2
{
    vec3 positions[3];
    vec3 attenuations[3];
    vec3 colors[3];
}buf2;

另见:

  

缓冲区限定符用于声明其值存储在a的数据存储中的全局变量   通过OpenGL API绑定的缓冲区对象。

 // use buffer to create a buffer block (shader storage block)
 buffer BufferName { // externally visible name of buffer
     int count; // typed, shared memory...
     ... // ...
     vec4 v[]; // last member may be an array that is not sized
               // until after link time (dynamically sized)
 } Name; // name of block within the shader