Show More
Commit Description:
Various UI improvements.
Commit Description:
Various UI improvements.
References:
File last commit:
Show/Diff file:
Action:
FNA/src/Graphics/Effect/Effect.cs
1026 lines | 38.5 KiB | text/x-csharp | CSharpLexer
1026 lines | 38.5 KiB | text/x-csharp | CSharpLexer
r0 | #region License | |||
/* FNA - XNA4 Reimplementation for Desktop Platforms | ||||
* Copyright 2009-2020 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 | ||||
{ | ||||
MojoShader.MOJOSHADER_effectSetTechnique( | ||||
glEffect.EffectData, | ||||
value.TechniquePointer | ||||
); | ||||
INTERNAL_currentTechnique = value; | ||||
} | ||||
} | ||||
public EffectParameterCollection Parameters | ||||
{ | ||||
get; | ||||
private set; | ||||
} | ||||
public EffectTechniqueCollection Techniques | ||||
{ | ||||
get; | ||||
private set; | ||||
} | ||||
#endregion | ||||
#region Internal Variables | ||||
internal IGLEffect 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.MOJOSHADER_textureFilterType[] XNAMag = | ||||
new MojoShader.MOJOSHADER_textureFilterType[] | ||||
{ | ||||
MojoShader.MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_LINEAR, // TextureFilter.Linear | ||||
MojoShader.MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_POINT, // TextureFilter.Point | ||||
MojoShader.MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_ANISOTROPIC, // TextureFilter.Anisotropic | ||||
MojoShader.MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_LINEAR, // TextureFilter.LinearMipPoint | ||||
MojoShader.MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_POINT, // TextureFilter.PointMipLinear | ||||
MojoShader.MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_POINT, // TextureFilter.MinLinearMagPointMipLinear | ||||
MojoShader.MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_POINT, // TextureFilter.MinLinearMagPointMipPoint | ||||
MojoShader.MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_LINEAR, // TextureFilter.MinPointMagLinearMipLinear | ||||
MojoShader.MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_LINEAR // TextureFilter.MinPointMagLinearMipPoint | ||||
}; | ||||
private static readonly MojoShader.MOJOSHADER_textureFilterType[] XNAMin = | ||||
new MojoShader.MOJOSHADER_textureFilterType[] | ||||
{ | ||||
MojoShader.MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_LINEAR, // TextureFilter.Linear | ||||
MojoShader.MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_POINT, // TextureFilter.Point | ||||
MojoShader.MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_ANISOTROPIC, // TextureFilter.Anisotropic | ||||
MojoShader.MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_LINEAR, // TextureFilter.LinearMipPoint | ||||
MojoShader.MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_POINT, // TextureFilter.PointMipLinear | ||||
MojoShader.MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_LINEAR, // TextureFilter.MinLinearMagPointMipLinear | ||||
MojoShader.MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_LINEAR, // TextureFilter.MinLinearMagPointMipPoint | ||||
MojoShader.MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_POINT, // TextureFilter.MinPointMagLinearMipLinear | ||||
MojoShader.MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_POINT // TextureFilter.MinPointMagLinearMipPoint | ||||
}; | ||||
private static readonly MojoShader.MOJOSHADER_textureFilterType[] XNAMip = | ||||
new MojoShader.MOJOSHADER_textureFilterType[] | ||||
{ | ||||
MojoShader.MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_LINEAR, // TextureFilter.Linear | ||||
MojoShader.MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_POINT, // TextureFilter.Point | ||||
MojoShader.MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_ANISOTROPIC, // TextureFilter.Anisotropic | ||||
MojoShader.MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_POINT, // TextureFilter.LinearMipPoint | ||||
MojoShader.MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_LINEAR, // TextureFilter.PointMipLinear | ||||
MojoShader.MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_LINEAR, // TextureFilter.MinLinearMagPointMipLinear | ||||
MojoShader.MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_POINT, // TextureFilter.MinLinearMagPointMipPoint | ||||
MojoShader.MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_LINEAR, // TextureFilter.MinPointMagLinearMipLinear | ||||
MojoShader.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 | ||||
glEffect = graphicsDevice.GLDevice.CreateEffect(effectCode); | ||||
// This is where it gets ugly... | ||||
INTERNAL_parseEffectStruct(); | ||||
// 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.MOJOSHADER_effectStateChanges) | ||||
); | ||||
MojoShader.MOJOSHADER_effectStateChanges *stateChanges = | ||||
(MojoShader.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 | ||||
glEffect = GraphicsDevice.GLDevice.CloneEffect( | ||||
cloneSource.glEffect | ||||
); | ||||
// Double the ugly, double the fun! | ||||
INTERNAL_parseEffectStruct(); | ||||
// 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.MOJOSHADER_effectStateChanges) | ||||
); | ||||
MojoShader.MOJOSHADER_effectStateChanges *stateChanges = | ||||
(MojoShader.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 != null) | ||||
{ | ||||
GraphicsDevice.GLDevice.AddDisposeEffect(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) | ||||
{ | ||||
GraphicsDevice.GLDevice.ApplyEffect( | ||||
glEffect, | ||||
CurrentTechnique.TechniquePointer, | ||||
pass, | ||||
stateChangesPtr | ||||
); | ||||
MojoShader.MOJOSHADER_effectStateChanges *stateChanges = | ||||
(MojoShader.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.MOJOSHADER_effectState* states = (MojoShader.MOJOSHADER_effectState*) stateChanges->render_state_changes; | ||||
for (int i = 0; i < stateChanges->render_state_change_count; i += 1) | ||||
{ | ||||
MojoShader.MOJOSHADER_renderStateType type = states[i].type; | ||||
if ( type == MojoShader.MOJOSHADER_renderStateType.MOJOSHADER_RS_VERTEXSHADER || | ||||
type == MojoShader.MOJOSHADER_renderStateType.MOJOSHADER_RS_PIXELSHADER ) | ||||
{ | ||||
// Skip shader states | ||||
continue; | ||||
} | ||||
if (type == MojoShader.MOJOSHADER_renderStateType.MOJOSHADER_RS_ZENABLE) | ||||
{ | ||||
MojoShader.MOJOSHADER_zBufferType* val = (MojoShader.MOJOSHADER_zBufferType*) states[i].value.values; | ||||
pipelineCache.DepthBufferEnable = | ||||
(*val == MojoShader.MOJOSHADER_zBufferType.MOJOSHADER_ZB_TRUE); | ||||
depthStencilStateChanged = true; | ||||
} | ||||
else if (type == MojoShader.MOJOSHADER_renderStateType.MOJOSHADER_RS_FILLMODE) | ||||
{ | ||||
MojoShader.MOJOSHADER_fillMode* val = (MojoShader.MOJOSHADER_fillMode*) states[i].value.values; | ||||
if (*val == MojoShader.MOJOSHADER_fillMode.MOJOSHADER_FILL_SOLID) | ||||
{ | ||||
pipelineCache.FillMode = FillMode.Solid; | ||||
} | ||||
else if (*val == MojoShader.MOJOSHADER_fillMode.MOJOSHADER_FILL_WIREFRAME) | ||||
{ | ||||
pipelineCache.FillMode = FillMode.WireFrame; | ||||
} | ||||
rasterizerStateChanged = true; | ||||
} | ||||
else if (type == MojoShader.MOJOSHADER_renderStateType.MOJOSHADER_RS_ZWRITEENABLE) | ||||
{ | ||||
int* val = (int*) states[i].value.values; | ||||
pipelineCache.DepthBufferWriteEnable = (*val == 1); | ||||
depthStencilStateChanged = true; | ||||
} | ||||
else if (type == MojoShader.MOJOSHADER_renderStateType.MOJOSHADER_RS_SRCBLEND) | ||||
{ | ||||
MojoShader.MOJOSHADER_blendMode* val = (MojoShader.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.MOJOSHADER_renderStateType.MOJOSHADER_RS_DESTBLEND) | ||||
{ | ||||
MojoShader.MOJOSHADER_blendMode* val = (MojoShader.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.MOJOSHADER_renderStateType.MOJOSHADER_RS_CULLMODE) | ||||
{ | ||||
MojoShader.MOJOSHADER_cullMode* val = (MojoShader.MOJOSHADER_cullMode*) states[i].value.values; | ||||
if (*val == MojoShader.MOJOSHADER_cullMode.MOJOSHADER_CULL_NONE) | ||||
{ | ||||
pipelineCache.CullMode = CullMode.None; | ||||
} | ||||
else if (*val == MojoShader.MOJOSHADER_cullMode.MOJOSHADER_CULL_CW) | ||||
{ | ||||
pipelineCache.CullMode = CullMode.CullClockwiseFace; | ||||
} | ||||
else if (*val == MojoShader.MOJOSHADER_cullMode.MOJOSHADER_CULL_CCW) | ||||
{ | ||||
pipelineCache.CullMode = CullMode.CullCounterClockwiseFace; | ||||
} | ||||
rasterizerStateChanged = true; | ||||
} | ||||
else if (type == MojoShader.MOJOSHADER_renderStateType.MOJOSHADER_RS_ZFUNC) | ||||
{ | ||||
MojoShader.MOJOSHADER_compareFunc* val = (MojoShader.MOJOSHADER_compareFunc*) states[i].value.values; | ||||
pipelineCache.DepthBufferFunction = XNACompare[(int) *val]; | ||||
depthStencilStateChanged = true; | ||||
} | ||||
else if (type == MojoShader.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.MOJOSHADER_renderStateType.MOJOSHADER_RS_STENCILENABLE) | ||||
{ | ||||
int* val = (int*) states[i].value.values; | ||||
pipelineCache.StencilEnable = (*val == 1); | ||||
depthStencilStateChanged = true; | ||||
} | ||||
else if (type == MojoShader.MOJOSHADER_renderStateType.MOJOSHADER_RS_STENCILFAIL) | ||||
{ | ||||
MojoShader.MOJOSHADER_stencilOp* val = (MojoShader.MOJOSHADER_stencilOp*) states[i].value.values; | ||||
pipelineCache.StencilFail = XNAStencilOp[(int) *val]; | ||||
depthStencilStateChanged = true; | ||||
} | ||||
else if (type == MojoShader.MOJOSHADER_renderStateType.MOJOSHADER_RS_STENCILZFAIL) | ||||
{ | ||||
MojoShader.MOJOSHADER_stencilOp* val = (MojoShader.MOJOSHADER_stencilOp*) states[i].value.values; | ||||
pipelineCache.StencilDepthBufferFail = XNAStencilOp[(int) *val]; | ||||
depthStencilStateChanged = true; | ||||
} | ||||
else if (type == MojoShader.MOJOSHADER_renderStateType.MOJOSHADER_RS_STENCILPASS) | ||||
{ | ||||
MojoShader.MOJOSHADER_stencilOp* val = (MojoShader.MOJOSHADER_stencilOp*) states[i].value.values; | ||||
pipelineCache.StencilPass = XNAStencilOp[(int) *val]; | ||||
depthStencilStateChanged = true; | ||||
} | ||||
else if (type == MojoShader.MOJOSHADER_renderStateType.MOJOSHADER_RS_STENCILFUNC) | ||||
{ | ||||
MojoShader.MOJOSHADER_compareFunc* val = (MojoShader.MOJOSHADER_compareFunc*) states[i].value.values; | ||||
pipelineCache.StencilFunction = XNACompare[(int) *val]; | ||||
depthStencilStateChanged = true; | ||||
} | ||||
else if (type == MojoShader.MOJOSHADER_renderStateType.MOJOSHADER_RS_STENCILREF) | ||||
{ | ||||
int* val = (int*) states[i].value.values; | ||||
pipelineCache.ReferenceStencil = *val; | ||||
depthStencilStateChanged = true; | ||||
} | ||||
else if (type == MojoShader.MOJOSHADER_renderStateType.MOJOSHADER_RS_STENCILMASK) | ||||
{ | ||||
int* val = (int*) states[i].value.values; | ||||
pipelineCache.StencilMask = *val; | ||||
depthStencilStateChanged = true; | ||||
} | ||||
else if (type == MojoShader.MOJOSHADER_renderStateType.MOJOSHADER_RS_STENCILWRITEMASK) | ||||
{ | ||||
int* val = (int*) states[i].value.values; | ||||
pipelineCache.StencilWriteMask = *val; | ||||
depthStencilStateChanged = true; | ||||
} | ||||
else if (type == MojoShader.MOJOSHADER_renderStateType.MOJOSHADER_RS_MULTISAMPLEANTIALIAS) | ||||
{ | ||||
int* val = (int*) states[i].value.values; | ||||
pipelineCache.MultiSampleAntiAlias = (*val == 1); | ||||
rasterizerStateChanged = true; | ||||
} | ||||
else if (type == MojoShader.MOJOSHADER_renderStateType.MOJOSHADER_RS_MULTISAMPLEMASK) | ||||
{ | ||||
int* val = (int*) states[i].value.values; | ||||
pipelineCache.MultiSampleMask = *val; | ||||
blendStateChanged = true; | ||||
} | ||||
else if (type == MojoShader.MOJOSHADER_renderStateType.MOJOSHADER_RS_COLORWRITEENABLE) | ||||
{ | ||||
int* val = (int*) states[i].value.values; | ||||
pipelineCache.ColorWriteChannels = (ColorWriteChannels) (*val); | ||||
blendStateChanged = true; | ||||
} | ||||
else if (type == MojoShader.MOJOSHADER_renderStateType.MOJOSHADER_RS_BLENDOP) | ||||
{ | ||||
MojoShader.MOJOSHADER_blendOp* val = (MojoShader.MOJOSHADER_blendOp*) states[i].value.values; | ||||
pipelineCache.ColorBlendFunction = XNABlendOp[(int) *val]; | ||||
blendStateChanged = true; | ||||
} | ||||
else if (type == MojoShader.MOJOSHADER_renderStateType.MOJOSHADER_RS_SCISSORTESTENABLE) | ||||
{ | ||||
int* val = (int*) states[i].value.values; | ||||
pipelineCache.ScissorTestEnable = (*val == 1); | ||||
rasterizerStateChanged = true; | ||||
} | ||||
else if (type == MojoShader.MOJOSHADER_renderStateType.MOJOSHADER_RS_SLOPESCALEDEPTHBIAS) | ||||
{ | ||||
float* val = (float*) states[i].value.values; | ||||
pipelineCache.SlopeScaleDepthBias = *val; | ||||
rasterizerStateChanged = true; | ||||
} | ||||
else if (type == MojoShader.MOJOSHADER_renderStateType.MOJOSHADER_RS_TWOSIDEDSTENCILMODE) | ||||
{ | ||||
int* val = (int*) states[i].value.values; | ||||
pipelineCache.TwoSidedStencilMode = (*val == 1); | ||||
depthStencilStateChanged = true; | ||||
} | ||||
else if (type == MojoShader.MOJOSHADER_renderStateType.MOJOSHADER_RS_CCW_STENCILFAIL) | ||||
{ | ||||
MojoShader.MOJOSHADER_stencilOp* val = (MojoShader.MOJOSHADER_stencilOp*) states[i].value.values; | ||||
pipelineCache.CCWStencilFail = XNAStencilOp[(int) *val]; | ||||
depthStencilStateChanged = true; | ||||
} | ||||
else if (type == MojoShader.MOJOSHADER_renderStateType.MOJOSHADER_RS_CCW_STENCILZFAIL) | ||||
{ | ||||
MojoShader.MOJOSHADER_stencilOp* val = (MojoShader.MOJOSHADER_stencilOp*) states[i].value.values; | ||||
pipelineCache.CCWStencilDepthBufferFail = XNAStencilOp[(int) *val]; | ||||
depthStencilStateChanged = true; | ||||
} | ||||
else if (type == MojoShader.MOJOSHADER_renderStateType.MOJOSHADER_RS_CCW_STENCILPASS) | ||||
{ | ||||
MojoShader.MOJOSHADER_stencilOp* val = (MojoShader.MOJOSHADER_stencilOp*) states[i].value.values; | ||||
pipelineCache.CCWStencilPass = XNAStencilOp[(int) *val]; | ||||
depthStencilStateChanged = true; | ||||
} | ||||
else if (type == MojoShader.MOJOSHADER_renderStateType.MOJOSHADER_RS_CCW_STENCILFUNC) | ||||
{ | ||||
MojoShader.MOJOSHADER_compareFunc* val = (MojoShader.MOJOSHADER_compareFunc*) states[i].value.values; | ||||
pipelineCache.CCWStencilFunction = XNACompare[(int) *val]; | ||||
depthStencilStateChanged = true; | ||||
} | ||||
else if (type == MojoShader.MOJOSHADER_renderStateType.MOJOSHADER_RS_COLORWRITEENABLE1) | ||||
{ | ||||
int* val = (int*) states[i].value.values; | ||||
pipelineCache.ColorWriteChannels1 = (ColorWriteChannels) (*val); | ||||
blendStateChanged = true; | ||||
} | ||||
else if (type == MojoShader.MOJOSHADER_renderStateType.MOJOSHADER_RS_COLORWRITEENABLE2) | ||||
{ | ||||
int* val = (int*) states[i].value.values; | ||||
pipelineCache.ColorWriteChannels2 = (ColorWriteChannels) (*val); | ||||
blendStateChanged = true; | ||||
} | ||||
else if (type == MojoShader.MOJOSHADER_renderStateType.MOJOSHADER_RS_COLORWRITEENABLE3) | ||||
{ | ||||
int* val = (int*) states[i].value.values; | ||||
pipelineCache.ColorWriteChannels3 = (ColorWriteChannels) (*val); | ||||
blendStateChanged = true; | ||||
} | ||||
else if (type == MojoShader.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.MOJOSHADER_renderStateType.MOJOSHADER_RS_DEPTHBIAS) | ||||
{ | ||||
float* val = (float*) states[i].value.values; | ||||
pipelineCache.DepthBias = *val; | ||||
rasterizerStateChanged = true; | ||||
} | ||||
else if (type == MojoShader.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.MOJOSHADER_renderStateType.MOJOSHADER_RS_SRCBLENDALPHA) | ||||
{ | ||||
MojoShader.MOJOSHADER_blendMode* val = (MojoShader.MOJOSHADER_blendMode*) states[i].value.values; | ||||
pipelineCache.AlphaSourceBlend = XNABlend[(int) *val]; | ||||
blendStateChanged = true; | ||||
} | ||||
else if (type == MojoShader.MOJOSHADER_renderStateType.MOJOSHADER_RS_DESTBLENDALPHA) | ||||
{ | ||||
MojoShader.MOJOSHADER_blendMode* val = (MojoShader.MOJOSHADER_blendMode*) states[i].value.values; | ||||
pipelineCache.AlphaDestinationBlend = XNABlend[(int) *val]; | ||||
blendStateChanged = true; | ||||
} | ||||
else if (type == MojoShader.MOJOSHADER_renderStateType.MOJOSHADER_RS_BLENDOPALPHA) | ||||
{ | ||||
MojoShader.MOJOSHADER_blendOp* val = (MojoShader.MOJOSHADER_blendOp*) states[i].value.values; | ||||
pipelineCache.AlphaBlendFunction = XNABlendOp[(int) *val]; | ||||
blendStateChanged = true; | ||||
} | ||||
else if (type == (MojoShader.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.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.MOJOSHADER_samplerStateRegister*) stateChanges->vertex_sampler_state_changes, | ||||
GraphicsDevice.VertexTextures, | ||||
GraphicsDevice.VertexSamplerStates | ||||
); | ||||
} | ||||
} | ||||
private unsafe void INTERNAL_updateSamplers( | ||||
uint changeCount, | ||||
MojoShader.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.MOJOSHADER_textureFilterType magFilter = XNAMag[(int) filter]; | ||||
MojoShader.MOJOSHADER_textureFilterType minFilter = XNAMin[(int) filter]; | ||||
MojoShader.MOJOSHADER_textureFilterType mipFilter = XNAMip[(int) filter]; | ||||
MojoShader.MOJOSHADER_effectSamplerState* states = (MojoShader.MOJOSHADER_effectSamplerState*) registers[i].sampler_states; | ||||
for (int j = 0; j < registers[i].sampler_state_count; j += 1) | ||||
{ | ||||
MojoShader.MOJOSHADER_samplerStateType type = states[j].type; | ||||
if (type == MojoShader.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.MOJOSHADER_samplerStateType.MOJOSHADER_SAMP_ADDRESSU) | ||||
{ | ||||
MojoShader.MOJOSHADER_textureAddress* val = (MojoShader.MOJOSHADER_textureAddress*) states[j].value.values; | ||||
pipelineCache.AddressU = XNAAddress[(int) *val]; | ||||
samplerChanged = true; | ||||
} | ||||
else if (type == MojoShader.MOJOSHADER_samplerStateType.MOJOSHADER_SAMP_ADDRESSV) | ||||
{ | ||||
MojoShader.MOJOSHADER_textureAddress* val = (MojoShader.MOJOSHADER_textureAddress*) states[j].value.values; | ||||
pipelineCache.AddressV = XNAAddress[(int) *val]; | ||||
samplerChanged = true; | ||||
} | ||||
else if (type == MojoShader.MOJOSHADER_samplerStateType.MOJOSHADER_SAMP_ADDRESSW) | ||||
{ | ||||
MojoShader.MOJOSHADER_textureAddress* val = (MojoShader.MOJOSHADER_textureAddress*) states[j].value.values; | ||||
pipelineCache.AddressW = XNAAddress[(int) *val]; | ||||
samplerChanged = true; | ||||
} | ||||
else if (type == MojoShader.MOJOSHADER_samplerStateType.MOJOSHADER_SAMP_MAGFILTER) | ||||
{ | ||||
MojoShader.MOJOSHADER_textureFilterType* val = (MojoShader.MOJOSHADER_textureFilterType*) states[j].value.values; | ||||
magFilter = *val; | ||||
filterChanged = true; | ||||
} | ||||
else if (type == MojoShader.MOJOSHADER_samplerStateType.MOJOSHADER_SAMP_MINFILTER) | ||||
{ | ||||
MojoShader.MOJOSHADER_textureFilterType* val = (MojoShader.MOJOSHADER_textureFilterType*) states[j].value.values; | ||||
minFilter = *val; | ||||
filterChanged = true; | ||||
} | ||||
else if (type == MojoShader.MOJOSHADER_samplerStateType.MOJOSHADER_SAMP_MIPFILTER) | ||||
{ | ||||
MojoShader.MOJOSHADER_textureFilterType* val = (MojoShader.MOJOSHADER_textureFilterType*) states[j].value.values; | ||||
mipFilter = *val; | ||||
filterChanged = true; | ||||
} | ||||
else if (type == MojoShader.MOJOSHADER_samplerStateType.MOJOSHADER_SAMP_MIPMAPLODBIAS) | ||||
{ | ||||
float* val = (float*) states[j].value.values; | ||||
pipelineCache.MipMapLODBias = *val; | ||||
samplerChanged = true; | ||||
} | ||||
else if (type == MojoShader.MOJOSHADER_samplerStateType.MOJOSHADER_SAMP_MAXMIPLEVEL) | ||||
{ | ||||
int* val = (int*) states[j].value.values; | ||||
pipelineCache.MaxMipLevel = *val; | ||||
samplerChanged = true; | ||||
} | ||||
else if (type == MojoShader.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.MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_POINT) | ||||
{ | ||||
if (minFilter == MojoShader.MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_POINT) | ||||
{ | ||||
if ( mipFilter == MojoShader.MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_NONE || | ||||
mipFilter == MojoShader.MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_POINT ) | ||||
{ | ||||
pipelineCache.Filter = TextureFilter.Point; | ||||
} | ||||
else if ( mipFilter == MojoShader.MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_LINEAR || | ||||
mipFilter == MojoShader.MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_ANISOTROPIC ) | ||||
{ | ||||
pipelineCache.Filter = TextureFilter.PointMipLinear; | ||||
} | ||||
else | ||||
{ | ||||
throw new NotImplementedException("Unhandled mipfilter type! " + mipFilter); | ||||
} | ||||
} | ||||
else if ( minFilter == MojoShader.MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_LINEAR || | ||||
minFilter == MojoShader.MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_ANISOTROPIC ) | ||||
{ | ||||
if ( mipFilter == MojoShader.MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_NONE || | ||||
mipFilter == MojoShader.MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_POINT ) | ||||
{ | ||||
pipelineCache.Filter = TextureFilter.MinLinearMagPointMipPoint; | ||||
} | ||||
else if ( mipFilter == MojoShader.MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_LINEAR || | ||||
mipFilter == MojoShader.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.MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_LINEAR || | ||||
magFilter == MojoShader.MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_ANISOTROPIC ) | ||||
{ | ||||
if (minFilter == MojoShader.MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_POINT) | ||||
{ | ||||
if ( mipFilter == MojoShader.MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_NONE || | ||||
mipFilter == MojoShader.MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_POINT ) | ||||
{ | ||||
pipelineCache.Filter = TextureFilter.MinPointMagLinearMipPoint; | ||||
} | ||||
else if ( mipFilter == MojoShader.MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_LINEAR || | ||||
mipFilter == MojoShader.MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_ANISOTROPIC ) | ||||
{ | ||||
pipelineCache.Filter = TextureFilter.MinPointMagLinearMipLinear; | ||||
} | ||||
else | ||||
{ | ||||
throw new NotImplementedException("Unhandled mipfilter type! " + mipFilter); | ||||
} | ||||
} | ||||
else if ( minFilter == MojoShader.MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_LINEAR || | ||||
minFilter == MojoShader.MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_ANISOTROPIC ) | ||||
{ | ||||
if ( mipFilter == MojoShader.MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_NONE || | ||||
mipFilter == MojoShader.MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_POINT ) | ||||
{ | ||||
pipelineCache.Filter = TextureFilter.LinearMipPoint; | ||||
} | ||||
else if ( mipFilter == MojoShader.MOJOSHADER_textureFilterType.MOJOSHADER_TEXTUREFILTER_LINEAR || | ||||
mipFilter == MojoShader.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() | ||||
{ | ||||
MojoShader.MOJOSHADER_effect* effectPtr = (MojoShader.MOJOSHADER_effect*) glEffect.EffectData; | ||||
// Set up Parameters | ||||
MojoShader.MOJOSHADER_effectParam* paramPtr = (MojoShader.MOJOSHADER_effectParam*) effectPtr->parameters; | ||||
List<EffectParameter> parameters = new List<EffectParameter>(); | ||||
for (int i = 0; i < effectPtr->param_count; i += 1) | ||||
{ | ||||
MojoShader.MOJOSHADER_effectParam param = paramPtr[i]; | ||||
if ( param.value.type.parameter_type == MojoShader.MOJOSHADER_symbolType.MOJOSHADER_SYMTYPE_VERTEXSHADER || | ||||
param.value.type.parameter_type == MojoShader.MOJOSHADER_symbolType.MOJOSHADER_SYMTYPE_PIXELSHADER ) | ||||
{ | ||||
// Skip shader objects... | ||||
continue; | ||||
} | ||||
else if ( param.value.type.parameter_type >= MojoShader.MOJOSHADER_symbolType.MOJOSHADER_SYMTYPE_SAMPLER && | ||||
param.value.type.parameter_type <= MojoShader.MOJOSHADER_symbolType.MOJOSHADER_SYMTYPE_SAMPLERCUBE ) | ||||
{ | ||||
string textureName = String.Empty; | ||||
MojoShader.MOJOSHADER_effectSamplerState* states = (MojoShader.MOJOSHADER_effectSamplerState*) param.value.values; | ||||
for (int j = 0; j < param.value.value_count; j += 1) | ||||
{ | ||||
if ( states[j].value.type.parameter_type >= MojoShader.MOJOSHADER_symbolType.MOJOSHADER_SYMTYPE_TEXTURE && | ||||
states[j].value.type.parameter_type <= MojoShader.MOJOSHADER_symbolType.MOJOSHADER_SYMTYPE_TEXTURECUBE ) | ||||
{ | ||||
MojoShader.MOJOSHADER_effectObject *objectPtr = (MojoShader.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.MOJOSHADER_symbolStructMember* mem = (MojoShader.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.MOJOSHADER_effectTechnique* techPtr = (MojoShader.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.MOJOSHADER_effectPass* passPtr = (MojoShader.MOJOSHADER_effectPass*) techPtr->passes; | ||||
List<EffectPass> passes = new List<EffectPass>((int) techPtr->pass_count); | ||||
for (int j = 0; j < passes.Capacity; j += 1) | ||||
{ | ||||
MojoShader.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.MOJOSHADER_effectAnnotation* annoPtr = (MojoShader.MOJOSHADER_effectAnnotation*) rawAnnotations; | ||||
List<EffectAnnotation> annotations = new List<EffectAnnotation>((int) numAnnotations); | ||||
for (int i = 0; i < numAnnotations; i += 1) | ||||
{ | ||||
MojoShader.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 | ||||
} | ||||
} | ||||