我一直在尝试研究 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, 0, image.Width, image.Height), ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, image.Width, image.Height, 0, 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,
.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, 2, VertexAttribPointerType.Float, false, 2 * sizeof(float), 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, 0, 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)
您需要做的就是指定范围 [0.0, 1.0] 内的纹理坐标:
List<float> vertex_data = {
// x y u v
-.25f, -.25f, 0.0f, 0.0f,
-.25f, .25f, 0.0f, 1.0f,
.25f, .25f, 1.0f, 1.0f,
.25f, -.25f, 1.0f, 0.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, VertexAttribPointerType.Float, false,
4 * sizeof(float), 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, -.25f,
-.25f, .25f,
.25f, .25f,
.25f, -.25f,
}
List<float> texture_data = {
// u v
0.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
1.0f, 0.0f,
};
// Load the 2D object
GL.UseProgram(program);
GL.BindBuffer(BufferTarget.ArrayBuffer, vbo);
GL.BufferData(BufferTarget.ArrayBuffer,
vertex_data.Count * sizeof(float) + texture_data.Count * sizeof(float),
IntPtr.Zero, BufferUsageHint.DynamicDraw);
GL.BufferSubData(BufferTarget.ArrayBuffer, 0,
vertex_data.Count * sizeof(float), vertex_data.ToArray())
GL.BufferSubData(BufferTarget.ArrayBuffer, vertex_data.Count * sizeof(float),
texture_data.Count * sizeof(float), texture_data.ToArray())
GL.EnableVertexAttribArray(attr_pos);
GL.VertexAttribPointer(attr_pos, 2, VertexAttribPointerType.Float, false,
2 * sizeof(float), 0);
GL.EnableVertexAttribArray(attr_uv);
GL.VertexAttribPointer(attr_uv, 2, VertexAttribPointerType.Float, false,
2 * sizeof(float), vertex_data.Count * sizeof(float));