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.
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;
}
I'm trying to draw a triangle using an OpenGL(OpenTK) fragment shader.
But always displayed black triangle. (even I changed color in fragment shader.)
Maybe fragment shader is not working.
How to fix it?
I attached my code.
P.S. I'm sorry if I do something wrong with this Post. This is my first time on this site.
Render
window.RenderFrame += (FrameEventArgs args) =>
{
GL.UseProgram(shaderProgram.shaderProgramId);
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
float[] verts = { -0.5f, -0.5f, 0.0f, 0.5f, -0.5f, 0.0f, 0.0f, 0.5f, 0.0f };
int vao = GL.GenVertexArray();
int vertices = GL.GenBuffer();
GL.BindVertexArray(vao);
GL.BindBuffer(BufferTarget.ArrayBuffer, vertices);
GL.BufferData(BufferTarget.ArrayBuffer, verts.Length * sizeof(float), verts, BufferUsageHint.StaticCopy);
GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false,3 * sizeof(float),0);
GL.EnableVertexAttribArray(0);
GL.DrawArrays(OpenTK.Graphics.OpenGL4.PrimitiveType.Triangles, 0, 3);
GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
GL.BindVertexArray(0);
GL.DeleteVertexArray(vao);
GL.DeleteBuffer(vertices);
window.SwapBuffers();
};
Shader Load
public static Shader LoadShader(string shaderLocation, ShaderType shaderType)
{
int shaderId = GL.CreateShader(shaderType);
GL.ShaderSource( shaderId, File.ReadAllText( shaderLocation ) );
GL.CompileShader( shaderId );
string infoLog = GL.GetShaderInfoLog(shaderId);
if (!string.IsNullOrEmpty(infoLog))
{
throw new Exception(infoLog);
}
return new Shader() {shaderId = shaderId};
}
Program binding
public static ShaderProgram LoadShaderProgram(string vertexShaderLocation, string fragmentShaderLocation)
{
int shaderProgramId = GL.CreateProgram();
Shader vertexShader = LoadShader(vertexShaderLocation, ShaderType.VertexShader);
Shader fragShader = LoadShader(fragmentShaderLocation, ShaderType.FragmentShader);
GL.AttachShader(shaderProgramId, vertexShader.shaderId);
GL.AttachShader(shaderProgramId, fragShader.shaderId);
GL.LinkProgram(shaderProgramId);
GL.DetachShader(shaderProgramId, vertexShader.shaderId);
GL.DetachShader(shaderProgramId, fragShader.shaderId);
GL.DeleteShader(vertexShader.shaderId);
GL.DeleteShader(fragShader.shaderId);
string infoLog = GL.GetProgramInfoLog(shaderProgramId);
if (!string.IsNullOrEmpty(infoLog))
{
throw new Exception(infoLog);
}
return new ShaderProgram() {shaderProgramId = shaderProgramId};
}
shaders
vertex
#version 330
layout(location=0) in vec3 vPosition;
out vec4 vertexColor;
void main() {
gl_Position = vec4( vPosition, 1.0);
vertexColor = vec4(0.0,1.0,0.0,1.0);
}
fragment
#version 330
out vec4 FragColor;
in vec4 vertexColor;
void main()
{
FragColor = vertexColor;
}
I see a couple of problems with your code. The main reason you may not see your shader in action is because you do not keep your shaders attached to your shader handle (shaderProgramId). Instead, you detach and delete them right after you compiled and attached them. What you are doing there is basically creating your shader program and then immediately throwing it away.
Another issue (which might not cause your main problem, but yet) may be your usage of a VAO. A VAO is actually meant to preserve the OpenGL states of the objects bound to it across state switches. It is rather a container for VBOs inside it, holding their descriptions. So what you want to do is to create your VAO, bind it, then create, bind and describe (glVertexAttribPointer) your VBOs. After that you can unbind your VAO. When you bind it again, you don't have to do anything extra (like binding VBOs or using glVertexAttribPointer again): What you did when first binding your VAO and adding your VBOs is stored in the VAO. Just bind the VAO, bind your shader (glUseProgram) and happily render away.
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
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