未能成功使用
#region 舍弃
GLSL语言:顶点着色器的shader(这里填写5,6是为了演示,可取0,1,2,3...)
// 顶点着色器
const string vertexCode = "#version 330 core\n" + // 3.30版本(版本申明)
"layout(location = 0) in vec3 position_1;\n" + // 三个浮点数 vector 向量表示位置。position是变量,并储存了这三个向量
"void main()\n" +
"{\n" +
"gl_Position = vec4(position_1, 1.0f);\n" + // 核心函数(位置信息赋值)
"}\n";
//string vertexShaderSource = @"
// #version 330 core
// layout(location = 5) in vec3 position;
// layout(location = 6) in vec4 color;
// out vec4 coInterim;
// void main()
// {
// gl_Position = vec4(position, 1.0);
// coInterim = color;
// }";
// 片元着色器
const string SliceShaderCode = "#version 330 core\n" + // 版本信息3.3
"out vec4 FragColor_1;\n" + // 输出是四个浮点数构成的一个向量 RGB+aerfa
"void main()\n" +
"{\n" +
"FragColor_1 = vec4(0.5f, 0.75f, 0.25f, 1.0f);\n" + // 核心函数(颜色信息赋值)
"}\n";
GLSL语言:片元着色器的shader
//string fragmentShaderSource = @"
//#version 330 core
//in vec4 coInterim;
//out vec4 FragColor;
//void main()
//{
// FragColor = coInterim;
//}";
//OpenGL? gl;
//uint[] vaos = new uint[1];
//uint[] vbos = new uint[2];
//uint[] EBO = new uint[1];
//private uint shaderProgram = 0;
//IntPtr pArrayIn1;
//IntPtr pArrayInColor1;
//float[] vertices = //顶点位置数组
// {
// -0.5f, 0.5f,-0f,
// 0.5f, 0.5f, -0f,
// 0.5f, -0.5f,-0f,
// -0.5f, -0.5f,-0f,
// };
//float[] colors = //颜色数组(rgba参数-渐变)
//{
// 1f, 1f, 1f, 1f,//白色
// 1f, 1f, 1f, 1f,//白色
// 0.94f, 0.69f, 0.45f,1f,//橙色
// 0.94f, 0.69f, 0.45f,1f//橙色
// };
/ <summary>
/ 顶点索引
/ </summary>
//int[] index;
/ <summary>
/ 颜色数组
/ </summary>
//float[] colors;
/ <summary>
/ 顶点数组
/ </summary>
//float[] vertices;
#endregion
/// <summary>
/// 初始化
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void OpenGLControl1_OpenGLInitialized(object sender, EventArgs e)
{
OpenGL gl = openGLControl1.OpenGL;
openGLControl1.FrameRate = 40; //帧率为40
#region 测试
//gl.ClearColor(0, 0, 0, 0);
//gl.Clear(OpenGL.GL_COLOR_BUFFER_BIT | OpenGL.GL_DEPTH_BUFFER_BIT);
//gl.Color(1, 0, 0, 1.0f);
创建并编译顶点着色器
创建顶点着色器对象
//uint vertexShader = gl.CreateShader(OpenGL.GL_VERTEX_SHADER);
将顶点着色器的内容传进来
//gl.ShaderSource(vertexShader, vertexShaderSource);
编译顶点着色器
//gl.CompileShader(vertexShader);
// 如果出错,用 glGetShaderInfoLog函数 来获取错误消息
StringBuilder glError = new StringBuilder();
gl.GetShaderInfoLog(vertexShader, 1000, new IntPtr(), glError);
//var check = GetCompileStatus(vertexShader);
创建并编译片段着色器
创建片元着色器对象
//uint fragmentShader = gl.CreateShader(OpenGL.GL_FRAGMENT_SHADER);
将片元着色器的内容传进来
//gl.ShaderSource(fragmentShader, fragmentShaderSource);
编译顶点着色器
//gl.CompileShader(fragmentShader);
// 如果出错,用 glGetShaderInfoLog函数 来获取错误消息
StringBuilder SliceShaderError = new StringBuilder();
gl.GetShaderInfoLog(fragmentShader, 1000, new IntPtr(), SliceShaderError);
//var check2 = GetCompileStatus(fragmentShader);
创建着色器程序并链接
glCreateProgram 函数会创建一个着色器程序,并返回新创建程序对象的 ID 引用。
//this.shaderProgram = gl.CreateProgram();
用 glLinkProgram 把之前编译的 顶点着色器 附加到程序对象上
//gl.AttachShader(this.shaderProgram, vertexShader);
用 glLinkProgram 把之前编译的 片元着色器 附加到程序对象上
//gl.AttachShader(this.shaderProgram, fragmentShader);
最后用 glLinkProgram 链接
//gl.LinkProgram(this.shaderProgram);
glValidateProgram — 验证程序对象
//gl.ValidateProgram(this.shaderProgram);
在把着色器对象链接到程序对象以后,记得删除着色器对象,我们不再需要它们了:(这可以释放资源,节省空间)
//gl.DeleteShader(vertexShader);
//gl.DeleteShader(fragmentShader);
// 如果出错,用 glGetShaderInfoLog函数 来获取错误消息
StringBuilder shaderProgramError = new StringBuilder();
gl.GetProgramInfoLog(shaderProgram, 1000, new IntPtr(), shaderProgramError);
获取自定义输入属性的位置(对应GLSL语言语言申明的location索引)信息
注意,若GLSL语言没有写对(或GLSL内部申明了location却没有使用),这里不报错,只是获取到的是 - 1
//var positionLocation = gl.GetAttribLocation(this.shaderProgram, "position");
//var colorLocation = gl.GetAttribLocation(this.shaderProgram, "color");
创建VAO并绑定
VAO 对应的一种 关联信息(顶点着色器和位置相映射) 绑定 VAO
//gl.GenVertexArrays(1, vaos);//创建1个VAO数组,但填入一个VAO,模拟一个VAO对应多个VBO
绑定 VAO 和 VBO
//gl.BindVertexArray(vaos[0]); //绑定VAO到上下文
VBO 主要负责传输数据 绑定 VBO
创建2个VBO用于存储顶点数据和颜色数据
//gl.GenBuffers(2, vbos);//创建2个VBO
绑定第一个VBO存顶点
把新创建的顶点缓冲对象绑定到 GL_ARRAY_BUFFER 目标上,顶点缓冲对象的缓冲类型是GL_ARRAY_BUFFER
//gl.BindBuffer(OpenGL.GL_ARRAY_BUFFER, vbos[0]);
GL_STATIC_DRAW:静态的画图(频繁地读)
//gl.BufferData(OpenGL.GL_ARRAY_BUFFER, vertices, OpenGL.GL_DYNAMIC_DRAW);
绑定 EBO
//gl.GenBuffers(1, EBO);
使用 glBindBuffer 函数把新创建的索引缓冲对象绑定到 GL_ELEMENT_ARRAY_BUFFER目标上
//gl.BindBuffer(OpenGL.GL_ELEMENT_ARRAY_BUFFER, EBO[0]);
GL_STATIC_DRAW:静态的画图(因为要频繁地读)
//gl.BufferData(OpenGL.GL_ELEMENT_ARRAY_BUFFER, indices_1, OpenGL.GL_STATIC_DRAW);
绑定 EBO
//gl.BindBuffer(OpenGL.GL_ELEMENT_ARRAY_BUFFER, EBO[0]);
画两个三角形 从第0个顶点开始 一共画 6 次(顺序为0,1,3,1,2,3)
//IntPtr intPtr = IntPtr.Zero;
//gl.DrawElements(OpenGL.GL_TRIANGLES, 6, OpenGL.GL_UNSIGNED_INT, intPtr);
解绑定 EBO
//gl.BindBuffer(OpenGL.GL_ELEMENT_ARRAY_BUFFER, 0);
//pArrayIn1 = Marshal.AllocHGlobal(vertices.Length * sizeof(float)); //申请数组的指针
///* 设置链接顶点属性 */
可以使用 glVertexAttribPointer 函数告诉 OpenGL 该如何解析顶点数据
申明位置解释规则。
//gl.VertexAttribPointer((uint)positionLocation, 3, OpenGL.GL_FLOAT, false, 0, IntPtr.Zero);
注意,这里第一个参数并不是像很多教程那样直接填0或1,很有歧义!实时上他是GLSL语言的location信息,只不过网上有些教程刚好使用了GLSL默认位置的0和1而已。
作为示范,我这里故意在GLSL语言中显示声明location = 5,而这里为了灵活,直接用位置变量
启用顶点属性(注:顶点属性默认是禁用的)。
//gl.EnableVertexAttribArray((uint)positionLocation);
绑定第二个VBO存颜色
//gl.BindBuffer(OpenGL.GL_ARRAY_BUFFER, vbos[1]);
//gl.BufferData(OpenGL.GL_ARRAY_BUFFER, colors, OpenGL.GL_DYNAMIC_DRAW); //GL_DYNAMIC_DRAW GL_STATIC_DRAW
pArrayInColor1 = Marshal.AllocHGlobal(colors.Length * sizeof(float)); //申请数组的指针。
//gl.VertexAttribPointer((uint)colorLocation, 4, OpenGL.GL_FLOAT, false, 0, IntPtr.Zero); //申明颜色解释规则。
//gl.EnableVertexAttribArray((uint)colorLocation);
解绑
//gl.BindVertexArray(0);
#endregion
gl.MatrixMode(OpenGL.GL_PROJECTION);
//投影初始化
gl.LoadIdentity();
//设置为正交投影
gl.Ortho(-2000, 2000, -2000, 2000, 0.00001, 10000.0);
//设置视角,相机视角在(0,0,2000),眼睛为(0,0,0)
gl.LookAt(0, 0, 2000, 0, 0, 0, 0, 1, 0);
//设置为视图模式
gl.MatrixMode(OpenGL.GL_MODELVIEW);
gl.GetFloat(OpenGL.GL_MODELVIEW_MATRIX, _modelviewMatrix);
}
/// <summary>
/// 获取编译状态
/// </summary>
/// <param name="shar"></param>
/// <returns></returns>
public bool GetCompileStatus(uint shar)
{
OpenGL gl = openGLControl1.OpenGL;
int[] parameters = new int[] { 0 };
gl!.GetShader(shar, OpenGL.GL_COMPILE_STATUS, parameters);
return parameters[0] == OpenGL.GL_TRUE;
}
/// <summary>
/// 绘制事件
/// </summary>
/// <param name="sender"></param>
/// <param name="args"></param>
private void openGLControl1_OpenGLDraw(object sender, RenderEventArgs args)
{
OpenGL gl = openGLControl1.OpenGL;
#region 测试
//gl.Clear(OpenGL.GL_COLOR_BUFFER_BIT | OpenGL.GL_DEPTH_BUFFER_BIT);//DEPTH_BUFFER_BIT在变化窗口大小时需要写,否则变化后不出图
//gl.EnableClientState(OpenGL.GL_VERTEX_ARRAY); //允许设置顶点
//gl.EnableClientState(OpenGL.GL_COLOR_ARRAY); //允许设置顶点颜色数组
//gl.EnableClientState(OpenGL.GL_INDEX_ARRAY);
//IntPtr pArray = Marshal.AllocHGlobal(vertices.Length * sizeof(float)); //申请数组的指针
//IntPtr pColorArray = Marshal.AllocHGlobal(colors.Length * sizeof(float));
IntPtr Index = Marshal.AllocHGlobal(index.Length * sizeof(int)); //申请数组的指针
//try
//{
// Marshal.Copy(vertices, 0, pArray, vertices.Length);
// gl.VertexPointer(3, OpenGL.GL_FLOAT, 0, pArray);//设置正方形的顶点数据
// Marshal.Copy(colors, 0, pColorArray, colors.Length);
// gl.ColorPointer(4, OpenGL.GL_FLOAT, 0, pColorArray);//设置正方形的顶点颜色数据
// //Marshal.Copy(index, 0, Index, index.Length);
// //gl.IndexPointer(OpenGL.GL_INT, 0, index);
//}
//finally
//{
// Marshal.FreeHGlobal(pArray); //释放数组内存
// Marshal.FreeHGlobal(pColorArray);
// //Marshal.FreeHGlobal(Index);
//}
gl.DrawElements(OpenGL.GL_TRIANGLE_FAN, index.Length, OpenGL.GL_UNSIGNED_INT, Index);
//gl.DrawArrays(OpenGL.GL_TRIANGLES, 0, vertices.Length - 1); //绘制正方形
//gl.DisableClientState(OpenGL.GL_VERTEX_ARRAY); //关闭顶点数组
//gl.DisableClientState(OpenGL.GL_COLOR_ARRAY); //关闭顶点颜色数组
//gl.DisableClientState(OpenGL.GL_INDEX_ARRAY);
#endregion
//ClearScreen();
gl.MatrixMode(OpenGL.GL_PROJECTION);
//投影初始化
gl.LoadIdentity();
//设置为正交投影
gl.Ortho(-2000, 2000, -2000, 2000, 0.00001, 10000.0);
//设置视角,相机视角在(0,0,2000),眼睛为(0,0,0)
gl.LookAt(0, 0, 2000, 0, 0, 0, 0, 1, 0);
//设置为视图模式
gl.MatrixMode(OpenGL.GL_MODELVIEW);
if (_readMatrixSw)
{//若窗口大小改变
//写入之前变换的矩阵
gl.LoadMatrixf(_modelviewMatrix);
_readMatrixSw = false;
}
//压入栈(保存数据)
gl.PushMatrix();
//绘制坐标系(可平移旋转)
DrawingCoordinateSystem(gl);
//对后续数据进行缩放
gl.Scale(_displacementDS.ScaleeX, _displacementDS.ScaleeY, _displacementDS.ScaleeZ);
//需要缩放的数据(可以平移旋转)
DrawVertex(_drawMode);
DrawExternalCircle(gl);
//出栈(清除数据)
gl.PopMatrix();
//获取已经变换的矩阵
gl.GetFloat(OpenGL.GL_MODELVIEW_MATRIX, _modelviewMatrix);
}