C#/OpenTK-将着色器应用于加载的纹理时出现问题.纹理按比例缩小并翻转
本文关键字:纹理 问题 按比例 翻转 缩小 OpenTK- 加载 应用于 | 更新日期: 2023-09-27 18:25:10
我一直在想办法让它发挥作用。我使用OpenTK for C#来修改图像。现在我可以成功加载图像,但当我尝试使用着色器修改图像时,我开始遇到问题。我有3种基本方法:
- 1) LoadTexture(将纹理设置为GL)
- 2) DrawImage(实际绘制纹理)
- 3) AddShaders(此方法在DrawImage内部调用。它应用着色器)
下面是我遇到的两个问题:
-
1) 我正在尝试创建两个横跨整个纹理的三角形。这是因为我希望我的碎片着色器在整个纹理实际上我得到的是一个大三角形屏幕的左侧,以及屏幕编辑:取得了一些进展!但看起来还是很奇怪。。。着色器脚本已更新。。编辑2:更新的进度图片上传
-
2) 当我想让它们使用纹理中的颜色,但修改了红色通道。对我需要能够分析每个像素。更改每个像素的红色通道只是我想要的概念的证明实际操作(使用颜色距离公式、色调偏移等)我需要先开始更简单)
这是我成功加载为纹理的图像:loaded texture
以下是LoadTexture的代码:
public int LoadTexture(string file)
{
Bitmap bitmap = new Bitmap(file);
int tex;
GL.Hint(HintTarget.PerspectiveCorrectionHint, HintMode.Nicest);
GL.GenTextures(1, out tex);
GL.BindTexture(TextureTarget.Texture2D, tex);
BitmapData data = bitmap.LockBits(new System.Drawing.Rectangle(0, 0, bitmap.Width, bitmap.Height),
ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, data.Width, data.Height, 0,
OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, data.Scan0);
bitmap.UnlockBits(data);
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);
return tex;
}
这是DrawImage的代码:
public static void DrawImage(int image)
{
GL.MatrixMode(MatrixMode.Projection);
GL.PushMatrix();
GL.LoadIdentity();
GL.Ortho(0, 1920, 0, 1080, -1, 1);
GL.MatrixMode(MatrixMode.Modelview);
GL.PushMatrix();
GL.LoadIdentity();
GL.Disable(EnableCap.Lighting);
GL.Enable(EnableCap.Texture2D);
GL.ActiveTexture(TextureUnit.Texture0);
GL.BindTexture(TextureTarget.Texture2D, image);
GL.Begin(PrimitiveType.Quads);
GL.TexCoord2(0,1);
GL.Vertex3(0, 0, 0);
GL.TexCoord2(1, 1);
GL.Vertex3(1920, 0, 0);
GL.TexCoord2(1, 0);
GL.Vertex3(1920, 1080, 0);
GL.TexCoord2(0, 0);
GL.Vertex3(0, 1080, 0);
GL.End();
AddShaders();
GL.Disable(EnableCap.Texture2D);
GL.PopMatrix();
GL.MatrixMode(MatrixMode.Projection);
GL.PopMatrix();
GL.MatrixMode(MatrixMode.Modelview);
ErrorCode ec = GL.GetError();
if (ec != 0)
System.Console.WriteLine(ec.ToString());
Console.Read();
}
这是AddShaders的代码:
private static void AddShaders()
{
/***********Vert Shader********************/
var vertShader = GL.CreateShader(ShaderType.VertexShader);
GL.ShaderSource(vertShader, @"attribute vec3 a_position;
varying vec2 vTexCoord;
void main() {
vTexCoord = a_position.xy;
gl_Position = vec4(a_position, 1);
}");
GL.CompileShader(vertShader);
/***********Frag Shader ****************/
var fragShader = GL.CreateShader(ShaderType.FragmentShader);
GL.ShaderSource(fragShader, @"uniform sampler2D sTexture;
varying vec2 vTexCoord;
void main ()
{
vec4 color = texture2D (sTexture, vTexCoord);
color.r = 0.5;
// Save the result
gl_FragColor = color;
}");
GL.CompileShader(fragShader);
var program = GL.CreateProgram();
GL.AttachShader(program, vertShader);
GL.AttachShader(program, fragShader);
GL.LinkProgram(program);
GL.ClearColor(Color.AliceBlue);
// OpenGL expects vertices to be defined counter clockwise by default
float[] vertices = {
// Left bottom triangle
-1f, 1f, 0f,
-1f, -1f, 0f,
1f, -1, 0f,
// Right top triangle
1f, -1f, 0f,
1f, 1f, 0f,
-1f, 1f, 0f
};
var buffer = GL.GenBuffer();
var positionLocation = GL.GetAttribLocation(program, "a_position");
GL.EnableVertexAttribArray(positionLocation);
GL.BindBuffer(BufferTarget.ArrayBuffer, buffer);
GL.VertexAttribPointer(positionLocation, 3, VertexAttribPointerType.Float,false,0,0);
GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)(vertices.Length * sizeof(ushort)), vertices, BufferUsageHint.StaticDraw);
GL.DrawArrays(PrimitiveType.Triangles, 0, vertices.Length);
GL.UseProgram(program);
}
我已经研究了几天了,我完全陷入了困境。感谢所有能看到我做错了什么的人。对我来说,这一定是一些小而愚蠢的事情!
编辑:当我删除AddShaders中所有与顶点相关的代码时,我会得到我想要的输出,除了它的1/4大小和在屏幕右上角翻转之外。所以,不知何故,我的着色器甚至不关心顶点。为什么它被缩小到1/4大小并被翻转?
第二版:好吧,多亏了罗伯特·鲁哈尼,我几乎做到了!进展看起来三角形的顶点可能被搞砸了??
这是我的新密码。我将功能重构为方法,停止在每帧创建程序/缓冲区等。现在我有了类级变量来保存特定于GL的数据,有了为应用程序创建GL程序、创建着色器、创建缓冲区等的方法。我还知道1920x1080硬编码是硬编码的。这是我要做的事情。
string file = "lambo2.png";
int program;
int vertShader;
int fragShader;
int buffer;
int positionLocation;
int texture;
float[] vertices = {
// Left bottom triangle
-1f, -1f, 0f,
1f, -1f, 0f,
1f, 1f, 0f,
// Right top triangle
1f, 1f, 0f,
-1f, 1f, 0f,
-1f, -1f, 0f
};
private void CreateProgram()
{
program = GL.CreateProgram();
GL.AttachShader(program, vertShader);
GL.AttachShader(program, fragShader);
GL.LinkProgram(program);
}
private void CreateShaders()
{
/***********Vert Shader********************/
vertShader = GL.CreateShader(ShaderType.VertexShader);
GL.ShaderSource(vertShader, @"attribute vec3 a_position;
varying vec2 vTexCoord;
void main() {
vTexCoord = (a_position.xy + 1) / 2;
gl_Position = vec4(a_position, 1);
}");
GL.CompileShader(vertShader);
/***********Frag Shader ****************/
fragShader = GL.CreateShader(ShaderType.FragmentShader);
GL.ShaderSource(fragShader, @"precision highp float;
uniform sampler2D sTexture;
varying vec2 vTexCoord;
void main ()
{
vec4 color = texture2D (sTexture, vTexCoord);
if(color.r < 0.3){color.r = 1.0;}
// Save the result
gl_FragColor = color;
}");
// GL.ShaderSource(fragShader, System.IO.File.ReadAllText(@"C:'Users'Matt'Desktop'hue-shader-backup.ps"));
GL.CompileShader(fragShader);
}
private void InitBuffers()
{
buffer = GL.GenBuffer();
positionLocation = GL.GetAttribLocation(program, "a_position");
GL.EnableVertexAttribArray(positionLocation);
GL.BindBuffer(BufferTarget.ArrayBuffer, buffer);
GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)(vertices.Length * sizeof(ushort)), vertices, BufferUsageHint.StaticDraw);
GL.VertexAttribPointer(positionLocation, 3, VertexAttribPointerType.Float, false, 0, 0);
}
private void Init()
{
texture = LoadTexture(file);
CreateShaders();
CreateProgram();
InitBuffers();
}
public int LoadTexture(string file)
{
Bitmap bitmap = new Bitmap(file);
int tex;
GL.Hint(HintTarget.PerspectiveCorrectionHint, HintMode.Nicest);
GL.GenTextures(1, out tex);
GL.BindTexture(TextureTarget.Texture2D, tex);
bitmap.RotateFlip(RotateFlipType.RotateNoneFlipY);
BitmapData data = bitmap.LockBits(new System.Drawing.Rectangle(0, 0, bitmap.Width, bitmap.Height),
ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, data.Width, data.Height, 0,
OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, data.Scan0);
bitmap.UnlockBits(data);
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.ClampToEdge);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.ClampToEdge);
return tex;
}
public void DrawImage(int image)
{
GL.Viewport(new Rectangle(0, 0, 1920, 1080));
GL.MatrixMode(MatrixMode.Projection);
GL.PushMatrix();
GL.LoadIdentity();
GL.Ortho(0, 1920, 0, 1080, 0, 1);
GL.MatrixMode(MatrixMode.Modelview);
GL.PushMatrix();
GL.LoadIdentity();
GL.Disable(EnableCap.Lighting);
GL.Enable(EnableCap.Texture2D);
GL.ActiveTexture(TextureUnit.Texture0);
GL.BindTexture(TextureTarget.Texture2D, image);
GL.Begin(PrimitiveType.Quads);
GL.TexCoord2(0, 1);
GL.Vertex3(0, 0, 0);
GL.TexCoord2(1, 1);
GL.Vertex3(1920, 0, 0);
GL.TexCoord2(1, 0);
GL.Vertex3(1920, 1080, 0);
GL.TexCoord2(0, 0);
GL.Vertex3(0, 1080, 0);
GL.End();
RunShaders();
GL.Disable(EnableCap.Texture2D);
GL.PopMatrix();
GL.MatrixMode(MatrixMode.Projection);
GL.PopMatrix();
GL.MatrixMode(MatrixMode.Modelview);
ErrorCode ec = GL.GetError();
if (ec != 0)
System.Console.WriteLine(ec.ToString());
Console.Read();
}
private void RunShaders()
{
GL.ClearColor(Color.AliceBlue);
GL.UseProgram(program);
GL.DrawArrays(PrimitiveType.Triangles, 0, vertices.Length / 3);
ErrorCode ec = GL.GetError();
if (ec != 0)
System.Console.WriteLine(ec.ToString());
Console.Read();
}
要开始一个答案,而不是继续注释。你仍然有一些小问题在加剧。您应该注释掉GL.Begin
和GL.End
之间的所有内容,因为RunShaders
函数应该将您需要的所有内容绘制到屏幕上。同时注释掉GL.Ortho
行,如果您正在处理[-1,1]范围内的顶点,则不需要它。
其次,您的问题是,您只将一半的顶点缓冲区上传到GPU。在GL.BufferData
行的InitBuffers
中,将sizeof(ushort)
更改为sizeof(float)
,因为顶点是浮点(4字节长)而不是ushports(2字节长)。
GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)(vertices.Length * sizeof(float)), vertices, BufferUsageHint.StaticDraw);
这应该会让你的程序发挥作用。