public static ParticleSystemCompiledShaderData BuildGpuLogicPixelShader(IEnumerable<ParticleSystemLogicStep> steps, LogicType logicType, VertexShaderType vsType, bool useUserValues, bool useColours, bool storeLifeData, ContentTargetPlatform targetPlatform, bool useUserDataPositionBuffer, string pathToShaderSystem) { if (steps == null) throw new ArgumentNullException(); StringBuilder output = new StringBuilder(); Random random = new Random(); foreach (ParticleSystemLogicStep step in steps) BuildStep(step, output, 1, random); //fixup the preprocssor defines string shaderCodeFixup = GpuParticleShaderBuilder.BaseShader.Replace("_#", "#"); //insert the custom code string shaderCode = shaderCodeFixup.Replace(GpuParticleShaderBuilder.replaceMarker, output.ToString()); //build the shader header and main method. StringBuilder header = new StringBuilder(); StringBuilder methodHeader = new StringBuilder(); StringBuilder methodPS = new StringBuilder(); methodPS.Append("void PS(float4 texRandIndex : TEXCOORD0"); if (logicType != LogicType.Frame) methodPS.Append(", float4 lifeIndex : TEXCOORD1"); else methodHeader.Append("float4 lifeIndex = 0;"); if (logicType == LogicType.Once) { methodPS.Append(", float4 defaultPosition : TEXCOORD2"); methodPS.Append(", float4 defaultVelocity : TEXCOORD3"); methodPS.Append(", float4 defaultColour : TEXCOORD4"); methodPS.Append(", float4 defaultUserData : TEXCOORD5"); } else { methodHeader.Append("float4 defaultPosition = 0, defaultVelocity = 0;"); methodHeader.Append("float4 defaultColour = 1, defaultUserData = 0;"); } int colIndex = 2; methodPS.Append(", out float4 posOut : COLOR0, out float4 velOut : COLOR1"); if (useColours) methodPS.AppendFormat(", out float4 colOut : COLOR{0}", colIndex++); else methodHeader.Append("float4 colOut = 1;"); if (useUserValues) methodPS.AppendFormat(", out float4 userOut : COLOR{0}", colIndex++); else methodHeader.Append("float4 userOut = 0;"); methodPS.AppendLine(")"); methodPS.AppendLine("{"); methodPS.Append("\t"); methodPS.Append(methodHeader); methodPS.AppendLine(); methodPS.Append("\t"); methodPS.AppendLine(@"PS_Method(texRandIndex,lifeIndex, defaultPosition, defaultVelocity, defaultColour, defaultUserData,posOut, velOut, colOut, userOut);"); methodPS.AppendLine("}"); int colourIndex = -1, userIndex = -1, lifeIndex = -1; if (logicType != LogicType.Once) { int samplerIndex = 3; header.AppendLine(); header.AppendLine("#define TEXTURE_PARTICLE_METHOD"); if (useColours) { colourIndex = samplerIndex; header.AppendLine("#define USER_COLOUR_TEX"); header.AppendLine(string.Format(@"sampler2D ColourSampler : register(ps,s{0});", samplerIndex++)); } if (useUserValues) { userIndex = samplerIndex; header.AppendLine("#define USER_USER_TEX"); header.AppendLine(string.Format(@"sampler2D UserSampler : register(ps,s{0});", samplerIndex++)); } if (storeLifeData && logicType == LogicType.Frame) { lifeIndex = samplerIndex; header.AppendLine("#define USER_LIFE_TEX"); header.AppendLine(string.Format(@"sampler2D LifeSampler : register(ps,s{0});", samplerIndex++)); } if (logicType == LogicType.Frame || logicType == LogicType.FrameMove) header.AppendLine("#define ADD_VELOCITY"); } switch (vsType) { case VertexShaderType.Clone: header.AppendLine("#define VS_CLONE"); break; case VertexShaderType.Frame: header.AppendLine("#define VS_FRAME"); break; case VertexShaderType.Once: header.AppendLine("#define VS_ONCE"); break; } if (useUserDataPositionBuffer) { header.AppendLine("#define POS_WRITTEN_TO_USER"); } StringBuilder completeShader = new StringBuilder(); completeShader.Append(header); completeShader.AppendLine(); completeShader.Append(shaderCode); completeShader.AppendLine(); completeShader.Append(methodPS); completeShader.AppendLine(); completeShader.Append(techniqueCode); completeShader.AppendLine(); if (ShaderCompileDelegate == null) LinkToShaderCompiler(pathToShaderSystem); string errors; byte[] shaderBytes = ShaderCompileDelegate(completeShader.ToString(), "", targetPlatform == ContentTargetPlatform.Xbox360, out errors); if (errors != null) throw new InvalidOperationException("GPU Particle System Pixel Shader failed to compile:" + Environment.NewLine + errors); return new ParticleSystemCompiledShaderData(shaderBytes, targetPlatform == ContentTargetPlatform.Xbox360, colourIndex, userIndex, lifeIndex); }
internal GpuParticleProcessorData(ParticleSystemTypeData typeData, bool useColourValues, bool usesUserValues, bool storeLifeData, ContentTargetPlatform targetPlatform, string pathToShaderSystem) : this( GpuParticleShaderBuilder.BuildGpuLogicPixelShader(typeData.ParticleLogicData.Once, GpuParticleShaderBuilder.LogicType.Once, GpuParticleShaderBuilder.VertexShaderType.Once, usesUserValues, useColourValues, storeLifeData, targetPlatform, typeData.GpuBufferPosition, pathToShaderSystem), GpuParticleShaderBuilder.BuildGpuLogicPixelShader(typeData.ParticleLogicData.Once, GpuParticleShaderBuilder.LogicType.OnceClone, GpuParticleShaderBuilder.VertexShaderType.Clone, usesUserValues, useColourValues, storeLifeData, targetPlatform, typeData.GpuBufferPosition, pathToShaderSystem), GpuParticleShaderBuilder.BuildGpuLogicPixelShader(typeData.ParticleLogicData.Frame, GpuParticleShaderBuilder.LogicType.Frame, GpuParticleShaderBuilder.VertexShaderType.Frame, usesUserValues, useColourValues, storeLifeData, targetPlatform, typeData.GpuBufferPosition, pathToShaderSystem), GpuParticleShaderBuilder.BuildGpuLogicPixelShader(typeData.ParticleLogicData.Frame, GpuParticleShaderBuilder.LogicType.FrameMove, GpuParticleShaderBuilder.VertexShaderType.Clone, usesUserValues, useColourValues, storeLifeData, targetPlatform, typeData.GpuBufferPosition, pathToShaderSystem)) { }