您的位置:首页 > 编程语言 > C#

CSharpGL(11)用C#直接编写GLSL程序

2016-01-30 18:12 411 查看
[b]CSharpGL(11)用C#直接编写GLSL程序 [/b]

+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吧。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: