|
|
#region License
|
|
|
/* FNA - XNA4 Reimplementation for Desktop Platforms
|
|
|
* Copyright 2009-2022 Ethan Lee and the MonoGame Team
|
|
|
*
|
|
|
* Released under the Microsoft Public License.
|
|
|
* See LICENSE for details.
|
|
|
*/
|
|
|
#endregion
|
|
|
|
|
|
#region Using Statements
|
|
|
using System;
|
|
|
using System.Collections.Generic;
|
|
|
using System.Runtime.InteropServices;
|
|
|
#endregion
|
|
|
|
|
|
namespace Microsoft.Xna.Framework.Graphics
|
|
|
{
|
|
|
public class Effect : GraphicsResource
|
|
|
{
|
|
|
#region Public Properties
|
|
|
|
|
|
private EffectTechnique INTERNAL_currentTechnique;
|
|
|
public EffectTechnique CurrentTechnique
|
|
|
{
|
|
|
get
|
|
|
{
|
|
|
return INTERNAL_currentTechnique;
|
|
|
}
|
|
|
set
|
|
|
{
|
|
|
FNA3D.FNA3D_SetEffectTechnique(
|
|
|
GraphicsDevice.GLDevice,
|
|
|
glEffect,
|
|
|
value.TechniquePointer
|
|
|
);
|
|
|
INTERNAL_currentTechnique = value;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
public EffectParameterCollection Parameters
|
|
|
{
|
|
|
get;
|
|
|
private set;
|
|
|
}
|
|
|
|
|
|
public EffectTechniqueCollection Techniques
|
|
|
{
|
|
|
get;
|
|
|
private set;
|
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
#region Internal FNA3D Variables
|
|
|
|
|
|
internal IntPtr glEffect;
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
#region Private Variables
|
|
|
|
|
|
private Dictionary<IntPtr, EffectParameter> samplerMap = new Dictionary<IntPtr, EffectParameter>(new IntPtrBoxlessComparer());
|
|
|
private class IntPtrBoxlessComparer : IEqualityComparer<IntPtr>
|
|
|
{
|
|
|
public bool Equals(IntPtr x, IntPtr y)
|
|
|
{
|
|
|
return x == y;
|
|
|
}
|
|
|
|
|
|
public int GetHashCode(IntPtr obj)
|
|
|
{
|
|
|
return obj.GetHashCode();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
private IntPtr stateChangesPtr;
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
#region Private Static Variables
|
|
|
|
|
|
private static readonly EffectParameterType[] XNAType = new EffectParameterType[]
|
|
|
{
|
|
|
EffectParameterType.Void, // MOJOSHADER_SYMTYPE_VOID
|
|
|
EffectParameterType.Bool, // MOJOSHADER_SYMTYPE_BOOL
|
|
|
EffectParameterType.Int32, // MOJOSHADER_SYMTYPE_INT
|
|
|
EffectParameterType.Single, // MOJOSHADER_SYMTYPE_FLOAT
|
|
|
EffectParameterType.String, // MOJOSHADER_SYMTYPE_STRING
|
|
|
EffectParameterType.Texture, // MOJOSHADER_SYMTYPE_TEXTURE
|
|
|
EffectParameterType.Texture1D, // MOJOSHADER_SYMTYPE_TEXTURE1D
|
|
|
EffectParameterType.Texture2D, // MOJOSHADER_SYMTYPE_TEXTURE2D
|
|
|
EffectParameterType.Texture3D, // MOJOSHADER_SYMTYPE_TEXTURE3D
|
|
|
EffectParameterType.TextureCube // MOJOSHADER_SYMTYPE_TEXTURECUBE
|
|
|
};
|
|
|
|
|
|
private static readonly EffectParameterClass[] XNAClass = new EffectParameterClass[]
|
|
|
{
|
|
|
EffectParameterClass.Scalar, // MOJOSHADER_SYMCLASS_SCALAR
|
|
|
EffectParameterClass.Vector, // MOJOSHADER_SYMCLASS_VECTOR
|
|
|
EffectParameterClass.Matrix, // MOJOSHADER_SYMCLASS_MATRIX_ROWS
|
|
|
EffectParameterClass.Matrix, // MOJOSHADER_SYMCLASS_MATRIX_COLUMNS
|
|
|
EffectParameterClass.Object, // MOJOSHADER_SYMCLASS_OBJECT
|
|
|
EffectParameterClass.Struct // MOJOSHADER_SYMCLASS_STRUCT
|
|
|
};
|
|
|
|
|
|
private static readonly Blend[] XNABlend = new Blend[]
|
|
|
{
|
|
|
(Blend) (-1), // NOPE
|
|
|
Blend.Zero, // MOJOSHADER_BLEND_ZERO
|
|
|
Blend.One, // MOJOSHADER_BLEND_ONE
|
|
|
Blend.SourceColor, // MOJOSHADER_BLEND_SRCCOLOR
|
|
|
Blend.InverseSourceColor, // MOJOSHADER_BLEND_INVSRCCOLOR
|
|
|
Blend.SourceAlpha, // MOJOSHADER_BLEND_SRCALPHA
|
|
|
Blend.InverseSourceAlpha, // MOJOSHADER_BLEND_INVSRCALPHA
|
|
|
Blend.DestinationAlpha, // MOJOSHADER_BLEND_DESTALPHA
|
|
|
Blend.InverseDestinationAlpha, // MOJOSHADER_BLEND_INVDESTALPHA
|
|
|
Blend.DestinationColor, // MOJOSHADER_BLEND_DESTCOLOR
|
|
|
Blend.InverseDestinationColor, // MOJOSHADER_BLEND_INVDESTCOLOR
|
|
|
Blend.SourceAlphaSaturation, // MOJOSHADER_BLEND_SRCALPHASAT
|
|
|
(Blend) (-1), // NOPE
|
|
|
(Blend) (-1), // NOPE
|
|
|
Blend.BlendFactor, // MOJOSHADER_BLEND_BLENDFACTOR
|
|
|
Blend.InverseBlendFactor // MOJOSHADER_BLEND_INVBLENDFACTOR
|
|
|
};
|
|
|
|
|
|
private static readonly BlendFunction[] XNABlendOp = new BlendFunction[]
|
|
|
{
|
|
|
(BlendFunction) (-1), // NOPE
|
|
|
BlendFunction.Add, // MOJOSHADER_BLENDOP_ADD
|
|
|
BlendFunction.Subtract, // MOJOSHADER_BLENDOP_SUBTRACT
|
|
|
BlendFunction.ReverseSubtract, // MOJOSHADER_BLENDOP_REVSUBTRACT
|
|
|
BlendFunction.Min, // MOJOSHADER_BLENDOP_MIN
|
|
|
BlendFunction.Max // MOJOSHADER_BLENDOP_MAX
|
|
|
};
|
|
|
|
|
|
private static readonly CompareFunction[] XNACompare = new CompareFunction[]
|
|
|
{
|
|
|
(CompareFunction) (-1), // NOPE
|
|
|
CompareFunction.Never, // MOJOSHADER_CMP_NEVER
|
|
|
CompareFunction.Less, // MOJOSHADER_CMP_LESS
|
|
|
CompareFunction.Equal, // MOJOSHADER_CMP_EQUAL
|
|
|
CompareFunction.LessEqual, // MOJOSHADER_CMP_LESSEQUAL
|
|
|
CompareFunction.Greater, // MOJOSHADER_CMP_GREATER
|
|
|
CompareFunction.NotEqual, // MOJOSHADER_CMP_NOTEQUAL
|
|
|
CompareFunction.GreaterEqual, // MOJOSHADER_CMP_GREATEREQUAL
|
|
|
CompareFunction.Always // MOJOSHADER_CMP_ALWAYS
|
|
|
};
|
|
|
|
|
|
private static readonly StencilOperation[] XNAStencilOp = new StencilOperation[]
|
|
|
{
|
|
|
(StencilOperation) (-1), // NOPE
|
|
|
StencilOperation.Keep, // MOJOSHADER_STENCILOP_KEEP
|
|
|
StencilOperation.Zero, // MOJOSHADER_STENCILOP_ZERO
|
|
|
StencilOperation.Replace, // MOJOSHADER_STENCILOP_REPLACE
|
|
|
StencilOperation.IncrementSaturation, // MOJOSHADER_STENCILOP_INCRSAT
|
|
|
StencilOperation.DecrementSaturation, // MOJOSHADER_STENCILOP_DECRSAT
|
|
|
StencilOperation.Invert, // MOJOSHADER_STENCILOP_INVERT
|
|
|
StencilOperation.Increment, // MOJOSHADER_STENCILOP_INCR
|
|
|
StencilOperation.Decrement // MOJOSHADER_STENCILOP_DECR
|
|
|
};
|
|
|
|
|
|
private static readonly TextureAddressMode[] XNAAddress = new TextureAddressMode[]
|
|
|
{
|
|
|
(TextureAddressMode) (-1), // NOPE
|
|
|
TextureAddressMode.Wrap, // MOJOSHADER_TADDRESS_WRAP
|
|
|
TextureAddressMode.Mirror, // MOJOSHADER_TADDRESS_MIRROR
|
|
|
TextureAddressMode.Clamp // MOJOSHADER_TADDRESS_CLAMP
|
|
|
};
|
|
|
|
|
|
private static readonly MOJOSHADER_textureFilterType[] XNAMag =
|
|
|
new MOJOSHADER_textureFilterType[]
|
|
|
{
|
|
|
MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_LINEAR, // TextureFilter.Linear
|
|
|
MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_POINT, // TextureFilter.Point
|
|
|
MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_ANISOTROPIC, // TextureFilter.Anisotropic
|
|
|
MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_LINEAR, // TextureFilter.LinearMipPoint
|
|
|
MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_POINT, // TextureFilter.PointMipLinear
|
|
|
MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_POINT, // TextureFilter.MinLinearMagPointMipLinear
|
|
|
MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_POINT, // TextureFilter.MinLinearMagPointMipPoint
|
|
|
MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_LINEAR, // TextureFilter.MinPointMagLinearMipLinear
|
|
|
MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_LINEAR // TextureFilter.MinPointMagLinearMipPoint
|
|
|
};
|
|
|
|
|
|
private static readonly MOJOSHADER_textureFilterType[] XNAMin =
|
|
|
new MOJOSHADER_textureFilterType[]
|
|
|
{
|
|
|
MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_LINEAR, // TextureFilter.Linear
|
|
|
MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_POINT, // TextureFilter.Point
|
|
|
MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_ANISOTROPIC, // TextureFilter.Anisotropic
|
|
|
MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_LINEAR, // TextureFilter.LinearMipPoint
|
|
|
MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_POINT, // TextureFilter.PointMipLinear
|
|
|
MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_LINEAR, // TextureFilter.MinLinearMagPointMipLinear
|
|
|
MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_LINEAR, // TextureFilter.MinLinearMagPointMipPoint
|
|
|
MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_POINT, // TextureFilter.MinPointMagLinearMipLinear
|
|
|
MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_POINT // TextureFilter.MinPointMagLinearMipPoint
|
|
|
};
|
|
|
|
|
|
private static readonly MOJOSHADER_textureFilterType[] XNAMip =
|
|
|
new MOJOSHADER_textureFilterType[]
|
|
|
{
|
|
|
MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_LINEAR, // TextureFilter.Linear
|
|
|
MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_POINT, // TextureFilter.Point
|
|
|
MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_ANISOTROPIC, // TextureFilter.Anisotropic
|
|
|
MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_POINT, // TextureFilter.LinearMipPoint
|
|
|
MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_LINEAR, // TextureFilter.PointMipLinear
|
|
|
MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_LINEAR, // TextureFilter.MinLinearMagPointMipLinear
|
|
|
MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_POINT, // TextureFilter.MinLinearMagPointMipPoint
|
|
|
MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_LINEAR, // TextureFilter.MinPointMagLinearMipLinear
|
|
|
MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_POINT // TextureFilter.MinPointMagLinearMipPoint
|
|
|
};
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
#region Public Constructor
|
|
|
|
|
|
public Effect(GraphicsDevice graphicsDevice, byte[] effectCode)
|
|
|
{
|
|
|
GraphicsDevice = graphicsDevice;
|
|
|
|
|
|
// Send the blob to the GLDevice to be parsed/compiled
|
|
|
IntPtr effectData;
|
|
|
FNA3D.FNA3D_CreateEffect(
|
|
|
graphicsDevice.GLDevice,
|
|
|
effectCode,
|
|
|
effectCode.Length,
|
|
|
out glEffect,
|
|
|
out effectData
|
|
|
);
|
|
|
|
|
|
// This is where it gets ugly...
|
|
|
INTERNAL_parseEffectStruct(effectData);
|
|
|
|
|
|
// The default technique is the first technique.
|
|
|
CurrentTechnique = Techniques[0];
|
|
|
|
|
|
// Use native memory for changes, .NET loves moving this around
|
|
|
unsafe
|
|
|
{
|
|
|
stateChangesPtr = Marshal.AllocHGlobal(
|
|
|
sizeof(MOJOSHADER_effectStateChanges)
|
|
|
);
|
|
|
MOJOSHADER_effectStateChanges *stateChanges =
|
|
|
(MOJOSHADER_effectStateChanges*) stateChangesPtr;
|
|
|
stateChanges->render_state_change_count = 0;
|
|
|
stateChanges->sampler_state_change_count = 0;
|
|
|
stateChanges->vertex_sampler_state_change_count = 0;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
#region Protected Constructor
|
|
|
|
|
|
protected Effect(Effect cloneSource)
|
|
|
{
|
|
|
GraphicsDevice = cloneSource.GraphicsDevice;
|
|
|
|
|
|
// Send the parsed data to be cloned and recompiled by MojoShader
|
|
|
IntPtr effectData;
|
|
|
FNA3D.FNA3D_CloneEffect(
|
|
|
GraphicsDevice.GLDevice,
|
|
|
cloneSource.glEffect,
|
|
|
out glEffect,
|
|
|
out effectData
|
|
|
);
|
|
|
|
|
|
// Double the ugly, double the fun!
|
|
|
INTERNAL_parseEffectStruct(effectData);
|
|
|
|
|
|
// Copy texture parameters, if applicable
|
|
|
for (int i = 0; i < cloneSource.Parameters.Count; i += 1)
|
|
|
{
|
|
|
Parameters[i].texture = cloneSource.Parameters[i].texture;
|
|
|
}
|
|
|
|
|
|
// The default technique is whatever the current technique was.
|
|
|
for (int i = 0; i < cloneSource.Techniques.Count; i += 1)
|
|
|
{
|
|
|
if (cloneSource.Techniques[i] == cloneSource.CurrentTechnique)
|
|
|
{
|
|
|
CurrentTechnique = Techniques[i];
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// Use native memory for changes, .NET loves moving this around
|
|
|
unsafe
|
|
|
{
|
|
|
stateChangesPtr = Marshal.AllocHGlobal(
|
|
|
sizeof(MOJOSHADER_effectStateChanges)
|
|
|
);
|
|
|
MOJOSHADER_effectStateChanges *stateChanges =
|
|
|
(MOJOSHADER_effectStateChanges*) stateChangesPtr;
|
|
|
stateChanges->render_state_change_count = 0;
|
|
|
stateChanges->sampler_state_change_count = 0;
|
|
|
stateChanges->vertex_sampler_state_change_count = 0;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
#region Public Methods
|
|
|
|
|
|
public virtual Effect Clone()
|
|
|
{
|
|
|
return new Effect(this);
|
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
#region Protected Methods
|
|
|
|
|
|
protected override void Dispose(bool disposing)
|
|
|
{
|
|
|
if (!IsDisposed)
|
|
|
{
|
|
|
if (glEffect != IntPtr.Zero)
|
|
|
{
|
|
|
FNA3D.FNA3D_AddDisposeEffect(
|
|
|
GraphicsDevice.GLDevice,
|
|
|
glEffect
|
|
|
);
|
|
|
}
|
|
|
if (stateChangesPtr != IntPtr.Zero)
|
|
|
{
|
|
|
Marshal.FreeHGlobal(stateChangesPtr);
|
|
|
stateChangesPtr = IntPtr.Zero;
|
|
|
}
|
|
|
}
|
|
|
base.Dispose(disposing);
|
|
|
}
|
|
|
|
|
|
protected internal virtual void OnApply()
|
|
|
{
|
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
#region Internal Methods
|
|
|
|
|
|
internal unsafe void INTERNAL_applyEffect(uint pass)
|
|
|
{
|
|
|
FNA3D.FNA3D_ApplyEffect(
|
|
|
GraphicsDevice.GLDevice,
|
|
|
glEffect,
|
|
|
pass,
|
|
|
stateChangesPtr
|
|
|
);
|
|
|
MOJOSHADER_effectStateChanges *stateChanges =
|
|
|
(MOJOSHADER_effectStateChanges*) stateChangesPtr;
|
|
|
if (stateChanges->render_state_change_count > 0)
|
|
|
{
|
|
|
PipelineCache pipelineCache = GraphicsDevice.PipelineCache;
|
|
|
pipelineCache.BeginApplyBlend();
|
|
|
pipelineCache.BeginApplyDepthStencil();
|
|
|
pipelineCache.BeginApplyRasterizer();
|
|
|
|
|
|
// Used to avoid redundant device state application
|
|
|
bool blendStateChanged = false;
|
|
|
bool depthStencilStateChanged = false;
|
|
|
bool rasterizerStateChanged = false;
|
|
|
|
|
|
MOJOSHADER_effectState* states = (MOJOSHADER_effectState*) stateChanges->render_state_changes;
|
|
|
for (int i = 0; i < stateChanges->render_state_change_count; i += 1)
|
|
|
{
|
|
|
MOJOSHADER_renderStateType type = states[i].type;
|
|
|
if ( type == MOJOSHADER_renderStateType.MOJOSHADER_RS_VERTEXSHADER ||
|
|
|
type == MOJOSHADER_renderStateType.MOJOSHADER_RS_PIXELSHADER )
|
|
|
{
|
|
|
// Skip shader states
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
if (type == MOJOSHADER_renderStateType.MOJOSHADER_RS_ZENABLE)
|
|
|
{
|
|
|
MOJOSHADER_zBufferType* val = (MOJOSHADER_zBufferType*) states[i].value.values;
|
|
|
pipelineCache.DepthBufferEnable =
|
|
|
(*val == MOJOSHADER_zBufferType.MOJOSHADER_ZB_TRUE);
|
|
|
depthStencilStateChanged = true;
|
|
|
}
|
|
|
else if (type == MOJOSHADER_renderStateType.MOJOSHADER_RS_FILLMODE)
|
|
|
{
|
|
|
MOJOSHADER_fillMode* val = (MOJOSHADER_fillMode*) states[i].value.values;
|
|
|
if (*val == MOJOSHADER_fillMode.MOJOSHADER_FILL_SOLID)
|
|
|
{
|
|
|
pipelineCache.FillMode = FillMode.Solid;
|
|
|
}
|
|
|
else if (*val == MOJOSHADER_fillMode.MOJOSHADER_FILL_WIREFRAME)
|
|
|
{
|
|
|
pipelineCache.FillMode = FillMode.WireFrame;
|
|
|
}
|
|
|
rasterizerStateChanged = true;
|
|
|
}
|
|
|
else if (type == MOJOSHADER_renderStateType.MOJOSHADER_RS_ZWRITEENABLE)
|
|
|
{
|
|
|
int* val = (int*) states[i].value.values;
|
|
|
pipelineCache.DepthBufferWriteEnable = (*val == 1);
|
|
|
depthStencilStateChanged = true;
|
|
|
}
|
|
|
else if (type == MOJOSHADER_renderStateType.MOJOSHADER_RS_SRCBLEND)
|
|
|
{
|
|
|
MOJOSHADER_blendMode* val = (MOJOSHADER_blendMode*) states[i].value.values;
|
|
|
pipelineCache.ColorSourceBlend = XNABlend[(int) *val];
|
|
|
if (!pipelineCache.SeparateAlphaBlend)
|
|
|
{
|
|
|
pipelineCache.AlphaSourceBlend = XNABlend[(int) *val];
|
|
|
}
|
|
|
blendStateChanged = true;
|
|
|
}
|
|
|
else if (type == MOJOSHADER_renderStateType.MOJOSHADER_RS_DESTBLEND)
|
|
|
{
|
|
|
MOJOSHADER_blendMode* val = (MOJOSHADER_blendMode*) states[i].value.values;
|
|
|
pipelineCache.ColorDestinationBlend = XNABlend[(int) *val];
|
|
|
if (!pipelineCache.SeparateAlphaBlend)
|
|
|
{
|
|
|
pipelineCache.AlphaDestinationBlend = XNABlend[(int) *val];
|
|
|
}
|
|
|
blendStateChanged = true;
|
|
|
}
|
|
|
else if (type == MOJOSHADER_renderStateType.MOJOSHADER_RS_CULLMODE)
|
|
|
{
|
|
|
MOJOSHADER_cullMode* val = (MOJOSHADER_cullMode*) states[i].value.values;
|
|
|
if (*val == MOJOSHADER_cullMode.MOJOSHADER_CULL_NONE)
|
|
|
{
|
|
|
pipelineCache.CullMode = CullMode.None;
|
|
|
}
|
|
|
else if (*val == MOJOSHADER_cullMode.MOJOSHADER_CULL_CW)
|
|
|
{
|
|
|
pipelineCache.CullMode = CullMode.CullClockwiseFace;
|
|
|
}
|
|
|
else if (*val == MOJOSHADER_cullMode.MOJOSHADER_CULL_CCW)
|
|
|
{
|
|
|
pipelineCache.CullMode = CullMode.CullCounterClockwiseFace;
|
|
|
}
|
|
|
rasterizerStateChanged = true;
|
|
|
}
|
|
|
else if (type == MOJOSHADER_renderStateType.MOJOSHADER_RS_ZFUNC)
|
|
|
{
|
|
|
MOJOSHADER_compareFunc* val = (MOJOSHADER_compareFunc*) states[i].value.values;
|
|
|
pipelineCache.DepthBufferFunction = XNACompare[(int) *val];
|
|
|
depthStencilStateChanged = true;
|
|
|
}
|
|
|
else if (type == MOJOSHADER_renderStateType.MOJOSHADER_RS_ALPHABLENDENABLE)
|
|
|
{
|
|
|
// FIXME: Assuming no other blend calls are made in the effect! -flibit
|
|
|
int* val = (int*) states[i].value.values;
|
|
|
if (*val == 0)
|
|
|
{
|
|
|
pipelineCache.ColorSourceBlend = Blend.One;
|
|
|
pipelineCache.ColorDestinationBlend = Blend.Zero;
|
|
|
pipelineCache.AlphaSourceBlend = Blend.One;
|
|
|
pipelineCache.AlphaDestinationBlend = Blend.Zero;
|
|
|
blendStateChanged = true;
|
|
|
}
|
|
|
}
|
|
|
else if (type == MOJOSHADER_renderStateType.MOJOSHADER_RS_STENCILENABLE)
|
|
|
{
|
|
|
int* val = (int*) states[i].value.values;
|
|
|
pipelineCache.StencilEnable = (*val == 1);
|
|
|
depthStencilStateChanged = true;
|
|
|
}
|
|
|
else if (type == MOJOSHADER_renderStateType.MOJOSHADER_RS_STENCILFAIL)
|
|
|
{
|
|
|
MOJOSHADER_stencilOp* val = (MOJOSHADER_stencilOp*) states[i].value.values;
|
|
|
pipelineCache.StencilFail = XNAStencilOp[(int) *val];
|
|
|
depthStencilStateChanged = true;
|
|
|
}
|
|
|
else if (type == MOJOSHADER_renderStateType.MOJOSHADER_RS_STENCILZFAIL)
|
|
|
{
|
|
|
MOJOSHADER_stencilOp* val = (MOJOSHADER_stencilOp*) states[i].value.values;
|
|
|
pipelineCache.StencilDepthBufferFail = XNAStencilOp[(int) *val];
|
|
|
depthStencilStateChanged = true;
|
|
|
}
|
|
|
else if (type == MOJOSHADER_renderStateType.MOJOSHADER_RS_STENCILPASS)
|
|
|
{
|
|
|
MOJOSHADER_stencilOp* val = (MOJOSHADER_stencilOp*) states[i].value.values;
|
|
|
pipelineCache.StencilPass = XNAStencilOp[(int) *val];
|
|
|
depthStencilStateChanged = true;
|
|
|
}
|
|
|
else if (type == MOJOSHADER_renderStateType.MOJOSHADER_RS_STENCILFUNC)
|
|
|
{
|
|
|
MOJOSHADER_compareFunc* val = (MOJOSHADER_compareFunc*) states[i].value.values;
|
|
|
pipelineCache.StencilFunction = XNACompare[(int) *val];
|
|
|
depthStencilStateChanged = true;
|
|
|
}
|
|
|
else if (type == MOJOSHADER_renderStateType.MOJOSHADER_RS_STENCILREF)
|
|
|
{
|
|
|
int* val = (int*) states[i].value.values;
|
|
|
pipelineCache.ReferenceStencil = *val;
|
|
|
depthStencilStateChanged = true;
|
|
|
}
|
|
|
else if (type == MOJOSHADER_renderStateType.MOJOSHADER_RS_STENCILMASK)
|
|
|
{
|
|
|
int* val = (int*) states[i].value.values;
|
|
|
pipelineCache.StencilMask = *val;
|
|
|
depthStencilStateChanged = true;
|
|
|
}
|
|
|
else if (type == MOJOSHADER_renderStateType.MOJOSHADER_RS_STENCILWRITEMASK)
|
|
|
{
|
|
|
int* val = (int*) states[i].value.values;
|
|
|
pipelineCache.StencilWriteMask = *val;
|
|
|
depthStencilStateChanged = true;
|
|
|
}
|
|
|
else if (type == MOJOSHADER_renderStateType.MOJOSHADER_RS_MULTISAMPLEANTIALIAS)
|
|
|
{
|
|
|
int* val = (int*) states[i].value.values;
|
|
|
pipelineCache.MultiSampleAntiAlias = (*val == 1);
|
|
|
rasterizerStateChanged = true;
|
|
|
}
|
|
|
else if (type == MOJOSHADER_renderStateType.MOJOSHADER_RS_MULTISAMPLEMASK)
|
|
|
{
|
|
|
int* val = (int*) states[i].value.values;
|
|
|
pipelineCache.MultiSampleMask = *val;
|
|
|
blendStateChanged = true;
|
|
|
}
|
|
|
else if (type == MOJOSHADER_renderStateType.MOJOSHADER_RS_COLORWRITEENABLE)
|
|
|
{
|
|
|
int* val = (int*) states[i].value.values;
|
|
|
pipelineCache.ColorWriteChannels = (ColorWriteChannels) (*val);
|
|
|
blendStateChanged = true;
|
|
|
}
|
|
|
else if (type == MOJOSHADER_renderStateType.MOJOSHADER_RS_BLENDOP)
|
|
|
{
|
|
|
MOJOSHADER_blendOp* val = (MOJOSHADER_blendOp*) states[i].value.values;
|
|
|
pipelineCache.ColorBlendFunction = XNABlendOp[(int) *val];
|
|
|
blendStateChanged = true;
|
|
|
}
|
|
|
else if (type == MOJOSHADER_renderStateType.MOJOSHADER_RS_SCISSORTESTENABLE)
|
|
|
{
|
|
|
int* val = (int*) states[i].value.values;
|
|
|
pipelineCache.ScissorTestEnable = (*val == 1);
|
|
|
rasterizerStateChanged = true;
|
|
|
}
|
|
|
else if (type == MOJOSHADER_renderStateType.MOJOSHADER_RS_SLOPESCALEDEPTHBIAS)
|
|
|
{
|
|
|
float* val = (float*) states[i].value.values;
|
|
|
pipelineCache.SlopeScaleDepthBias = *val;
|
|
|
rasterizerStateChanged = true;
|
|
|
}
|
|
|
else if (type == MOJOSHADER_renderStateType.MOJOSHADER_RS_TWOSIDEDSTENCILMODE)
|
|
|
{
|
|
|
int* val = (int*) states[i].value.values;
|
|
|
pipelineCache.TwoSidedStencilMode = (*val == 1);
|
|
|
depthStencilStateChanged = true;
|
|
|
}
|
|
|
else if (type == MOJOSHADER_renderStateType.MOJOSHADER_RS_CCW_STENCILFAIL)
|
|
|
{
|
|
|
MOJOSHADER_stencilOp* val = (MOJOSHADER_stencilOp*) states[i].value.values;
|
|
|
pipelineCache.CCWStencilFail = XNAStencilOp[(int) *val];
|
|
|
depthStencilStateChanged = true;
|
|
|
}
|
|
|
else if (type == MOJOSHADER_renderStateType.MOJOSHADER_RS_CCW_STENCILZFAIL)
|
|
|
{
|
|
|
MOJOSHADER_stencilOp* val = (MOJOSHADER_stencilOp*) states[i].value.values;
|
|
|
pipelineCache.CCWStencilDepthBufferFail = XNAStencilOp[(int) *val];
|
|
|
depthStencilStateChanged = true;
|
|
|
}
|
|
|
else if (type == MOJOSHADER_renderStateType.MOJOSHADER_RS_CCW_STENCILPASS)
|
|
|
{
|
|
|
MOJOSHADER_stencilOp* val = (MOJOSHADER_stencilOp*) states[i].value.values;
|
|
|
pipelineCache.CCWStencilPass = XNAStencilOp[(int) *val];
|
|
|
depthStencilStateChanged = true;
|
|
|
}
|
|
|
else if (type == MOJOSHADER_renderStateType.MOJOSHADER_RS_CCW_STENCILFUNC)
|
|
|
{
|
|
|
MOJOSHADER_compareFunc* val = (MOJOSHADER_compareFunc*) states[i].value.values;
|
|
|
pipelineCache.CCWStencilFunction = XNACompare[(int) *val];
|
|
|
depthStencilStateChanged = true;
|
|
|
}
|
|
|
else if (type == MOJOSHADER_renderStateType.MOJOSHADER_RS_COLORWRITEENABLE1)
|
|
|
{
|
|
|
int* val = (int*) states[i].value.values;
|
|
|
pipelineCache.ColorWriteChannels1 = (ColorWriteChannels) (*val);
|
|
|
blendStateChanged = true;
|
|
|
}
|
|
|
else if (type == MOJOSHADER_renderStateType.MOJOSHADER_RS_COLORWRITEENABLE2)
|
|
|
{
|
|
|
int* val = (int*) states[i].value.values;
|
|
|
pipelineCache.ColorWriteChannels2 = (ColorWriteChannels) (*val);
|
|
|
blendStateChanged = true;
|
|
|
}
|
|
|
else if (type == MOJOSHADER_renderStateType.MOJOSHADER_RS_COLORWRITEENABLE3)
|
|
|
{
|
|
|
int* val = (int*) states[i].value.values;
|
|
|
pipelineCache.ColorWriteChannels3 = (ColorWriteChannels) (*val);
|
|
|
blendStateChanged = true;
|
|
|
}
|
|
|
else if (type == MOJOSHADER_renderStateType.MOJOSHADER_RS_BLENDFACTOR)
|
|
|
{
|
|
|
// FIXME: RGBA? -flibit
|
|
|
int* val = (int*) states[i].value.values;
|
|
|
pipelineCache.BlendFactor = new Color(
|
|
|
(*val >> 24) & 0xFF,
|
|
|
(*val >> 16) & 0xFF,
|
|
|
(*val >> 8) & 0xFF,
|
|
|
*val & 0xFF
|
|
|
);
|
|
|
blendStateChanged = true;
|
|
|
}
|
|
|
else if (type == MOJOSHADER_renderStateType.MOJOSHADER_RS_DEPTHBIAS)
|
|
|
{
|
|
|
float* val = (float*) states[i].value.values;
|
|
|
pipelineCache.DepthBias = *val;
|
|
|
rasterizerStateChanged = true;
|
|
|
}
|
|
|
else if (type == MOJOSHADER_renderStateType.MOJOSHADER_RS_SEPARATEALPHABLENDENABLE)
|
|
|
{
|
|
|
int* val = (int*) states[i].value.values;
|
|
|
pipelineCache.SeparateAlphaBlend = (*val == 1);
|
|
|
// FIXME: Do we want to update the state for this...? -flibit
|
|
|
}
|
|
|
else if (type == MOJOSHADER_renderStateType.MOJOSHADER_RS_SRCBLENDALPHA)
|
|
|
{
|
|
|
MOJOSHADER_blendMode* val = (MOJOSHADER_blendMode*) states[i].value.values;
|
|
|
pipelineCache.AlphaSourceBlend = XNABlend[(int) *val];
|
|
|
blendStateChanged = true;
|
|
|
}
|
|
|
else if (type == MOJOSHADER_renderStateType.MOJOSHADER_RS_DESTBLENDALPHA)
|
|
|
{
|
|
|
MOJOSHADER_blendMode* val = (MOJOSHADER_blendMode*) states[i].value.values;
|
|
|
pipelineCache.AlphaDestinationBlend = XNABlend[(int) *val];
|
|
|
blendStateChanged = true;
|
|
|
}
|
|
|
else if (type == MOJOSHADER_renderStateType.MOJOSHADER_RS_BLENDOPALPHA)
|
|
|
{
|
|
|
MOJOSHADER_blendOp* val = (MOJOSHADER_blendOp*) states[i].value.values;
|
|
|
pipelineCache.AlphaBlendFunction = XNABlendOp[(int) *val];
|
|
|
blendStateChanged = true;
|
|
|
}
|
|
|
else if (type == (MOJOSHADER_renderStateType) 178)
|
|
|
{
|
|
|
/* Apparently this is "SetSampler"? */
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
throw new NotImplementedException("Unhandled render state! " + type);
|
|
|
}
|
|
|
}
|
|
|
if (blendStateChanged)
|
|
|
{
|
|
|
pipelineCache.EndApplyBlend();
|
|
|
}
|
|
|
if (depthStencilStateChanged)
|
|
|
{
|
|
|
pipelineCache.EndApplyDepthStencil();
|
|
|
}
|
|
|
if (rasterizerStateChanged)
|
|
|
{
|
|
|
pipelineCache.EndApplyRasterizer();
|
|
|
}
|
|
|
}
|
|
|
if (stateChanges->sampler_state_change_count > 0)
|
|
|
{
|
|
|
INTERNAL_updateSamplers(
|
|
|
stateChanges->sampler_state_change_count,
|
|
|
(MOJOSHADER_samplerStateRegister*) stateChanges->sampler_state_changes,
|
|
|
GraphicsDevice.Textures,
|
|
|
GraphicsDevice.SamplerStates
|
|
|
);
|
|
|
}
|
|
|
if (stateChanges->vertex_sampler_state_change_count > 0)
|
|
|
{
|
|
|
INTERNAL_updateSamplers(
|
|
|
stateChanges->vertex_sampler_state_change_count,
|
|
|
(MOJOSHADER_samplerStateRegister*) stateChanges->vertex_sampler_state_changes,
|
|
|
GraphicsDevice.VertexTextures,
|
|
|
GraphicsDevice.VertexSamplerStates
|
|
|
);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
private unsafe void INTERNAL_updateSamplers(
|
|
|
uint changeCount,
|
|
|
MOJOSHADER_samplerStateRegister* registers,
|
|
|
TextureCollection textures,
|
|
|
SamplerStateCollection samplers
|
|
|
) {
|
|
|
for (int i = 0; i < changeCount; i += 1)
|
|
|
{
|
|
|
if (registers[i].sampler_state_count == 0)
|
|
|
{
|
|
|
// Nothing to do
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
int register = (int) registers[i].sampler_register;
|
|
|
|
|
|
PipelineCache pipelineCache = GraphicsDevice.PipelineCache;
|
|
|
pipelineCache.BeginApplySampler(samplers, register);
|
|
|
|
|
|
// Used to prevent redundant sampler changes
|
|
|
bool samplerChanged = false;
|
|
|
bool filterChanged = false;
|
|
|
|
|
|
// Current sampler filter
|
|
|
TextureFilter filter = pipelineCache.Filter;
|
|
|
MOJOSHADER_textureFilterType magFilter = XNAMag[(int) filter];
|
|
|
MOJOSHADER_textureFilterType minFilter = XNAMin[(int) filter];
|
|
|
MOJOSHADER_textureFilterType mipFilter = XNAMip[(int) filter];
|
|
|
|
|
|
MOJOSHADER_effectSamplerState* states = (MOJOSHADER_effectSamplerState*) registers[i].sampler_states;
|
|
|
for (int j = 0; j < registers[i].sampler_state_count; j += 1)
|
|
|
{
|
|
|
MOJOSHADER_samplerStateType type = states[j].type;
|
|
|
if (type == MOJOSHADER_samplerStateType.MOJOSHADER_SAMP_TEXTURE)
|
|
|
{
|
|
|
EffectParameter texParam;
|
|
|
if (samplerMap.TryGetValue(registers[i].sampler_name, out texParam))
|
|
|
{
|
|
|
Texture texture = texParam.texture;
|
|
|
if (texture != null)
|
|
|
{
|
|
|
textures[register] = texture;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
else if (type == MOJOSHADER_samplerStateType.MOJOSHADER_SAMP_ADDRESSU)
|
|
|
{
|
|
|
MOJOSHADER_textureAddress* val = (MOJOSHADER_textureAddress*) states[j].value.values;
|
|
|
pipelineCache.AddressU = XNAAddress[(int) *val];
|
|
|
samplerChanged = true;
|
|
|
}
|
|
|
else if (type == MOJOSHADER_samplerStateType.MOJOSHADER_SAMP_ADDRESSV)
|
|
|
{
|
|
|
MOJOSHADER_textureAddress* val = (MOJOSHADER_textureAddress*) states[j].value.values;
|
|
|
pipelineCache.AddressV = XNAAddress[(int) *val];
|
|
|
samplerChanged = true;
|
|
|
}
|
|
|
else if (type == MOJOSHADER_samplerStateType.MOJOSHADER_SAMP_ADDRESSW)
|
|
|
{
|
|
|
MOJOSHADER_textureAddress* val = (MOJOSHADER_textureAddress*) states[j].value.values;
|
|
|
pipelineCache.AddressW = XNAAddress[(int) *val];
|
|
|
samplerChanged = true;
|
|
|
}
|
|
|
else if (type == MOJOSHADER_samplerStateType.MOJOSHADER_SAMP_MAGFILTER)
|
|
|
{
|
|
|
MOJOSHADER_textureFilterType* val = (MOJOSHADER_textureFilterType*) states[j].value.values;
|
|
|
magFilter = *val;
|
|
|
filterChanged = true;
|
|
|
}
|
|
|
else if (type == MOJOSHADER_samplerStateType.MOJOSHADER_SAMP_MINFILTER)
|
|
|
{
|
|
|
MOJOSHADER_textureFilterType* val = (MOJOSHADER_textureFilterType*) states[j].value.values;
|
|
|
minFilter = *val;
|
|
|
filterChanged = true;
|
|
|
}
|
|
|
else if (type == MOJOSHADER_samplerStateType.MOJOSHADER_SAMP_MIPFILTER)
|
|
|
{
|
|
|
MOJOSHADER_textureFilterType* val = (MOJOSHADER_textureFilterType*) states[j].value.values;
|
|
|
mipFilter = *val;
|
|
|
filterChanged = true;
|
|
|
}
|
|
|
else if (type == MOJOSHADER_samplerStateType.MOJOSHADER_SAMP_MIPMAPLODBIAS)
|
|
|
{
|
|
|
float* val = (float*) states[j].value.values;
|
|
|
pipelineCache.MipMapLODBias = *val;
|
|
|
samplerChanged = true;
|
|
|
}
|
|
|
else if (type == MOJOSHADER_samplerStateType.MOJOSHADER_SAMP_MAXMIPLEVEL)
|
|
|
{
|
|
|
int* val = (int*) states[j].value.values;
|
|
|
pipelineCache.MaxMipLevel = *val;
|
|
|
samplerChanged = true;
|
|
|
}
|
|
|
else if (type == MOJOSHADER_samplerStateType.MOJOSHADER_SAMP_MAXANISOTROPY)
|
|
|
{
|
|
|
int* val = (int*) states[j].value.values;
|
|
|
pipelineCache.MaxAnisotropy = *val;
|
|
|
samplerChanged = true;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
throw new NotImplementedException("Unhandled sampler state! " + type);
|
|
|
}
|
|
|
}
|
|
|
if (filterChanged)
|
|
|
{
|
|
|
if (magFilter == MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_POINT)
|
|
|
{
|
|
|
if (minFilter == MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_POINT)
|
|
|
{
|
|
|
if ( mipFilter == MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_NONE ||
|
|
|
mipFilter == MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_POINT )
|
|
|
{
|
|
|
pipelineCache.Filter = TextureFilter.Point;
|
|
|
}
|
|
|
else if ( mipFilter == MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_LINEAR ||
|
|
|
mipFilter == MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_ANISOTROPIC )
|
|
|
{
|
|
|
pipelineCache.Filter = TextureFilter.PointMipLinear;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
throw new NotImplementedException("Unhandled mipfilter type! " + mipFilter);
|
|
|
}
|
|
|
}
|
|
|
else if ( minFilter == MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_LINEAR ||
|
|
|
minFilter == MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_ANISOTROPIC )
|
|
|
{
|
|
|
if ( mipFilter == MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_NONE ||
|
|
|
mipFilter == MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_POINT )
|
|
|
{
|
|
|
pipelineCache.Filter = TextureFilter.MinLinearMagPointMipPoint;
|
|
|
}
|
|
|
else if ( mipFilter == MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_LINEAR ||
|
|
|
mipFilter == MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_ANISOTROPIC )
|
|
|
{
|
|
|
pipelineCache.Filter = TextureFilter.MinLinearMagPointMipLinear;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
throw new NotImplementedException("Unhandled mipfilter type! " + mipFilter);
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
throw new NotImplementedException("Unhandled minfilter type! " + minFilter);
|
|
|
}
|
|
|
}
|
|
|
else if ( magFilter == MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_LINEAR ||
|
|
|
magFilter == MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_ANISOTROPIC )
|
|
|
{
|
|
|
if (minFilter == MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_POINT)
|
|
|
{
|
|
|
if ( mipFilter == MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_NONE ||
|
|
|
mipFilter == MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_POINT )
|
|
|
{
|
|
|
pipelineCache.Filter = TextureFilter.MinPointMagLinearMipPoint;
|
|
|
}
|
|
|
else if ( mipFilter == MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_LINEAR ||
|
|
|
mipFilter == MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_ANISOTROPIC )
|
|
|
{
|
|
|
pipelineCache.Filter = TextureFilter.MinPointMagLinearMipLinear;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
throw new NotImplementedException("Unhandled mipfilter type! " + mipFilter);
|
|
|
}
|
|
|
}
|
|
|
else if ( minFilter == MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_LINEAR ||
|
|
|
minFilter == MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_ANISOTROPIC )
|
|
|
{
|
|
|
if ( mipFilter == MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_NONE ||
|
|
|
mipFilter == MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_POINT )
|
|
|
{
|
|
|
pipelineCache.Filter = TextureFilter.LinearMipPoint;
|
|
|
}
|
|
|
else if ( mipFilter == MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_LINEAR ||
|
|
|
mipFilter == MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_ANISOTROPIC )
|
|
|
{
|
|
|
pipelineCache.Filter = TextureFilter.Linear;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
throw new NotImplementedException("Unhandled mipfilter type! " + mipFilter);
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
throw new NotImplementedException("Unhandled minfilter type! " + minFilter);
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
throw new NotImplementedException("Unhandled magfilter type! " + magFilter);
|
|
|
}
|
|
|
samplerChanged = true;
|
|
|
}
|
|
|
|
|
|
if (samplerChanged)
|
|
|
{
|
|
|
pipelineCache.EndApplySampler(samplers, register);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
#region Private Methods
|
|
|
|
|
|
private unsafe void INTERNAL_parseEffectStruct(IntPtr effectData)
|
|
|
{
|
|
|
MOJOSHADER_effect* effectPtr = (MOJOSHADER_effect*) effectData;
|
|
|
|
|
|
// Set up Parameters
|
|
|
MOJOSHADER_effectParam* paramPtr = (MOJOSHADER_effectParam*) effectPtr->parameters;
|
|
|
List<EffectParameter> parameters = new List<EffectParameter>();
|
|
|
for (int i = 0; i < effectPtr->param_count; i += 1)
|
|
|
{
|
|
|
MOJOSHADER_effectParam param = paramPtr[i];
|
|
|
if ( param.value.type.parameter_type == MOJOSHADER_symbolType.MOJOSHADER_SYMTYPE_VERTEXSHADER ||
|
|
|
param.value.type.parameter_type == MOJOSHADER_symbolType.MOJOSHADER_SYMTYPE_PIXELSHADER )
|
|
|
{
|
|
|
// Skip shader objects...
|
|
|
continue;
|
|
|
}
|
|
|
else if ( param.value.type.parameter_type >= MOJOSHADER_symbolType.MOJOSHADER_SYMTYPE_SAMPLER &&
|
|
|
param.value.type.parameter_type <= MOJOSHADER_symbolType.MOJOSHADER_SYMTYPE_SAMPLERCUBE )
|
|
|
{
|
|
|
string textureName = String.Empty;
|
|
|
MOJOSHADER_effectSamplerState* states = (MOJOSHADER_effectSamplerState*) param.value.values;
|
|
|
for (int j = 0; j < param.value.value_count; j += 1)
|
|
|
{
|
|
|
if ( states[j].value.type.parameter_type >= MOJOSHADER_symbolType.MOJOSHADER_SYMTYPE_TEXTURE &&
|
|
|
states[j].value.type.parameter_type <= MOJOSHADER_symbolType.MOJOSHADER_SYMTYPE_TEXTURECUBE )
|
|
|
{
|
|
|
MOJOSHADER_effectObject *objectPtr = (MOJOSHADER_effectObject*) effectPtr->objects;
|
|
|
int* index = (int*) states[j].value.values;
|
|
|
textureName = Marshal.PtrToStringAnsi(objectPtr[*index].mapping.name);
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
/* Because textures have to be declared before the sampler,
|
|
|
* we can assume that it will always be in the list by the
|
|
|
* time we get to this point.
|
|
|
* -flibit
|
|
|
*/
|
|
|
for (int j = 0; j < parameters.Count; j += 1)
|
|
|
{
|
|
|
if (textureName.Equals(parameters[j].Name))
|
|
|
{
|
|
|
samplerMap[param.value.name] = parameters[j];
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
EffectParameterCollection structMembers = null;
|
|
|
if (param.value.type.member_count > 0)
|
|
|
{
|
|
|
List<EffectParameter> memList = new List<EffectParameter>();
|
|
|
unsafe
|
|
|
{
|
|
|
MOJOSHADER_symbolStructMember* mem = (MOJOSHADER_symbolStructMember*) param.value.type.members;
|
|
|
IntPtr curOffset = IntPtr.Zero;
|
|
|
for (int j = 0; j < param.value.type.member_count; j += 1)
|
|
|
{
|
|
|
uint memSize = mem[j].info.rows * mem[j].info.columns;
|
|
|
if (mem[j].info.elements > 0)
|
|
|
{
|
|
|
memSize *= mem[j].info.elements;
|
|
|
}
|
|
|
memList.Add(new EffectParameter(
|
|
|
Marshal.PtrToStringAnsi(mem[j].name),
|
|
|
null,
|
|
|
(int) mem[j].info.rows,
|
|
|
(int) mem[j].info.columns,
|
|
|
(int) mem[j].info.elements,
|
|
|
XNAClass[(int) mem[j].info.parameter_class],
|
|
|
XNAType[(int) mem[j].info.parameter_type],
|
|
|
null, // FIXME: Nested structs! -flibit
|
|
|
null,
|
|
|
param.value.values + curOffset.ToInt32(),
|
|
|
memSize * 4
|
|
|
));
|
|
|
curOffset += (int) memSize * 4;
|
|
|
}
|
|
|
}
|
|
|
structMembers = new EffectParameterCollection(memList);
|
|
|
}
|
|
|
|
|
|
parameters.Add(new EffectParameter(
|
|
|
Marshal.PtrToStringAnsi(param.value.name),
|
|
|
Marshal.PtrToStringAnsi(param.value.semantic),
|
|
|
(int) param.value.type.rows,
|
|
|
(int) param.value.type.columns,
|
|
|
(int) param.value.type.elements,
|
|
|
XNAClass[(int) param.value.type.parameter_class],
|
|
|
XNAType[(int) param.value.type.parameter_type],
|
|
|
structMembers,
|
|
|
INTERNAL_readAnnotations(
|
|
|
param.annotations,
|
|
|
param.annotation_count
|
|
|
),
|
|
|
param.value.values,
|
|
|
param.value.value_count * sizeof(float)
|
|
|
));
|
|
|
}
|
|
|
Parameters = new EffectParameterCollection(parameters);
|
|
|
|
|
|
// Set up Techniques
|
|
|
MOJOSHADER_effectTechnique* techPtr = (MOJOSHADER_effectTechnique*) effectPtr->techniques;
|
|
|
List<EffectTechnique> techniques = new List<EffectTechnique>(effectPtr->technique_count);
|
|
|
for (int i = 0; i < techniques.Capacity; i += 1, techPtr += 1)
|
|
|
{
|
|
|
// Set up Passes
|
|
|
MOJOSHADER_effectPass* passPtr = (MOJOSHADER_effectPass*) techPtr->passes;
|
|
|
List<EffectPass> passes = new List<EffectPass>((int) techPtr->pass_count);
|
|
|
for (int j = 0; j < passes.Capacity; j += 1)
|
|
|
{
|
|
|
MOJOSHADER_effectPass pass = passPtr[j];
|
|
|
passes.Add(new EffectPass(
|
|
|
Marshal.PtrToStringAnsi(pass.name),
|
|
|
INTERNAL_readAnnotations(
|
|
|
pass.annotations,
|
|
|
pass.annotation_count
|
|
|
),
|
|
|
this,
|
|
|
(IntPtr) techPtr,
|
|
|
(uint) j
|
|
|
));
|
|
|
}
|
|
|
|
|
|
techniques.Add(new EffectTechnique(
|
|
|
Marshal.PtrToStringAnsi(techPtr->name),
|
|
|
(IntPtr) techPtr,
|
|
|
new EffectPassCollection(passes),
|
|
|
INTERNAL_readAnnotations(
|
|
|
techPtr->annotations,
|
|
|
techPtr->annotation_count
|
|
|
)
|
|
|
));
|
|
|
}
|
|
|
Techniques = new EffectTechniqueCollection(techniques);
|
|
|
}
|
|
|
|
|
|
private unsafe EffectAnnotationCollection INTERNAL_readAnnotations(
|
|
|
IntPtr rawAnnotations,
|
|
|
uint numAnnotations
|
|
|
) {
|
|
|
MOJOSHADER_effectAnnotation* annoPtr = (MOJOSHADER_effectAnnotation*) rawAnnotations;
|
|
|
List<EffectAnnotation> annotations = new List<EffectAnnotation>((int) numAnnotations);
|
|
|
for (int i = 0; i < numAnnotations; i += 1)
|
|
|
{
|
|
|
MOJOSHADER_effectAnnotation anno = annoPtr[i];
|
|
|
annotations.Add(new EffectAnnotation(
|
|
|
Marshal.PtrToStringAnsi(anno.name),
|
|
|
Marshal.PtrToStringAnsi(anno.semantic),
|
|
|
(int) anno.type.rows,
|
|
|
(int) anno.type.columns,
|
|
|
XNAClass[(int) anno.type.parameter_class],
|
|
|
XNAType[(int) anno.type.parameter_type],
|
|
|
anno.values
|
|
|
));
|
|
|
}
|
|
|
return new EffectAnnotationCollection(annotations);
|
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
#region MojoShader Interop
|
|
|
|
|
|
/* Shader Parse Interface */
|
|
|
|
|
|
private enum MOJOSHADER_symbolClass
|
|
|
{
|
|
|
MOJOSHADER_SYMCLASS_SCALAR = 0,
|
|
|
MOJOSHADER_SYMCLASS_VECTOR,
|
|
|
MOJOSHADER_SYMCLASS_MATRIX_ROWS,
|
|
|
MOJOSHADER_SYMCLASS_MATRIX_COLUMNS,
|
|
|
MOJOSHADER_SYMCLASS_OBJECT,
|
|
|
MOJOSHADER_SYMCLASS_STRUCT,
|
|
|
MOJOSHADER_SYMCLASS_TOTAL
|
|
|
}
|
|
|
|
|
|
private enum MOJOSHADER_symbolType
|
|
|
{
|
|
|
MOJOSHADER_SYMTYPE_VOID = 0,
|
|
|
MOJOSHADER_SYMTYPE_BOOL,
|
|
|
MOJOSHADER_SYMTYPE_INT,
|
|
|
MOJOSHADER_SYMTYPE_FLOAT,
|
|
|
MOJOSHADER_SYMTYPE_STRING,
|
|
|
MOJOSHADER_SYMTYPE_TEXTURE,
|
|
|
MOJOSHADER_SYMTYPE_TEXTURE1D,
|
|
|
MOJOSHADER_SYMTYPE_TEXTURE2D,
|
|
|
MOJOSHADER_SYMTYPE_TEXTURE3D,
|
|
|
MOJOSHADER_SYMTYPE_TEXTURECUBE,
|
|
|
MOJOSHADER_SYMTYPE_SAMPLER,
|
|
|
MOJOSHADER_SYMTYPE_SAMPLER1D,
|
|
|
MOJOSHADER_SYMTYPE_SAMPLER2D,
|
|
|
MOJOSHADER_SYMTYPE_SAMPLER3D,
|
|
|
MOJOSHADER_SYMTYPE_SAMPLERCUBE,
|
|
|
MOJOSHADER_SYMTYPE_PIXELSHADER,
|
|
|
MOJOSHADER_SYMTYPE_VERTEXSHADER,
|
|
|
MOJOSHADER_SYMTYPE_PIXELFRAGMENT,
|
|
|
MOJOSHADER_SYMTYPE_VERTEXFRAGMENT,
|
|
|
MOJOSHADER_SYMTYPE_UNSUPPORTED,
|
|
|
MOJOSHADER_SYMTYPE_TOTAL
|
|
|
}
|
|
|
|
|
|
[StructLayout(LayoutKind.Sequential)]
|
|
|
private struct MOJOSHADER_symbolTypeInfo
|
|
|
{
|
|
|
public MOJOSHADER_symbolClass parameter_class;
|
|
|
public MOJOSHADER_symbolType parameter_type;
|
|
|
public uint rows;
|
|
|
public uint columns;
|
|
|
public uint elements;
|
|
|
public uint member_count;
|
|
|
public IntPtr members; // MOJOSHADER_symbolStructMember*
|
|
|
}
|
|
|
|
|
|
[StructLayout(LayoutKind.Sequential)]
|
|
|
private struct MOJOSHADER_symbolStructMember
|
|
|
{
|
|
|
public IntPtr name; //const char*
|
|
|
public MOJOSHADER_symbolTypeInfo info;
|
|
|
}
|
|
|
|
|
|
/* MOJOSHADER_effectState types... */
|
|
|
|
|
|
private enum MOJOSHADER_renderStateType
|
|
|
{
|
|
|
MOJOSHADER_RS_ZENABLE,
|
|
|
MOJOSHADER_RS_FILLMODE,
|
|
|
MOJOSHADER_RS_SHADEMODE,
|
|
|
MOJOSHADER_RS_ZWRITEENABLE,
|
|
|
MOJOSHADER_RS_ALPHATESTENABLE,
|
|
|
MOJOSHADER_RS_LASTPIXEL,
|
|
|
MOJOSHADER_RS_SRCBLEND,
|
|
|
MOJOSHADER_RS_DESTBLEND,
|
|
|
MOJOSHADER_RS_CULLMODE,
|
|
|
MOJOSHADER_RS_ZFUNC,
|
|
|
MOJOSHADER_RS_ALPHAREF,
|
|
|
MOJOSHADER_RS_ALPHAFUNC,
|
|
|
MOJOSHADER_RS_DITHERENABLE,
|
|
|
MOJOSHADER_RS_ALPHABLENDENABLE,
|
|
|
MOJOSHADER_RS_FOGENABLE,
|
|
|
MOJOSHADER_RS_SPECULARENABLE,
|
|
|
MOJOSHADER_RS_FOGCOLOR,
|
|
|
MOJOSHADER_RS_FOGTABLEMODE,
|
|
|
MOJOSHADER_RS_FOGSTART,
|
|
|
MOJOSHADER_RS_FOGEND,
|
|
|
MOJOSHADER_RS_FOGDENSITY,
|
|
|
MOJOSHADER_RS_RANGEFOGENABLE,
|
|
|
MOJOSHADER_RS_STENCILENABLE,
|
|
|
MOJOSHADER_RS_STENCILFAIL,
|
|
|
MOJOSHADER_RS_STENCILZFAIL,
|
|
|
MOJOSHADER_RS_STENCILPASS,
|
|
|
MOJOSHADER_RS_STENCILFUNC,
|
|
|
MOJOSHADER_RS_STENCILREF,
|
|
|
MOJOSHADER_RS_STENCILMASK,
|
|
|
MOJOSHADER_RS_STENCILWRITEMASK,
|
|
|
MOJOSHADER_RS_TEXTUREFACTOR,
|
|
|
MOJOSHADER_RS_WRAP0,
|
|
|
MOJOSHADER_RS_WRAP1,
|
|
|
MOJOSHADER_RS_WRAP2,
|
|
|
MOJOSHADER_RS_WRAP3,
|
|
|
MOJOSHADER_RS_WRAP4,
|
|
|
MOJOSHADER_RS_WRAP5,
|
|
|
MOJOSHADER_RS_WRAP6,
|
|
|
MOJOSHADER_RS_WRAP7,
|
|
|
MOJOSHADER_RS_WRAP8,
|
|
|
MOJOSHADER_RS_WRAP9,
|
|
|
MOJOSHADER_RS_WRAP10,
|
|
|
MOJOSHADER_RS_WRAP11,
|
|
|
MOJOSHADER_RS_WRAP12,
|
|
|
MOJOSHADER_RS_WRAP13,
|
|
|
MOJOSHADER_RS_WRAP14,
|
|
|
MOJOSHADER_RS_WRAP15,
|
|
|
MOJOSHADER_RS_CLIPPING,
|
|
|
MOJOSHADER_RS_LIGHTING,
|
|
|
MOJOSHADER_RS_AMBIENT,
|
|
|
MOJOSHADER_RS_FOGVERTEXMODE,
|
|
|
MOJOSHADER_RS_COLORVERTEX,
|
|
|
MOJOSHADER_RS_LOCALVIEWER,
|
|
|
MOJOSHADER_RS_NORMALIZENORMALS,
|
|
|
MOJOSHADER_RS_DIFFUSEMATERIALSOURCE,
|
|
|
MOJOSHADER_RS_SPECULARMATERIALSOURCE,
|
|
|
MOJOSHADER_RS_AMBIENTMATERIALSOURCE,
|
|
|
MOJOSHADER_RS_EMISSIVEMATERIALSOURCE,
|
|
|
MOJOSHADER_RS_VERTEXBLEND,
|
|
|
MOJOSHADER_RS_CLIPPLANEENABLE,
|
|
|
MOJOSHADER_RS_POINTSIZE,
|
|
|
MOJOSHADER_RS_POINTSIZE_MIN,
|
|
|
MOJOSHADER_RS_POINTSPRITEENABLE,
|
|
|
MOJOSHADER_RS_POINTSCALEENABLE,
|
|
|
MOJOSHADER_RS_POINTSCALE_A,
|
|
|
MOJOSHADER_RS_POINTSCALE_B,
|
|
|
MOJOSHADER_RS_POINTSCALE_C,
|
|
|
MOJOSHADER_RS_MULTISAMPLEANTIALIAS,
|
|
|
MOJOSHADER_RS_MULTISAMPLEMASK,
|
|
|
MOJOSHADER_RS_PATCHEDGESTYLE,
|
|
|
MOJOSHADER_RS_DEBUGMONITORTOKEN,
|
|
|
MOJOSHADER_RS_POINTSIZE_MAX,
|
|
|
MOJOSHADER_RS_INDEXEDVERTEXBLENDENABLE,
|
|
|
MOJOSHADER_RS_COLORWRITEENABLE,
|
|
|
MOJOSHADER_RS_TWEENFACTOR,
|
|
|
MOJOSHADER_RS_BLENDOP,
|
|
|
MOJOSHADER_RS_POSITIONDEGREE,
|
|
|
MOJOSHADER_RS_NORMALDEGREE,
|
|
|
MOJOSHADER_RS_SCISSORTESTENABLE,
|
|
|
MOJOSHADER_RS_SLOPESCALEDEPTHBIAS,
|
|
|
MOJOSHADER_RS_ANTIALIASEDLINEENABLE,
|
|
|
MOJOSHADER_RS_MINTESSELLATIONLEVEL,
|
|
|
MOJOSHADER_RS_MAXTESSELLATIONLEVEL,
|
|
|
MOJOSHADER_RS_ADAPTIVETESS_X,
|
|
|
MOJOSHADER_RS_ADAPTIVETESS_Y,
|
|
|
MOJOSHADER_RS_ADAPTIVETESS_Z,
|
|
|
MOJOSHADER_RS_ADAPTIVETESS_W,
|
|
|
MOJOSHADER_RS_ENABLEADAPTIVETESSELLATION,
|
|
|
MOJOSHADER_RS_TWOSIDEDSTENCILMODE,
|
|
|
MOJOSHADER_RS_CCW_STENCILFAIL,
|
|
|
MOJOSHADER_RS_CCW_STENCILZFAIL,
|
|
|
MOJOSHADER_RS_CCW_STENCILPASS,
|
|
|
MOJOSHADER_RS_CCW_STENCILFUNC,
|
|
|
MOJOSHADER_RS_COLORWRITEENABLE1,
|
|
|
MOJOSHADER_RS_COLORWRITEENABLE2,
|
|
|
MOJOSHADER_RS_COLORWRITEENABLE3,
|
|
|
MOJOSHADER_RS_BLENDFACTOR,
|
|
|
MOJOSHADER_RS_SRGBWRITEENABLE,
|
|
|
MOJOSHADER_RS_DEPTHBIAS,
|
|
|
MOJOSHADER_RS_SEPARATEALPHABLENDENABLE,
|
|
|
MOJOSHADER_RS_SRCBLENDALPHA,
|
|
|
MOJOSHADER_RS_DESTBLENDALPHA,
|
|
|
MOJOSHADER_RS_BLENDOPALPHA,
|
|
|
MOJOSHADER_RS_VERTEXSHADER = 146,
|
|
|
MOJOSHADER_RS_PIXELSHADER = 147
|
|
|
}
|
|
|
|
|
|
private enum MOJOSHADER_zBufferType
|
|
|
{
|
|
|
MOJOSHADER_ZB_FALSE,
|
|
|
MOJOSHADER_ZB_TRUE,
|
|
|
MOJOSHADER_ZB_USEW
|
|
|
}
|
|
|
|
|
|
private enum MOJOSHADER_fillMode
|
|
|
{
|
|
|
MOJOSHADER_FILL_POINT = 1,
|
|
|
MOJOSHADER_FILL_WIREFRAME = 2,
|
|
|
MOJOSHADER_FILL_SOLID = 3
|
|
|
}
|
|
|
|
|
|
private enum MOJOSHADER_blendMode
|
|
|
{
|
|
|
MOJOSHADER_BLEND_ZERO = 1,
|
|
|
MOJOSHADER_BLEND_ONE = 2,
|
|
|
MOJOSHADER_BLEND_SRCCOLOR = 3,
|
|
|
MOJOSHADER_BLEND_INVSRCCOLOR = 4,
|
|
|
MOJOSHADER_BLEND_SRCALPHA = 5,
|
|
|
MOJOSHADER_BLEND_INVSRCALPHA = 6,
|
|
|
MOJOSHADER_BLEND_DESTALPHA = 7,
|
|
|
MOJOSHADER_BLEND_INVDESTALPHA = 8,
|
|
|
MOJOSHADER_BLEND_DESTCOLOR = 9,
|
|
|
MOJOSHADER_BLEND_INVDESTCOLOR = 10,
|
|
|
MOJOSHADER_BLEND_SRCALPHASAT = 11,
|
|
|
MOJOSHADER_BLEND_BOTHSRCALPHA = 12,
|
|
|
MOJOSHADER_BLEND_BOTHINVSRCALPHA = 13,
|
|
|
MOJOSHADER_BLEND_BLENDFACTOR = 14,
|
|
|
MOJOSHADER_BLEND_INVBLENDFACTOR = 15,
|
|
|
MOJOSHADER_BLEND_SRCCOLOR2 = 16,
|
|
|
MOJOSHADER_BLEND_INVSRCCOLOR2 = 17
|
|
|
}
|
|
|
|
|
|
private enum MOJOSHADER_cullMode
|
|
|
{
|
|
|
MOJOSHADER_CULL_NONE = 1,
|
|
|
MOJOSHADER_CULL_CW = 2,
|
|
|
MOJOSHADER_CULL_CCW = 3
|
|
|
}
|
|
|
|
|
|
private enum MOJOSHADER_compareFunc
|
|
|
{
|
|
|
MOJOSHADER_CMP_NEVER = 1,
|
|
|
MOJOSHADER_CMP_LESS = 2,
|
|
|
MOJOSHADER_CMP_EQUAL = 3,
|
|
|
MOJOSHADER_CMP_LESSEQUAL = 4,
|
|
|
MOJOSHADER_CMP_GREATER = 5,
|
|
|
MOJOSHADER_CMP_NOTEQUAL = 6,
|
|
|
MOJOSHADER_CMP_GREATEREQUAL = 7,
|
|
|
MOJOSHADER_CMP_ALWAYS = 8
|
|
|
}
|
|
|
|
|
|
private enum MOJOSHADER_stencilOp
|
|
|
{
|
|
|
MOJOSHADER_STENCILOP_KEEP = 1,
|
|
|
MOJOSHADER_STENCILOP_ZERO = 2,
|
|
|
MOJOSHADER_STENCILOP_REPLACE = 3,
|
|
|
MOJOSHADER_STENCILOP_INCRSAT = 4,
|
|
|
MOJOSHADER_STENCILOP_DECRSAT = 5,
|
|
|
MOJOSHADER_STENCILOP_INVERT = 6,
|
|
|
MOJOSHADER_STENCILOP_INCR = 7,
|
|
|
MOJOSHADER_STENCILOP_DECR = 8
|
|
|
}
|
|
|
|
|
|
private enum MOJOSHADER_blendOp
|
|
|
{
|
|
|
MOJOSHADER_BLENDOP_ADD = 1,
|
|
|
MOJOSHADER_BLENDOP_SUBTRACT = 2,
|
|
|
MOJOSHADER_BLENDOP_REVSUBTRACT = 3,
|
|
|
MOJOSHADER_BLENDOP_MIN = 4,
|
|
|
MOJOSHADER_BLENDOP_MAX = 5
|
|
|
}
|
|
|
|
|
|
/* MOJOSHADER_effectSamplerState types... */
|
|
|
|
|
|
private enum MOJOSHADER_samplerStateType
|
|
|
{
|
|
|
MOJOSHADER_SAMP_UNKNOWN0 = 0,
|
|
|
MOJOSHADER_SAMP_UNKNOWN1 = 1,
|
|
|
MOJOSHADER_SAMP_UNKNOWN2 = 2,
|
|
|
MOJOSHADER_SAMP_UNKNOWN3 = 3,
|
|
|
MOJOSHADER_SAMP_TEXTURE = 4,
|
|
|
MOJOSHADER_SAMP_ADDRESSU = 5,
|
|
|
MOJOSHADER_SAMP_ADDRESSV = 6,
|
|
|
MOJOSHADER_SAMP_ADDRESSW = 7,
|
|
|
MOJOSHADER_SAMP_BORDERCOLOR = 8,
|
|
|
MOJOSHADER_SAMP_MAGFILTER = 9,
|
|
|
MOJOSHADER_SAMP_MINFILTER = 10,
|
|
|
MOJOSHADER_SAMP_MIPFILTER = 11,
|
|
|
MOJOSHADER_SAMP_MIPMAPLODBIAS = 12,
|
|
|
MOJOSHADER_SAMP_MAXMIPLEVEL = 13,
|
|
|
MOJOSHADER_SAMP_MAXANISOTROPY = 14,
|
|
|
MOJOSHADER_SAMP_SRGBTEXTURE = 15,
|
|
|
MOJOSHADER_SAMP_ELEMENTINDEX = 16,
|
|
|
MOJOSHADER_SAMP_DMAPOFFSET = 17
|
|
|
}
|
|
|
|
|
|
private enum MOJOSHADER_textureAddress
|
|
|
{
|
|
|
MOJOSHADER_TADDRESS_WRAP = 1,
|
|
|
MOJOSHADER_TADDRESS_MIRROR = 2,
|
|
|
MOJOSHADER_TADDRESS_CLAMP = 3,
|
|
|
MOJOSHADER_TADDRESS_BORDER = 4,
|
|
|
MOJOSHADER_TADDRESS_MIRRORONCE = 5
|
|
|
}
|
|
|
|
|
|
private enum MOJOSHADER_textureFilterType
|
|
|
{
|
|
|
MOJOSHADER_TEXTUREFILTER_NONE,
|
|
|
MOJOSHADER_TEXTUREFILTER_POINT,
|
|
|
MOJOSHADER_TEXTUREFILTER_LINEAR,
|
|
|
MOJOSHADER_TEXTUREFILTER_ANISOTROPIC,
|
|
|
MOJOSHADER_TEXTUREFILTER_PYRAMIDALQUAD,
|
|
|
MOJOSHADER_TEXTUREFILTER_GAUSSIANQUAD,
|
|
|
MOJOSHADER_TEXTUREFILTER_CONVOLUTIONMONO
|
|
|
}
|
|
|
|
|
|
/* Effect value types... */
|
|
|
|
|
|
[StructLayout(LayoutKind.Sequential)]
|
|
|
private struct MOJOSHADER_effectValue
|
|
|
{
|
|
|
public IntPtr name; // const char*
|
|
|
public IntPtr semantic; // const char*
|
|
|
public MOJOSHADER_symbolTypeInfo type;
|
|
|
public uint value_count;
|
|
|
public IntPtr values; // You know what, just look at the C header...
|
|
|
}
|
|
|
|
|
|
[StructLayout(LayoutKind.Sequential)]
|
|
|
private struct MOJOSHADER_effectState
|
|
|
{
|
|
|
public MOJOSHADER_renderStateType type;
|
|
|
public MOJOSHADER_effectValue value;
|
|
|
}
|
|
|
|
|
|
[StructLayout(LayoutKind.Sequential)]
|
|
|
private struct MOJOSHADER_effectSamplerState
|
|
|
{
|
|
|
public MOJOSHADER_samplerStateType type;
|
|
|
public MOJOSHADER_effectValue value;
|
|
|
}
|
|
|
|
|
|
/* typedef MOJOSHADER_effectValue MOJOSHADER_effectAnnotation; */
|
|
|
[StructLayout(LayoutKind.Sequential)]
|
|
|
private struct MOJOSHADER_effectAnnotation
|
|
|
{
|
|
|
public IntPtr name; // const char*
|
|
|
public IntPtr semantic; // const char*
|
|
|
public MOJOSHADER_symbolTypeInfo type;
|
|
|
public uint value_count;
|
|
|
public IntPtr values; // You know what, just look at the C header...
|
|
|
}
|
|
|
|
|
|
/* Effect interface structures... */
|
|
|
|
|
|
[StructLayout(LayoutKind.Sequential)]
|
|
|
private struct MOJOSHADER_effectParam
|
|
|
{
|
|
|
public MOJOSHADER_effectValue value;
|
|
|
public uint annotation_count;
|
|
|
public IntPtr annotations; // MOJOSHADER_effectAnnotations*
|
|
|
}
|
|
|
|
|
|
[StructLayout(LayoutKind.Sequential)]
|
|
|
private struct MOJOSHADER_effectPass
|
|
|
{
|
|
|
public IntPtr name; // const char*
|
|
|
public uint state_count;
|
|
|
public IntPtr states; // MOJOSHADER_effectState*
|
|
|
public uint annotation_count;
|
|
|
public IntPtr annotations; // MOJOSHADER_effectAnnotations*
|
|
|
}
|
|
|
|
|
|
[StructLayout(LayoutKind.Sequential)]
|
|
|
private struct MOJOSHADER_effectTechnique
|
|
|
{
|
|
|
public IntPtr name; // const char*
|
|
|
public uint pass_count;
|
|
|
public IntPtr passes; // MOJOSHADER_effectPass*
|
|
|
public uint annotation_count;
|
|
|
public IntPtr annotations; // MOJOSHADER_effectAnnotations*
|
|
|
}
|
|
|
|
|
|
/* Effect "objects"... */
|
|
|
|
|
|
[StructLayout(LayoutKind.Sequential)]
|
|
|
private struct MOJOSHADER_effectShader
|
|
|
{
|
|
|
public MOJOSHADER_symbolType type;
|
|
|
public uint technique;
|
|
|
public uint pass;
|
|
|
public uint is_preshader;
|
|
|
public uint preshader_param_count;
|
|
|
public IntPtr preshader_params; // unsigned int*
|
|
|
public uint param_count;
|
|
|
public IntPtr parameters; // unsigned int*
|
|
|
public uint sampler_count;
|
|
|
public IntPtr samplers; // MOJOSHADER_samplerStateRegister*
|
|
|
public IntPtr shader; // *shader/*preshader union
|
|
|
}
|
|
|
|
|
|
[StructLayout(LayoutKind.Sequential)]
|
|
|
private struct MOJOSHADER_effectSamplerMap
|
|
|
{
|
|
|
public MOJOSHADER_symbolType type;
|
|
|
public IntPtr name; // const char*
|
|
|
}
|
|
|
|
|
|
[StructLayout(LayoutKind.Sequential)]
|
|
|
private struct MOJOSHADER_effectString
|
|
|
{
|
|
|
public MOJOSHADER_symbolType type;
|
|
|
public IntPtr stringvalue; // const char*
|
|
|
}
|
|
|
|
|
|
[StructLayout(LayoutKind.Sequential)]
|
|
|
private struct MOJOSHADER_effectTexture
|
|
|
{
|
|
|
public MOJOSHADER_symbolType type;
|
|
|
}
|
|
|
|
|
|
[StructLayout(LayoutKind.Explicit)]
|
|
|
private struct MOJOSHADER_effectObject
|
|
|
{
|
|
|
[FieldOffset(0)]
|
|
|
public MOJOSHADER_symbolType type;
|
|
|
[FieldOffset(0)]
|
|
|
public MOJOSHADER_effectShader shader;
|
|
|
[FieldOffset(0)]
|
|
|
public MOJOSHADER_effectSamplerMap mapping;
|
|
|
[FieldOffset(0)]
|
|
|
public MOJOSHADER_effectString stringvalue;
|
|
|
[FieldOffset(0)]
|
|
|
public MOJOSHADER_effectTexture texture;
|
|
|
}
|
|
|
|
|
|
/* Effect state change types... */
|
|
|
|
|
|
[StructLayout(LayoutKind.Sequential)]
|
|
|
private struct MOJOSHADER_samplerStateRegister
|
|
|
{
|
|
|
public IntPtr sampler_name; // const char*
|
|
|
public uint sampler_register;
|
|
|
public uint sampler_state_count;
|
|
|
public IntPtr sampler_states; // const MOJOSHADER_effectSamplerState*
|
|
|
}
|
|
|
|
|
|
// Needed by VideoPlayer...
|
|
|
[StructLayout(LayoutKind.Sequential)]
|
|
|
internal struct MOJOSHADER_effectStateChanges
|
|
|
{
|
|
|
public uint render_state_change_count;
|
|
|
public IntPtr render_state_changes; // const MOJOSHADER_effectState*
|
|
|
public uint sampler_state_change_count;
|
|
|
public IntPtr sampler_state_changes; // const MOJOSHADER_samplerStateRegister*
|
|
|
public uint vertex_sampler_state_change_count;
|
|
|
public IntPtr vertex_sampler_state_changes; // const MOJOSHADER_samplerStateRegister*
|
|
|
}
|
|
|
|
|
|
/* Effect parsing interface... this is a partial struct! */
|
|
|
|
|
|
[StructLayout(LayoutKind.Sequential)]
|
|
|
private struct MOJOSHADER_effect
|
|
|
{
|
|
|
public int error_count;
|
|
|
public IntPtr errors; // MOJOSHADER_error*
|
|
|
public int param_count;
|
|
|
public IntPtr parameters; // MOJOSHADER_effectParam* params, lolC#
|
|
|
public int technique_count;
|
|
|
public IntPtr techniques; // MOJOSHADER_effectTechnique*
|
|
|
public int object_count;
|
|
|
public IntPtr objects; // MOJOSHADER_effectObject*
|
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
}
|
|
|
}
|
|
|
|