using OpenTK.GLControl;
using OpenTK.Graphics.OpenGL4;
using OpenTK.Mathematics;
using Sof.ClientApplication.Framework.ViewModels;
using System.Runtime.InteropServices;
using Waferscan.GUI.Result.OpenGL;
using Waferscan.GUI.Result.View;
using Waferscan.GUI.Result.ViewModel;
using Waferscan.Logics.Algorithm.Model;
using Waferscan.Recipe.Enums;
using Waferscan.Result.Models;
namespace Waferscan.GUI.Result.WaferMap
{
public class Haze3dDraw : BaseMapDraw
{
public Channel Channel => _wafermap.Channel;
public float MinThreshold { get; set; }
public float MaxThreshold { get; set; }
#region const
const float SHOW_RATE = 0.999f; //显示区域缩小,防止部分像素点落在视野外
#endregion
#region filed
private Shader _shader;
private int _hazeBufferObject;
private int _hazeArrayObject;
private int _meshBufferObject;
private float[] _hazeDatas;
private MeshData _meshData;
private float[] _colors;
#endregion
public override void Init(ResultDisplayViewModel resultDisplay,WaferMapViewModel waferMap)
{
base.Init(resultDisplay, waferMap);
((Camera3D)_camera).UpdateViewport(_glControl.Width, _glControl.Height);
_glControl.MakeCurrent();
_shader = new Shader("Shaders/shader_haze3d.vert", "Shaders/shader_haze3d.frag");
_hazeBufferObject = GL.GenBuffer();
GL.BindBuffer(BufferTarget.ArrayBuffer, _hazeBufferObject);
_hazeArrayObject = GL.GenVertexArray();
GL.BindVertexArray(_hazeArrayObject);
GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, 3 * sizeof(float), 0);
GL.EnableVertexAttribArray(0);
//mesh
_meshBufferObject = GL.GenBuffer();
GL.BindBuffer(BufferTarget.ElementArrayBuffer, _meshBufferObject);
}
protected override ICamera CreateCamera()
{
IsCtrlDown= true;
var camera= new Camera3D();
return camera;
}
public override void KeyUp(object sender, System.Windows.Input.KeyEventArgs e)
{
}
public override void Release()
{
_glControl.MakeCurrent();
// Unbind all the resources by binding the targets to 0/null.
GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
GL.BindVertexArray(0);
GL.UseProgram(0);
// Delete all the resources.
GL.DeleteBuffer(_hazeBufferObject);
GL.DeleteBuffer(_meshBufferObject);
GL.DeleteVertexArray(_hazeArrayObject);
GL.DeleteProgram(_shader.Handle);
}
public override void Draw(ResultDisplayModel result)
{
_glControl.MakeCurrent();
//
var hazeDatas = result.HazeDatas?[(int)Channel - 1];
if (hazeDatas == null || hazeDatas.Length < (int)Channel)
{
_hazeDatas = new float[0];
_glControl.Invalidate();
return;
}
//着色
var colorBar = _wafermap.ColorBar.BinsOrHazeItems;
_colors = new float[colorBar.Count * 3];
for (int i = 0; i < colorBar.Count; i++)
{
_colors[i * 3] = (float)colorBar[i].R / 255;
_colors[i * 3 + 1] = (float)colorBar[i].G / 255;
_colors[i * 3 + 2] = (float)colorBar[i].B / 255;
}
_shader.SetVector3("colors[0]", _colors);
//
_hazeDatas = Normalize((int)result.WaferSize, hazeDatas);
_meshData = PointCloud.BuildMesh(_hazeDatas, _hazeDatas.Length);
//数据绑定
GL.BindBuffer(BufferTarget.ArrayBuffer, _hazeBufferObject);
GL.BufferData(BufferTarget.ArrayBuffer, _hazeDatas.Length * sizeof(float), _hazeDatas, BufferUsageHint.StaticDraw);
GL.BindBuffer(BufferTarget.ElementArrayBuffer, _meshBufferObject);
GL.BufferData(BufferTarget.ElementArrayBuffer, _meshData.size * sizeof(uint), _meshData.ptr, BufferUsageHint.StaticDraw);
//重绘
_glControl.Invalidate();
}
public override void ReDraw()
{
}
public float[] Normalize(int wafersize, HazeData[] hazeDatas)
{
var rSize = wafersize / 2 * 1000;
MinThreshold = (float)_wafermap.ColorBar.HazeMinThreshold;
MaxThreshold = (float)_wafermap.ColorBar.HazeMaxThreshold;
if (MinThreshold == 0 && MaxThreshold == 0)
{
var haze2 = hazeDatas.OrderBy(x => x.Z).ToList();
MinThreshold = haze2[haze2.Count / 10].Z;
MaxThreshold = haze2[haze2.Count / 10 * 9].Z;
}
var _hazeDatas = new float[hazeDatas.Length * 3];
for (int i = 0; i < hazeDatas.Length; i++)
{
_hazeDatas[i * 3] = (hazeDatas[i].X / rSize - 1) * SHOW_RATE;
_hazeDatas[i * 3 + 1] = (hazeDatas[i].Y / rSize - 1) * SHOW_RATE;
var signal = hazeDatas[i].Z;
if (signal <= MinThreshold)
_hazeDatas[i * 3 + 2] = 0;
else if (signal >= MaxThreshold)
_hazeDatas[i * 3 + 2] = 0.5f;
else
_hazeDatas[i * 3 + 2] = (signal - MinThreshold) / (MaxThreshold - MinThreshold) *0.5f;
}
return _hazeDatas;
}
private Matrix4 _modelMatrix = Matrix4.Identity;
public override void Paint(object? sender, PaintEventArgs e)
{
lock (this)
{
_glControl.MakeCurrent();
}
GL.Clear(ClearBufferMask.ColorBufferBit);
if (_hazeDatas == null || _hazeDatas.Length == 0)
return;
_shader.Use();
_shader.SetMatrix4("haze3dModel",_modelMatrix);
_shader.SetMatrix4("haze3dView", _camera.GetViewMatrix());
_shader.SetMatrix4("haze3dProjection",((Camera3D) _camera).GetProjectionMatrix());
GL.BindVertexArray(_hazeArrayObject);
GL.DrawElements(PrimitiveType.Triangles, _meshData.size, DrawElementsType.UnsignedInt, 0);
_glControl.SwapBuffers();
}
}
class PointCloud
{
[DllImport("Waferscan.Result.PointCloud.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern MeshData BuildMesh(float[] datas, int size);
}
public struct MeshData
{
public IntPtr ptr;
public int size;
}
}
这是Draw的代码,#version 330 core
layout(location = 0) in vec3 aPosition;
uniform mat4 haze3dView;
uniform mat4 haze3dModel;
uniform mat4 haze3dProjection;
out vec3 vPos;
void main()
{
gl_Position = haze3dProjection * haze3dView * haze3dModel * vec4(aPosition, 1.0);
vPos = aPosition;
}这是.vert的代码,using OpenTK.Graphics.OpenGL4;
using OpenTK;
using OpenTK.Mathematics;
namespace Waferscan.GUI.Result.OpenGL
{
public class Camera3D : ICamera
{
// Default camera values
const float YAW = -90.0f;
const float PITCH = 0.0f;
const float SPEED = 2.5f;
const float SENSITIVITY = 0.1f;
const float DEFAULT_ZOOM = 45.0f;
// camera Attributes
public Vector3 Position { get; set; }=new Vector3(0.0f,0.0f,5.0f);
Vector3 Front;
Vector3 Up;
Vector3 Right;
Vector3 WorldUp=new Vector3(0.0f,1.0f,0.0f);
// euler Angles
private float Yaw=YAW;
private float Pitch=PITCH;
private float _viewportWidth = 800;
private float _viewportHeight = 600;
public void UpdateViewport(int Height, int Width)
{
_viewportHeight = Height;
_viewportWidth = Width;
}
// camera options
float MovementSpeed= SPEED;
float MouseSensitivity = SENSITIVITY;
public float _fieldOfView = MathHelper.DegreesToRadians(DEFAULT_ZOOM);
//Projection parameters
public float FieldOfView
{
get=>_fieldOfView;
set=>_fieldOfView=value;
}
public float AspectRatio { get; set; } = 16.0f / 9.0f;
public float NearPlane { get; set; } = 0.1f;
public float FarPlane { get; set; } = 1000.0f;
//Model matrix
public Matrix4 ModelMatrix { get; private set; } = Matrix4.Identity;
//Fog effect parameters
public float FogStart { get; set; } = 0.0f;
public float FogEnd { get; set; } = 10.0f;
public float Scale { get; set; } = 1.0f;
public Camera3D()
{
UpdateModelMatrix(Vector3.Zero, Vector3.Zero, Vector3.One);
updateCameraVectors();
}
// returns the view matrix calculated using Euler Angles and the LookAt Matrix
public Matrix4 GetViewMatrix()
{
return Matrix4.LookAt(Position, Position + Front, Up);
}
//returns the projection matrix calculated using the Euler angle and the LookAt matrix
public Matrix4 GetProjectionMatrix()
{
float fov = _fieldOfView;
float aspectRatio = _viewportWidth / _viewportHeight;
float near = NearPlane;
float far = FarPlane;
return Matrix4.CreatePerspectiveFieldOfView(fov, aspectRatio, near, far );
}
/// <summary>
/// Update the model fov, aspectRatio, near, far) (position, rotation, scale) and save the current state
/// </summary>
public void UpdateModelMatrix(Vector3 position, Vector3 rotation, Vector3 scale)
{
//Matrix multiplication order: first scale, then rotate, and finally translate
ModelMatrix = Matrix4.Identity;
ModelMatrix *= Matrix4.CreateScale(scale);
ModelMatrix *= Matrix4.CreateRotationX(MathHelper.DegreesToRadians(rotation.X));
ModelMatrix *= Matrix4.CreateRotationY(MathHelper.DegreesToRadians(rotation.Y));
ModelMatrix *= Matrix4.CreateRotationZ(MathHelper.DegreesToRadians(rotation.Z));
ModelMatrix *= Matrix4.CreateTranslation(position);
}
//Pass parameters to the shader
public void SetShaderParameters(int shaderProgram)
{
if (shaderProgram == 0)
{
Console.WriteLine("Error: Shader program is not initialized!");
return;
}
//Pass model matrix
var tempModel = ModelMatrix;
int modelLoc = GL.GetUniformLocation(shaderProgram, "haze3dModel");
Console.WriteLine($"modelLoc: {modelLoc}");
Console.WriteLine($"ModelMatrix: {ModelMatrix}");
if (modelLoc != -1)
GL.UniformMatrix4(modelLoc, false, ref tempModel);
else
Console.WriteLine("Warning: Uniform 'haze3dModel' not found in shader!");
//Pass view matrix
Matrix4 viewMatrix =GetViewMatrix();
int viewLoc = GL.GetUniformLocation(shaderProgram, "haze3dView");
if (viewLoc != -1)
GL.UniformMatrix4(viewLoc, false, ref viewMatrix);
else
Console.WriteLine("Warning: Uniform 'haze3dView' not found in shader!");
//Pass projection matrix
Matrix4 projectionMatrix =GetProjectionMatrix();
int projectionLoc = GL.GetUniformLocation(shaderProgram, "haze3dProjection"); // 确保名称严格匹配着色器
if (projectionLoc == -1)
{
Console.WriteLine("ERROR: Uniform 'haze3dProjection' not found in shader!");
}
if (projectionLoc != -1)
GL.UniformMatrix4(projectionLoc, false, ref projectionMatrix);
else
Console.WriteLine("Warning: Uniform 'haze3dProjection' not found in shader!");
//Pass the fog effect parameters
int fogStartLoc = GL.GetUniformLocation(shaderProgram, "fogStart");
if (fogStartLoc != -1)
GL.Uniform1(fogStartLoc, FogStart);
else
Console.WriteLine("Warning: Uniform 'fogStart' not found in shader!");
int fogEndLoc = GL.GetUniformLocation(shaderProgram, "fogEnd");
if (fogEndLoc != -1)
GL.Uniform1(fogEndLoc, FogEnd);
else
Console.WriteLine("Warning: Uniform 'fogEnd' not found in shader!");
}
public Vector3 GetMouseViewPos(Vector2 mousePos)
{
throw new NotImplementedException();
}
// processes input received from a mouse input system. Expects the offset value in both the x and y direction.
public void ProcessMouseMovement(float xoffset, float yoffset)
{
xoffset *= MouseSensitivity;
yoffset *= MouseSensitivity;
Yaw += xoffset;
Pitch += yoffset;
// make sure that when pitch is out of bounds, screen doesn't get flipped
Pitch = MathHelper.Clamp(Pitch, -89.0f, 89.0f);
// Normalize yaw to 0-360 degrees
Yaw = Yaw % 360.0f;
// update Front, Right and Up Vectors using the updated Euler angles
updateCameraVectors();
}
// processes input received from a mouse scroll-wheel event. Only requires input on the vertical wheel-axis
public void ProcessMouseScroll(float x, float y, float delta)
{
Scale = MathHelper.Clamp(Scale-delta,1.0f,45.0f);
}
// Update camera direction vectors
private void updateCameraVectors()
{
// calculate the new Front vector
Vector3 front = new Vector3
{
X = (float)(Math.Cos(MathHelper.DegreesToRadians(Yaw)) * Math.Cos(MathHelper.DegreesToRadians(Pitch))),
Y = (float)Math.Sin(MathHelper.DegreesToRadians(Pitch)),
Z = (float)(Math.Sin(MathHelper.DegreesToRadians(Yaw)) * Math.Cos(MathHelper.DegreesToRadians(Pitch))),
};
Front = Vector3.Normalize(front);
// also re-calculate the Right and Up vector
Right = Vector3.Normalize(Vector3.Cross(Front, WorldUp)); // normalize the vectors, because their length gets closer to 0 the more you look up or down which results in slower movement.
Up = Vector3.Normalize(Vector3.Cross(Right, Front));
}
public void ReSet()
{
//Reset the position
Position = new Vector3(0.0f, 0.0f, 5.0f);
//Reset Euler angle
Yaw = YAW;
Pitch = PITCH;
//Reset the field of view angle
FieldOfView = MathHelper.DegreesToRadians(DEFAULT_ZOOM);
ModelMatrix = Matrix4.Identity;
//update Front, Right and Up Vectors using the updated Euler angles
updateCameraVectors();
}
}
}
这是Camera的代码 请问对于实现三个矩阵有什么问题呢