CSharpGL(11)用C#直接编写GLSL程序
2016-01-30 18:12
411 查看
[b]CSharpGL(11)用C#直接编写GLSL程序 [/b]
+BIT祝威+悄悄在此留下版了个权的信息说:
现在(2016年1月30日)编写GLSL的shader程序时,并没有什么好的开发环境。智能提示、代码补全、自动排版都没有。基本上我是用notepad++之类的编辑器写的。
很苦恼,一度导致我对shader有偏见。
GLSL是类似C语言的。我发现几乎所有的GLSL里出现的语法形式都可以用C#以相同的方式写出来。那么用C#来写"GLSL代码",之后再自动转换为纯粹的GLSL代码,岂非一大快事?!
在本项目定义的类型基础上,你就可以直接用C#来写GLSL代码了。(只有很少的几点不同,到时候你会立即明白的。)
C#版的GLSL,以后就称为CSSL(C# Shader Language)。
+BIT祝威+悄悄在此留下版了个权的信息说:
+BIT祝威+悄悄在此留下版了个权的信息说:
稍微有所不同的是,'in','out','uniform'等这些qualifier只好用Attribute代表了。
子函数尚未涉及,到时候再说。
不同类型的shader(vertex、fragment、geometry、tessellation等)都有些相同的内置函数,也都有各自独特的内置变量,这就是本项目的类库设计要描述的对象。
对于用户来说,用户只需写出CSSL的代码,即可一键自动获取GLSL的代码。
CSSL写好了,当然应该自动地转换为GLSL。否则还有什么意义。
设计方案很简单。包含CSSL的*.cs文件作为输入,对应的GLSL文件(*.vert或*.frag)作为输出。用反射获取in、out、uniform这些变量,用正则表达式获取main函数代码。最后用字符串拼接起来就是。Shader有多种,所以要有一个抽象和继承关系。
CSSL2GLSLDump20160216-125347.simple.log
而在有了cssl.cs扩展名这个规定后,我发现完整版log常常和精简版log的内容完全相同。这也成了一种快速推测cssl是否有问题的方式。
还有下面这样的,都支持。
对应上面的两个GLSL类型,C#中的CSSL写法是这样的:
这个会自动转换为GLSL中的:
+BIT祝威+悄悄在此留下版了个权的信息说:
由来
本项目的目的:使开发者可以直接用C#书写GLSL代码。现在(2016年1月30日)编写GLSL的shader程序时,并没有什么好的开发环境。智能提示、代码补全、自动排版都没有。基本上我是用notepad++之类的编辑器写的。
很苦恼,一度导致我对shader有偏见。
GLSL是类似C语言的。我发现几乎所有的GLSL里出现的语法形式都可以用C#以相同的方式写出来。那么用C#来写"GLSL代码",之后再自动转换为纯粹的GLSL代码,岂非一大快事?!
在本项目定义的类型基础上,你就可以直接用C#来写GLSL代码了。(只有很少的几点不同,到时候你会立即明白的。)
C#版的GLSL,以后就称为CSSL(C# Shader Language)。
下载
这个项目是CSharpGL的一部分,CSharpGL已在GitHub开源,欢迎对OpenGL有兴趣的同学加入(https://github.com/bitzhuwei/CSharpGL)+BIT祝威+悄悄在此留下版了个权的信息说:
示例
从一个简单的例子来抽象出整个项目的设计方案来。Vertex shader(GLSL)
这是一个典型的vertex shader。#version 150 core in vec3 in_Position; in vec2 in_UV; out vec2 pass_UV; uniform mat4 projectionMatrix; uniform mat4 viewMatrix; uniform mat4 modelMatrix; void main(void) { gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(in_Position, 1.0); pass_UV = in_UV; }
对应的C#写法(CSSL)
我用如下的C#代码与之对应,并期望将来能够将其自动转化为上文的vertex shader。class DemoVert { vec4 gl_Position; [In] vec3 in_Position; [In] vec2 in_UV; [Out] vec2 pass_UV; [Uniform] mat4 projectionMatrix; [Uniform] mat4 viewMatrix; [Uniform] mat4 modelMatrix; void main() { gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(in_Position, 1.0); pass_UV = in_UV; } }
Fragment shader(GLSL)
这是一个典型的fragment shader。与上文的vertex shader可以组成一个shader program。#version 150 core in vec2 pass_UV; out vec4 out_Color; uniform sampler2D texture1; uniform sampler2D texture2; uniform float percent; void main(void) { vec4 color = texture(texture1, pass_UV) * percent + texture(texture2, pass_UV) * (1.0 - percent); out_Color = color; //out_Color = texture(texture2, pass_UV); //out_Color = texture(texture1, pass_UV); }
对应的C#写法(CSSL)
我用如下的C#代码与之对应,并期望将来能够将其自动转化为上文的fragment shader。class DemoFrag { [In] vec2 pass_UV; [Out] vec4 out_Color; [Uniform] sampler2D texture1; [Uniform] sampler2D texture2; [Uniform] float percent; void main() { vec4 color = texture(texture1, pass_UV) * percent + texture(texture2, pass_UV) * (1.0f - percent); out_Color = color; //out_Color = texture(texture2, pass_UV); //out_Color = texture(texture1, pass_UV); } private vec4 texture(sampler2D texture1, vec2 pass_UV) { throw new NotImplementedException(); } }
+BIT祝威+悄悄在此留下版了个权的信息说:
设计
大体思路就如上面的例子。顶点属性、uniform变量都可以用C#字段表示。main函数、内置函数、内置变量都可以用C#相应的函数和类型表示。稍微有所不同的是,'in','out','uniform'等这些qualifier只好用Attribute代表了。
子函数尚未涉及,到时候再说。
不同类型的shader(vertex、fragment、geometry、tessellation等)都有些相同的内置函数,也都有各自独特的内置变量,这就是本项目的类库设计要描述的对象。
对于用户来说,用户只需写出CSSL的代码,即可一键自动获取GLSL的代码。
CSSL写好了,当然应该自动地转换为GLSL。否则还有什么意义。
CSSL
将C#代码转换为另一种形式,无非是反射+字符串解析拼接之类的东西。设计方案很简单。包含CSSL的*.cs文件作为输入,对应的GLSL文件(*.vert或*.frag)作为输出。用反射获取in、out、uniform这些变量,用正则表达式获取main函数代码。最后用字符串拼接起来就是。Shader有多种,所以要有一个抽象和继承关系。
Directory: C:\Users\威\Documents\GitHub\CSharpGL Found 20 CSSL shaders, and 0 of them are dumped to GLSL as needed. --> Translating C:\Users\威\Documents\GitHub\CSharpGL\Demos\CSharpGL.LightEffects\DiffuseReflectionDirectionalLight.cssl.cs 2 CSSL shaders: Not need to dump [DiffuseReflectionDirectionalLightVert] to [DiffuseReflectionDirectionalLight.vert] OK! Not need to dump [DiffuseReflectionDirectionalLightFrag] to [DiffuseReflectionDirectionalLight.frag] OK! --> Translating C:\Users\威\Documents\GitHub\CSharpGL\Demos\CSharpGL.LightEffects\DiffuseReflectionPointLight.cssl.cs 2 CSSL shaders: Not need to dump [DiffuseReflectionPointLightVert] to [DiffuseReflectionPointLight.vert] OK! Not need to dump [DiffuseReflectionPointLightFrag] to [DiffuseReflectionPointLight.frag] OK! --> Translating C:\Users\威\Documents\GitHub\CSharpGL\Demos\CSharpGL.LightEffects\PhongPointLight.cssl.cs 2 CSSL shaders: Not need to dump [PhongPointLightVert] to [PhongPointLight.vert] OK! Not need to dump [PhongPointLightFrag] to [PhongPointLight.frag] OK! --> Translating C:\Users\威\Documents\GitHub\CSharpGL\Demos\CSharpGL.Objects.Demos\NormalLine.cssl.cs 3 CSSL shaders: Not need to dump [NormalLineVert] to [NormalLine.vert] OK! Not need to dump [NormalLineFrag] to [NormalLine.frag] OK! Not need to dump [NormalLineGeom] to [NormalLine.geom] OK! --> Translating C:\Users\威\Documents\GitHub\CSharpGL\Demos\CSharpGL.Objects.Demos\Simple.cssl.cs 3 CSSL shaders: Not need to dump [SimpleVert] to [Simple.vert] OK! Not need to dump [SimpleFrag] to [Simple.frag] OK! Not need to dump [SimpleGeom] to [Simple.geom] OK! --> Translating C:\Users\威\Documents\GitHub\CSharpGL\Functions\CSharpGL.Objects.Common\AxisElement.cssl.cs 2 CSSL shaders: Not need to dump [AxisElementVert] to [AxisElement.vert] OK! Not need to dump [AxisElementFrag] to [AxisElement.frag] OK! --> Translating C:\Users\威\Documents\GitHub\CSharpGL\Tools\CSharpGL.ObjViewer\ObjFile.cssl.cs 3 CSSL shaders: Not need to dump [ObjFileVert] to [ObjFile.vert] OK! Not need to dump [ObjFileGeom] to [ObjFile.geom] OK! Not need to dump [ObjFileFrag] to [ObjFile.frag] OK! --> Translating C:\Users\威\Documents\GitHub\CSharpGL\Tools\ShaderLab\Some.cssl.cs 3 CSSL shaders: Not need to dump [SomeVert] to [Some.vert] OK! Not need to dump [SomeFrag] to [Some.frag] OK! Not need to dump [SomeGeom] to [Some.geom] OK! Translation all done!
CSSL2GLSLDump20160216-125347.simple.log
而在有了cssl.cs扩展名这个规定后,我发现完整版log常常和精简版log的内容完全相同。这也成了一种快速推测cssl是否有问题的方式。
支持geometry shader
现在的CSSL支持geometry shader的编写和代码生成。并且,代码生成过程中也会自动解析用户自定义的结构类型,例如下面这样的:1 in VS_GS_VERTEX 2 { 3 vec3 normal; 4 } vertex_in[];
还有下面这样的,都支持。
1 out GS_FS_VERTEX 2 { 3 vec3 color; 4 } vertex_out;
对应上面的两个GLSL类型,C#中的CSSL写法是这样的:
1 class VS_GS_VERTEX 2 { 3 public vec3 normal;//必须是public的字段 4 } 5 [In] 6 VS_GS_VERTEX[] vertex_in;
1 class GS_FS_VERTEX 2 { 3 public vec3 color;//必须是public的字段 4 } 5 [Out] 6 GS_FS_VERTEX vertex_out;
初始值的自动转化
此外,像下面这样的C#中的初始值也支持自动转化到GLSL。1 [Uniform] 2 float normalLength = 0.5f;
这个会自动转换为GLSL中的:
1 uniform float normalLength = 0.5;
总结
目前的CSSL并未完全覆盖GLSL的功能。因为我原本就没有多少写GLSL的经历。等我慢慢用GLSL的情形多了,再逐步补充CSSL吧。相关文章推荐
- 全面解读C#编程中的析构函数用法
- 解析C#中的私有构造函数和静态构造函数
- 详解C#编程中构造函数的使用
- 浅谈C#指针问题
- 理解C#中参数的值和引用以及传递结构和类引用的区别
- 深入解析C#中的命名实参和可选实参
- C# split字符串 依据1个或多个空格
- C#基础(WinForm窗体的单例模式,避免窗体被实例化多次)
- C#基础(WinForm窗体的单例模式,避免窗体被实例化多次)
- 解析C#面向对象编程中方法(method)的使用
- C# 多线程运用
- C# LinQ的认识
- 详解C#中的接口属性以及属性访问器的访问限制
- C#基础之类型转换
- c#多线程与异步开发 (下)
- 举例讲解C#中自动实现的属性
- c#之params参数
- c#之ref参数
- C#文件读/写
- c#之out参数