Page 1 of 2
Stupid Lua Question- GLSL Shader Integration
Posted: 22 Oct 2008, 02:33
by Argh
Um, basically, it's like this. I have experience making shaders from node software, and Mental Mill has made a node-editor available that will output GLSL. I'm building some GLSL shaders that I think might be cool.
Question is: what do I have to do to integrate them with Lua in Spring? I've been looking over the stuff that's available, and I'm still pretty confused about what I need to do- stuff like declaring that the POINT_LIGHT is the Sun, declaring texture values, etc. I get the idea that we have a vertex shader and a fragment shader, etc., I'm just not quite sure how I "hook that up" with the rest of things yet.
Anybody willing to help out? I'm not quite sure where I'm going with this yet- I have stuff that looks cool, but I need to know how to get it integrated with Spring.
Re: Stupid Lua Question- GLSL Shader Integration
Posted: 22 Oct 2008, 08:57
by Argh
Well, thus far, I've gotten a shader made with Mental Mill to compile without errors, and it appears that Uniforms are referring to the locations of the variables to be used at runtime (iow, if you want to swap out textures, you need a uniform for that gl.texture callout, etc.).
Now let's see if I can get it to all work with a gl.Unit call and appropriate settings for the uniforms... code here in a bit, if I can get it running (or get really stuck, thus far this has not been nearly as nasty as I feared, which probably means I'm about to hit a wall, heh)...
Hmm. Got it "working", but the results are bizarre. The unit is drawing via GLSL, but it's like its geometry's inverted...
Re: Stupid Lua Question- GLSL Shader Integration
Posted: 22 Oct 2008, 09:07
by lurker
You need to set the proper depth test, seems to happen a lot to people rendering things from lualand..
Re: Stupid Lua Question- GLSL Shader Integration
Posted: 22 Oct 2008, 09:17
by Argh
KK... LEQUAL?
Yes, LEQUAL.
Meh... so close now. It's drawing right-side-out, at least.
Re: Stupid Lua Question- GLSL Shader Integration
Posted: 23 Oct 2008, 02:14
by Argh
Ok, here's what I've managed to do, thus far:
Code: Select all
function widget:GetInfo()
return {
name = "GLSL Bumpmap",
desc = "The P.U.R.E. GLSL Bumpmap implementation.",
author = "Argh",
date = "October 22, 2008",
license = "(C) Wolfe Games, 2008",
layer = 0,
--handler = true,
enabled = true -- loaded by default?
}
end
local CameraPos
local BumpList = {
[UnitDefNames.engineeringteam.id] = "engineeringteam",
}
function widget:Initialize()
GLSL_BUMP_Shader = gl.CreateShader({
vertex = [[
attribute vec3 tangent;
attribute vec3 binormal;
// inverse light radius ie.. 1.0/light radius;
uniform float u_invRad;
varying vec3 g_lightVec;
varying vec3 g_viewVec;
void main()
{
gl_Position = ftransform();
gl_TexCoord[0] = gl_MultiTexCoord0;
mat3 TBN_Matrix = gl_NormalMatrix * mat3(tangent, binormal, gl_Normal);
vec4 mv_Vertex = gl_ModelViewMatrix * gl_Vertex;
g_viewVec = vec3(-mv_Vertex) * TBN_Matrix;
vec4 light = gl_ModelViewMatrix * gl_LightSource[0].position;
vec3 lightVec = u_invRad * (light.xyz - mv_Vertex.xyz);
g_lightVec = lightVec * TBN_Matrix;
}
]],
fragment = [[
uniform sampler2D Normal;
uniform sampler2D base_tex;
uniform sampler2D Base_Height; // height in alpha ch.
varying vec3 g_lightVec;
varying vec3 g_viewVec;
uniform vec2 cBumpSize;// = 0.02 * vec2 (2.0, -1.0);
void main()
{
float LightAttenuation = clamp(1.0 - dot(g_lightVec, g_lightVec), 0.0, 1.0);
vec3 lightVec = normalize(g_lightVec);
vec3 viewVec = normalize(g_viewVec);
float height = texture2D(Base_Height, gl_TexCoord[0].xy).r;
height = height * cBumpSize.x + cBumpSize.y;
vec2 newUV = gl_TexCoord[0].xy + viewVec.xy * height;
vec4 color_base = texture2D(base_tex,newUV);
vec3 bump = texture2D(Normal, newUV.xy).rgb * 2.0 - 1.0;
bump = normalize(bump);
float base = texture2D(Base_Height, newUV.xy).r;
float diffuse = clamp(dot(lightVec, bump), 0.5, 1.0);
float specular = pow(clamp(dot(reflect(-viewVec, bump), lightVec), 0.0, 1.0), 16.0);
gl_FragColor = color_base * gl_LightSource[0].diffuse
* (diffuse * base + 0.7 * specular)
* LightAttenuation;
gl_FragColor.a = 1.0;
}
]],
uniform = {
u_invRad = 0.000001,
cBumpSize = {0.04200005,-0.04999996},
Normal = 0,
base_tex = 2,
Base_Height = 2,
}
})
if (GLSL_BUMP_Shader == nil) then
Spring.Echo("GLSL Bump Shader Failed"..gl.GetShaderLog())
return false
else
Spring.Echo("GLSL Bump Shader Succeeded")
--CameraPos = gl.GetUniformLocation(GLSL_BUMP_Shader, 'CAMERA_POSITION')
end
end
function widget:DrawWorld()
local myIDList = Spring.GetVisibleUnits(-1,3000,false)
if myIDList[1] ~= nil then
for _,myID in ipairs(myIDList) do
if (Spring.IsUnitVisible(myID)) then
local teamID = Spring.GetUnitTeam(myID)
if (teamID) then
local id = Spring.GetUnitDefID(myID)
if BumpList[id] then
gl.DepthTest(GL.LEQUAL)
--gl.Uniform(CameraPos,Spring.GetCameraPosition())
--gl.DepthTest(true)
gl.Color(1,1,1,1)
gl.UseShader(GLSL_BUMP_Shader)
gl.Texture(2,":c:unittextures/EngineeringTeam_Test.tga")
gl.Texture(0,":c:unittextures/EngineeringTeam_Test_Normal2.tga")
gl.Texture(1,":c:unittextures/EngineeringTeam_Test.tga")
gl.PolygonOffset(-4,-4)
gl.Unit(myID,true)
gl.PolygonOffset(0,0)
gl.ResetState()
end
end
end
end
end
end
It "works", in the sense that something draws, and it seems to react to the position of the lightsource. However, it doesn't seem to be doing the multiplication of the base texture by the specular value anything like correctly. Any ideas what's going wrong?
Re: Stupid Lua Question- GLSL Shader Integration
Posted: 23 Oct 2008, 02:42
by Kloot
Perhaps you should simply not copy-paste shader code from wherever
into your scripts when clearly you do not understand the math behind
it (and hence why it fails)? dot3 bumpmapping (that being the name of
the technique you "implemented" above) operates in tangent-space,
it needs tangents and binormals for the lighting evaluation to make
sense and you can't get those by pressing ctrl+v. Sorry for being blunt,
but don't you think a ***map shader wouldn't already be commonplace
if it was _that_ simple?
Re: Stupid Lua Question- GLSL Shader Integration
Posted: 23 Oct 2008, 03:24
by Peet
But it is trivial

Re: Stupid Lua Question- GLSL Shader Integration
Posted: 23 Oct 2008, 04:53
by Argh
Basically, the problem as Kloot describes it is that I'm getting zeros in the multiplication somewhere. That makes sense.
I've taken a look, and Mental Mill has a shader function called "normalize normals", that looks promising. I'll see if I can plug the product into the bump shader, as it figures out the tangent and binormal...
Re: Stupid Lua Question- GLSL Shader Integration
Posted: 23 Oct 2008, 07:08
by Argh
Slightly closer to functional. The normalmap is reacting to the lightsource. Can't see the diffuse texture at all, though, and the way that it reacts to the angle of the lightsource is clearly screwed up- turn the model one way, and it goes pretty dark, turn it another, like this, and it's nearly fullbright.
Found out that you pretty much need to specify a light... that, and the result of the binormal / tangent matrix may need to be solved for Spring's worldspace coordinates. Dunno how to do that yet, and I'm tempted to just try all of the combos of 0,1,-1 until I get that part right, it'd probably be faster than teaching myself matrix math.
Code: Select all
function widget:GetInfo()
return {
name = "GLSL Bumpmap",
desc = "The P.U.R.E. GLSL Bumpmap implementation.",
author = "Argh",
date = "October 22, 2008",
license = "(C) Wolfe Games, 2008",
layer = 0,
--handler = true,
enabled = true -- loaded by default?
}
end
local CameraPos
local BumpList = {
[UnitDefNames.engineeringteam.id] = "engineeringteam",
}
function widget:Initialize()
GLSL_BUMP_Shader = gl.CreateShader({
vertex = [[
// from main program
//uniform mat4 mvi;
// pass to FragmentProgram
varying vec3 lightVec;
varying vec3 viewVec;
void main()
{
// mvi--major row to major column. Use point light
lightVec = vec3((gl_ModelViewMatrix * gl_LightSource[0].position).xyz - gl_Vertex.xyz);
// TBN Matrix--converting to tangent space
vec3 tangent = vec3(-1.0, 0.0, 0.0);
vec3 binormal = vec3(0.0,-1.0, 0.0);
mat3 TBNMatrix = mat3(tangent, binormal, gl_Normal);
// Convert lightVec to tangent space.
lightVec = normalize(lightVec * TBNMatrix);
// get viewVec
viewVec = normalize(-gl_Vertex.xyz);
// OpenGL glsl stuff
gl_TexCoord[0] = gl_MultiTexCoord0;
gl_Position = ftransform();
}
]],
fragment = [[
// from main program
uniform sampler2D ColorMap;
uniform sampler2D NormalMap;
// from VertexProgram
varying vec3 lightVec;
varying vec3 viewVec;
void main()
{
// Get color from color map
vec3 color = texture2D(ColorMap, gl_TexCoord[0].st).xyz;
// get normals from normal map
vec3 normals = texture2D(NormalMap, gl_TexCoord[0].st).xyz;
// fix normals
normals = normalize((normals - 0.5) * 2.0);
// get reflect vector
vec3 reflectVec = reflect(-lightVec, normals);
// get diffuse
float diffuse = max(dot(lightVec, normals), 0.0);
float spec = 0.0;
// spec only on lit parts
if (diffuse > 0.0)
{
// get spec
float spec = max(dot(reflectVec, viewVec), 0.0);
// spec highlights size
spec = pow(spec, 10.0);
}
// set diffuse and spec strength
float diffuseStrength = 0.9;
float specStrength = 0.2;
// get light intensity
float intensity = diffuseStrength * diffuse + specStrength * spec;
// set color intensity and add ambient light of 0.2
vec4 texture = vec4 ((color * intensity) + (color * 1.0), 1.0);
// Use it
gl_FragColor = texture;
}
]],
uniform = {
ColorMap = 1,
NormalMap = 0,
--mvi={},
--CAMERA_POSITION = {100,0,0},
}
})
if (GLSL_BUMP_Shader == nil) then
Spring.Echo("GLSL Bump Shader Failed"..gl.GetShaderLog())
return false
else
Spring.Echo("GLSL Bump Shader Succeeded")
--MultMatrix = gl.GetUniformLocation(GLSL_BUMP_Shader, 'mvi')
end
end
function widget:DrawWorld()
local myIDList = Spring.GetVisibleUnits(-1,3000,false)
if myIDList[1] ~= nil then
for _,myID in ipairs(myIDList) do
if (Spring.IsUnitVisible(myID)) then
local teamID = Spring.GetUnitTeam(myID)
if (teamID) then
local id = Spring.GetUnitDefID(myID)
if BumpList[id] then
gl.DepthTest(GL.LEQUAL)
gl.Lighting(true)
gl.Light(0,GL.POSITION,1000,1000,0)
--gl.Uniform(MultMatrix,gl.UnitMultMatrix(myID))
--gl.DepthTest(true)
gl.Color(1,1,1,1)
gl.UseShader(GLSL_BUMP_Shader)
gl.Texture(2,":c:unittextures/EngineeringTeam_Test.tga")
gl.Texture(0,":c:unittextures/EngineeringTeam_Test_Normal2.tga")
gl.Texture(1,":c:unittextures/EngineeringTeam_Test.tga")
gl.PolygonOffset(-4,-4)
gl.Unit(myID,true,0)
gl.PolygonOffset(0,0)
gl.ResetState()
gl.Lighting(false)
end
end
end
end
end
end
Re: Stupid Lua Question- GLSL Shader Integration
Posted: 23 Oct 2008, 08:05
by Argh
Ok, unless my eyes are lying to me, I'm pretty close now. See the highlights?
Problems remaining:
1. I can't seem to get the damn diffuse map to blend with the highlight stage. I'm sure that's really basic stuff, anybody want to take a look at what might be wrong?
2. The light doesn't seem to work right. It's like the object is getting some bizarro inverted values for the light's position. It's at 0,100000,0- it's directly overhead, basically, these screens are all at the upper-left of the map. Must be a screwup in the vertex portion of the shader.
Code: Select all
function widget:GetInfo()
return {
name = "GLSL Bumpmap",
desc = "The P.U.R.E. GLSL Bumpmap implementation.",
author = "Argh",
date = "October 22, 2008",
license = "(C) Wolfe Games, 2008",
layer = 0,
--handler = true,
enabled = true -- loaded by default?
}
end
local CameraPos
local BumpList = {
[UnitDefNames.engineeringteam.id] = "engineeringteam",
}
function widget:Initialize()
GLSL_BUMP_Shader = gl.CreateShader({
vertex = [[
// from main program
//uniform mat4 mvi;
// pass to FragmentProgram
varying vec3 lightVec;
varying vec3 viewVec;
void main()
{
// mvi--major row to major column. Use point light
lightVec = vec3((gl_ModelViewMatrix * gl_LightSource[0].position).xyz - gl_Vertex.xyz);
// TBN Matrix--converting to tangent space
vec3 tangent = vec3(-1.0, 0.0, 0.0);
vec3 binormal = vec3(0.0,-1.0, 0.0);
mat3 TBNMatrix = mat3(tangent, binormal, gl_Normal);
// Convert lightVec to tangent space.
lightVec = normalize(lightVec * TBNMatrix);
// get viewVec
viewVec = normalize(gl_Vertex.xyz);
// OpenGL glsl stuff
gl_TexCoord[0] = gl_MultiTexCoord0;
gl_Position = ftransform();
}
]],
fragment = [[
// from main program
uniform sampler2D ColorMap;
uniform sampler2D NormalMap;
// from VertexProgram
varying vec3 lightVec;
varying vec3 viewVec;
void main()
{
// Get color from color map
vec3 color = texture2D(ColorMap, gl_TexCoord[0].st).xyz;
// get normals from normal map
vec3 normals = texture2D(NormalMap, gl_TexCoord[0].st).xyz;
// fix normals
normals = normalize((normals - 0.5) * 2.0);
// get reflect vector
vec3 reflectVec = reflect(-lightVec, normals);
// get diffuse
float diffuse = max(dot(lightVec, normals), 0.0);
float spec = 0.0;
// spec only on lit parts
if (diffuse > 0.0)
{
// get spec
float spec = max(dot(reflectVec, viewVec), 0.0);
// spec highlights size
spec = pow(spec, 1.0);
}
// set diffuse and spec strength
float diffuseStrength = 0.9;
float specStrength = 0.9;
// get light intensity
float intensity = diffuseStrength * diffuse + specStrength * spec;
// set color intensity and add ambient light of 0.2
vec4 texture = vec4 ((color * intensity) + (color * 0.2), 1.0);
// Use it
gl_FragColor = texture;
}
]],
uniform = {
ColorMap = 1,
NormalMap = 0,
--mvi={},
--CAMERA_POSITION = {100,0,0},
}
})
if (GLSL_BUMP_Shader == nil) then
Spring.Echo("GLSL Bump Shader Failed"..gl.GetShaderLog())
return false
else
Spring.Echo("GLSL Bump Shader Succeeded")
--MultMatrix = gl.GetUniformLocation(GLSL_BUMP_Shader, 'mvi')
end
end
function widget:DrawWorld()
local myIDList = Spring.GetVisibleUnits(-1,3000,false)
if myIDList[1] ~= nil then
for _,myID in ipairs(myIDList) do
if (Spring.IsUnitVisible(myID)) then
local teamID = Spring.GetUnitTeam(myID)
if (teamID) then
local id = Spring.GetUnitDefID(myID)
if BumpList[id] then
gl.DepthTest(true)
gl.Lighting(true)
gl.Light(0,GL.POSITION,0,1000000,0)
--gl.Uniform(MultMatrix,gl.UnitMultMatrix(myID))
--gl.DepthTest(true)
gl.Color(1,1,1,1)
gl.UseShader(GLSL_BUMP_Shader)
--gl.Texture(2,":c:unittextures/EngineeringTeam_Test.tga")
gl.Texture(0,":c:unittextures/EngineeringTeam_Test_Normal2.tga")
gl.Texture(1,":c:unittextures/EngineeringTeam_Test.tga")
gl.PolygonOffset(-4,-4)
gl.Unit(myID,true,0)
gl.PolygonOffset(0,0)
gl.ResetState()
gl.Lighting(false)
end
end
end
end
end
end
Re: Stupid Lua Question- GLSL Shader Integration
Posted: 23 Oct 2008, 20:26
by MelTraX
Didn't trepan have a bumpmap already? I'm pretty sure he did.
Re: Stupid Lua Question- GLSL Shader Integration
Posted: 23 Oct 2008, 20:33
by trepan
bumpmapping -- too easy, too 90's, no fun
relief mapping, had a picture lying around here somewhere...
Re: Stupid Lua Question- GLSL Shader Integration
Posted: 23 Oct 2008, 22:30
by Argh
I'm pretty sure that solving this makes relief mapping an easy proposition. Anybody have a comment on the obvious issues, or am I still going to just solve this entirely by myself? The light-angle issue, especially, is troubling me- I'm pretty sure that the light angle needs to be corrected somehow every pass, and I'm not sure how yet.
Re: Stupid Lua Question- GLSL Shader Integration
Posted: 23 Oct 2008, 23:34
by Argh
Ok, I have a clue what's wrong. The gl_ModelViewMatrix is returning incorrect results when the object is > some heading value. It's definitely heading- the results are "correct" based on pitch. So, if > blah, reverse, blah.
<codes>
Put that into place- still doesn't correct the main problem, but it gave me a clue about what's going on.
After doing a couple more experiments, it appears that this is a problem with the gl_ModelViewMatrix. I can get the object to change shading aspects by going to free cam and rotating the camera. So, obviously I need to use a different matrix.
Re: Stupid Lua Question- GLSL Shader Integration
Posted: 24 Oct 2008, 00:01
by Argh

The lighting angle is fixed
Remaining bugs:
1. There's a lot of obvious clipping going on- z-order issues or something, where it draws faces that should be hidden. How do I cull them?
2. The multiplication stage is, obviously, not working worth a damn yet. That whole formula needs to get reworked, obviously. Anybody have a clue as to where I need to go with that?
Re: Stupid Lua Question- GLSL Shader Integration
Posted: 24 Oct 2008, 09:58
by Argh

It's working. Sorry, the effect's still pretty subtle, I haven't had time to look at tweaking it yet.
It turned out, after hours of stupid tests... that having the section labeled "uniform" instead of "uniformInt" was what was wrong
Yay, science.
Now... this won't be really cool until I can combine it with a cubemap for reflectivity, and get glow working- glow should be pretty easy, but I have no idea how I'm going to combine a cubemap with the normalmap to get a combined specular value.
Oh... and does anybody have any coherent advice about how to get rid of the clipping issues?
Re: Stupid Lua Question- GLSL Shader Integration
Posted: 24 Oct 2008, 10:20
by lurker
Where is it clipping? Pix?
Re: Stupid Lua Question- GLSL Shader Integration
Posted: 24 Oct 2008, 10:24
by Argh
Hold on, I'll get one. Sorry, beauty-shot instincts... lemme show the ugly.
Re: Stupid Lua Question- GLSL Shader Integration
Posted: 24 Oct 2008, 10:28
by Argh

See it, on the left side?
Maybe it's just the base Unit drawing through... lemme tell Lua to just draw the Unit image derived from the shader.
I also want to note, for the record, that I don't have the plug-in values for the light, etc., set up yet, but that's all trivial now that it works.
Re: Stupid Lua Question- GLSL Shader Integration
Posted: 24 Oct 2008, 11:54
by Chosker
uhm the effect seems subtle because to me the normalmap seems subtle, lots of straight angles in there. normalmapping makes the effect better with more curves and relief (seems to me it's a heightmap converted into a normalmap, while normalmaps always give a bigger/better effect when they come from a baked hi-poly model)
also, I'm not seeing any clipping
also about the cubemap, to me it sounds like not the best style if you just cover it all with reflection uniformly. metal is most of the time too opaque to even see any reflections, while using a specular map for regular specularity (which I haven't seen on Spring either) gets the job done quite properly.
but if you still want to use reflections my advice would be to use a specular map to determine the amount values of the reflection. I did it for a different project and I could have a sword blade reflecting and the hilt opaque, and using the same specular map for regular specular shinyness, it gave a great effect of the sword actually be built from different materials. I think the same thing applies for tanks, even if they're mostly steel it's not all the same color/material
when you're finished I'm hoping you can release the full implementation/mod. I have some experience with shaders (DX9, but seems the differences are small) so if you keep your style maybe I could modify it for a more subtle style, maybe add specular highlights, a specular map and maybe fresnel shinyness too
anyway great work, really looking forward to this