OpenGL4 无法将纹理加载到 Sampler2D
OpenGL4 fails to load Texture into Sampler2D
我无法将纹理绑定到片段着色器中的 sampler2D。理论上我的程序应该用一种颜色绘制整个场景(我的图像是一个红色的 64x64 大正方形)。当使用 textureSize 获取 sampler2D 的尺寸时,它 return 1x1.
TextureID 或 SamplerLocation 都不是 return -1
我现在在做什么:
- 将图像加载到gpu内存中并使用loadImage()获取Location (int TextureID)。
- 获取我的 sampler2D 的 UniformLocation (int SamplerLocation)
- 在渲染方法中:绑定纹理并相应地设置统一位置
源代码:
从 http://neokabuto.blogspot.de/
复制的 loadImage 方法
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 方法在启动时调用一次
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 方法
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();
}
我的片段着色器:
#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));
}
您传递给采样器的整数必须是纹理绑定到的纹理单元的索引,而不是纹理ID。除非你在某处调用 GL.ActiveTexture
,否则活动纹理单元是 TextureUnit.Texture0
,这意味着你必须将 0 传递给 GL.Uniform1
:
GL.ActiveTexture(TextureUnit.Texture0);
GL.BindTexture(TextureTarget.Texture2D, TextureID);
GL.Uniform1(SamplerLocation, 0);
我无法将纹理绑定到片段着色器中的 sampler2D。理论上我的程序应该用一种颜色绘制整个场景(我的图像是一个红色的 64x64 大正方形)。当使用 textureSize 获取 sampler2D 的尺寸时,它 return 1x1.
TextureID 或 SamplerLocation 都不是 return -1
我现在在做什么:
- 将图像加载到gpu内存中并使用loadImage()获取Location (int TextureID)。
- 获取我的 sampler2D 的 UniformLocation (int SamplerLocation)
- 在渲染方法中:绑定纹理并相应地设置统一位置
源代码:
从 http://neokabuto.blogspot.de/
复制的 loadImage 方法 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 方法在启动时调用一次
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 方法
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();
}
我的片段着色器:
#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));
}
您传递给采样器的整数必须是纹理绑定到的纹理单元的索引,而不是纹理ID。除非你在某处调用 GL.ActiveTexture
,否则活动纹理单元是 TextureUnit.Texture0
,这意味着你必须将 0 传递给 GL.Uniform1
:
GL.ActiveTexture(TextureUnit.Texture0);
GL.BindTexture(TextureTarget.Texture2D, TextureID);
GL.Uniform1(SamplerLocation, 0);