在 openTK 中旋转图像
Rotate an image in openTK
我想将 GLControl 中显示的图像旋转 10 度。为此,我使用 c# 代码旋转了位图并将这个旋转的位图传递给 opengl 着色器代码。但是结果图像看起来像旋转的部分是 hiding/cut 如下所示。旋转时是否需要对其视口进行任何更改?还是在着色器代码本身中旋转图像好?
public void DrawImage(int image, int glcontrolWidth, int glcontrolHeight,Matrix4 **transformMatrix**)
{
GL.Viewport(new Rectangle(0, 0, glcontrolWidth, glcontrolHeight));
GL.MatrixMode(MatrixMode.Projection);
GL.PushMatrix();
GL.LoadIdentity();
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.Uniform1(positionLocation1, 0);
RunShaders();
GL.Disable(EnableCap.Texture2D);
GL.PopMatrix();
GL.MatrixMode(MatrixMode.Projection);
GL.PopMatrix();
GL.MatrixMode(MatrixMode.Modelview);
}
public void RunShaders()
{
GL.UseProgram(program);
**GL.UniformMatrix4(transformLocation, false, ref transformMatrix);**
GL.DrawArrays(PrimitiveType.Triangles, 0, vertices.Length / 3);
ErrorCode ec = GL.GetError();
if (ec != 0)
System.Console.WriteLine(ec.ToString());
Console.Read();
}
public void Init()
{
CreateShaders();
CreateProgram();
InitBuffers();
}
public void CreateProgram()
{
program = GL.CreateProgram();
GL.AttachShader(program, vertShader);
GL.AttachShader(program, fragShader);
GL.LinkProgram(program);
}
public void InitBuffers()
{
buffer = GL.GenBuffer();
positionLocation = GL.GetAttribLocation(program, "a_position");
positionLocation1 = GL.GetUniformLocation(program, "sTexture");
**transformLocation = GL.GetUniformLocation(program, "u_transform");**
GL.EnableVertexAttribArray(positionLocation);
GL.BindBuffer(BufferTarget.ArrayBuffer, buffer);
GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)(vertices.Length * sizeof(float)), vertices, BufferUsageHint.StaticDraw);
GL.VertexAttribPointer(positionLocation, 3, VertexAttribPointerType.Float, false, 0, 0);
}
public void CreateShaders()
{
/***********Vert Shader********************/
vertShader = GL.CreateShader(ShaderType.VertexShader);
GL.ShaderSource(vertShader, @"attribute vec3 a_position;
varying vec2 vTexCoord;
**uniform mat4 u_transform;**
void main() {
vTexCoord = (a_position.xy+1)/2 ;
**gl_Position = u_transform * vec4(a_position, 1);**
}");
GL.CompileShader(vertShader);
/***********Frag Shader ****************/
fragShader = GL.CreateShader(ShaderType.FragmentShader);
GL.ShaderSource(fragShader, @"precision highp float;
uniform sampler2D sTexture_2;varying vec2 vTexCoord;
void main ()
{
vec4 color = texture2D (sTexture_2, vec2(vTexCoord.x, vTexCoord.y));
gl_FragColor =color;
}"); GL.CompileShader(fragShader);
}
不旋转图像,旋转并缩放顶点坐标。
向顶点着色器添加变换矩阵:
attribute vec3 a_position;
varying vec2 vTexCoord;
uniform mat4 u_transform;
void main()
{
vTexCoord = (a_position.xy+1)/2;
gl_Position = u_transform * vec4(a_position, 1);
}
获取变换矩阵uniform(``u_transform´)的位置(程序链接后)
int transformLocation = GL.GetUniformLocation(program, "u_transform");
根据角度计算比例:
double diagonal = Math.Sqrt(bmp.Width * bmp.Width + bmp.Height * bmp.Height);
double dia_angle1 = Math.Atan2(bmp.Height, bmp.Width) + angle * Math.PI / 180;
double dia_angle2 = Math.Atan2(bmp.Height, -bmp.Width) + angle * Math.PI / 180;
double rot_w = Math.Max(Math.Abs(diagonal * Math.Cos(dia_angle1)), Math.Abs(diagonal * Math.Cos(dia_angle2)));
double rot_h = Math.Max(Math.Abs(diagonal * Math.Sin(dia_angle1)), Math.Abs(diagonal * Math.Sin(dia_angle2)));
double scale = Math.Min(bmp.Width / rot_w, bmp.Height / rot_h);
定义一个变换矩阵,根据纵横比缩放和旋转图像:
Matrix4 transformMatrix =
Matrix4.CreateScale((float)scale) *
Matrix4.CreateScale(this.Width, this.Height, 1.0f) *
Matrix4.CreateRotationZ((float)(angle * Math.PI / 180)) *
Matrix4.CreateScale(1.0f / this.Width, 1.0f / this.Height, 1.0f);
设置矩阵统一,程序安装后(GL.UseProgram
后):
GL.UniformMatrix4(transformLocation, false, ref transformMatrix);
我想将 GLControl 中显示的图像旋转 10 度。为此,我使用 c# 代码旋转了位图并将这个旋转的位图传递给 opengl 着色器代码。但是结果图像看起来像旋转的部分是 hiding/cut 如下所示。旋转时是否需要对其视口进行任何更改?还是在着色器代码本身中旋转图像好?
public void DrawImage(int image, int glcontrolWidth, int glcontrolHeight,Matrix4 **transformMatrix**)
{
GL.Viewport(new Rectangle(0, 0, glcontrolWidth, glcontrolHeight));
GL.MatrixMode(MatrixMode.Projection);
GL.PushMatrix();
GL.LoadIdentity();
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.Uniform1(positionLocation1, 0);
RunShaders();
GL.Disable(EnableCap.Texture2D);
GL.PopMatrix();
GL.MatrixMode(MatrixMode.Projection);
GL.PopMatrix();
GL.MatrixMode(MatrixMode.Modelview);
}
public void RunShaders()
{
GL.UseProgram(program);
**GL.UniformMatrix4(transformLocation, false, ref transformMatrix);**
GL.DrawArrays(PrimitiveType.Triangles, 0, vertices.Length / 3);
ErrorCode ec = GL.GetError();
if (ec != 0)
System.Console.WriteLine(ec.ToString());
Console.Read();
}
public void Init()
{
CreateShaders();
CreateProgram();
InitBuffers();
}
public void CreateProgram()
{
program = GL.CreateProgram();
GL.AttachShader(program, vertShader);
GL.AttachShader(program, fragShader);
GL.LinkProgram(program);
}
public void InitBuffers()
{
buffer = GL.GenBuffer();
positionLocation = GL.GetAttribLocation(program, "a_position");
positionLocation1 = GL.GetUniformLocation(program, "sTexture");
**transformLocation = GL.GetUniformLocation(program, "u_transform");**
GL.EnableVertexAttribArray(positionLocation);
GL.BindBuffer(BufferTarget.ArrayBuffer, buffer);
GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)(vertices.Length * sizeof(float)), vertices, BufferUsageHint.StaticDraw);
GL.VertexAttribPointer(positionLocation, 3, VertexAttribPointerType.Float, false, 0, 0);
}
public void CreateShaders()
{
/***********Vert Shader********************/
vertShader = GL.CreateShader(ShaderType.VertexShader);
GL.ShaderSource(vertShader, @"attribute vec3 a_position;
varying vec2 vTexCoord;
**uniform mat4 u_transform;**
void main() {
vTexCoord = (a_position.xy+1)/2 ;
**gl_Position = u_transform * vec4(a_position, 1);**
}");
GL.CompileShader(vertShader);
/***********Frag Shader ****************/
fragShader = GL.CreateShader(ShaderType.FragmentShader);
GL.ShaderSource(fragShader, @"precision highp float;
uniform sampler2D sTexture_2;varying vec2 vTexCoord;
void main ()
{
vec4 color = texture2D (sTexture_2, vec2(vTexCoord.x, vTexCoord.y));
gl_FragColor =color;
}"); GL.CompileShader(fragShader);
}
不旋转图像,旋转并缩放顶点坐标。
向顶点着色器添加变换矩阵:
attribute vec3 a_position;
varying vec2 vTexCoord;
uniform mat4 u_transform;
void main()
{
vTexCoord = (a_position.xy+1)/2;
gl_Position = u_transform * vec4(a_position, 1);
}
获取变换矩阵uniform(``u_transform´)的位置(程序链接后)
int transformLocation = GL.GetUniformLocation(program, "u_transform");
根据角度计算比例:
double diagonal = Math.Sqrt(bmp.Width * bmp.Width + bmp.Height * bmp.Height);
double dia_angle1 = Math.Atan2(bmp.Height, bmp.Width) + angle * Math.PI / 180;
double dia_angle2 = Math.Atan2(bmp.Height, -bmp.Width) + angle * Math.PI / 180;
double rot_w = Math.Max(Math.Abs(diagonal * Math.Cos(dia_angle1)), Math.Abs(diagonal * Math.Cos(dia_angle2)));
double rot_h = Math.Max(Math.Abs(diagonal * Math.Sin(dia_angle1)), Math.Abs(diagonal * Math.Sin(dia_angle2)));
double scale = Math.Min(bmp.Width / rot_w, bmp.Height / rot_h);
定义一个变换矩阵,根据纵横比缩放和旋转图像:
Matrix4 transformMatrix =
Matrix4.CreateScale((float)scale) *
Matrix4.CreateScale(this.Width, this.Height, 1.0f) *
Matrix4.CreateRotationZ((float)(angle * Math.PI / 180)) *
Matrix4.CreateScale(1.0f / this.Width, 1.0f / this.Height, 1.0f);
设置矩阵统一,程序安装后(GL.UseProgram
后):
GL.UniformMatrix4(transformLocation, false, ref transformMatrix);