C#+OpenGL3编程之第一个红色三角形(Shade)

 本文基础:C#+OpenGL3编程之第一个三角形

 教程原文地址:http://www.opengl-tutorial.org/beginners-tutorials/tutorial-2-the-first-triangle/


 本教程从这里开始,越来越不适合初学者阅读了。。。我也没法,不知道老外是怎么想的。

原Lib BUG有这么几个:


glCreateProgram 没有返回值,不知道老外怎么用啊。

更要命的是,做文字处理时候没有考虑.net string是Unicode问题,直接就转。。。太无语了。

我都在注释里面说了,怎么修改上面两个问题,哎。。。

我的解决方案不是十全十美的,比如不支持X64,这个问题留给大家自己思考吧。


首先我还是再次说明下,为了简化我们的教程,我使用了C# 类继承,把我们主要目标放在教程的范围内容。

谁也不希望一个特性却要去几百行代码里面找吧。


using System;
using System.Diagnostics;
using System.Windows.Forms;
using OpenGLDotNet;

namespace OpenGLTK
{
	/// <summary>
	///C# by 大师♂罗莊
	/// 把C移植到C#,并不是那么简单,从这里开始后......
	/// </summary>
	class OpenGL3tutorial2shade : OpenGL3tutorial2
	{
		OpenGL3LoadShaders shade = new OpenGL3LoadShaders();
		public OpenGL3tutorial2shade()
			: base()
		{
			
//			有的显卡支持在线编译,可能有的显卡只支持二进制格式的shader,检测显卡是否支持在线编译调用函数glGetBooleanv(GL_SHADER_COMPILER),如果支持在线编译shader就可以使用函数glShaderSource来指定shader
			bool[] supportSHADER_COMPILER=new bool[1];
			GL.GetBooleanv(GL.GL_SHADER_COMPILER,supportSHADER_COMPILER);
			if(supportSHADER_COMPILER[0]==false)
			{
				MessageBox.Show("您的显卡不支持编译Shade");
			}
			
			shade.LoadShadersinapplication("SimpleVertexShader.vertexshader", "SimpleFragmentShader.fragmentshader");
			Debug.WriteLine( "shade.FragmentShaderErrorMessageString");
			Debug.WriteLine( shade.FragmentShaderErrorMessageString);
			Debug.WriteLine( "shade.getVertexShaderErrorMessageString");
			Debug.WriteLine(shade.getVertexShaderErrorMessageString);
			Debug.WriteLine(shade.ProgramErrorMessageString);
			//ERROR: 0:1: '#version' :  syntax error
			//首先值得一提的是,OpenGL 3.0/3.1/3.2所附带的GLSL标准版本号分别为1.30/1.40/1.50,而如今直接蹦到了3.3/4.0,目的是为了保持和OpenGL的一致性,方便开发人员区分和使用,显著增强图形质量、加速性能、提升编程弹性。
		}

		public override void Dispose()
		{
			shade.Dispose();
			base.Dispose();

		}
		public override void DrawGLScene()
		{
			shade.useshade();
			base.DrawGLScene();
		}
	}
}



/*
 * Created by SharpDevelop.
 * User: luozhuang
 * Date: 2014/12/31
 * Time: 13:38
 * 
 * To change this template use Tools | Options | Coding | Edit Standard Headers.
 */
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using OpenGLDotNet;
using System.IO;
namespace OpenGLTK
{
	/// <summary>
	/// LoadShader加载类by 大师♂罗莊
	/// </summary>
	public class OpenGL3LoadShaders:IDisposable
	{
		#region IDisposable implementation

		public void Dispose()
		{
			GL.DeleteProgram(programID);
		}

		#endregion

		public OpenGL3LoadShaders()
		{
		}
		
		public uint LoadShadersinapplication(String vertex_file_path, String fragment_file_path)
		{
			return LoadShaders(Path.Combine(Application.StartupPath, @"shade\" + vertex_file_path).ToString(), Path.Combine(Application.StartupPath, @"shade\" + fragment_file_path).ToString());
		}
		
		byte[] VertexShaderErrorMessage, FragmentShaderErrorMessage, ProgramErrorMessage;
		uint ProgramID;
		
		public string getVertexShaderErrorMessageString {
			get {
				if (VertexShaderErrorMessage == null || VertexShaderErrorMessage.Length < 1) {
					return string.Empty;
				}
				return Encoding.UTF8.GetString(VertexShaderErrorMessage);
			}
		}
		
		public string FragmentShaderErrorMessageString {
			get {
				if (FragmentShaderErrorMessage == null || FragmentShaderErrorMessage.Length < 1) {
					return string.Empty;
				}
				return Encoding.UTF8.GetString(FragmentShaderErrorMessage);
			}
		}
		
		public string ProgramErrorMessageString {
			get {
				if (ProgramErrorMessage == null || ProgramErrorMessage.Length < 1) {
					return string.Empty;
				}
				return Encoding.UTF8.GetString(ProgramErrorMessage);
			}
		}
		public uint LoadShaders(String vertex_file_path, String fragment_file_path)
		{
			
			
			// Create the shaders
			//需要修改源代码
			// GLAPI GLuint APIENTRY glCreateProgram (void);
			//        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
			//        private delegate GLuint TglCreateProgram();
			//        private static TglCreateProgram glCreateProgram = null;
			//        // GLAPI GLuint APIENTRY glCreateShader (GLenum type);
			//        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
			//        private delegate GLuint TglCreateShader(GLenum type);
			//        private static TglCreateShader glCreateShader = null;
			//原代码没有返回值,不知道以后咋用啊。。

			uint VertexShaderID = GL.CreateShader(GL.GL_VERTEX_SHADER);
			uint FragmentShaderID = GL.CreateShader(GL.GL_FRAGMENT_SHADER);
			
			// 读取 Vertex Shader文件
			//文本编码根据Shader文件决定,不会的自己用EmEditor这些工具查看编码
			string[] VertexShaderCode = new string[]{ File.ReadAllText(vertex_file_path, Encoding.ASCII) };
			
			// 读取Fragment Shader文件
			string[] FragmentShaderCode = new string[]{ File.ReadAllText(fragment_file_path, Encoding.ASCII) };
			
			
			int[] Result = new int[1];
			int[] InfoLoGLength = new int[1];
			
			//ERROR: 0:1: '' : syntax error: #version is mandatory and should be set before any other token
			//.net字符串都是unicode,可是OpenGL都是Ascii,需要转换。
			
			/// GLAPI void APIENTRY glShaderSource (GLuint shader, GLsizei count, const GLchar* *string, const GLint *length)
			/// /// MARSHALING FUNCTIONS.net字符串都是unicode,可是OpenGL都是Ascii,需要转换。
			///原方法用String转char* 是不行的。
	/// GLAPI void APIENTRY glShaderSource (GLuint shader, GLsizei count, const GLchar* *string, const GLint *length)
		/// /// MARSHALING FUNCTIONS.net字符串都是unicode,可是OpenGL都是Ascii,需要转换。
		///原方法用String转char* 是不行的。
		/// 修改过支持ASCII文字by 大师♂罗莊
//		public unsafe static void ShaderSourceASCII(GLuint shader, GLsizei count, string[] strings, GLint[] length)
//		{
//			if (glShaderSource != null) {
//				IntPtr strptrtable = BuildStringIntPtrTableASCII(strings);
//
//				fixed (GLint* ptr_length = length) {
//					glShaderSource(shader, count, (GLchar**)strptrtable, ptr_length);
//				}
//
//				Marshal.FreeHGlobal(strptrtable);
//			}
//		}
//		///
//		
//		///
//		// MARSHALING FUNCTIONS
//		///
//		/// 修改过支持ASCII文字by 大师♂罗莊
//		private unsafe static IntPtr BuildStringIntPtrTableASCII(string[] strings)
//		{
//			IntPtr StrPtrTable = IntPtr.Zero;
//
//			if (strings != null) {
//				StrPtrTable = Marshal.AllocHGlobal(strings.Length * 4);
//
//				for (int counter = 0; counter < strings.Length; counter++) {
//					//定义是public struct System.Byte GLchar
//					GLchar[] code = System.Text.Encoding.UTF8.GetBytes(strings[counter]);
//					if (code == null || code.Length < 1) {
//						continue;
//					}
//					fixed (GLchar* StrPtr =&code[0]) {
//						IntPtr StrIntPtr = (IntPtr)StrPtr;
//						Marshal.WriteInt32(StrPtrTable, counter * 4, StrIntPtr.ToInt32());
//					}
//				}
//			}
//
//			return StrPtrTable;
//		}

			int[] Stringlength = new int[VertexShaderCode.Length];
			for (int counter = 0; counter < Stringlength.Length; counter++) {
				Stringlength[counter] =	VertexShaderCode[counter].Length;
			}
			
			// 编译 Vertex Shader
			//这里大家要多看SDK文档,因为ShaderSource 最后一个参数传null意思是自动按照null算字符长度,我们需要传多个字符,需要指定长度
			GL.ShaderSourceASCII(VertexShaderID, 1, VertexShaderCode, Stringlength);
			GL.CompileShader(VertexShaderID);
			
			//(0) : error C0206: invalid token "<null atom>" in version line
			//如果提示这个错误,请用下面代码检查一下你传入的代码
			//检查传入的代码对不对,只是作为教程时候使用,我自己加的
			int buffersize = 2048;//这个根据你写的shade文件大小决定,教程也就1KB不到
			//真搞不懂,为什么GetShaderSource用byte[],而ShaderSource用GLchar**....
			byte[] returnstring = new byte[buffersize];
			GL.GetShaderSource(VertexShaderID, buffersize, Stringlength, returnstring);
			string CheckString = System.Text.UTF8Encoding.UTF8.GetString(returnstring);
			
			
			// 检查 Vertex Shader
			GL.GetShaderiv(VertexShaderID, GL.GL_COMPILE_STATUS, Result);
			GL.GetShaderiv(VertexShaderID, GL.GL_INFO_LOG_LENGTH, InfoLoGLength);
			VertexShaderErrorMessage = new byte[InfoLoGLength[0]];
			GL.GetShaderInfoLog(VertexShaderID, InfoLoGLength[0], null, VertexShaderErrorMessage);
			
			
			Stringlength = new int[FragmentShaderCode.Length];
			for (int counter = 0; counter < Stringlength.Length; counter++) {
				Stringlength[counter] =	FragmentShaderCode[counter].Length;
			}
			// 编译 Fragment Shader
			GL.ShaderSourceASCII(FragmentShaderID, 1, FragmentShaderCode, Stringlength);
			GL.CompileShader(FragmentShaderID);
			
			// 检查 Fragment Shader
			GL.GetShaderiv(FragmentShaderID, GL.GL_COMPILE_STATUS, Result);
			GL.GetShaderiv(FragmentShaderID, GL.GL_INFO_LOG_LENGTH, InfoLoGLength);
			FragmentShaderErrorMessage = new byte[InfoLoGLength[0]];
			GL.GetShaderInfoLog(FragmentShaderID, InfoLoGLength[0], null, FragmentShaderErrorMessage);
			
			
			// 链接到 program
			
			ProgramID = GL.CreateProgram();
			GL.AttachShader(ProgramID, VertexShaderID);
			GL.AttachShader(ProgramID, FragmentShaderID);
			GL.LinkProgram(ProgramID);
			
			// 检查  program
			GL.GetProgramiv(ProgramID, GL.GL_LINK_STATUS, Result);
			GL.GetProgramiv(ProgramID, GL.GL_INFO_LOG_LENGTH, InfoLoGLength);
			ProgramErrorMessage = new byte[InfoLoGLength[0]];
			GL.GetProgramInfoLog(ProgramID, InfoLoGLength[0], null, ProgramErrorMessage);
			
			
			GL.DeleteShader(VertexShaderID);
			GL.DeleteShader(FragmentShaderID);
			
			return ProgramID;
		}
		private static string[] ReadAllLines(string path, Encoding encoding)
		{
			List<string> list = new List<string>();
			using (StreamReader streamReader = new StreamReader(path, encoding)) {
				string item;
				while ((item = streamReader.ReadLine()) != null) {
					if (String.IsNullOrEmpty(item)) {
						continue;
					}
					list.Add(item);
				}
			}
			return list.ToArray();
		}
		public void useshade()
		{
			GL.UseProgram(ProgramID);
		}
	}
}


我的机器结果:


  Intel HD 4000  显示一个红色的三角形


  GT 650m 显示一个红色的三角形


  Vmware SVGA  3D 无法显示

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值