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
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:
OpenGL Shading Language 4.6 specification - 4.3.7 Buffer Variables
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
OpenGL Shading Language 4.6 specification - 4.4.5 Uniform and Shader Storage Block Layout Qualifiers
Related
When I enable shader program, texture doesnt work
A_andrew is texture in alias (Part of|in Texture2D)
alias is alias (Texture2D)
CSharp Code
GL.ClearColor(255, 255, 255, 255);
GL.Clear(ClearBufferMask.DepthBufferBit);
A_andrew.Bind();
//shaderProgram.Use(); when enabled texture are disapeare
shaderProgram.GetUniform("texture0").SetVec1(alias.id);
GL.Begin(BeginMode.Quads);
AliasTexture2D tex = Draw.CurrentTexutre;
GL.TexCoord2(tex.GetLeftBottom());
GL.Vertex2(-0.6f, -0.4f);
GL.TexCoord2(tex.GetRightBottom());
GL.Vertex2(0.6f, -0.4f);
GL.TexCoord2(tex.GetRightTop());
GL.Vertex2(0.6f, 0.4f);
GL.TexCoord2(tex.GetLeftTop());
GL.Vertex2(-0.6f, 0.4f);
GL.End();
window.SwapBuffers();
Fragment Shader
version 330 core
in vec2 texCords;
uniform sampler2D texture0;
out vec4 color;
void main()
{
vec4 texColor = texture(texture0, texCords);
color = texColor;
}
Vertex Shader
version 330 core
layout (location = 0) in vec3 inPosition;
layout (location = 1) in vec2 inTexCords;
out vec2 texCords;
void main()
{
texCords = inTexCords;
gl_Position = vec4(inPosition.xyz, 1.0);
}
I think problem in Fragment Shader, he dont get texture or|and texture cordinates
You cannot mix fixed function attributes and the fixed function matrix stack with a version 3.30 shader program.
You have to use the built in attributes such as gl_Vertex and gl_MultiTexCoord0 (see Vertex Attributes).
You have to use the the built in uniform variables like gl_ModelViewProjectionMatrix. In legacy OpenGL (GLSL 1.20) there are provided built-in uniforms. See OpenGL Shading Language 1.20 Specification; 7.5 Built-In Uniform State.
One of them is gl_ModelViewProjectionMatrix of type mat4, which provides the transformation by the model view and projection matrix. There also exist separated varables gl_ModelViewMatrix and gl_ProjectionMatrix vor the model view and projection matrix.
Vertex shader:
version 120
varying vec2 texCords;
void main()
{
texCords = gl_MultiTexCoord0.xy;
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}
This is a part of my VS:
#version 450
#extension GL_ARB_explicit_uniform_location : enable
#extension GL_ARB_separate_shader_objects : enable
#extension GL_ARB_gpu_shader5 : enable
//Imports
#include "/common.glsl"
#include "/common_structs.glsl"
//Mesh Attributes
layout(location=0) in vec4 vPosition;
layout(location=1) in vec2 uvPosition0;
layout(location=2) in vec4 nPosition; //normals
layout(location=3) in vec4 tPosition; //tangents
layout(location=4) in vec4 bPosition; //bitangents
layout(location=5) in vec4 blendIndices;
layout(location=6) in vec4 blendWeights;
//Uniform Blocks
layout (std140) uniform Uniforms
{
CommonPerFrameUniforms mpCommonPerFrame;
CommonPerMeshUniforms mpCommonPerMesh;
};
//Outputs
out vec3 E;
out vec3 N;
out vec2 uv0;
out float l_distance;
out mat3 TBN;
out vec3 default_color;
out vec4 finalPos;
out vec4 finalNormal;
void main()
{...}
This is a part of my FS:
#version 450
#extension GL_ARB_explicit_uniform_location : enable
#extension GL_ARB_separate_shader_objects : enable
#extension GL_ARB_texture_query_lod : enable
#extension GL_ARB_gpu_shader5 : enable
//Includes
#include "/common.glsl"
#include "/common_structs.glsl"
layout(location = 200) uniform MaterialUniforms mpCustomPerMaterial;
//Uniform Blocks
layout (std140) uniform Uniforms
{
CommonPerFrameUniforms mpCommonPerFrame;
CommonPerMeshUniforms mpCommonPerMesh;
};
in vec3 E;
in vec3 N;
in vec2 uv0;
in float l_distance;
in mat3 TBN;
in vec3 default_color;
in vec4 finalPos;
//Deferred Shading outputs
out vec4 outcolors[3];
void main
{...}
The #include statements are actually preprocessor statements that I use in order to include common structs and functions to the shaders. One of them is the following:
struct MaterialUniforms
{
bool matflags[64];
sampler2DArray diffuseTex;
sampler2DArray maskTex;
sampler2DArray normalTex;
vec4 ColourVec4;
vec4 ParamsVec4;
};
So the problem is that if I use
layout(location = 200) uniform MaterialUniforms mpCustomPerMaterial;
then I get the following error from the linker:
Link info
---------
Error Duplicate location 201 for uniform mpCustomPerMaterial.diffuseTex
Error Duplicate location 202 for uniform mpCustomPerMaterial.maskTex
Error Duplicate location 203 for uniform mpCustomPerMaterial.normalTex
Error Duplicate location 204 for uniform mpCustomPerMaterial.gMaterialColourVec4
Error Duplicate location 205 for uniform mpCustomPerMaterial.gMaterialParamsVec4
When I remove the layout(location=200) from the uniform definition, then the shader gets compiled successfully. I've experimented with different values for the location, but I can't understand why this is happening. Is there any chance that the uniform blocks that I use, conflict with the struct uniforms?
I am creating a game engine that includes basic game needs. Using glslDevil, it turns out my bind VBO method throws an InvalidValue error. A call of glVertexPointer and a call of glEnableVertexPointer cause the issue. The vertex attribute index is causing the issue. The index is 4294967295 which is well over 15. Everything else works perfectly fine. I am using OpenTK. Here is the bind to attribute method.
public void BindToAttribute(ShaderProgram prog, string attribute)
{
int location = GL.GetAttribLocation(prog.ProgramID, attribute);
GL.EnableVertexAttribArray(location);
Bind();
GL.VertexAttribPointer(location, Size, PointerType, true, TSize, 0);
}
public void Bind()
{
GL.BindBuffer(Target, ID);
}
Here are my shaders if required.
Vertex Shader:
uniform mat4 transform;
uniform mat4 projection;
uniform mat4 camera;
in vec3 vertex;
in vec3 normal;
in vec4 color;
in vec2 uv;
out vec3 rnormal;
out vec4 rcolor;
out vec2 ruv;
void main(void)
{
rcolor = color;
rnormal = normal;
ruv = uv;
gl_Position = camera * projection * transform * vec4(vertex, 1);
}
Fragment Shader:
in vec3 rnormal;
in vec4 rcolor;
in vec2 ruv;
uniform sampler2D texture;
void main(void)
{
gl_FragColor = texture2D(texture, ruv) * rcolor;
}
Am I not obtaining the index correctly or is there another issue?
the index that you are getting seems to be the problem: that is the index that you get when opengl doesn't find a valid attribute/uniform with that name.
There are a few things that might be going on:
you are passing a string that doesn't exist in the shader program (check case sensitive and whatnot)
the uniform exists and you are passing the correct string, but you are not using that attribute in the shader so the driver has removed all the occurrences of that attribute in the final code due to optimization (therefore it doesn't exists anymore)
In general though, that number shows that OpenGL can't find the uniform or attribute you were looking for
EDIT:
One trick is the following: let's assume you have some pixel shader code that returns a value that is the sum of many values:
out vec4 color;
void main()
{
// this shader does many calculations when you are
// using many values, but let's assume you want to debug
// just the diffuse color... how do you do it?
// if you change the output to return just the diffuse color,
// the optimizer might remove code and you might have problems
//
// if you have this
color = various_calculation_1 + various_calculation_2 + ....;
// what you can do is the following
color *= 0.0000001f; // so basically it's still calculated
// but it almost won't show up
color += value_to_debug; // example, the diffuse color
}
I have a fairly simple fragmentshader that does not work. It appears to have something to do with the textureCube method.
This is the fragment shader:
in vec3 ReflectDir;
in vec3 RefractDir;
uniform samplerCube CubeMapTex;
uniform bool DrawSkyBox;
uniform float MaterialReflectionFactor;
void main()
{
// Access the cube map texture
vec4 reflectColor = textureCube(CubeMapTex, ReflectDir);
vec4 refractColor = textureCube(CubeMapTex, RefractDir);
if( DrawSkyBox )
{
gl_FragColor = reflectColor;
gl_FragColor = vec4(ReflectDir, 1); //This line
}
else
gl_FragColor = vec4(1,0,0,1);
}
ReflectDir and RefractDir come from a vertex shader, but that seems to be in order.
If I comment the second line in the if statement the whole screen is black (incliding the teapot), otherwise it looks like this (ReflectDir seems ok):
http://i.imgur.com/MkHX6kT.png
Also the cubemap is rendered properly (well the images orders are bad). This is how the scene looks like without the shader program:
http://i.imgur.com/6kKzA2x.jpg
Aditional info:
the texture is loaded with GL_TEXTURE_CUBE_MAP on active texture TEXTURE0
uniform CubeMapTex is set to 0
DrawSkyBox is set to true when drawing the skybox, false after that
I used SharpGL
When I bind my buffers to attributes for my shaders, they seem to be getting flipped.
So, I've got a vertex shader:
precision highp float;
uniform mat4 projection_matrix;
uniform mat4 modelview_matrix;
in vec3 in_position;
in vec3 in_color;
out vec3 ex_Color;
void main(void)
{
gl_Position = projection_matrix * modelview_matrix * vec4(in_position, 1);
ex_Color = in_color;
}
and a fragment shader
precision highp float;
in vec3 ex_Color;
out vec4 out_frag_color;
void main(void)
{
out_frag_color = vec4(ex_Color, 1.0);
}
Nothing too complicated. There are two inputs: one for vertex locations, and one for colors. (As a newb, I didn't want to deal with textures or light yet.)
Now, in my client code, I put data into two arrays of vectors, positionVboData and colorVboData, and I create the VBOs...
GL.GenBuffers(1, out positionVboHandle);
GL.BindBuffer(BufferTarget.ArrayBuffer, positionVboHandle);
GL.BufferData<Vector3>(BufferTarget.ArrayBuffer,
new IntPtr(positionVboData.Length * Vector3.SizeInBytes),
positionVboData, BufferUsageHint.StaticDraw);
GL.GenBuffers(1, out colorVboHandle);
GL.BindBuffer(BufferTarget.ArrayBuffer, colorVboHandle);
GL.BufferData<Vector3>(BufferTarget.ArrayBuffer,
new IntPtr(colorVboData.Length * Vector3.SizeInBytes),
colorVboData, BufferUsageHint.StaticDraw);
and then, I would expect the following code to work to bind the vbos to the attributes for the shaders:
GL.EnableVertexAttribArray(0);
GL.BindBuffer(BufferTarget.ArrayBuffer, positionVboHandle);
GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, true, Vector3.SizeInBytes, 0);
GL.BindAttribLocation(shaderProgramHandle, 0, "in_position");
GL.EnableVertexAttribArray(1);
GL.BindBuffer(BufferTarget.ArrayBuffer, colorVboHandle);
GL.VertexAttribPointer(1, 3, VertexAttribPointerType.Float, true, Vector3.SizeInBytes, 0);
GL.BindAttribLocation(shaderProgramHandle, 1, "in_color");
But, in fact I have to swap positionVboHandle and colorVboHandle in the last code sample and then it works perfectly. But that seems backwards to me. What am I missing?
Update
Something weird is going on. If I change the vertex shader to this:
precision highp float;
uniform mat4 projection_matrix;
uniform mat4 modelview_matrix;
in vec3 in_position;
in vec3 in_color;
out vec3 ex_Color;
void main(void)
{
gl_Position = projection_matrix * modelview_matrix * vec4(in_position, 1);
//ex_Color = in_color;
ex_Color = vec3(1.0, 1.0, 1.0);
}"
And make no other changes (other than the fix suggested to move the program link after all the set up, it loads the correct attribute, the vertex positions, into in_position rather than into in_color.
GL.BindAttribLocation must be performed before GL.LinkProgram. Are you calling GL.LinkProgram after this code fragment?
EDIT:
Answering to your Update - because you don't use in_color, then OpenGL simply ignores this input. And your vertex shader taks only in_position as input. Most likely it binds it in location 0. That's why your code works. You should bind locations before linking program as it is described in link above.
So, with Mārtiņš Možeiko's help, I was able to figure this out. I was calling BindAttribLocation before LinkProgram correctly. However, I wasn't calling GL.CreateProgram() BEFORE I was binding any of the attribute locations.