Multitexturing's cheaper per render pass, on this engine. Geometry and setup becomes a major drag, due to duplication (more on this further down). And of course, it's all in-hand with the approach I'm building, where textures for maps are part of a big tileset collection- instead of having, say, 50MB for a single SMF, I can spend 200MB on tilesets for 40 maps...hmmm Id think multitexturing would be a little dubious at best, cant you just rerender the unit but with the second/third/ etc textures? It'd be more robust/flexible in terms of graphics card support
Besides which, it's what Blizzard's doing, except they're smarter than I am and they've figured out a cute way to rebuild the normalmaps from a two-channel solution (which, if I were smart enough to do, I'd have another channel of data available for all sorts of fun tricks) and I am almost entirely certain that they're using a vertex shader to displace the map grid. One of the things I've found out during all this is that map geometry load isn't a major big deal- we can go up to about 90K triangles before it really starts to hurt. 90K triangles, FYI, is a ridiculous amount of real detail, if you use an optimized mesh approach... but because the shadowmaps still don't handle large triangles correctly (distortion is a major issue) I've been forced to use next-best, which is a uniform mesh that has had some tessellation applied- I'll show a screenshot of the latest, compare it with the ones above, the difference is pretty obvious. This is an OK solution, but then I hit resolution problems, in terms of mismatch between heightmap and geometry, but I can get pretty close by forcing the heightmap downwards, I think. Haven't had time to add that last little tweak.
Anyhow, long story short, multitexture's the way Blizzard is doing it; they were doing it with the Warcraft 3 engine, they've refined it for SC2, but it's basically the same stuff but with extra fanciness (normalmaps and reflectivity, dunno whether they bothered with glow, but glow is very very cheap).
Anyhow, in terms of Spring, there are other issues that make a multi-pass concept very un-attractive; you'd need to use gl.Unit, and there isn't a normalmap shader for gl.Unit passes, and I'm not sure what I'd need to change in terms of the matrix side to make it happen. I presume that's easy, if you understand the matrix side of things, which I don't. But really, it's a geometry throughput problem- each Unit is multiple display lists, instead of being one display list whose vertexes are being manipulated by a vertex shader that handles the Piece conditions.
And there are other complications, in terms of the purely unitRendering stuff I am doing right now:
A. UnitRendering does not actually allow us to use one geometry load, texture load and OpenGL state setup for all three of the major passes- diffuse, reflection, shadowmap. This really sucks; amongst other things, it means that the tex1 / tex2 are being re-sent to the video card, and that there's a lot of other needless duplication going on.
B. More specifically, unitRendering, as currently set up, has some very big problems if you go outside some very limited scope.
For example, as in the screenshot below, I got translucency working in jK's shader framework; however, it costs a lot per pass because some genius set the alpha test threshold in Spring to GL_GREATER,0.5, when in fact it should be GL_GREATER,0.01, so that anything that isn't basically black is treated as opaque. So I have to invoke gl.AlphaTest(GL.GREATER,0.01) within the predl, which is quite expensive. I really wish that was fixed, it's annoying and it's utterly unjustified- it won't screw up anything that was made properly and it won't impact 3DO rendering at all.
Then there are textures. Basically, Spring's shadow and reflection passes expect tex1 / tex2, but they don't use consistent gl.Texture positions. This is causing some needlessly wasteful behaviors, and I would like to see them fixed.
What I think should happen, more or less:
1. For this pass, load Unit textures from PBO. Tex1, Tex2, Shadow and Reflection, in that order always for all Units. If additional textures are specified in the textures defined in a unitRendering setup, then they should be loaded now. IOW, do all setup one time only per num Units of type (unitDefID) on the screen or within the shadow frustrum.
2. Render Unit reflection, using unitRendering setup (it's pretty pathetic that it uses the ARB shader instead of consolidating it into two passes with no duplication of setup).
3. Render Unit diffuse (i.e., the main render) using the reflections from Now and the shadow from Last Time (the error will be very small, and for various reasons it will be cheaper this way).
4. Render Unit shadows to shadow Now. Use FBO to flip shadow Now with shadow Last Time.
Basically, I'd like to see less duplication of stuff we don't need duplicated- the biggest issue in this sense is re-sending textures multiple times when it's really not necessary, which is quite expensive. I know there's no way around some of the other setup costs, ofc, but the texture and geometry duplication is truly wasteful behavior.
Lastly, when are we going to be able to specify multiple lights in a Spring scene? I'd really prefer to do lighting in a less clunky way- it's preposterous that the engine still only supports one light that you can't change during runtime unless you implement the entire lighting from scratch per Unit, when supporting 1 global light and 15 point lights with distance culling would be cheap enough, let alone the fancier lighting systems used in modern engines

Anyhow... basically, things are a lot less of an orkish kludge, I am basically just needing to split up the shaders into smaller, smarter ones for specific tasks, and then I will be able to release it.
Screenshots in a minute... I want to run the demo on this hardware, get a feel for how things are working and make sure it's non-broken on both platforms.
Big screens, so that you all can get a better feel for the sheer detail you'd see at a typical play distance- there's some tiling, but frankly that's more due to me not having put enough time into the map, not the process. I wish I'd had more time to mess with it, but I've been busy with RL lately.
Funny thing, though- shadowmaps failed to work on the 9800, even though it's working at home on the ATi... probably a driver setup issue, but whatever

Click to enlarge.
[EDIT]jK, to illustrate what I'm talking about, in terms of required context switches and other nasty things I have to do for each Unit using your framework, here's a sample preDL setup, using your framework (with my modifications) to implement translucency.
That glTexture (normalTex) is absolutely required, btw; setting it up in the unit's mat doesn't actually work correctly- I tried doing it like it says it's supposed to work, and found that textures were getting overwritten on a regular basis...
Code: Select all
if (unitDef.customParams.normalmaps == "yes") then
Spring.Echo("Found Normalmap",unitDefID,unitDef.name)
materialDefs[unitDefID] = {
shader = include("LuaRules/Configs/UnitShaders/normalmappedS3O.lua"),
usecamera = false,
culling = GL.BACK,
predl= gl.CreateList(
function()
local glAlphaTest = gl.AlphaTest
local glBlending = gl.Blending
local GL_GREATER = GL.GREATER
local GL_SRC_ALPHA = GL.SRC_ALPHA
local GL_ONE_MINUS_SRC_ALPHA = GL.ONE_MINUS_SRC_ALPHA
local glTexture = gl.Texture
glAlphaTest(GL_GREATER,0.01)
glBlending(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
local normalTex = "unittextures/"..unitDef.customParams.normalmap_name
glTexture(4,normalTex)
end),
texunits = {
[0] = '%' .. unitDefID .. ":0",
[1] = '%' .. unitDefID .. ":1",
[2] = {tex = "$reflection", enable = false},
[3] = "$shadow",
},
}
unitShaderDefs[unitDefID] = unitDefID
end