I can't bind my texture to the sampler2D in the fragment shader. In theory my program should draw the whole scene in one color (My image is a red, 64x64 large square). When using textureSize to get the sampler2D's dimensions, it return 1x1.
Neither the TextureID or the SamplerLocation return -1
What I am doing at the moment:
loadImage Method copied from http://neokabuto.blogspot.de/
int loadImage(Bitmap image)
{
int texID = GL.GenTexture();
GL.BindTexture(TextureTarget.Texture2D, texID);
BitmapData data = image.LockBits(new System.Drawing.Rectangle(0, 0, image.Width, image.Height),
ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, data.Width, data.Height, 0,
OpenTK.Graphics.OpenGL4.PixelFormat.Bgra, PixelType.UnsignedByte, data.Scan0);
image.UnlockBits(data);
GL.GenerateMipmap(GenerateMipmapTarget.Texture2D);
return texID;
}
OnLoad Method called once on startup
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
int status_code;
string info;
Console.Out.WriteLine(GL.GetString(StringName.Version));
m.loadFromOBJ("C:/Users/Anwender/Downloads/lpm_yard.obj");
m.init();
TextureID = loadImage("C:/Users/Anwender/Desktop/test.png");
// Setup openGL
GL.ClearColor(0.0f, 0.0f, 0.0f, 1.0f);
GL.Enable(EnableCap.DepthTest);
GL.DepthFunc(DepthFunction.Lequal);
// Create MVP-Matrices and Camera Data
ProjectionMatrix = Matrix4.CreatePerspectiveFieldOfView(MathHelper.PiOver4, Width / (float)Height, 0.5f, 10000.0f);
WorldMatrix = new Matrix4();
ModelviewMatrix = new Matrix4();
CameraPosition = new Vector3(0.5f, 0.5f, 0);
defaultPickSSB = new PickSSB();
defaultPickSSB.DepthValue = float.MaxValue;
defaultPickSSB.PickIndex = -1;
string VertexSource = File.ReadAllText("C:/Users/Anwender/Source/Repos/ShaderDemo/ShaderDemo/Shader/vs.glsl");
string FragmentSource = File.ReadAllText("C:/Users/Anwender/Source/Repos/ShaderDemo/ShaderDemo/Shader/fr.glsl");
// Create Shaders
int VertexID = GL.CreateShader(ShaderType.VertexShader);
int FragmentID = GL.CreateShader(ShaderType.FragmentShader);
// Compile vertex shader
GL.ShaderSource(VertexID, VertexSource);
GL.CompileShader(VertexID);
GL.GetShaderInfoLog(VertexID, out info);
GL.GetShader(VertexID, ShaderParameter.CompileStatus, out status_code);
if (status_code != 1)
throw new ApplicationException(info);
// Compile fragment shader
GL.ShaderSource(FragmentID, FragmentSource);
GL.CompileShader(FragmentID);
GL.GetShaderInfoLog(FragmentID, out info);
GL.GetShader(FragmentID, ShaderParameter.CompileStatus, out status_code);
if (status_code != 1)
throw new ApplicationException(info);
// Create and Link Program
Program = GL.CreateProgram();
GL.AttachShader(Program, FragmentID);
GL.AttachShader(Program, VertexID);
GL.BindFragDataLocation(Program, 0, "color");
GL.LinkProgram(Program);
GL.UseProgram(Program);
// Get Buffer Locations
PickColorLocation = GL.GetAttribLocation(Program, "vertex_pick_index");
PositionLocation = GL.GetAttribLocation(Program, "vertex_position");
NormalLocation = GL.GetAttribLocation(Program, "vertex_normal");
ColorLocation = GL.GetAttribLocation(Program, "vertex_color");
UniformMVPMatrixLocation = GL.GetUniformLocation(Program, "mvp_matrix");
UniformMouseXLocation = GL.GetUniformLocation(Program, "mouse_x");
UniformMouseYLocation = GL.GetUniformLocation(Program, "mouse_y");
SamplerLocation = GL.GetUniformLocation(Program, "main_texture");
GL.GenBuffers(1, out SSB);
GL.BindBuffer(BufferTarget.ShaderStorageBuffer, SSB);
GL.BufferData(BufferTarget.ShaderStorageBuffer, (IntPtr)(4 * sizeof(float)), ref defaultPickSSB, BufferUsageHint.DynamicCopy);
GL.BindBufferBase(BufferRangeTarget.ShaderStorageBuffer, 0, SSB);
GL.UseProgram(0);
}
OnRenderFrame Method
protected override void OnRenderFrame(FrameEventArgs e)
{
base.OnRenderFrame(e);
GL.Viewport(0, 0, Width, Height);
GL.ClearColor(0.0f, 0.8f, 0.8f, 1.0f);
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
GL.UseProgram(Program);
GL.BindTexture(TextureTarget.Texture2D, TextureID);
GL.Uniform1(SamplerLocation, TextureID);
m.draw(PositionLocation, NormalLocation, ColorLocation, PickColorLocation);
GL.UseProgram(0);
SwapBuffers();
}
My fragment shader:
#version 430
in vec4 frag_color;
in vec4 gl_FragCoord;
flat in int frag_pick_index;
out vec4 color;
layout (std430, binding = 0) buffer mouse_color { int pick_index; float depth_value; };
uniform int mouse_x;
uniform int mouse_y;
uniform sampler2D main_texture;
void main(void)
{
if (int(gl_FragCoord.x) == mouse_x && int(gl_FragCoord.y) == mouse_y) {
if (gl_FragCoord.z < depth_value)
{
pick_index = frag_pick_index;
depth_value = gl_FragCoord.z;
}
}
// pick_index = textureSize(main_texture, 0).y;
if (int(gl_FragCoord.x) == mouse_x || int(gl_FragCoord.y) == mouse_y) {
color = vec4(0.0f, 1,0,1.0f);
} else {
color = frag_color;
}
color = texture(main_texture, vec2(0.5f, 0.5f));
}
The integer you pass to the sampler has to be the index of the texture unit the texture is bound to, not the texture id. Unless you called GL.ActiveTexture
somewhere, the active texture unit is TextureUnit.Texture0
, which means you have to pass 0 to GL.Uniform1
:
GL.ActiveTexture(TextureUnit.Texture0);
GL.BindTexture(TextureTarget.Texture2D, TextureID);
GL.Uniform1(SamplerLocation, 0);