How can you read so many papers and still not knowing the difference between culling, alphatest, stencil buffer and depth buffer?Argh wrote:I just showed you that, depending on the order in which translucent objects are called vs. opaque ones, you get different results when culling occurs.
Drawing Order
Moderator: Moderators
Re: Drawing Order
Re: Drawing Order
How can you see the fucking screenshots, and yet still not know what you're talking about?
Seriously... somebody, write the goddamn basic sort... not even the secondary... and I will show you, via screenshots, that it all works, as fucking described. It will not take more than 20 minutes to write that sort, dammit, and I will test it and show the results.
Seriously... somebody, write the goddamn basic sort... not even the secondary... and I will show you, via screenshots, that it all works, as fucking described. It will not take more than 20 minutes to write that sort, dammit, and I will test it and show the results.
Last edited by Argh on 13 Aug 2009, 00:14, edited 1 time in total.
Re: Drawing Order
brilliant. 10/10Argh wrote:How can you see the fucking screenshots, and yet still not know what you're talking about?
Re: Drawing Order
argh, Imma have to ask you to calm down a bit.
also, screenshots aren't the source of ultimate wisdom, and tests *can* be misinterpreted if you don't completely understand the underlying technology.
also, screenshots aren't the source of ultimate wisdom, and tests *can* be misinterpreted if you don't completely understand the underlying technology.
Re: Drawing Order
Fine, fine, I'll take deep breaths and stuff. Tell jK that he needs to show some proof, though, this is ridiculous. I'll give him the entire GLSL so that he can test it.argh, Imma have to ask you to calm down a bit.
Fair enough. That's why I reversed the test conditions and showed that the results were what I predicted. That's science.tests *can* be misinterpreted if you don't completely understand the underlying technology.
Here's the code.
Code: Select all
function gadget:GetInfo()
return {
name = "unit_normalmap_shader_tst.lua",
desc = "adds normal-mapping to S3O models",
author = "Kloot",
date = "31-1-2009",
license = "GPL v2",
layer = 0,
enabled = true
}
end
if (gadgetHandler:IsSyncedCode()) then
function gadget:Initialize()
-- desc = "adds normal-mapping to S3O models (gadgetized)",
-- author = "Kloot",
-- date = "April 6, 2009",
-- license = "GPL v2",
end
function gadget:UnitGiven(unitID)
SendToUnsynced("MyUnitCrea", unitID)
return true
end
function gadget:UnitCreated(unitID)
SendToUnsynced("MyUnitCrea", unitID)
return true
end
function gadget:UnitDestroyed(unitID)
SendToUnsynced("MyUnitDest", unitID)
return true
end
else
local glLoadIdentity = gl.LoadIdentity
local glPushMatrix = gl.PushMatrix
local glPopMatrix = gl.PopMatrix
local glTranslate = gl.Translate
local glBeginEnd = gl.BeginEnd
local glNormal = gl.Normal
local glVertex = gl.Vertex
local glColor = gl.Color
local glLight = gl.Light
local glLighting = gl.Lighting
local glBlending = gl.Blending
local glPushAttrib = gl.PushAttrib
local glPopAttrib = gl.PopAttrib
local glCulling = gl.Culling
local glDepthMask = gl.DepthMask
local glDepthTest = gl.DepthTest
local glAlphaTest = gl.AlphaTest
local glCreateList = gl.CreateList
local glDeleteList = gl.DeleteList
local glUnit = gl.Unit
local glUnitRaw = gl.UnitRaw
local glTexture = gl.Texture
local glTexCoord = gl.TexCoord
local glMultiTexCoord = gl.MultiTexCoord
local glUnitMultMatrix = gl.UnitMultMatrix
local glGetSun = gl.GetSun
local glGetShadowMapParams = gl.GetShadowMapParams
local glGetMatrixData = gl.GetMatrixData
local glGetShaderLog = gl.GetShaderLog
local glCreateShader = gl.CreateShader
local glDeleteShader = gl.DeleteShader
local glUseShader = gl.UseShader
local glUniformMatrix = gl.UniformMatrix
local glUniformInt = gl.UniformInt
local glUniform = gl.Uniform
local glGetUniformLocation = gl.GetUniformLocation
local glGetActiveUniforms = gl.GetActiveUniforms
local normalMapNames = {}
local textureNames = {}
local preDisplayLists = {}
local pstDisplayLists = {}
local luaShader = nil
local luaShaderLocs = {
cameraMatrixLoc = -1,
cameraInvMatrixLoc = -1,
shadowMatrixLoc = -1,
shadowParamsLoc = -1,
shadowDensityLoc = -1,
unitAmbientLightLoc = -1,
unitDiffuseLightLoc = -1,
shadowMapLoc = -1,
textureS3O1Loc = -1,
textureS3O2Loc = -1,
--specularMapLoc = -1,
reflectMapLoc = -1,
normalMapLoc = -1,
}
local sprGetGameFrame = Spring.GetGameFrame
local sprGetUnitDefID = Spring.GetUnitDefID
local sprGetAllUnits = Spring.GetAllUnits
local sprGetVisibleUnits = Spring.GetVisibleUnits
local sprIsUnitVisible = Spring.IsUnitVisible
local sprGetUnitTeam = Spring.GetUnitTeam
local sprGetCameraPosition = Spring.GetCameraPosition
local sprGetTeamColor = Spring.GetTeamColor
local sprSetUnitNoDraw = Spring.SetUnitNoDraw
local sprHaveShadows = Spring.HaveShadows
local sprGetUnitTransformMatrix = Spring.GetUnitTransformMatrix
local SUR = Spring.UnitRendering
local function GetPreDisplayList(unitID)
local unitTeam = sprGetUnitTeam(unitID)
local unitDefID = sprGetUnitDefID(unitID)
if (preDisplayLists[unitDefID] == nil) then
preDisplayLists[unitDefID] = {}
end
if (preDisplayLists[unitDefID][unitTeam] == nil) then
local sdx, sdy, sdz = glGetSun("pos")
local tcr, tcg, tcb, tca = sprGetTeamColor(unitTeam)
preDisplayLists[unitDefID][unitTeam] = glCreateList(
function()
glPushAttrib(GL_ALL_ATTRIB_BITS)
glAlphaTest(GL.GREATER,0.01)
glBlending(GL.SRC_ALPHA, GL.ONE_MINUS_SRC_ALPHA)
glDepthMask(true)
glDepthTest(GL.LEQUAL)
glCulling(GL.BACK)
glLighting(true)
glLight(0, true)
glLight(1, false)
glLight(0, GL.POSITION, sdx, sdy, sdz, 0)
glPushMatrix()
glColor(tcr, tcg, tcb, tca)
glTexture(4, normalMapNames[unitDefID][1])
end)
end
return preDisplayLists[unitDefID][unitTeam]
end
local function GetPostDisplayList(unitID)
local unitTeam = sprGetUnitTeam(unitID)
local unitDefID = sprGetUnitDefID(unitID)
if (pstDisplayLists[unitDefID] == nil) then
pstDisplayLists[unitDefID] = {}
end
if (pstDisplayLists[unitDefID][unitTeam] == nil) then
pstDisplayLists[unitDefID][unitTeam] = glCreateList(
function()
glTexture(4, false)
glColor(1.0, 1.0, 1.0, 1.0)
glPopMatrix()
glLight(0, false)
glLighting(false)
glCulling(GL.FRONT)
glDepthTest(false)
glDepthMask(false)
glBlending(true)
glPopAttrib()
end)
end
return pstDisplayLists[unitDefID][unitTeam]
end
local function GetUnitDefMaterial(unitDefID, preDL, pstDL)
local matTbl = {
texunits = {
[0] = {tex = textureNames[unitDefID][1], enable = true},
[1] = {tex = textureNames[unitDefID][2], enable = true},
[2] = {tex = "$reflection", enable = true},
[3] = {tex = normalMapNames[unitDefID][1], enable = true},
[4] = {tex = "$shadow", enable = true}
},
culling = GL.BACK,
shader = luaShader,
cameraloc = luaShaderLocs.cameraMatrixLoc,
-- camerainvloc = luaShaderLocs.cameraInvMatrixLoc, -- Spring 0.79
shadowloc = luaShaderLocs.shadowMatrixLoc,
shadowparamsloc = luaShaderLocs.shadowParamsLoc,
prelist = preDL,
postlist = pstDL
}
return matTbl
end
local function MyUnitCrea(unitID)
local unitDefID = sprGetUnitDefID(unitID)
if (normalMapNames[unitDefID] ~= nil) then
if (textureNames[unitDefID] == nil) then
textureNames[unitDefID] = {
[1] = '%' .. unitDefID .. ":0",
[2] = '%' .. unitDefID .. ":1"
}
end
--Spring.Echo("Found Unit",unitID)
local preDL = GetPreDisplayList(unitID)
local pstDL = GetPostDisplayList(unitID)
SUR.SetLODCount(unitID, 1)
SUR.SetMaterial(unitID, 1, "opaque", GetUnitDefMaterial(unitDefID, preDL, pstDL))
SUR.SetUnitLuaDraw(unitID, true)
for pieceID, pieceName in pairs(Spring.GetUnitPieceList(unitID) or {}) do
if (pieceID ~= "n") then
SUR.SetPieceList(unitID, 1, pieceID)
end
end
end
end
local function MyUnitDest(unitID)
local unitDefID = sprGetUnitDefID(unitID)
if (normalMapNames[unitDefID] ~= nil) then
SUR.SetUnitLuaDraw(unitID, false)
SUR.SetLODCount(unitID, 0)
end
end
local function SetShaderUniformLocations(s)
luaShaderLocs.cameraMatrixLoc = glGetUniformLocation(s, "cameraMatrix")
luaShaderLocs.cameraInvMatrixLoc = glGetUniformLocation(s, "cameraInvMatrix")
luaShaderLocs.shadowMatrixLoc = glGetUniformLocation(s, "shadowMatrix")
luaShaderLocs.haveShadowsLoc = glGetUniformLocation(luaShader, "haveShadows")
luaShaderLocs.shadowParamsLoc = glGetUniformLocation(luaShader, "shadowParams")
luaShaderLocs.shadowDensityLoc = glGetUniformLocation(luaShader, "shadowDensity")
end
local function CreateShader1()
local s = glCreateShader({
vertex = [[
varying vec3 lvES;
varying vec3 hvES;
varying vec3 nvES;
varying mat3 tbnInvMatrix;
varying vec3 cdES;
//varying vec3 cdTS;
uniform int haveShadows;
uniform mat4 shadowMatrix;
uniform vec4 shadowParams;
uniform mat4 cameraMatrix;
uniform mat4 cameraInvMatrix;
void main(void) {
mat4 modelMatrix = cameraInvMatrix * gl_ModelViewMatrix;
mat4 modelInvMatrix = gl_ModelViewMatrixInverse * cameraMatrix;
vec3 vpES = (gl_ModelViewMatrix * gl_Vertex).xyz;
vec3 cpES = vec3(0.0, 0.0, 1.0);
vec3 svOS = gl_MultiTexCoord5.xyz;
vec3 tvOS = gl_MultiTexCoord6.xyz;
//Manual transform of the matrix, for GLSL 1.X compatibility
mat3 tbnMatrix = mat3(svOS, tvOS, gl_Normal);
tbnInvMatrix[0].x = tbnMatrix[0].x;
tbnInvMatrix[0].y = tbnMatrix[1].x;
tbnInvMatrix[0].z = tbnMatrix[2].x;
tbnInvMatrix[1].x = tbnMatrix[0].y;
tbnInvMatrix[1].y = tbnMatrix[1].y;
tbnInvMatrix[1].z = tbnMatrix[2].y;
tbnInvMatrix[2].x = tbnMatrix[0].z;
tbnInvMatrix[2].y = tbnMatrix[1].z;
tbnInvMatrix[2].z = tbnMatrix[2].z;
cdES = (vpES - cpES);
//cdTS = (tbnInvMatrix * (gl_ModelViewMatrixInverse * vec4(cdES, gl_Vertex.w)).xyz);
nvES = normalize(gl_NormalMatrix * gl_Normal);
lvES = normalize(gl_LightSource[0].position.xyz);
hvES = normalize(gl_LightSource[0].halfVector.xyz);
gl_FrontColor = gl_Color;
gl_TexCoord[0].st = gl_MultiTexCoord0.st;
gl_Position = gl_ProjectionMatrix * cameraMatrix * modelMatrix * gl_Vertex;
if (haveShadows != 0) {
vec4 vpWS = (modelMatrix * gl_Vertex);
gl_TexCoord[3] = shadowMatrix * vpWS;
gl_TexCoord[3].st *= (1 / sqrt(abs(gl_TexCoord[3].st) + shadowParams.z) + shadowParams.w);
gl_TexCoord[3].st += shadowParams.xy;
}
}
]],
fragment = [[
varying vec3 lvES;
varying vec3 hvES;
varying vec3 nvES;
varying vec3 cdES;
//varying vec3 cdTS;
uniform sampler2D textureS3O1;
uniform sampler2D textureS3O2;
uniform samplerCube reflectMap;
uniform sampler2D normalMap;
uniform sampler2D shadowMap;
uniform int haveShadows;
uniform vec3 unitAmbientLight;
uniform vec3 unitDiffuseLight;
varying mat3 tbnInvMatrix;
void main(void) {
//Manual transform of the matrix, for GLSL 1.X compatibility
mat3 tbnMatrix;
tbnMatrix[0].x = tbnInvMatrix[0].x;
tbnMatrix[0].y = tbnInvMatrix[1].x;
tbnMatrix[0].z = tbnInvMatrix[2].x;
tbnMatrix[1].x = tbnInvMatrix[0].y;
tbnMatrix[1].y = tbnInvMatrix[1].y;
tbnMatrix[1].z = tbnInvMatrix[2].y;
tbnMatrix[2].x = tbnInvMatrix[0].z;
tbnMatrix[2].y = tbnInvMatrix[1].z;
tbnMatrix[2].z = tbnInvMatrix[2].z;
vec2 tc = vec2(gl_TexCoord[0].s, gl_TexCoord[0].t);
/*vec4 normalColor = texture2D(normalMap, tc);
vec3 cdTS = (tbnInvMatrix * (gl_ModelViewMatrixInverse * vec4(cdES,normalColor.a)).xyz);
// parallax-mapping
float s = 0.005;
float b = -0.001;
//float h;
float h = (float(texture2D(normalMap, tc)) * s) + b;
//h = (h * s) + b;
tc += (h * (normalize(cdTS)).xy);*/
vec3 nvTS = ((texture2D(normalMap, tc) * 2.0) - 1.0);
vec4 basicColor = texture2D(textureS3O1, tc);
vec4 extraColor = texture2D(textureS3O2, tc);
float nvDOTlv = 0.0;
float nvDOThv = 0.0;
vec3 reDirES;
vec3 nv_OS = normalize(tbnMatrix * nvTS);
vec3 nv_ES = normalize(gl_NormalMatrix * nv_OS);
nvDOTlv = max(nvDOTlv, dot(nv_ES, lvES));
nvDOThv = max(nvDOThv, dot(nv_ES, hvES));
reDirES = reflect(normalize(cdES), nv_ES);
float shininess = extraColor.g * 4.0;
float specPow =
(nvDOTlv > 0.0 && nvDOThv > 0.0)?
max(0.0, pow(nvDOThv, shininess)):
0.0;
if (extraColor.b > 0.0)
{
specPow = specPow * extraColor.b;
}
vec3 specColor = textureCube(reflectMap, reDirES).rgb * specPow * extraColor.g;
vec3 reflColor = textureCube(reflectMap, reDirES).rgb;
vec3 diffColor = (unitDiffuseLight * nvDOTlv) + unitAmbientLight * 1.25;
reflColor = mix(diffColor, reflColor, extraColor.g);
reflColor += extraColor.r;
gl_FragColor = basicColor;
gl_FragColor.rgb = mix(gl_FragColor.rgb, gl_Color.rgb, gl_FragColor.a);
gl_FragColor.rgb = gl_FragColor.rgb * reflColor + specColor;
if(haveShadows != 0)
{
vec2 tc = vec2(gl_TexCoord[3].s, gl_TexCoord[3].t);
float depth = texture2D(shadowMap, tc).z;
if (depth < 0.05)
{
gl_FragColor.rgb = gl_FragColor.rgb * vec3(extraColor.r + unitAmbientLight.r + extraColor.g, extraColor.r + unitAmbientLight.g + extraColor.g, extraColor.r + unitAmbientLight.b + extraColor.g);
if (basicColor.a > 0.0)
{
gl_FragColor.rgb = mix(gl_FragColor.rgb, gl_Color, basicColor.a);
}
}
}
gl_FragColor.a = extraColor.a;
}
]],
uniformInt = {
textureS3O1 = 0,
textureS3O2 = 1,
reflectMap = 2,
normalMap = 3,
shadowMap = 4,
},
uniform = {
unitAmbientLight = {glGetSun("ambient", "unit")},
unitDiffuseLight = {glGetSun("diffuse", "unit")},
},
uniformMatrix = {
shadowMatrix = {glGetMatrixData("shadow")},
}
})
return s
end
function gadget:Initialize()
if (glCreateShader == nil) then
Spring.Echo("[unit_normalmap_shader:Initialize] no shader support")
gadgetHandler:RemoveGadget()
return
end
luaShader = CreateShader1()
if (luaShader == nil) then
Spring.Echo("[unit_normalmap_shader:Initialize] shader1 compilation failed")
Spring.Echo(glGetShaderLog())
gadgetHandler:RemoveGadget()
return
end
SetShaderUniformLocations(luaShader)
for unitDefID, unitDef in pairs(UnitDefs) do
if (unitDef.customParams.normalmaps == "yes") then
--Spring.Echo("Found Normalmap",unitDefID)
normalMapNames[unitDefID] = {"unittextures/" .. unitDef.customParams.normalmap_name, true, true}
--Spring.Echo(normalMapNames[unitDefID])
end
end
end
function gadget:Shutdown()
for unitDefID, _ in pairs(UnitDefs) do
if (preDisplayLists[unitDefID] ~= nil) then
for i = 0, 1024 do
if (preDisplayLists[unitDefID][i] ~= nil) then glDeleteList(preDisplayLists[unitDefID][i]) end
if (pstDisplayLists[unitDefID][i] ~= nil) then glDeleteList(pstDisplayLists[unitDefID][i]) end
end
end
end
--glDeleteShader(luaShader or 0)
end
function gadget:RecvFromSynced(fun, unitID)
if (fun == "MyUnitCrea") then MyUnitCrea(unitID) return true end
if (fun == "MyUnitDest") then MyUnitDest(unitID) return true end
return false
end
function gadget:DrawUnit(unitID, gameDrawMode)
glUniformMatrix(luaShaderLocs.cameraInvMatrixLoc, glGetMatrixData("caminv")) -- Spring 0.78.2.*
glUniformInt(luaShaderLocs.haveShadowsLoc, ((sprHaveShadows() and 1) or 0))
if (sprHaveShadows()) then
glUniform(luaShaderLocs.shadowParamsLoc, glGetShadowMapParams())
glUniform(luaShaderLocs.shadowDensityLoc, glGetSun("shadowDensity", "unit"))
end
glUnitRaw(unitID, true)
return true
end
end
Last edited by Argh on 13 Aug 2009, 00:27, edited 1 time in total.
Re: Drawing Order
sounds to me like all sheep in scotland are black
Re: Drawing Order
Peet its quite simple, your point stands, but the execution of this thread has proven you right and then gone further unnecessarily. It's this furtherness that I am commenting on.
The developers have already stated why they think Argh is wrong and explained their point.
Yet argh continues to post in response, argh, if you are right then your results speak for themselves, every post you make arguing that you are correc tis not benefiting you or the community but actually damaging it.
Every developer who continues to respond to these arguements and repeat the same arguments and try to persuade argh are also demeaning themselves and perpetuate the thread.
This is a thread whose context is a flame war over who is right and wrong regardless of results. You've already made your points so why are you still reiterating them over and over again? If argh si wrong then anybody who follows his wisdom will also eb wrong and will get incorrect results and learn from the mistakes. Anyone who sees the wisdom of argh will also see the developers response, and only a fool would do something despite a set fo well reasoned good explanations of why it is wrong.
More time is spent here explainign why argh is wrong than is taken to actually explain the correct way of doing it before argh posts anything.
Argh spends more time arguing that he did it right than he does actually doing things.
Aegis speaks sense
The developers have already stated why they think Argh is wrong and explained their point.
Yet argh continues to post in response, argh, if you are right then your results speak for themselves, every post you make arguing that you are correc tis not benefiting you or the community but actually damaging it.
Every developer who continues to respond to these arguements and repeat the same arguments and try to persuade argh are also demeaning themselves and perpetuate the thread.
This is a thread whose context is a flame war over who is right and wrong regardless of results. You've already made your points so why are you still reiterating them over and over again? If argh si wrong then anybody who follows his wisdom will also eb wrong and will get incorrect results and learn from the mistakes. Anyone who sees the wisdom of argh will also see the developers response, and only a fool would do something despite a set fo well reasoned good explanations of why it is wrong.
More time is spent here explainign why argh is wrong than is taken to actually explain the correct way of doing it before argh posts anything.
Argh spends more time arguing that he did it right than he does actually doing things.
Aegis speaks sense
Re: Drawing Order
A simple depth-sort of the visible UnitIDs is not that big of a deal, AF. If jK hadn't decided that his ego rides on whether I'm right about anything, Lurker would have gotten it done and I'd be happily testing it.
20 minutes of coding. One test compile. That's all I'm asking for.
20 minutes of coding. One test compile. That's all I'm asking for.
Re: Drawing Order
Because I am a motivated person that cares what people think.
Re: Drawing Order
you borked at this:
but then wrote this:Argh wrote:Then they'll just draw through mountains, etc., and what if you have transparent stuff on the underside of something? lol.KDR_11k wrote:Generally translucent surfaces are rendered last but not sorted. Just make sure you draw yours after everything else is drawn.
Is it me or is it you thats missing something obvious here?Argh wrote:I don't think that most professional engines bother depth-sorting the pieces. They're just doing what I did. They just draw the translucent stuff last and hope for the best, and 99% of the time, nobody can tell..
Last edited by momfreeek on 13 Aug 2009, 04:21, edited 2 times in total.
Re: Drawing Order
No, I'm just mangling terminology, as usual. Makes it hard to make myself understood sometimes, I don't speak Graphic Engine Development.Is it me or is it you thats missing something obvious here?
I think that professional engines draw using a depth sort, per Unit-equivalent (or brush). They defer the objects that need alpha testing until the end of the drawing process per Unit-equivalent. I.E., they draw Unit-equivalent objects in depth order, then draw the Piece-equivelants in that Unit-equivalent in order of whether they're opaque or translucent.
They do this with a material system. Go look at a Fallout 3 GameBryo model. It's obvious that each sub-mesh has a material assigned. MD5? Same thing. Freelancer's engine? Same thing. They wouldn't do all be doing that, if there wasn't some agreement that that's the right way to do things.
In Freelancer's engine, for example, it's obvious that it works that way, because two translucent objects may be in the wrong order, leading to geometry being culled. Not only that, but you have to assign a "glass" material to objects for them to be translucent at all, since they use a shader per material. Since they didn't depth-sort the Piece equivalents, if you put a transparent dome inside another transparent dome, the second one is frequently totally culled. If they'd added an integer to the end of each Piece-equivalent's mesh specification, artists could have manually set up the drawing order for the best results under most circumstances, but they didn't, so it frequently borks.
Now, there may be new-fangled, more advanced ways to do it. I have no clue about that stuff, that's Deep Graphics Development of the CryEngine sort. But, short of doing a depth-sort of every triangle first, then doing alpha-tests, it's probably just a smarter, sleeker variation of the material system, where the real optimization is in the sorting procedures, not the basic process.
I faked the material system, by taking advantage of a funky element of S3O, which is that it draws strictly in the numerical order of the Pieces. I discovered this by accident, after I did the simple stuff. It works, and that's pretty much why all I need is a depth-sort of the UnitIDs, because then I have a chain of rendering order- farthest Unit first, then the next one draws, and probably won't have culling issues during the alpha test, because it's probably not behind the other unit's geometry at any point.
This will not result in a perfect result every time, as AF pointed out and I elaborated upon. The giant, transparent dome scenario will probably cause borks. I'm just not feeling like building one, just to prove this, though.
So, a secondary sort based on a boolean translucence UnitDef tag is probably necessary, to get the best sort with the lowest overhead and the fewest final errors.
Will it be 100% error-free? No. Does that matter a lot? No. Can I use what I have now, regardless of the outcome of this discussion? Yes. Does it look cooler than anything else on this engine atm? Yes.
So, given that... screw it, I surrender. I'm right, but if I can't get to prove it beyond all doubt, who cares.
I'll just accept that nobody will do this simple test setup, so that I can finish showing why jK's statements are erroneous, and move on. I don't need this level of hassle for what was such a minor request.
But, for the record, t's really lame that people can see screens of something working this well already and then choose to argue instead of cooperating to make it fully functional, especially after providing so much proof.
Last edited by Argh on 13 Aug 2009, 01:36, edited 1 time in total.
Re: Drawing Order
...I have no idea what you're talking about, there are so many rendering problems with that picture and it's not even translucent!Argh wrote:Wish granted, the entire object, translucency 128:
Before:
http://www.wolfegames.com/TA_Section/gl ... rency8.jpg
After
http://www.wolfegames.com/TA_Section/gl ... rency9.jpgSo... eh... I guess you didn't get that whole thing about drawing order within the geometry. Are we all on the same page now?
The Arc on the top is clearly not translucent, I'm not even going to begin going through anything else. I asked for something colourful so rendering errors would be obvious.
For reference, this is an example of translucency correctly rendered (though the rendering technique is useless for spring):

Re: Drawing Order
Wow... OK.. you're blind, eh? Maybe that's the problem here....I have no idea what you're talking about, there are so many rendering problems with that picture and it's not even translucent!
Here... lowered overall translucency to 15%.
Now, even if you're blind, you can see the shadowmap through the Unit geometry and the map's texture as well.


Here, for the ultra-blind... I'll raise it off the ground, so that we can see things a bit clearer:

Re: Drawing Order
....I give up....Maybe you'll wake up tomorrow and realise...
Re: Drawing Order
ok, even shorter quotes:
this was the solution that you borked at:
from what i understand there's one obvious, massive optimisation to your proposed solution: you don't need to include fully opaque models in the sort.. just draw them all first.
this was the solution that you borked at:
this is how you fixed your problem internally:KDR_11k wrote:translucent surfaces are rendered last
where's the mix up in terminology?Argh wrote:draw the translucent stuff last
from what i understand there's one obvious, massive optimisation to your proposed solution: you don't need to include fully opaque models in the sort.. just draw them all first.
Re: Drawing Order
Ok... I've moved everything to DrawWorld, where it probably should have been in the first place, because that lets us do arbitrary crap like what I want, let alone what other people will want.
It's not working perfectly yet. There are some hideous flaws that I haven't addressed yet. But it's back to this point:

I'll post the code when it works in a halfway-decent fashion, it's still really nasty.
It's not working perfectly yet. There are some hideous flaws that I haven't addressed yet. But it's back to this point:

I'll post the code when it works in a halfway-decent fashion, it's still really nasty.
Re: Drawing Order
Big, fat, edit:
It was almost there, but one minor bork remained. Now it's there, other than writing the actual depth-sort, and figuring out where this can be optimized a lot better.
Fixed the matrix issue. Camerainv was commented out in the SUR section for some reason. Oh well. Now I really have to get a nap. Here's updated (correctly-working) sourcecode of the DrawWorld implementation:
It was almost there, but one minor bork remained. Now it's there, other than writing the actual depth-sort, and figuring out where this can be optimized a lot better.
Fixed the matrix issue. Camerainv was commented out in the SUR section for some reason. Oh well. Now I really have to get a nap. Here's updated (correctly-working) sourcecode of the DrawWorld implementation:
Code: Select all
function gadget:GetInfo()
return {
name = "unit_normalmap_shader_tst.lua",
desc = "adds normal-mapping to S3O models",
author = "Kloot",
date = "31-1-2009",
license = "GPL v2",
layer = 0,
enabled = true
}
end
if (gadgetHandler:IsSyncedCode()) then
function gadget:Initialize()
-- desc = "adds normal-mapping to S3O models (gadgetized)",
-- author = "Kloot",
-- date = "April 6, 2009",
-- license = "GPL v2",
end
function gadget:UnitGiven(unitID)
SendToUnsynced("MyUnitCrea", unitID)
return true
end
function gadget:UnitCreated(unitID)
SendToUnsynced("MyUnitCrea", unitID)
return true
end
function gadget:UnitDestroyed(unitID)
SendToUnsynced("MyUnitDest", unitID)
return true
end
else
local glLoadIdentity = gl.LoadIdentity
local glPushMatrix = gl.PushMatrix
local glPopMatrix = gl.PopMatrix
local glTranslate = gl.Translate
local glBeginEnd = gl.BeginEnd
local glNormal = gl.Normal
local glVertex = gl.Vertex
local glColor = gl.Color
local glLight = gl.Light
local glLighting = gl.Lighting
local glBlending = gl.Blending
local glPushAttrib = gl.PushAttrib
local glPopAttrib = gl.PopAttrib
local glCulling = gl.Culling
local glDepthMask = gl.DepthMask
local glDepthTest = gl.DepthTest
local glAlphaTest = gl.AlphaTest
local glCreateList = gl.CreateList
local glDeleteList = gl.DeleteList
local glUnit = gl.Unit
local glUnitRaw = gl.UnitRaw
local glTexture = gl.Texture
local glTexCoord = gl.TexCoord
local glMultiTexCoord = gl.MultiTexCoord
local glUnitMultMatrix = gl.UnitMultMatrix
local glGetSun = gl.GetSun
local glGetShadowMapParams = gl.GetShadowMapParams
local glGetMatrixData = gl.GetMatrixData
local glGetShaderLog = gl.GetShaderLog
local glCreateShader = gl.CreateShader
local glDeleteShader = gl.DeleteShader
local glUseShader = gl.UseShader
local glUniformMatrix = gl.UniformMatrix
local glUniformInt = gl.UniformInt
local glUniform = gl.Uniform
local glGetUniformLocation = gl.GetUniformLocation
local glGetActiveUniforms = gl.GetActiveUniforms
local normalMapList = {}
local normalMapNames = {}
local textureNames = {}
local preDisplayLists = {}
local pstDisplayLists = {}
local luaShader = nil
local luaShaderLocs = {
cameraMatrixLoc = -1,
cameraInvMatrixLoc = -1,
shadowMatrixLoc = -1,
shadowParamsLoc = -1,
shadowDensityLoc = -1,
unitAmbientLightLoc = -1,
unitDiffuseLightLoc = -1,
shadowMapLoc = -1,
textureS3O1Loc = -1,
textureS3O2Loc = -1,
--specularMapLoc = -1,
reflectMapLoc = -1,
normalMapLoc = -1,
}
local sprGetGameFrame = Spring.GetGameFrame
local sprGetUnitDefID = Spring.GetUnitDefID
local sprGetAllUnits = Spring.GetAllUnits
local sprGetVisibleUnits = Spring.GetVisibleUnits
local sprIsUnitVisible = Spring.IsUnitVisible
local sprGetUnitTeam = Spring.GetUnitTeam
local sprGetCameraPosition = Spring.GetCameraPosition
local sprGetTeamColor = Spring.GetTeamColor
local sprSetUnitNoDraw = Spring.SetUnitNoDraw
local sprHaveShadows = Spring.HaveShadows
local sprGetUnitTransformMatrix = Spring.GetUnitTransformMatrix
local SUR = Spring.UnitRendering
local function GetPreDisplayList(unitID)
local unitTeam = sprGetUnitTeam(unitID)
local unitDefID = sprGetUnitDefID(unitID)
if (preDisplayLists[unitDefID] == nil) then
preDisplayLists[unitDefID] = {}
end
if (preDisplayLists[unitDefID][unitTeam] == nil) then
local sdx, sdy, sdz = glGetSun("pos")
local tcr, tcg, tcb, tca = sprGetTeamColor(unitTeam)
preDisplayLists[unitDefID][unitTeam] = glCreateList(
function()
glPushAttrib(GL_ALL_ATTRIB_BITS)
glAlphaTest(GL.GREATER,0.01)
glBlending(GL.SRC_ALPHA, GL.ONE_MINUS_SRC_ALPHA)
glDepthMask(true)
glDepthTest(GL.LEQUAL)
glCulling(GL.BACK)
glLighting(true)
glLight(0, true)
glLight(1, false)
glLight(0, GL.POSITION, sdx, sdy, sdz, 0)
glPushMatrix()
glColor(tcr, tcg, tcb, tca)
glTexture(3, "unittextures/" .. UnitDefs[unitDefID].customParams.normalmap_name)
end)
end
return preDisplayLists[unitDefID][unitTeam]
end
local function GetPostDisplayList(unitID)
local unitTeam = sprGetUnitTeam(unitID)
local unitDefID = sprGetUnitDefID(unitID)
if (pstDisplayLists[unitDefID] == nil) then
pstDisplayLists[unitDefID] = {}
end
if (pstDisplayLists[unitDefID][unitTeam] == nil) then
pstDisplayLists[unitDefID][unitTeam] = glCreateList(
function()
glTexture(3, false)
glColor(1.0, 1.0, 1.0, 1.0)
glPopMatrix()
glLight(0, false)
glLighting(false)
glCulling(GL.FRONT)
glDepthTest(false)
glDepthMask(false)
glBlending(true)
glPopAttrib()
end)
end
return pstDisplayLists[unitDefID][unitTeam]
end
local function GetUnitDefMaterial(unitDefID, preDL, pstDL)
local matTbl = {
texunits = {
[0] = {tex = textureNames[unitDefID][1], enable = true},
[1] = {tex = textureNames[unitDefID][2], enable = true},
[2] = {tex = "$reflection", enable = true},
[3] = {tex = "unittextures/" .. UnitDefs[unitDefID].customParams.normalmap_name, enable = true},
[4] = {tex = "$shadow", enable = true}
},
culling = GL.BACK,
shader = luaShader,
cameraloc = luaShaderLocs.cameraMatrixLoc,
camerainvloc = luaShaderLocs.cameraInvMatrixLoc, -- Spring 0.79
shadowloc = luaShaderLocs.shadowMatrixLoc,
shadowparamsloc = luaShaderLocs.shadowParamsLoc,
prelist = preDL,
postlist = pstDL
}
return matTbl
end
local function MyUnitCrea(unitID)
local unitDefID = sprGetUnitDefID(unitID)
if (normalMapNames[unitDefID] ~= nil) then
if (textureNames[unitDefID] == nil) then
textureNames[unitDefID] = {
[1] = '%' .. unitDefID .. ":0",
[2] = '%' .. unitDefID .. ":1"
}
end
--Spring.Echo("Found Unit",unitID)
local preDL = GetPreDisplayList(unitID)
local pstDL = GetPostDisplayList(unitID)
SUR.SetLODCount(unitID, 1)
SUR.SetMaterial(unitID, 1, "opaque", GetUnitDefMaterial(unitDefID, preDL, pstDL))
SUR.SetUnitLuaDraw(unitID, true)
for pieceID, pieceName in pairs(Spring.GetUnitPieceList(unitID) or {}) do
if (pieceID ~= "n") then
SUR.SetPieceList(unitID, 1, pieceID)
end
end
end
end
local function MyUnitDest(unitID)
local unitDefID = sprGetUnitDefID(unitID)
if (normalMapNames[unitDefID] ~= nil) then
SUR.SetUnitLuaDraw(unitID, false)
SUR.SetLODCount(unitID, 0)
end
end
local function CreateShader1()
local s = glCreateShader({
vertex = [[
varying vec3 lvES;
varying vec3 hvES;
varying vec3 nvES;
varying mat3 tbnInvMatrix;
varying vec3 cdES;
uniform int haveShadows;
uniform mat4 shadowMatrix;
uniform vec4 shadowParams;
uniform mat4 cameraMatrix;
uniform mat4 cameraInvMatrix;
void main(void) {
mat4 modelMatrix = cameraInvMatrix * gl_ModelViewMatrix;
mat4 modelInvMatrix = gl_ModelViewMatrixInverse * cameraMatrix;
vec3 vpES = (gl_ModelViewMatrix * gl_Vertex).xyz;
vec3 cpES = vec3(0.0, 0.0, 1.0);
vec3 svOS = gl_MultiTexCoord5.xyz;
vec3 tvOS = gl_MultiTexCoord6.xyz;
//Manual transform of the matrix, for GLSL 1.X compatibility
mat3 tbnMatrix = mat3(svOS, tvOS, gl_Normal);
tbnInvMatrix[0].x = tbnMatrix[0].x;
tbnInvMatrix[0].y = tbnMatrix[1].x;
tbnInvMatrix[0].z = tbnMatrix[2].x;
tbnInvMatrix[1].x = tbnMatrix[0].y;
tbnInvMatrix[1].y = tbnMatrix[1].y;
tbnInvMatrix[1].z = tbnMatrix[2].y;
tbnInvMatrix[2].x = tbnMatrix[0].z;
tbnInvMatrix[2].y = tbnMatrix[1].z;
tbnInvMatrix[2].z = tbnMatrix[2].z;
cdES = (vpES - cpES);
nvES = normalize(gl_NormalMatrix * gl_Normal);
lvES = normalize(gl_LightSource[0].position.xyz);
hvES = normalize(gl_LightSource[0].halfVector.xyz);
gl_FrontColor = gl_Color;
gl_TexCoord[0].st = gl_MultiTexCoord0.st;
gl_Position = gl_ProjectionMatrix * cameraMatrix * modelMatrix * gl_Vertex;
if (haveShadows != 0) {
vec4 vpWS = (modelMatrix * gl_Vertex);
gl_TexCoord[3] = shadowMatrix * vpWS;
gl_TexCoord[3].st *= (1 / sqrt(abs(gl_TexCoord[3].st) + shadowParams.z) + shadowParams.w);
gl_TexCoord[3].st += shadowParams.xy;
}
}
]],
fragment = [[
varying vec3 lvES;
varying vec3 hvES;
varying vec3 nvES;
varying vec3 cdES;
uniform sampler2D textureS3O1;
uniform sampler2D textureS3O2;
uniform samplerCube reflectMap;
uniform sampler2D normalMap;
uniform sampler2D shadowMap;
uniform int haveShadows;
uniform vec3 unitAmbientLight;
uniform vec3 unitDiffuseLight;
varying mat3 tbnInvMatrix;
void main(void) {
//Manual transform of the matrix, for GLSL 1.X compatibility
mat3 tbnMatrix;
tbnMatrix[0].x = tbnInvMatrix[0].x;
tbnMatrix[0].y = tbnInvMatrix[1].x;
tbnMatrix[0].z = tbnInvMatrix[2].x;
tbnMatrix[1].x = tbnInvMatrix[0].y;
tbnMatrix[1].y = tbnInvMatrix[1].y;
tbnMatrix[1].z = tbnInvMatrix[2].y;
tbnMatrix[2].x = tbnInvMatrix[0].z;
tbnMatrix[2].y = tbnInvMatrix[1].z;
tbnMatrix[2].z = tbnInvMatrix[2].z;
vec2 tc = vec2(gl_TexCoord[0].s, gl_TexCoord[0].t);
vec3 nvTS = ((texture2D(normalMap, tc) * 2.0) - 1.0);
vec4 basicColor = texture2D(textureS3O1, tc);
vec4 extraColor = texture2D(textureS3O2, tc);
float nvDOTlv = 0.0;
float nvDOThv = 0.0;
vec3 reDirES;
vec3 nv_OS = normalize(tbnMatrix * nvTS);
vec3 nv_ES = normalize(gl_NormalMatrix * nv_OS);
nvDOTlv = max(nvDOTlv, dot(nv_ES, lvES));
nvDOThv = max(nvDOThv, dot(nv_ES, hvES));
reDirES = reflect(normalize(cdES), nv_ES);
float shininess = extraColor.g * 4.0;
float specPow =
(nvDOTlv > 0.0 && nvDOThv > 0.0)?
max(0.0, pow(nvDOThv, shininess)):
0.0;
if (extraColor.b > 0.0)
{
specPow = specPow * extraColor.b;
}
vec3 specColor = textureCube(reflectMap, reDirES).rgb * specPow * extraColor.g;
vec3 reflColor = textureCube(reflectMap, reDirES).rgb;
vec3 diffColor = (unitDiffuseLight * nvDOTlv) + unitAmbientLight * 1.25;
reflColor = mix(diffColor, reflColor, extraColor.g);
reflColor += extraColor.r;
gl_FragColor = basicColor;
gl_FragColor.rgb = mix(gl_FragColor.rgb, gl_Color.rgb, gl_FragColor.a);
gl_FragColor.rgb = gl_FragColor.rgb * reflColor + specColor;
if(haveShadows != 0)
{
vec2 tc = vec2(gl_TexCoord[3].s, gl_TexCoord[3].t);
float depth = texture2D(shadowMap, tc).z;
if (depth < 0.05)
{
gl_FragColor.rgb = gl_FragColor.rgb * vec3(extraColor.r + unitAmbientLight.r + extraColor.g,
extraColor.r + unitAmbientLight.g + extraColor.g, extraColor.r + unitAmbientLight.b + extraColor.g);
if (basicColor.a > 0.0)
{
gl_FragColor.rgb = mix(gl_FragColor.rgb, gl_Color, basicColor.a);
}
}
}
gl_FragColor.a = extraColor.a;
}
]],
uniformInt = {
textureS3O1 = 0,
textureS3O2 = 1,
reflectMap = 2,
normalMap = 3,
shadowMap = 4,
},
uniform = {
unitAmbientLight = {glGetSun("ambient", "unit")},
unitDiffuseLight = {glGetSun("diffuse", "unit")},
},
uniformMatrix = {
shadowMatrix = {glGetMatrixData("shadow")},
}
})
return s
end
local function SetShaderUniformLocations(s)
luaShaderLocs.cameraMatrixLoc = glGetUniformLocation(s, "cameraMatrix")
luaShaderLocs.cameraInvMatrixLoc = glGetUniformLocation(s, "cameraInvMatrix")
luaShaderLocs.shadowMatrixLoc = glGetUniformLocation(s, "shadowMatrix")
luaShaderLocs.haveShadowsLoc = glGetUniformLocation(luaShader, "haveShadows")
luaShaderLocs.shadowParamsLoc = glGetUniformLocation(luaShader, "shadowParams")
luaShaderLocs.shadowDensityLoc = glGetUniformLocation(luaShader, "shadowDensity")
end
function gadget:Initialize()
if (glCreateShader == nil) then
Spring.Echo("[unit_normalmap_shader:Initialize] no shader support")
gadgetHandler:RemoveGadget()
return
end
luaShader = CreateShader1()
if (luaShader == nil) then
Spring.Echo("[unit_normalmap_shader:Initialize] shader1 compilation failed")
Spring.Echo(glGetShaderLog())
gadgetHandler:RemoveGadget()
return
end
SetShaderUniformLocations(luaShader)
for unitDefID, unitDef in pairs(UnitDefs) do
if (unitDef.customParams.normalmaps == "yes") then
--Spring.Echo("Found Normalmap",unitDefID)
normalMapNames[unitDefID] = {"unittextures/" .. unitDef.customParams.normalmap_name, true, true}
--Spring.Echo(normalMapNames[unitDefID])
table.insert(normalMapList,unitDefID,1)
end
end
end
function gadget:Shutdown()
end
function gadget:RecvFromSynced(fun, unitID)
if (fun == "MyUnitCrea") then MyUnitCrea(unitID) return true end
if (fun == "MyUnitDest") then MyUnitDest(unitID) return true end
return false
end
function gadget:DrawUnit(unitID, gameDrawMode)
ud = Spring.GetUnitDefID(unitID)
if normalMapList[ud] then
return false
else
return true
end
end
local unitIDList = {}
local renderPassList = {}
function gadget:DrawWorld()
local frame = Spring.GetGameFrame()
if (((frame + 5) % 15) < 0.1) then
Spring.Echo("updating list")
unitIDList = Spring.GetVisibleUnits(-1,5000,false)
for _,unitID in ipairs(unitIDList) do
id = Spring.GetUnitDefID(unitID)
if normalMapList[id] == nil then
table.remove(unitIDList,unitID)
end
end
end
if unitIDList[1] ~= nil then
for i,unitID in ipairs(unitIDList) do
glUniformMatrix(luaShaderLocs.cameraInvMatrixLoc, glGetMatrixData("caminv")) -- Spring 0.78.2.*
glUniformInt(luaShaderLocs.haveShadowsLoc, ((sprHaveShadows() and 1) or 0))
if (sprHaveShadows()) then
glUniform(luaShaderLocs.shadowParamsLoc, glGetShadowMapParams())
glUniform(luaShaderLocs.shadowDensityLoc, glGetSun("shadowDensity", "unit"))
end
glUseShader(luaShader)
end
end
end
end
Re: Drawing Order
what about this:
Argh writes the dept sort of units for spring himself.
He does it very simple, using one point per unit, eg the center of hte model or something. As i get it, this is simple map, and can be done fast, right?
so he does that, and if it does not hurt performance at all, in BA eg, we include it, and possibly make it a mod option.
Then we have no work, Argh has what he wants, and if he falsly thinks it is benefitial, nobody else has to pay for it.
Argh writes the dept sort of units for spring himself.
He does it very simple, using one point per unit, eg the center of hte model or something. As i get it, this is simple map, and can be done fast, right?
so he does that, and if it does not hurt performance at all, in BA eg, we include it, and possibly make it a mod option.
Then we have no work, Argh has what he wants, and if he falsly thinks it is benefitial, nobody else has to pay for it.
Re: Drawing Order
I built the sort in Lua already. It works just fine, and costs practically nothing, even in Lua, and even with a couple of hundred Units on the screen. I run it every SlowUpdate or so, and that's fine.
It doesn't solve my problem, though.
All Units we want to render must go through the UnitRendering pathway, which is locked to UnitID order. Or you can do gl.Unit, but then you don't have a TBN matrix.
This absolutely must get done through the engine, basically.
It doesn't solve my problem, though.
All Units we want to render must go through the UnitRendering pathway, which is locked to UnitID order. Or you can do gl.Unit, but then you don't have a TBN matrix.
This absolutely must get done through the engine, basically.