如何解决如何在 OpenTK 中的四边形内拟合图像纹理?
我一直在尝试研究 OpenTK 中纹理的不同示例,但是,几乎没有代码示例使用我想要的相同方法,或者需要许多不符合我需求的无意义解决方法。我只是想在 OpenTK 中绘制图像而不会扭曲或变形它们的 UV。或者更确切地说,我如何使它们变形以适应原始(在这种情况下为四边形/正方形)在 2D 世界中的任何位置?
考虑这个图像(这是我的纹理,我试图放入一个四边形基元中):
这是不需要的结果。如您所见,它被裁剪了。我不关心包装,因为我计划将整个图像放入正方形内(不需要纵横比)。不同的包装设置没有任何作用。图像的中心仍然在正方形之外。
透明度和调色板是我要担心的,我只需要帮助将整个图像拟合到正方形内即可!
这是我加载纹理的代码:
public Texture(Bitmap image)
{
ID = GL.GenTexture();
GL.ActiveTexture(TextureUnit.Texture0);
GL.BindTexture(TextureTarget.Texture2D,ID);
BitmapData data = image.LockBits(new Rectangle(0,image.Width,image.Height),ImageLockMode.ReadOnly,System.Drawing.Imaging.PixelFormat.Format32bppArgb);
GL.TexImage2D(TextureTarget.Texture2D,PixelInternalFormat.Rgba,image.Height,OpenTK.Graphics.OpenGL.PixelFormat.Bgra,PixelType.UnsignedByte,data.Scan0);
GL.TexParameter(TextureTarget.Texture2D,TextureParameterName.TextureMinFilter,(int)TextureMinFilter.Linear);
GL.TexParameter(TextureTarget.Texture2D,TextureParameterName.TextureMagFilter,(int)TextureMagFilter.Linear);
GL.TexParameter(TextureTarget.Texture2D,TextureParameterName.TextureWrapS,(int)TextureWrapMode.Repeat);
GL.TexParameter(TextureTarget.Texture2D,TextureParameterName.TextureWrapT,(int)TextureWrapMode.Repeat);
GL.GenerateMipmap(GenerateMipmapTarget.Texture2D);
}
然后这是我将顶点数据加载到着色器并绘制图元的代码:
List<float> vertex_data = {
-.25f,-.25f,.25f,-.25f
};
// Load the 2D object
GL.UseProgram(program);
GL.BindBuffer(BufferTarget.ArrayBuffer,vbo);
GL.BufferData(BufferTarget.ArrayBuffer,vertex_data.Count * sizeof(float),vertex_data.ToArray(),BufferUsageHint.DynamicDraw);
GL.EnabLevertexAttribArray(attr_pos);
GL.VertexAttribPointer(attr_pos,2,VertexAttribPointerType.Float,false,2 * sizeof(float),0);
GL.EnabLevertexAttribArray(attr_uv);
GL.VertexAttribPointer(attr_uv,0);
// ^^ Using the same position data for the UV as well.
// ...
// Drawing the 2D object
GL.UseProgram(program);
GL.BindBuffer(BufferTarget.ArrayBuffer,vbo);
GL.ActiveTexture(TextureUnit.Texture0);
GL.BindTexture(TextureTarget.Texture2D,ID);
GL.DrawArrays(PrimitiveType.Quads,4);
以及顶点和片段着色器:
垂直:
#version 330 core
layout(location = 1) in vec3 vertex_pos;
layout(location = 2) in vec2 vertex_uv;
out vec2 uv;
uniform mat4 mvp;
void main() {
gl_Position = mvp * vec4(vertex_pos,1);
uv = vertex_uv;
}
碎片:
#version 330 core
in vec2 uv;
out vec4 color;
uniform sampler2D texture0;
void main() {
color = texture(texture0,uv);
}
解决方法
您需要做的就是指定范围 [0.0,1.0] 内的纹理坐标:
List<float> vertex_data = {
// x y u v
-.25f,-.25f,0.0f,.25f,1.0f,};
// Load the 2D object
GL.UseProgram(program);
GL.BindBuffer(BufferTarget.ArrayBuffer,vbo);
GL.BufferData(BufferTarget.ArrayBuffer,vertex_data.Count * sizeof(float),vertex_data.ToArray(),BufferUsageHint.DynamicDraw);
GL.EnableVertexAttribArray(attr_pos);
GL.VertexAttribPointer(attr_pos,2,VertexAttribPointerType.Float,false,4 * sizeof(float),0);
GL.EnableVertexAttribArray(attr_uv);
GL.VertexAttribPointer(attr_uv,2 * sizeof(float));
纹理坐标 (0,0) 指向纹理的左下边缘,纹理坐标 (1,1) 指向纹理的右上边缘。
您必须将纹理坐标 (0,0) 关联到四边形的左下角,将纹理坐标 (1,1) 关联到四边形的右上角。
GL.VertexAttribPointe
(strid) 的第四个参数指定了连续通用顶点属性之间的字节偏移量。由于每个属性由 4 个 flaot (x,y,u,v) 类型的元素组成,所以这是 4*sizeof(float)
。最后一个参数是属性的字节偏移量。顶点坐标的偏移量为0,纹理坐标的偏移量为2*sizeof(float)
当然可以使用2个单独的属性数组。在这种情况下,对于顶点坐标和纹理坐标,stride 是 2*sizeof(float)
。顶点坐标的偏移量为0,纹理坐标的偏移量为所有顶点坐标的大小(8*sizeof(float)
):
使用GL.BufferSubData
初始化缓冲区数据:
List<float> vertex_data = {
// x y
-.25f,}
List<float> texture_data = {
// u v
0.0f,vertex_data.Count * sizeof(float) + texture_data.Count * sizeof(float),IntPtr.Zero,BufferUsageHint.DynamicDraw);
GL.BufferSubData(BufferTarget.ArrayBuffer,vertex_data.ToArray())
GL.BufferSubData(BufferTarget.ArrayBuffer,texture_data.Count * sizeof(float),texture_data.ToArray())
GL.EnableVertexAttribArray(attr_pos);
GL.VertexAttribPointer(attr_pos,2 * sizeof(float),vertex_data.Count * sizeof(float));
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。