private static bool ShaderVarMatches(ref ShaderFieldInfo varInfo, VertexElementType type, int count) { //if (varInfo.Scope != ShaderFieldScope.Attribute) return false; Type elementPrimitive = varInfo.Type.GetElementPrimitive(); Type requiredPrimitive = null; switch (type) { case VertexElementType.Byte: requiredPrimitive = typeof(byte); break; case VertexElementType.Float: requiredPrimitive = typeof(float); break; } // ToDo: Bugfix to allow Color (byte to float) conversion if (elementPrimitive != requiredPrimitive && !(elementPrimitive == typeof(float) && requiredPrimitive == typeof(byte))) { return(false); } int elementCount = varInfo.Type.GetElementCount(); if (count != elementCount * varInfo.ArrayLength) { return(false); } return(true); }
MergeResult PackFields(ShaderFieldInfo info, ref ShaderFieldInfo merged) { if (merged.elementCount % 4 == 0) { return(MergeResult.Full); } if (info.type != merged.type) { Error("can't merge '" + merged.DeclString() + "' and '" + info.DeclString() + "' into the same register because they have incompatible types. Consider reordering the fields so that adjacent fields have the same primitive type."); return(MergeResult.Failed); // incompatible types } if (info.cols > 1 || merged.cols > 1) { Error("merging matrix types not yet supported ('" + merged.DeclString() + "' and '" + info.DeclString() + "'). Consider reordering the fields to place matrix-typed variables on four-component vector boundaries."); return(MergeResult.Failed); // don't merge matrix types } if (info.rows + merged.rows > 4) { // @TODO: lift the restriction Error("can't merge '" + merged.DeclString() + "' and '" + info.DeclString() + "' because then " + info.name + " would cross register boundary. Consider reordering the fields so that none of them cross four-component vector boundaries when packed."); return(MergeResult.Failed); // out of space } merged.rows += info.rows; merged.name += "_" + info.name; return(MergeResult.Merged); }
private static bool ShaderVarMatches(ref ShaderFieldInfo varInfo, VertexElementType type, int count) { if (varInfo.Scope != ShaderFieldScope.Attribute) { return(false); } Type elementPrimitive = varInfo.Type.GetElementPrimitive(); Type requiredPrimitive = null; switch (type) { case VertexElementType.Byte: requiredPrimitive = typeof(byte); break; case VertexElementType.Float: requiredPrimitive = typeof(float); break; } if (elementPrimitive != requiredPrimitive) { return(false); } int elementCount = varInfo.Type.GetElementCount(); if (count != elementCount * varInfo.ArrayLength) { return(false); } return(true); }
public object Clone() { ShaderFieldInfo info = new ShaderFieldInfo(type, name, rows, cols, comment); info.swizzleOffset = swizzleOffset; info.packed = packed; info.accessor = accessor; return(info); }
/// <summary> /// Applies the specified parameter values to all currently active shaders. /// </summary> /// <param name="sharedParams"></param> /// <seealso cref="RetrieveActiveShaders"/> private void SetupSharedParameters(ShaderParameterCollection sharedParams) { this.sharedSamplerBindings = 0; this.sharedShaderParameters.Clear(); if (sharedParams == null) { return; } foreach (NativeShaderProgram shader in this.activeShaders) { NativeShaderProgram.Bind(shader); ShaderFieldInfo[] varInfo = shader.Fields; int[] locations = shader.FieldLocations; // Setup shared sampler bindings and uniform data for (int i = 0; i < varInfo.Length; i++) { ShaderFieldInfo field = varInfo[i]; int location = locations[i]; if (field.Scope == ShaderFieldScope.Attribute) { continue; } if (field.Type == ShaderFieldType.Sampler2D) { ContentRef <Texture> texRef; if (!sharedParams.TryGetInternal(field.Name, out texRef)) { continue; } NativeTexture.Bind(texRef, this.sharedSamplerBindings); GL.Uniform1(location, this.sharedSamplerBindings); this.sharedSamplerBindings++; } else { float[] data; if (!sharedParams.TryGetInternal(field.Name, out data)) { continue; } NativeShaderProgram.SetUniform(field, location, data); } this.sharedShaderParameters.Add(field.Name); } } NativeShaderProgram.Bind(null); }
private void PrepareEditorConfigData(ShaderFieldInfo field, List <EditorHintAttribute> configData) { if (field.Type != ShaderFieldType.Int) { configData.Add(new EditorHintIncrementAttribute(0.1f)); } if (field.MinValue != float.MinValue || field.MaxValue != float.MaxValue) { configData.Add(new EditorHintRangeAttribute( field.MinValue, field.MaxValue)); } }
protected PropertyEditor CreateTextureEditor(ShaderFieldInfo field) { PropertyEditor editor = null; editor = this.ParentGrid.CreateEditor(typeof(ContentRef <Texture>), this); editor.Getter = this.CreateTextureValueGetter(field.Name); editor.Setter = !this.ReadOnly ? this.CreateTextureValueSetter(field.Name) : null; editor.PropertyName = field.Name; editor.PropertyDesc = field.Description; this.ParentGrid.ConfigureEditor(editor); return(editor); }
List <ShaderFieldInfo> Pack(List <ShaderFieldInfo> shaderFields) { List <ShaderFieldInfo> mergedFields = new List <ShaderFieldInfo>(); using (var e = shaderFields.GetEnumerator()) { if (!e.MoveNext()) { // Empty shader struct definition. return(shaderFields); } ShaderFieldInfo current = e.Current.Clone() as ShaderFieldInfo; while (e.MoveNext()) { while (true) { int offset = current.elementCount; var result = PackFields(e.Current, ref current); if (result == MergeResult.Failed) { return(null); } else if (result == MergeResult.Full) { break; } // merge accessors var acc = current.accessor; acc.name = current.name; e.Current.accessor = acc; e.Current.swizzleOffset += offset; current.packed = e.Current.packed = true; if (!e.MoveNext()) { mergedFields.Add(current); return(mergedFields); } } mergedFields.Add(current); current = e.Current.Clone() as ShaderFieldInfo; } } return(mergedFields); }
public static void SetUniform(ShaderFieldInfo field, int location, float[] data) { if (field.Scope != ShaderFieldScope.Uniform) { return; } if (location == -1) { return; } switch (field.Type) { case ShaderFieldType.Bool: case ShaderFieldType.Int: int[] arrI = new int[field.ArrayLength]; for (int j = 0; j < arrI.Length; j++) { arrI[j] = (int)data[j]; } GL.Uniform1(location, arrI.Length, arrI); break; case ShaderFieldType.Float: GL.Uniform1(location, data.Length, data); break; case ShaderFieldType.Vec2: GL.Uniform2(location, data.Length / 2, data); break; case ShaderFieldType.Vec3: GL.Uniform3(location, data.Length / 3, data); break; case ShaderFieldType.Vec4: GL.Uniform4(location, data.Length / 4, data); break; case ShaderFieldType.Mat2: GL.UniformMatrix2(location, data.Length / 4, false, data); break; case ShaderFieldType.Mat3: GL.UniformMatrix3(location, data.Length / 9, false, data); break; case ShaderFieldType.Mat4: GL.UniformMatrix4(location, data.Length / 16, false, data); break; } }
public static void SetUniform(ref ShaderFieldInfo field, WebGLUniformLocation location, params float[] data) { if (field.Scope != ShaderFieldScope.Uniform) { return; } if (location == null) { return; } switch (field.Type) { case ShaderFieldType.Bool: case ShaderFieldType.Int: int[] arrI = new int[field.ArrayLength]; for (int j = 0; j < arrI.Length; j++) { arrI[j] = (int)data[j]; } GraphicsBackend.GL.Uniform1iv(location, new Span <int>(arrI)); break; case ShaderFieldType.Float: GraphicsBackend.GL.Uniform1fv(location, new Span <float>(data)); break; case ShaderFieldType.Vec2: GraphicsBackend.GL.Uniform2fv(location, new Span <float>(data)); break; case ShaderFieldType.Vec3: GraphicsBackend.GL.Uniform3fv(location, new Span <float>(data)); break; case ShaderFieldType.Vec4: GraphicsBackend.GL.Uniform4fv(location, new Span <float>(data)); break; case ShaderFieldType.Mat2: GraphicsBackend.GL.UniformMatrix2fv(location, false, new Span <float>(data)); break; case ShaderFieldType.Mat3: GraphicsBackend.GL.UniformMatrix3fv(location, false, new Span <float>(data)); break; case ShaderFieldType.Mat4: GraphicsBackend.GL.UniformMatrix4fv(location, false, new Span <float>(data)); break; } }
protected override void OnUpdateFromObjects(object[] values) { base.OnUpdateFromObjects(values); if (values.Any(o => o != null)) { IEnumerable <BatchInfo> batchInfos = values.Cast <BatchInfo>(); DrawTechnique refTech = batchInfos.NotNull().First().Technique.Res; // Retrieve a list of shader variables to edit IReadOnlyList <ShaderFieldInfo> shaderFields = null; if (refTech != null) { shaderFields = refTech.DeclaredFields; } else { shaderFields = EmptyShaderFields; } // Remove editors that are no longer needed or no longer match their shader field List <string> removeEditors = null; foreach (var pair in this.fieldEditors) { bool isMatchingEditor = shaderFields.Contains(pair.Value.Field) && pair.Value.Field.Name == pair.Key; if (!isMatchingEditor) { if (removeEditors == null) { removeEditors = new List <string>(); } removeEditors.Add(pair.Key); } } if (removeEditors != null) { foreach (string fieldName in removeEditors) { this.RemovePropertyEditor(this.fieldEditors[fieldName].Editor); this.fieldEditors.Remove(fieldName); } } // Create editors for fields that do not yet have a matching editor, or which // were removed because they did no longer match. int autoCreateEditorCount = 1; int displayedFieldIndex = -1; for (int i = 0; i < shaderFields.Count; i++) { ShaderFieldInfo field = shaderFields[i]; // Skip fields that shouldn't be displayed if (field.IsPrivate) { continue; } if (field.Scope != ShaderFieldScope.Uniform) { continue; } displayedFieldIndex++; // Skip fields that already have a matching editor if (this.fieldEditors.ContainsKey(field.Name)) { continue; } // Create a new editor for this field PropertyEditor editor; if (field.Type == ShaderFieldType.Sampler2D) { editor = this.CreateTextureEditor(field); } else { editor = this.CreateUniformEditor(field); } // Add and register this editor this.fieldEditors[field.Name] = new FieldEditorItem { Editor = editor, Field = field }; if (autoCreateEditorCount + displayedFieldIndex <= this.ChildEditors.Count) { this.AddPropertyEditor(editor, autoCreateEditorCount + displayedFieldIndex); } else { this.AddPropertyEditor(editor); } } } }
protected PropertyEditor CreateUniformEditor(ShaderFieldInfo field) { PropertyEditor editor = null; bool mainEditorIsArray = false; if (field.ArrayLength == 1) { if (field.EditorTypeTag == "ColorRgba") { editor = this.ParentGrid.CreateEditor(typeof(ColorRgba), this); editor.Getter = this.CreateUniformValueGetter <ColorRgba>(field.Name); editor.Setter = !this.ReadOnly ? this.CreateUniformValueSetter <ColorRgba>(field.Name) : null; } else if (field.EditorTypeTag == "ColorHsva") { editor = this.ParentGrid.CreateEditor(typeof(ColorHsva), this); editor.Getter = this.CreateUniformValueGetter <ColorHsva>(field.Name); editor.Setter = !this.ReadOnly ? this.CreateUniformValueSetter <ColorHsva>(field.Name) : null; } else if (field.Type == ShaderFieldType.Float || field.Type == ShaderFieldType.Int) { Type editType = typeof(float); if (field.Type == ShaderFieldType.Int) { editType = typeof(int); } editor = this.ParentGrid.CreateEditor(editType, this); if (field.Type == ShaderFieldType.Int) { editor.Getter = this.CreateUniformValueGetter <int>(field.Name); editor.Setter = !this.ReadOnly ? this.CreateUniformValueSetter <int>(field.Name) : null; } else { editor.Getter = this.CreateUniformValueGetter <float>(field.Name); editor.Setter = !this.ReadOnly ? this.CreateUniformValueSetter <float>(field.Name) : null; } } else if (field.Type == ShaderFieldType.Vec2) { editor = this.ParentGrid.CreateEditor(typeof(Vector2), this); editor.Getter = this.CreateUniformValueGetter <Vector2>(field.Name); editor.Setter = !this.ReadOnly ? this.CreateUniformValueSetter <Vector2>(field.Name) : null; } else if (field.Type == ShaderFieldType.Vec3) { editor = this.ParentGrid.CreateEditor(typeof(Vector3), this); editor.Getter = this.CreateUniformValueGetter <Vector3>(field.Name); editor.Setter = !this.ReadOnly ? this.CreateUniformValueSetter <Vector3>(field.Name) : null; } else if (field.Type == ShaderFieldType.Vec4) { editor = this.ParentGrid.CreateEditor(typeof(Vector4), this); editor.Getter = this.CreateUniformValueGetter <Vector4>(field.Name); editor.Setter = !this.ReadOnly ? this.CreateUniformValueSetter <Vector4>(field.Name) : null; } else { editor = this.ParentGrid.CreateEditor(typeof(float[]), this); editor.Getter = this.CreateUniformArrayValueGetter <float>(field.Name); editor.Setter = !this.ReadOnly ? this.CreateUniformArrayValueSetter <float>(field.Name) : null; mainEditorIsArray = true; } } else { mainEditorIsArray = true; if (field.EditorTypeTag == "ColorRgba") { editor = this.ParentGrid.CreateEditor(typeof(ColorRgba[]), this); editor.Getter = this.CreateUniformArrayValueGetter <ColorRgba>(field.Name); editor.Setter = !this.ReadOnly ? this.CreateUniformArrayValueSetter <ColorRgba>(field.Name) : null; editor.ForceWriteBack = true; } else if (field.EditorTypeTag == "ColorHsva") { editor = this.ParentGrid.CreateEditor(typeof(ColorHsva[]), this); editor.Getter = this.CreateUniformArrayValueGetter <ColorHsva>(field.Name); editor.Setter = !this.ReadOnly ? this.CreateUniformArrayValueSetter <ColorHsva>(field.Name) : null; editor.ForceWriteBack = true; } else if (field.Type == ShaderFieldType.Float || field.Type == ShaderFieldType.Int) { Type editType = typeof(float); if (field.Type == ShaderFieldType.Int) { editType = typeof(int); } editor = this.ParentGrid.CreateEditor(editType.MakeArrayType(), this); editor.Getter = this.CreateUniformArrayValueGetter <float>(field.Name); editor.Setter = !this.ReadOnly ? this.CreateUniformArrayValueSetter <float>(field.Name) : null; editor.ForceWriteBack = true; } else if (field.Type == ShaderFieldType.Vec2) { editor = this.ParentGrid.CreateEditor(typeof(Vector2[]), this); editor.Getter = this.CreateUniformArrayValueGetter <Vector2>(field.Name); editor.Setter = !this.ReadOnly ? this.CreateUniformArrayValueSetter <Vector2>(field.Name) : null; editor.ForceWriteBack = true; } else if (field.Type == ShaderFieldType.Vec3) { editor = this.ParentGrid.CreateEditor(typeof(Vector3[]), this); editor.Getter = this.CreateUniformArrayValueGetter <Vector3>(field.Name); editor.Setter = !this.ReadOnly ? this.CreateUniformArrayValueSetter <Vector3>(field.Name) : null; editor.ForceWriteBack = true; } else if (field.Type == ShaderFieldType.Vec4) { editor = this.ParentGrid.CreateEditor(typeof(Vector4[]), this); editor.Getter = this.CreateUniformArrayValueGetter <Vector4>(field.Name); editor.Setter = !this.ReadOnly ? this.CreateUniformArrayValueSetter <Vector4>(field.Name) : null; editor.ForceWriteBack = true; } else { editor = this.ParentGrid.CreateEditor(typeof(float[]), this); editor.Getter = this.CreateUniformArrayValueGetter <float>(field.Name); editor.Setter = !this.ReadOnly ? this.CreateUniformArrayValueSetter <float>(field.Name) : null; } } List <EditorHintAttribute> configData = new List <EditorHintAttribute>(); if (mainEditorIsArray) { GroupedPropertyEditor groupedMainEditor = editor as GroupedPropertyEditor; if (groupedMainEditor != null) { groupedMainEditor.EditorAdded += this.UniformList_EditorAdded; } } else { this.PrepareEditorConfigData(field, configData); } editor.PropertyName = field.Name; editor.PropertyDesc = field.Description; this.ParentGrid.ConfigureEditor(editor, configData); return(editor); }
protected override void OnUpdateFromObjects(object[] values) { base.OnUpdateFromObjects(values); if (values.Any(o => o != null)) { bool invokeSetter = false; IEnumerable <BatchInfo> batchInfos = null; DrawTechnique refTech = null; batchInfos = values.Cast <BatchInfo>(); refTech = batchInfos.NotNull().First().Technique.Res; // Retrieve data about shader variables ShaderFieldInfo[] varInfoArray = null; if (refTech != null && refTech.Shader.IsAvailable) { if (!refTech.Shader.Res.Compiled) { refTech.Shader.Res.Compile(); } varInfoArray = refTech.Shader.Res.Fields; } else { varInfoArray = new ShaderFieldInfo[] { new ShaderFieldInfo( ShaderFieldInfo.DefaultNameMainTex, ShaderFieldType.Sampler2D, ShaderFieldScope.Uniform) }; } // Get rid of unused variables (This changes actual Resource data!) if (!this.ReadOnly) { foreach (BatchInfo info in batchInfos.NotNull()) { List <string> texRemoveSched = null; List <string> uniRemoveSched = null; if (info.Textures != null) { foreach (var pair in info.Textures) { if (!varInfoArray.Any(v => v.Scope == ShaderFieldScope.Uniform && v.Type == ShaderFieldType.Sampler2D && v.Name == pair.Key)) { if (texRemoveSched == null) { texRemoveSched = new List <string>(); } texRemoveSched.Add(pair.Key); } } } if (info.Uniforms != null) { foreach (var pair in info.Uniforms) { if (!varInfoArray.Any(v => v.Scope == ShaderFieldScope.Uniform && v.Type != ShaderFieldType.Sampler2D && v.Name == pair.Key)) { if (uniRemoveSched == null) { uniRemoveSched = new List <string>(); } uniRemoveSched.Add(pair.Key); } } } if (texRemoveSched != null) { foreach (string name in texRemoveSched) { info.SetTexture(name, null); } invokeSetter = true; } if (uniRemoveSched != null) { foreach (string name in uniRemoveSched) { info.SetUniform(name, null); } invokeSetter = true; } } } // Create BatchInfo variables according to Shader uniforms, if not existing yet if (!this.ReadOnly) { foreach (ShaderFieldInfo varInfo in varInfoArray) { if (varInfo.Scope != ShaderFieldScope.Uniform) { continue; } // Set Texture variables if (varInfo.Type == ShaderFieldType.Sampler2D) { foreach (BatchInfo info in batchInfos.NotNull()) { if (info.GetTexture(varInfo.Name).IsExplicitNull) { info.SetTexture(varInfo.Name, Texture.White); invokeSetter = true; } } } // Set other uniform variables else { float[] uniformVal = new float[varInfo.ArrayLength * varInfo.Type.GetElementCount()]; if (uniformVal != null) { foreach (BatchInfo info in batchInfos.NotNull()) { float[] oldVal = info.GetUniform(varInfo.Name); if (oldVal == null) { info.SetUniform(varInfo.Name, uniformVal); invokeSetter = true; } else if (oldVal.Length != uniformVal.Length) { for (int i = 0; i < Math.Min(oldVal.Length, uniformVal.Length); i++) { uniformVal[i] = oldVal[i]; } info.SetUniform(varInfo.Name, uniformVal); invokeSetter = true; } } } } } } // Create editors according to existing variables var texDict = batchInfos.NotNull().First().Textures; var uniformDict = batchInfos.NotNull().First().Uniforms; Dictionary <string, PropertyEditor> oldEditors = new Dictionary <string, PropertyEditor>(this.shaderVarEditors); if (texDict != null) { foreach (var tex in texDict) { ShaderFieldInfo varInfo = varInfoArray.FirstOrDefault(v => v.Scope == ShaderFieldScope.Uniform && v.Name == tex.Key); if (varInfo.IsPrivate) { continue; } string texName = varInfo.Name; if (oldEditors.ContainsKey(texName)) { oldEditors.Remove(texName); } else { PropertyEditor e = this.ParentGrid.CreateEditor(typeof(ContentRef <Texture>), this); e.Getter = this.CreateTextureValueGetter(texName); e.Setter = !this.ReadOnly ? this.CreateTextureValueSetter(texName) : null; e.PropertyName = texName; this.shaderVarEditors[texName] = e; this.ParentGrid.ConfigureEditor(e); this.AddPropertyEditor(e); } } } if (uniformDict != null) { foreach (var uniform in uniformDict) { ShaderFieldInfo varInfo = varInfoArray.FirstOrDefault(v => v.Scope == ShaderFieldScope.Uniform && v.Name == uniform.Key); if (varInfo.IsPrivate) { continue; } PropertyEditor e = this.CreateUniformEditor(varInfo); if (e != null) { if (oldEditors.ContainsValue(e)) { oldEditors.Remove(varInfo.Name); } else { e.PropertyName = uniform.Key; this.shaderVarEditors[uniform.Key] = e; this.AddPropertyEditor(e); } } } } // Remove old editors that aren't needed anymore foreach (var pair in oldEditors) { if (this.shaderVarEditors[pair.Key] == pair.Value) { this.shaderVarEditors.Remove(pair.Key); } this.RemovePropertyEditor(pair.Value); } // If we actually changed (updated) data here, invoke the setter if (invokeSetter) { this.SetValues(batchInfos); if (!this.IsUpdating) { this.PerformGetValue(); } } } }
protected PropertyEditor CreateUniformEditor(ShaderFieldInfo varInfo) { PropertyEditor oldEditor; this.shaderVarEditors.TryGetValue(varInfo.Name, out oldEditor); List <EditorHintAttribute> configData = new List <EditorHintAttribute>(); if (varInfo.ArrayLength == 1) { if (varInfo.Type == ShaderFieldType.Float || varInfo.Type == ShaderFieldType.Int) { Type editType = typeof(float); if (varInfo.Type == ShaderFieldType.Int) { editType = typeof(int); } if (oldEditor != null && oldEditor.EditedType == editType) { return(oldEditor); } else { PropertyEditor e = this.ParentGrid.CreateEditor(editType, this); if (varInfo.Type == ShaderFieldType.Int) { e.Getter = this.CreateUniformIntValueGetter(varInfo.Name); e.Setter = !this.ReadOnly ? this.CreateUniformIntValueSetter(varInfo.Name) : null; } else { e.Getter = this.CreateUniformFloatValueGetter(varInfo.Name); e.Setter = !this.ReadOnly ? this.CreateUniformFloatValueSetter(varInfo.Name) : null; configData.Add(new EditorHintIncrementAttribute(0.1f)); } this.ParentGrid.ConfigureEditor(e, configData); return(e); } } else if (varInfo.Type == ShaderFieldType.Vec2) { if (oldEditor != null && oldEditor.EditedType == typeof(Vector2)) { return(oldEditor); } else { PropertyEditor e = this.ParentGrid.CreateEditor(typeof(Vector2), this); e.Getter = this.CreateUniformVec2ValueGetter(varInfo.Name); e.Setter = !this.ReadOnly ? this.CreateUniformVec2ValueSetter(varInfo.Name) : null; configData.Add(new EditorHintIncrementAttribute(0.1f)); this.ParentGrid.ConfigureEditor(e, configData); return(e); } } else if (varInfo.Type == ShaderFieldType.Vec3) { if (oldEditor != null && oldEditor.EditedType == typeof(Vector3)) { return(oldEditor); } else { PropertyEditor e = this.ParentGrid.CreateEditor(typeof(Vector3), this); e.Getter = this.CreateUniformVec3ValueGetter(varInfo.Name); e.Setter = !this.ReadOnly ? this.CreateUniformVec3ValueSetter(varInfo.Name) : null; configData.Add(new EditorHintIncrementAttribute(0.1f)); this.ParentGrid.ConfigureEditor(e, configData); return(e); } } else { if (oldEditor != null && oldEditor.EditedType == typeof(float[])) { return(oldEditor); } else { PropertyEditor e = this.ParentGrid.CreateEditor(typeof(float[]), this); e.Getter = this.CreateUniformValueGetter(varInfo.Name); e.Setter = !this.ReadOnly ? this.CreateUniformValueSetter(varInfo.Name) : null; if (e is GroupedPropertyEditor) { (e as GroupedPropertyEditor).EditorAdded += this.UniformList_EditorAdded; } this.ParentGrid.ConfigureEditor(e, configData); return(e); } } } else { Array oldValue = oldEditor != null ? (oldEditor as IListPropertyEditor).DisplayedValue as Array : null; Type oldElementType = oldValue != null?oldValue.GetType().GetElementType() : null; int oldLen = oldValue != null ? oldValue.Length : -1; if (varInfo.Type == ShaderFieldType.Float || varInfo.Type == ShaderFieldType.Int) { Type editType = typeof(float); if (varInfo.Type == ShaderFieldType.Int) { editType = typeof(int); } if (oldLen == varInfo.ArrayLength && oldElementType == editType) { return(oldEditor); } else { PropertyEditor e = this.ParentGrid.CreateEditor(editType.MakeArrayType(), this); e.Getter = this.CreateUniformValueGetter(varInfo.Name); e.Setter = !this.ReadOnly ? this.CreateUniformValueSetter(varInfo.Name) : null; e.ForceWriteBack = true; if (e is GroupedPropertyEditor) { if (varInfo.Type == ShaderFieldType.Float) { (e as GroupedPropertyEditor).EditorAdded += this.UniformList_EditorAdded; } } this.ParentGrid.ConfigureEditor(e, configData); return(e); } } else if (varInfo.Type == ShaderFieldType.Vec2) { if (oldLen == varInfo.ArrayLength && oldElementType == typeof(Vector2)) { return(oldEditor); } else { PropertyEditor e = this.ParentGrid.CreateEditor(typeof(Vector2[]), this); e.Getter = this.CreateUniformVec2ArrayValueGetter(varInfo.Name); e.Setter = !this.ReadOnly ? this.CreateUniformVec2ArrayValueSetter(varInfo.Name) : null; e.ForceWriteBack = true; if (e is GroupedPropertyEditor) { (e as GroupedPropertyEditor).EditorAdded += this.UniformList_EditorAdded; } this.ParentGrid.ConfigureEditor(e, configData); return(e); } } else if (varInfo.Type == ShaderFieldType.Vec3) { if (oldLen == varInfo.ArrayLength && oldElementType == typeof(Vector3)) { return(oldEditor); } else { PropertyEditor e = this.ParentGrid.CreateEditor(typeof(Vector3[]), this); e.Getter = this.CreateUniformVec3ArrayValueGetter(varInfo.Name); e.Setter = !this.ReadOnly ? this.CreateUniformVec3ArrayValueSetter(varInfo.Name) : null; e.ForceWriteBack = true; if (e is GroupedPropertyEditor) { (e as GroupedPropertyEditor).EditorAdded += this.UniformList_EditorAdded; } this.ParentGrid.ConfigureEditor(e, configData); return(e); } } else { if (oldLen == varInfo.ArrayLength) { return(oldEditor); } else { PropertyEditor e = this.ParentGrid.CreateEditor(typeof(float[][]), this); e.Getter = this.CreateUniformArrayValueGetter(varInfo.Name, varInfo.ArrayLength); e.Setter = !this.ReadOnly ? this.CreateUniformArrayValueSetter(varInfo.Name) : null; e.ForceWriteBack = true; if (e is GroupedPropertyEditor) { (e as GroupedPropertyEditor).EditorAdded += this.UniformList_EditorAdded; } this.ParentGrid.ConfigureEditor(e, configData); return(e); } } } }
private void SetupMaterial(BatchInfo material, BatchInfo lastMaterial) { DrawTechnique tech = material.Technique.Res ?? DrawTechnique.Solid.Res; DrawTechnique lastTech = lastMaterial != null ? lastMaterial.Technique.Res : null; // Setup BlendType if (lastTech == null || tech.Blending != lastTech.Blending) { this.SetupBlendState(tech.Blending); } // Bind Shader NativeShaderProgram nativeShader = tech.NativeShader as NativeShaderProgram; NativeShaderProgram.Bind(nativeShader); // Setup shader data ShaderFieldInfo[] varInfo = nativeShader.Fields; int[] locations = nativeShader.FieldLocations; // Setup sampler bindings and uniform data int curSamplerIndex = this.sharedSamplerBindings; for (int i = 0; i < varInfo.Length; i++) { ShaderFieldInfo field = varInfo[i]; int location = locations[i]; if (field.Scope == ShaderFieldScope.Attribute) { continue; } if (this.sharedShaderParameters.Contains(field.Name)) { continue; } if (field.Type == ShaderFieldType.Sampler2D) { ContentRef <Texture> texRef = material.GetInternalTexture(field.Name); if (texRef == null) { this.internalShaderState.TryGetInternal(field.Name, out texRef); } NativeTexture.Bind(texRef, curSamplerIndex); GL.Uniform1(location, curSamplerIndex); curSamplerIndex++; } else { float[] data = material.GetInternalData(field.Name); if (data == null && !this.internalShaderState.TryGetInternal(field.Name, out data)) { continue; } NativeShaderProgram.SetUniform(field, location, data); } } NativeTexture.ResetBinding(curSamplerIndex); }
[Test] public void FieldParsingBasics() { ShaderSourceBuilder builder = new ShaderSourceBuilder(); string mainShader = new StringBuilder() .AppendLine("#pragma duality editorType ColorRgba") .AppendLine("#pragma duality description \"Test firstUniform Desc\"") .AppendLine("uniform vec4 firstUniform;") .AppendLine() .AppendLine("#pragma duality editorType Single") .AppendLine("#pragma duality description \"Test secondUniform Desc\"") .AppendLine("// Some comment") .AppendLine("uniform float secondUniform;") .AppendLine() .AppendLine("#pragma duality editorType ColorRgba") .AppendLine() .AppendLine("#pragma duality description \"Test firstAttribute Desc\"") .AppendLine() .AppendLine("in vec4 firstAttribute;") .AppendLine() .AppendLine("#pragma duality editorType Single") .AppendLine("#pragma duality description \"Test secondAttribute Desc\"") .AppendLine() .AppendLine("in vec4 secondAttribute;") .AppendLine() .AppendLine("void main()") .AppendLine("{") .AppendLine(" gl_Position = vec4(0.0, 0.0, 0.0, 1.0);") .AppendLine("}") .ToString(); builder.SetMainChunk(mainShader); string resultShader = builder.Build(); Assert.AreEqual(4, builder.Fields.Count); ShaderFieldInfo firstUniform = builder.Fields[0]; ShaderFieldInfo secondUniform = builder.Fields[1]; ShaderFieldInfo firstAttribute = builder.Fields[2]; ShaderFieldInfo secondAttribute = builder.Fields[3]; Assert.AreEqual("firstUniform", firstUniform.Name); Assert.AreEqual(ShaderFieldScope.Uniform, firstUniform.Scope); Assert.AreEqual(ShaderFieldType.Vec4, firstUniform.Type); Assert.AreEqual("ColorRgba", firstUniform.EditorTypeTag); Assert.AreEqual("Test firstUniform Desc", firstUniform.Description); Assert.AreEqual(1, firstUniform.ArrayLength); Assert.AreEqual(false, firstUniform.IsPrivate); Assert.AreEqual("secondUniform", secondUniform.Name); Assert.AreEqual(ShaderFieldScope.Uniform, secondUniform.Scope); Assert.AreEqual(ShaderFieldType.Float, secondUniform.Type); Assert.AreEqual("Single", secondUniform.EditorTypeTag); Assert.AreEqual("Test secondUniform Desc", secondUniform.Description); Assert.AreEqual(1, secondUniform.ArrayLength); Assert.AreEqual(false, secondUniform.IsPrivate); Assert.AreEqual("firstAttribute", firstAttribute.Name); Assert.AreEqual(ShaderFieldScope.Attribute, firstAttribute.Scope); Assert.AreEqual(ShaderFieldType.Vec4, firstAttribute.Type); Assert.AreEqual("ColorRgba", firstAttribute.EditorTypeTag); Assert.AreEqual("Test firstAttribute Desc", firstAttribute.Description); Assert.AreEqual(1, firstAttribute.ArrayLength); Assert.AreEqual(false, firstAttribute.IsPrivate); Assert.AreEqual("secondAttribute", secondAttribute.Name); Assert.AreEqual(ShaderFieldScope.Attribute, secondAttribute.Scope); Assert.AreEqual(ShaderFieldType.Vec4, secondAttribute.Type); Assert.AreEqual("Single", secondAttribute.EditorTypeTag); Assert.AreEqual("Test secondAttribute Desc", secondAttribute.Description); Assert.AreEqual(1, secondAttribute.ArrayLength); Assert.AreEqual(false, secondAttribute.IsPrivate); }