//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
// file="Shader.cs"
// Project: StgSharp
// AuthorGroup: Nitload Space
// Copyright (c) Nitload Space. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the “Software”), to deal in the Software without restriction,
// including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software,
// and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and
// this permission notice shall be included in all copies
// or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”,
// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
using StgSharp;
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;
namespace StgSharp.Graphics
{
public partial class Form
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
protected Shader CreateShader(ShaderType type, int count)
{
return new Shader(this.gl, gl.CreateShaderSet(count, type), type);
}
///
/// Create an instance of program
///
/// New instance of instance.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
protected ShaderProgram CreateShaderProgram()
{
return new ShaderProgram(GL);
}
}
public class Shader
{
private readonly IglFunc GL;
internal readonly glHandleSet handle;
public readonly ShaderType type;
internal Shader(IglFunc gl, glHandleSet handle, ShaderType usage)
{
this.handle = handle;
GL = gl;
type = usage;
}
//TODO:写链接着色器的文档注释
///
///
///
///
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void AttachTo(int index, ShaderProgram target)
{
GL.AttachShader(target.handle, handle[index]);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public unsafe void Compile(int index, string code)
{
if (code == null)
{
throw new ArgumentNullException("Must provide enough code");
}
GL.LoadShaderSource(handle[index], $"{code}\0");
GL.CompileShader(handle[index]);
}
public override string ToString()
{
return $"This is a {type} shader, its shader handles are {handle.ToString()}.";
}
}
public class ShaderProgram
{
private readonly IglFunc GL;
internal readonly glHandle handle;
///
/// Inti a shader with no program attached.
///
internal unsafe ShaderProgram(IglFunc gl)
{
GL = gl;
handle = GL.CreateProgram();
}
///
/// Get a uniform form current shader,
/// the value type of the uniform should be provided.
///
/// Name of the Uniform in shader code
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public unsafe Uniform GetUniform(string name) where T : struct
{
return new Uniform(this, name, GL);
}
///
/// Get a uniform form current shader,
/// the value type of the uniform should be provided.
///
/// Name of the Uniform in shader code
///
public unsafe Uniform GetUniform(string name)
where T : struct
where U : struct
{
return new Uniform(this, name, GL);
}
///
/// Get a uniform form current shader,
/// the value type of the uniform should be provided.
///
/// Name of the Uniform in shader code
///
public unsafe Uniform GetUniform(string name)
where T : struct
where U : struct
where V : struct
{
return new Uniform(this, name, GL);
}
///
/// Link the shader to current context.
///
public unsafe void Link()
{
if (InternalIO.InternalLinkShaderProgram(GL.Context, handle.Value) == 0)
{
IntPtr logPtr = InternalIO.InternalReadSSCLog();
try
{
byte[] logByte = new byte[512];
Marshal.Copy(logPtr, logByte, 0, 512);
string log = Encoding.UTF8.GetString(logByte);
log = log.Replace("\0", string.Empty);
InternalIO.InternalWriteLog(log, LogType.Error);
}
catch (Exception ex)
{
InternalIO.InternalWriteLog(ex.Message, LogType.Error);
}
}
}
///
/// Let the current context use this shader.
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public unsafe void Use()
{
GL.UseProgram(handle);
}
}
}