Sync it
Sync it

Reputation: 1198

Opengl 4.3: Using One SSBO Object in Vertex & Fragment Shader

I've been trying to Use Shader Storage Buffer Objects(SSBO) with opengl 4.3 core for some time but cant even get my Shader Program To Link

Here is the Code For My Vertex Shader

# 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;

}

And Here Is The Code for My Fragment Shader

# 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;
}

The Code common to both These Shaders is

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

This is an SSBO I'm using for my Lighting Calculations

I need to use this one single buffer in both Vertex & Fragment Shader because in my Vertex Shader This part of code

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

Uses The Light Positions defined in The SSBO

And in the Fragment Shader the

float getAtten(i) and
vec3 computeLight()

Method Uses the buffers colors[3] and attenuations[3] "Arrays" to compute diffuse and specular components

But i cannot Link The Vertex & Fragement Shader using the above SSBO Definition And The Shader Info Log is empty So I don't know the error either

Is There A Way to Use The Above Defined SSBO In both the Vertex And Fragement Shader Without Creating 2 Separate SSBO i.e one for Vertex Shader And One for fragement Shader?

This Is My Shader Class. All My Shaders Extends To This Class For Implementation

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);
 }        
}

I'm Using LWJGL 2.9.3 Java Opengl Version

The program compiles fine but glLinkprogram () return false and the shader info log is empty

I haven't even created any buffer object of any sort I'm just learning the syntax at the moment

Any help will be greatly appreciated thank u in advance and to those who have helped me in the comments but I'm greatly frustrated at the moment

Upvotes: 1

Views: 3092

Answers (1)

Rabbid76
Rabbid76

Reputation: 211278

In youre code I get the linker error:

error: binding mismatch between shaders for SSBO (named Lights)

You have to use the same binding point for equal named buffer objects in the different shader stages.

In your vertex shader:

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

Lights ist the externally visible name of the buffer and buf1 is the name of the block within the shader.

This means you have to use the same binding point for the buffer object Lights in the fragment shader:

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

See also:

The buffer qualifier is used to declare global variables whose values are stored in the data store of a buffer object bound through the 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

Upvotes: 2

Related Questions