MoNo.OpenGL.MGL¶
OpenGL のAPIを .NET (C#/F#) から利用しやすくするための薄いラッパーです。
OpenGL の関数はC言語形式なので、そのままでは .NET から利用しづらいと感じることがあります。より .NET から利用しやすくするため下記の点を改善するラッパーとして MGL
を用意しました。
- MoNo.RAIL のデータ型の利用
Vector3d
やHmMatrix3d
といった MoNo.RAIL で用意されているプリミティブなデータ型に対応させました。これにより、例えば OpenGL では3次元ベクトルを長さ3のdouble
/float
配列として入出力する仕様だが、ラッパーによりVector3d
などのデータ型で入出力できるようになりました。
- プロパティによる状態の get/set
- OpenGL では状態の取得と設定が別々の関数になっていますが(例えば
glIsEnabled()
とglEnable(), glDisable()
など)、.NET では get と set はひとつのプロパティにまとめたほうが自然であり使いやすくなります。例えばGL_DEPTH_TEST
の有効/無効状態をMGL.DepthTestEnabled
というプロパティでラップすることによって使いやすくしました。
- 頂点配列の描画の簡略化
- 頂点配列に関する OpenGL のAPIは非常に柔軟性が高く設計されていますが、その分だけ利用にあたっては定型的なコードが増えてしまいがちで気軽に利用することが出来ません。MGL では例えば
PointNormal3f
などといった MoNo.RAIL で用意されているデータ型の配列を受け取るラッパー関数群MGL.DrawArrays()
を備えており、簡便に頂点配列を利用することができます。
- その他
- テクスチャ、シェーダー、FBO、VBO といった機能もラップすることでより簡便に利用できるようになっています。
Contents
プロパティ¶
MGL Property | OpenGL constant |
---|---|
LightingEnabled | GL_LIGHTING |
DepthTestEnabled | GL_DEPTH_TEST |
StencilTestEnabled | GL_STENCIL_TEST |
AlphaTestEnabled | GL_ALPHA_TEST |
CullFaceEnabled | GL_CULL_FACE |
ColorMaterialEnabled | GL_COLOR_MATERIAL |
LineStippleEnabled | GL_LINE_STIPPLE |
PolygonOffsetFillEnabled | GL_POLYGON_OFFSET_FILL |
PolygonOffsetLineEnabled | GL_POLYGON_OFFSET_LINE |
PolygonOffsetPointEnabled | GL_POLYGON_OFFSET_POINT |
NormalizeEnabled | GL_NORMALIZE |
AutoNormalEnabled | GL_AUTO_NORMAL |
MGL Property | glGet constant | OpenGL func. |
---|---|---|
DepthMask | GL_DEPTH_WRITEMASK | glDepthMask |
StencilMask | GL_STENCIL_WRITEMASK | glStencilMask |
StencilMaskFront | GL_STENCIL_WRITEMASK | glStencilMaskSeparate |
StencilMaskBack | GL_STENCIL_BACK_WRITEMASK | glStencilMaskSeparate |
ColorMask | GL_COLOR_WRITEMASK | glColorMask |
DepthFunc | GL_DEPTH_FUNC | glDepthFunc |
Normal | GL_CURRENT_NORMAL | glNormal3d |
Color | GL_CURRENT_COLOR | glColor4f |
SrcBuffer | GL_READ_BUFFER | glReadBuffer |
DstBuffer | GL_DRAW_BUFFER | glDrawBuffer |
PolygonOffsetFactor | GL_POLYGON_OFFSET_FACTOR | glPolygonOffset |
PolygonOffsetUnits | GL_POLYGON_OFFSET_UNITS | glPolygonOffset |
FrontPolygonMode | GL_POLYGONMODE | glPolygonMode |
BackPolygonMode | GL_POLYGONMODE | glPolygonMode |
CullFace | GL_CULL_FACE_MODE | glCullFace |
LightingTwoSide | GL_LIGHT_MODEL_TWO_SIDE | glLightModeli |
LineStipplePattern | GL_LINE_STIPPLE_PATTERN | glLineStipple |
PointSize | GL_POINT_SIZE | glPointSize |
LineWidth | GL_LINE_WIDTH | glLineWidth |
Matrix | GL_MODELVIEW_MATRIX | glLoadMatrixf |
Viewport | GL_VIEWPORT | glViewport |
ColorClearValue | GL_COLOR_CLEAR_VALUE | glClearColor |
DepthClearValue | GL_DEPTH_CLEAR_VALUE | glClearDepth |
StencilClearValue | GL_STENCIL_CLEAR_VALUE | glClearStencil |
GLRenderMode | RenderMode GL_RENDER_MODE | glRenderMode |
光源¶
static class MGL
{
public static readonly LightCollection Lights = new LightCollection();
public class Light
{
public bool IsEnabled { get; set; }
public Color4f Ambient { get; set; }
public Color4f Diffuse { get; set; }
public Color4f Specular { get; set; }
public HmCod3f Position { get; set; }
public Vector3f SpotDirection { get; set; }
public float SpotExponent { get; set; }
public Angle SpotCutoff { get; set; }
public float ConstantAttenuation { get; set; }
public float LinearAttenuation { get; set; }
public float QuadraticAttenuation { get; set; }
}
public class LightCollection : IEnumerable<Light>
{
public int Count { get; }
public Light this[int i] { get; }
}
}
頂点配列¶
頂点のデータ型として使えるものを下記に示します。
- Point3f
- Point3d
- PointNormal3f
- PointNormal3d
- PointNormalUV3f
- PointUV3f
- ColoredPoint3f
- ColoredPointNormal3f
OpenGL の頂点配列には、大きく分けて次の2種類があります。
- glDrawArrays() によるもの
- glDrawElements() によるもの
MGL.DrawArrays( GLPrimType type, 頂点データ型[] points )
¶
glDrawArrays
によって頂点配列を描画します。
「頂点データ型」として上記のデータ型が使えるようにオーバーロードされています。
MGL.DrawArrays( GLPrimType type, 頂点データ型[] points, int[] indices )
¶
glDrawElements
によって頂点配列を描画します。
MGL.DrawArrays( 頂点データ型[] points, params Array<int>[] elements )
¶
glDrawElements
によって頂点配列を描画します。
MGL.Array<T>
は次のように定義されています。
static class MGL
{
public sealed class Array<T>
{
public readonly GLPrimType Type;
public readonly T[] Data;
public Array( GLPrimType type, params T[] data );
}
}
Texture Mapping¶
MGL.ITexture
¶
※ ほとんどの場合、次節の MGL.ITextureObject を利用するほうが適切です。
public static class MGL
{
public interface ITexture : IContextual
{
GLTextureTarget Target { get; }
uint Handle { get; }
ITextureBinding Bind();
}
public static ITexture GenTexture( Bitmap bmp );
...
}
var tex = MGL.GenTexture( bitmap );
using ( var binding = tex.Bind() ) {
binding.SetTexFilterParams( ... ); // 必要ならこういった設定を行う
... // ここに描画処理を書く
}
ITexture
はレンダリングコンテキストに依存しています。
GenTexture()
を呼ぶと内部では glGenTextures()
が呼び出され、そのとき有効なレンダリングコンテキストにテクスチャが生成されます。
そのテクスチャIDは Handle
プロパティで取得できます。
ITexture のオブジェクトを使って複数のレンダリングコンテキストでテクスチャマッピングを行うことはできません。
3Dビューが複数あるアプリケーションの開発では注意して下さい。そういった場合は下記の ITextureObject
を使用して下さい。
MGL.ITextureObject
¶
public static class MGL
{
public interface ITextureObject : IObject
{
new ITexture Current { get; }
Size2i ImageSize { get; }
ITextureBinding Bind();
}
public static ITextureObject CreateTextureObject( Bitmap bitmap );
...
}
// 事前にテクスチャオブジェクトを生成しておく
var tex = MGL.CreateTextureObject( bitmap );
// 描画処理において(IScene.Draw メソッドの中など)次のように書く
using ( var binding = tex.Bind() ) {
binding.SetTexFilterParams( ... ); // 必要ならこういった設定を行う
... // ここに描画処理を書く
}
ITextureObject
は複数のレンダリングコンテキストにまたがって利用できます。
常に現在アクティブなレンダリングコンテキストを確認し、適切な ITexture
を取得・生成してテクスチャマッピングを行います。
Current
プロパティは、現在のレンダリングコンテキストに合わせた ITexture
を返します。
Shader¶
using MoNo.OpenGL;
string shadersrcV = ...; // source code of vertex shader
string shadersrcF = ...; // source code of fragment shader
var program = MGL.CreateProgramObject( shadersrcV, shadersrcF );
using ( var use = program.Use() ) {
use.Uniform( "hoge", .. ); // pass uniform variables to shader program.
... // ここに描画処理を書く
}
- 代表的な使用例です。
- なお、このコードでは
CreateProgramObject()
の直後に描画処理に入っていますが、毎フレームの描画のたびにCreateProgramObject()
を呼び出す必要はありません。 事前にCreateProgramObject()
してそのオブジェクトを保持しておけば、描画の際にはUse()
するだけでOKです。 - シェーダーのソースコードは、DLLのリソースとして定義しておくのが良いでしょう。
各インターフェイス¶
※ RC = Rendering Context
RC非依存 | RC依存 | 説明 |
---|---|---|
IProgramObject |
IProgram |
複数のシェーダーを束ねたもの。 |
IShaderObject |
IShader |
バーテックスシェーダー、フラグメントシェーダーなど |
Example¶
let vs = """
#version 120
void main(void){ gl_Position=gl_ModelViewProjectionMatrix* gl_Vertex; }
"""
let fs = """
#version 120
void main (void) { gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); }
"""
let program = MGL.CreateProgramObject(vs,fs)
let scene = GraphicsUT.CreateScene (fun sc ->
use scope = sc.Push()
use prog = program.Use()
sc.DrawQuads (fun gl ->
gl.Vertex( 0.0, 0.0, 0.0 )
gl.Vertex( 1.0, 0.0, 0.0 )
gl.Vertex( 1.0, 1.0, 0.0 )
gl.Vertex( 0.0, 1.0, 0.0 )))
古いGLSL(version 120)で書いたほうがMVP行列の値が自動で受け継がれるので楽