Platform-agnostic renderer

Started by
50 comments, last by ATC 11 years, 7 months ago

It's close but the key thing I would say is that a 'material' is a combination of shader and it's resources.

Nor should it have to worry about 'external FX variables'; anything which isn't set by the material or the draw call directly (per-instance/batch stuff) should be handled by some external system. So things like camera position and the like, which are setup once per scene, would be set via something else and just read.

In the context of DX11 this would be a per-scene constant block, the material would be a per-material constant block and the instance data would be one or more per-instance blocks.

Keep your frequency of updates down as much as you can for each block, try to instance things too as CPU time is still a killer if you want to handle lots of draw calls.


Thank you... So my initial design of having the Material class hold a reference to a Shader was actually not incorrect/badly-designed?

I didn't say the Material class would worry about "external" variables... I only meant that variables can be set on the shader from without the Material (e.g., an update call to set a World or WVP matrix)... that's what I mean by them being "global", as a model, for instance, will typically apply the same world transformation to all its mesh-parts (excepting some animation cases; in which case certain bone/parent transformations will be "global" to child nodes). Sound more reasonable?
_______________________________________________________________________________
CEO & Lead Developer at ATCWARE™
"Project X-1"; a 100% managed, platform-agnostic game & simulation engine

Please visit our new forums and help us test them and break the ice!
___________________________________________________________________________________
Advertisement
Hey guys, maybe you can help me get back on the right track? I'm still struggling with ideas on how best to implement the shading and material system, and how the renderer should handle it. Like I said earlier, I came up with the idea of allowing users to supply a simple type of script alongside a Material, to control how it uses the underlying shader. Here's an example of this proposed script and how it might look:

[source lang="csharp"]technique = 1
{
passes
{
p0,
p1,
p2,
};
};[/source]

The parser for such scripts could be quite simple... perhaps even this simple:

[source lang="csharp"]public class Test
{
static readonly string[] _keywords = new[]
{
"technique",
"passes",
"commands"
};

internal static Technique _ProcessScript(string script) {

//! Ensure script is valid!
if (string.IsNullOrEmpty(script))
throw new NullReferenceException("Invalid/null material script!");

//! Select defaults if blank...
if (script.Length < 1)
return new Technique("0", new Pass("ALL"));

var next = "";
List<string> tokens = new List<string>();

foreach (char c in script) {
switch © {
case ' ':
case '\n':
case '\r':
case ' ':
case '{':
case '}':
case ';':
case '"':
case '=':
case ',':
if (!string.IsNullOrEmpty(next) && !(next == "technique") && !(next == "passes"))
tokens.Add(next);
next = "";
break;

default:
if(!char.IsLetterOrDigit©)
throw new Exception(string.Format(
"Invalid token '{0}' in script!", c.ToString()));

next += c;
break;
}
}

Technique technique = new Technique(tokens[0]);

for (int i = 1; i < tokens.Count; ++i)
technique.Passes.Add(new Pass(tokens));

return technique;
}
}[/source]

And here are example supporting classes for "Technique" and "Pass", which really only serve for identification's sake...

[source lang="csharp"] public class Pass
{
public Pass(string name) {
this.Name = name;
}

public string Name { get; set; }
}

public class Technique
{
public Technique(string name) {
this.Name = name;
this.Passes = new List<Pass>();
}

public Technique(string name, params Pass[] passes) {
if (passes == null)
throw new ArgumentNullException("techniques");

this.Name = name;
this.Passes = new List<Pass>(passes);
}

public Technique(string name, List<Pass> passes) {
if (passes == null)
throw new ArgumentNullException("passes");

this.Name = name;
this.Passes = passes;
}

public string Name { get; set; }

public List<Pass> Passes { get; set; }
}[/source]

Does pursuing this concept further seem like a bad idea? Why or why not? What do you think is the best way to implement such a thing, or should this whole material script idea be trashed and a better method used (if so, what is that better method?)?

Maybe most importantly, I'm wondering how the Renderer should, in theory, break down all this data to process and render it. This is the first time I've written any platform-agnostic game or engine code, and my first true data-driven Renderer implementation. So much of this is new to me and I'm trying to grasp the concepts/design; writing the code is the easy part! ;-)

------------------------------------------------------------------------
EDIT:
------------------------------------------------------------------------
To whom it may concern, there is a bug with the forum code blocks... With C# selected it does not seem compatible with the '<' and '>' characters used for generics. For instance, "List<Pass> passes" comes out as "List passes".
_______________________________________________________________________________
CEO & Lead Developer at ATCWARE™
"Project X-1"; a 100% managed, platform-agnostic game & simulation engine

Please visit our new forums and help us test them and break the ice!
___________________________________________________________________________________

This topic is closed to new replies.

Advertisement