Simple Real-Time lighting (example code) - Page 2

Simple Real-Time lighting (example code)

Discuss Lua based Spring scripts (LuaUI widgets, mission scripts, gaia scripts, mod-rules scripts, scripted keybindings, etc...)

Moderator: Moderators

dizekat
Posts: 437
Joined: 07 Dec 2007, 12:10

Re: Simple Real-Time lighting (example code)

Post by dizekat »

Argh wrote:1. It's not a directional light, it's a point light, with the position treated as the vector for the resulting rays, per vertex.
Yet this shader code is made for directional lights only. It does not compute difference between light position and vertex position (with correctly applied transformations), which it would have to, if it was to actually do point lights.
2. Yes, it handles exactly one light at present, but I'm still deciding how to go about additive stuff efficiently. I don't suppose you have a magic solution for that?
Actually you're already rendering every unit multiple times for each light, no? You can set up blending and have it add up, however that'll really sux performance-wise.

Alternatively you can learn some opengl and see that the default "shader" supplied by opengl implementation does almost same thing as this copypasted shader. Or you can learn some glsl, some mathematics, and actually write a shader.
A shader is a sort of program code. It is tad more complex than a texture image that you can grab somewhere and use.

3. The GLSL shader is based on the basic vertex shader from Typhoon Labs' GLSL course, Chapter 3, and is pretty much used verbatim, except for one little thing which I did that you can figure out yourselves by comparing sources- it's not like it's a lot of code or anything ;)
In further contributions, I'd recommend commenting where the code was taken from. I'll be both easier for you later on (suppose you forget exact URL), and clearer for others. Copy-paste programming fails.
User avatar
Argh
Posts: 10920
Joined: 21 Feb 2005, 03:38

Re: Simple Real-Time lighting (example code)

Post by Argh »

:roll: Somebody needs to get off his lazy ass and actually test this, before offering further "advice".
User avatar
Zpock
Posts: 1218
Joined: 16 Sep 2004, 23:20

Re: Simple Real-Time lighting (example code)

Post by Zpock »

Yes your code is really really far from perfect argh, so really sticks in the eyes of someone who would know how to do it right (but won't ever actually do it), but still it's put into practice in spring in an actual game which is where it's at, good job.
User avatar
Argh
Posts: 10920
Joined: 21 Feb 2005, 03:38

Re: Simple Real-Time lighting (example code)

Post by Argh »

Meh. If people want to fix it, make it more elegant without greatly increasing load, etc., they're more than welcome to do so.

I just can't be arsed to take people seriously when they just have negative attitudes about stuff, and give me problems, not solutions.

I could give a flying fuck about whether I'm "smart enough" or "know enough"- if it's not getting done by anybody more competent, and it must get done... then I guess I am, by default. Dirty jobs, and all that.

Lastly, none of this involves fundamentally new math or even really new algorithms. Even at the fancy end, we're talking about well-known fundamental lighting equations- Phong, Blinn-Phong, etc., so I don't want to hear any more silly bullshit about whether I'm supposed to have a small e-peen because what I'm doing isn't novel. It's not novel, people. None of you geniuses invented those equations, either, and we're all standing on the shoulders of giants here. Get over it.

This is all stuff from the 1970s-80s, re-written for a new generation of rendering hardware, and that's all. The fact that I don't understand it all doesn't really bother me a lot, considering that this isn't exactly my cup o' tea and I've been learning this from scratch for less than a month.
User avatar
Zpock
Posts: 1218
Joined: 16 Sep 2004, 23:20

Re: Simple Real-Time lighting (example code)

Post by Zpock »

I think ppl aren't that eager to jump in spend a few hours doing a ton of math/programming to "fix it" for something like:


'Breaking NEWS: Impressive cool lighting shader by Argh (fixd by xxx).'


So you might have to listen to these suggestions and do it yourself, but as long as it looks sort of cool and doesn't kill performance, it's better then nothing as is so you could just ignore them if you feel like it.
dizekat
Posts: 437
Joined: 07 Dec 2007, 12:10

Re: Simple Real-Time lighting (example code)

Post by dizekat »

argh:
Yes, even worse, if I see someone claiming that 2*2=5, I'm too lazy to check on the calculator.

lol, new post:
Why the hell anyway are you posting experimental and copypasted code(when you don't know what code does) on forum here, if not to get told what the code actually does, and what is problems with it?

Its not that its not novel, its that it is just, wrong. I'd even say, btw, that lighting equation required is not stuff from 1970-80s, more like from 18th or 19th century, and even largely from ancient Greeks.

Few things at first glance:
1: its directional light, not point light.
2: direction is set as gl.Light(0,GL.POSITION,-x,y,z) . Makes no sense. Light just gonna have different direction depending to unit's place on the map (but not in the way how point light would).
3: light position needs 4 parameters, x y z w , (generally w=0 for directions w=1 for positions), here opengl using whatever value happens to be at memory location after z, in the lua opengl wrapper code.
4: for each unit, its checking all lights against it, to find light with equal ID (rather than using ID --> light table). Quite slow.
[probably missed some other things]
5: could just use "no shader", set up lights, and behind the scenes, opengl implementation makes correct shader for you, which really makes more sense than copy-pasting a shader from tutorial.

Of course, you can dismiss all that, whatever.
User avatar
Argh
Posts: 10920
Joined: 21 Feb 2005, 03:38

Re: Simple Real-Time lighting (example code)

Post by Argh »

1. I am aware that the matrix doesn't always come out entirely correctly, but if you'd paid a little more attention, you'd notice that I'm not using worldspace coordinates, but piecespace coordinates.

Given that all land Units are in positive worldspace at all times, this works out pretty well with a -x, under most conditions. The only exception is a fairly narrow range of angles near "true north", where I get reversed results, and no, I have no idea why. That's probably curable with a simple hack-around, but it's already working well enough that most players won't notice anyhow, so long as it's not mounted on an aircraft (tried that, and it's an absolute disaster).

2. Setting a light position with a 4th parameter, either 0 or 1, resulted in very strange matrix results, even after correcting the Piece position back to worldspace and of course putting that offensive -x back to x ;)

I'll look into that later, because I assume that's important- it's probably the key to getting it to work perfectly all the time, frankly, but I dunno yet.

3. Meh, I suppose I could use the unitID as the key value, to shorten the search. Truthfully, that's not that big of a deal most of the time right now, because the LightList is so small, because they're all transient events, but yes, that could be improved. Finally, something I vaguely agree with.

4. I have no idea what you're talking about yet, but it sounds very CPU-side, which is bad- the whole idea here is to offload as much as possible to the GPU, or I might as well just do it in plain OpenGL. Pre-compiled shaders are definitely the way to go here, unless somebody has something more substantial to cite than mere enthusiasm- I'm very dubious about the cost savings implied.
User avatar
lurker
Posts: 3842
Joined: 08 Jan 2007, 06:13

Re: Simple Real-Time lighting (example code)

Post by lurker »

Plain OpenGL?
User avatar
Argh
Posts: 10920
Joined: 21 Feb 2005, 03:38

Re: Simple Real-Time lighting (example code)

Post by Argh »

Hmm. Sat down with Typhoon Labs GLSL course again. Implemented the point-light algorithm, this time correctly, at least in theory:

Code: Select all

GLSL_LIGHT_Shader = gl.CreateShader({
    vertex = [[
varying vec4 diffuse;
void main()
{
	gl_Position = ftransform();
	vec3 normal = gl_Normal;
	vec3 lightVector = gl_LightSource[1].position - gl_Vertex.xyz;
	float dist = length(lightVector);
	float attenuation = 1.0 / (gl_LightSource[1].constantAttenuation +
			gl_LightSource[1].linearAttenuation * dist +
			gl_LightSource[1].quadraticAttenuation * dist * dist);
	lightVector = normalize(lightVector);
	float nxDir = max(0.0, dot(normal, lightVector));
	diffuse = gl_FrontMaterial.diffuse * nxDir * attenuation;
}

]],
   fragment = [[
	varying vec4 diffuse;
	void main()
	{
		gl_FragColor = (gl_LightSource[1].ambient + diffuse);
	}
    ]],
})
It "works", but something is wrong with the vec3 that's returned in lightVector. I've tried various hacks- it's pretty clear that that's where stuff is breaking. Yet I'm absolutely sure that the light's in worldspace coordinates, that it's correct, etc., so it's not something wrong with the light itself, and it's set up as a point source for certain, now that I've looked at that. And the attenuation, etc., is all working, too, so it's really not any of that stuff, it's something very basically wrong with lightVector.

jK, I saw that line in your GLSL version, where you're computing gl_Position differently than the Fourier transform I see in most example code... is that just to get the position corrected for the reflections, or does it fix the problems I'm seeing with the matrix result? If so, what Lua can I use to get and deliver that mat4?
dizekat
Posts: 437
Joined: 07 Dec 2007, 12:10

Re: Simple Real-Time lighting (example code)

Post by dizekat »

regarding 'plain opengl': driver has shader that does lighting as per opengl specification (or actually several shaders, used depending to what do you use). When you dont specify other shader, this shader is used. On hardware, it works pretty much same as your shader would, except, being provided by graphics card manufacturer rather than copypasted out of tutorial, it could likely be more efficient.
It is practically guaranteed to run on GPU, unlike custom vertex shader, which might be using functionality not really supported by that specific GPU, and consequently be run in software, on CPU.
Argh wrote:Hmm. Sat down with Typhoon Labs GLSL course again. Implemented the point-light algorithm, this time correctly, at least in theory:

Code: Select all

GLSL_LIGHT_Shader = gl.CreateShader({
    vertex = [[
varying vec4 diffuse;
void main()
{
	gl_Position = ftransform();
	vec3 normal = gl_Normal;
	vec3 lightVector = gl_LightSource[1].position - gl_Vertex.xyz;
	float dist = length(lightVector);
	float attenuation = 1.0 / (gl_LightSource[1].constantAttenuation +
			gl_LightSource[1].linearAttenuation * dist +
			gl_LightSource[1].quadraticAttenuation * dist * dist);
	lightVector = normalize(lightVector);
	float nxDir = max(0.0, dot(normal, lightVector));
	diffuse = gl_FrontMaterial.diffuse * nxDir * attenuation;
}

]],
   fragment = [[
	varying vec4 diffuse;
	void main()
	{
		gl_FragColor = (gl_LightSource[1].ambient + diffuse);
	}
    ]],
})
Copypasted code seems correct, yes.
edit: no, it isn't, unless you're actually setting second light (that has number 1). Its GLSL, the lights numbering starts from 0 .
Also, you need to provide attenuation parameters, obviously.
It "works", but something is wrong with the vec3 that's returned in lightVector.
its depending on what you provide with
gl.Light(0,GL.POSITION,-x,y,z)

You really should try to actually learn some stuff, then you could write the lua code providing the parameters to shader correctly, on first try, rather than fiddling with things until you get something that sorta works, in one specific rare case on one computer.
jK, I saw that line in your GLSL version, where you're computing gl_Position differently than the Fourier transform I see in most example code... is that just to get the position corrected for the reflections, or does it fix the problems I'm seeing with the matrix result? If so, what Lua can I use to get and deliver that mat4?
fourier transform? LMAO.
User avatar
jK
Spring Developer
Posts: 2299
Joined: 28 Jun 2007, 07:30

Re: Simple Real-Time lighting (example code)

Post by jK »

Info:
gl_LightSource[].position is auto multiplied with gl_ModelViewMatrix (performance reasons), so glVertex and glLight(GL_POSITION) have to be in the same space (if you use gl.Unit() they won't).

and dizekat means:
Modern GPUs don't have anymore a Fixed Function Pipeline (FFP), instead they totaly emulate the old native opengl functions (lighting, multitexture, fog, ...) with shaders, which are dynamically compiled and adjusted on runtime. So he just means that you should use native OpenGL for such thingies.
Not that it would be faster or something, it wouldn't even easier imo. But you should just start to write the shaders yourself, so you understand what they are doing and you should start to read the tutorials and not just the pseudo code on page 1 and then copy/paste the final shader.

Hint:
ftransform() := fixed (functionality) transform

PS:
Spring gives you already a feature to render units, without all that lua overhead. You just have to check the wiki + changelog. I can even give you an WIP example code for it (the api isn't obvious).
dizekat
Posts: 437
Joined: 07 Dec 2007, 12:10

Re: Simple Real-Time lighting (example code)

Post by dizekat »

jK: well, Argh's just making first baby steps with OpenGL, right? The problem he's getting is that he can't position a light. Which isn't much shader related per se.
Info:
gl_LightSource[].position is auto multiplied with gl_ModelViewMatrix (performance reasons), so glVertex and glLight(GL_POSITION) have to be in the same space (if you use gl.Unit() they won't).
Or shader could use gl_ModelViewMatrix*gl_Vertex instead of gl_Vertex when computing distance, then both are same space (eye space, before projection) regardless of which transforms are applied in gl.Unit .
User avatar
jK
Spring Developer
Posts: 2299
Joined: 28 Jun 2007, 07:30

Re: Simple Real-Time lighting (example code)

Post by jK »

dizekat wrote:jK: well, Argh's just making first baby steps with OpenGL, right? The problem he's getting is that he can't position a light. Which isn't much shader related per se.
It is a opengl+math issue:
1. u need to know gl_LightSource[].position isn't the input of glLight(GL_POSITION) (man page og glLight tells ya)
2. you need to know what gl_ModelViewMatrix is and how to work with it
3. you need to be able to differ between directional and point lights
dizekat wrote:
Info:
gl_LightSource[].position is auto multiplied with gl_ModelViewMatrix (performance reasons), so glVertex and glLight(GL_POSITION) have to be in the same space (if you use gl.Unit() they won't).
Or shader could use gl_ModelViewMatrix*gl_Vertex instead of gl_Vertex when computing distance, then both are same space (eye space, before projection) regardless of which transforms are applied in gl.Unit
Yup. (btw the light position is transformed by the modelview matrix when glLight is called and not at shader runtime, so gl_LightSource[].position can be in a different space than gl_ModelViewMatrix*gl_Vertex)
dizekat
Posts: 437
Joined: 07 Dec 2007, 12:10

Re: Simple Real-Time lighting (example code)

Post by dizekat »

jK wrote:
dizekat wrote:jK: well, Argh's just making first baby steps with OpenGL, right? The problem he's getting is that he can't position a light. Which isn't much shader related per se.
It is a opengl+math issue:
1. u need to know gl_LightSource[].position isn't the input of glLight(GL_POSITION) (man page og glLight tells ya)
2. you need to know what gl_ModelViewMatrix is and how to work with it
3. you need to be able to differ between directional and point lights
dizekat wrote:
Info:
gl_LightSource[].position is auto multiplied with gl_ModelViewMatrix (performance reasons), so glVertex and glLight(GL_POSITION) have to be in the same space (if you use gl.Unit() they won't).
Or shader could use gl_ModelViewMatrix*gl_Vertex instead of gl_Vertex when computing distance, then both are same space (eye space, before projection) regardless of which transforms are applied in gl.Unit
Yup. (btw the light position is transformed by the modelview matrix when glLight is called and not at shader runtime, so gl_LightSource[].position can be in a different space than gl_ModelViewMatrix*gl_Vertex)
I'm not sure what you mean by different space here.

The reason why gl_LightSource[].position is transformed the way it is transformed is so that this kind of sequence of calls:

glMatrixMode(GL_MODELVIEW)
glLoadMatrix(camera's view matrix);
DrawSphereAt(x,y,z);// display sphere as marker where light source is
glLight(0,GL_POSITION,x,y,z,1);
glPushMatrix();
glMulMatrix(tank's body matrix)
render tank body
glPushMatrix();
glMulMatrix(tank's turret matrix)
render tank turret
glPopMatrix();
glPopMatrix();

works the obvious, sensible way, with light lighting the tank body and tank turret as if it was inside the marker sphere that got drawn earlier. You can also position both light and sphere together with glTranslate();
User avatar
Argh
Posts: 10920
Joined: 21 Feb 2005, 03:38

Re: Simple Real-Time lighting (example code)

Post by Argh »

Here, try this:

Code: Select all

function widget:GetInfo()
  return {
    name      = "Lighting Test",
    desc      = "Test of point lights.",
    author    = "Argh",
    date      = "November 6, 2008",
    license   = "Public Domain, or the least-restrictive rights in your country of residence",
    layer     = 0,
    --handler   = true,
    enabled  = true -- loaded by default?
  }
end

function widget:DrawWorld()
	local myIDList = Spring.GetVisibleUnits(-1,3000,false)
		if myIDList[1] ~= nil then
			for _,myID in ipairs(myIDList) do
					gl.DepthTest(GL.LEQUAL)
					gl.Culling(GL.BACK)
					--gl.Blending(true)
					gl.Lighting(true)
					local x,y,z = 100, -1000, -100
					gl.Light(0,GL.POSITION,x,y,z,1)
					gl.Color(1, 0, 0, 1.0)
					gl.PolygonOffset(-2,-2)
					gl.Unit(myID,true)
							
					gl.Light(0,false)
					gl.PolygonOffset(0,0)
					gl.ResetState()
					gl.Lighting(false)
		end
	end	
end
Try changing the positions of x,y,z and see for yourselves. It just uses the sun light, and refuses to use anything else. This doesn't happen if I construct a cube, so it's obviously something wrong with the way that gl.Unit works- it shouldn't be overriding that light, but it does.

So, there isn't any fast way to go about this, except for using shaders. Shaders seem (operative word- "seem") like they are doing everything after piece-space / unit-space / world-space transformations and rotations. My only issue is getting the darn vectors for the light source in the shader to make any sense.

In addition, this:

vec3 (gl_LightSource[].position - (gl_Vertex * gl_ModelViewMatrix).xyz)

Does not result in the correct vector for point lights. In fact, it seems to act like a constant vector at that point- I get a light that "works", but has nothing to do with the Piece position fed into x,y,z- no matter where I rotate that Piece, the vector returned is the same. So the object's always lit from the "right" or the "left", and that seems to be "correct", but it's obviously not.
User avatar
Argh
Posts: 10920
Joined: 21 Feb 2005, 03:38

Re: Simple Real-Time lighting (example code)

Post by Argh »

gl_LightSource[].position is auto multiplied with gl_ModelViewMatrix (performance reasons), so glVertex and glLight(GL_POSITION) have to be in the same space (if you use gl.Unit() they won't)
Ok, so you're saying that gl_LightSource[].position = vec3 (glLight(GL_POSITION) * gl_ModelViewMatrix).xyz? Or am I doing that wrong?

For a point light, though, we want an absolute position in worldspace vs. absolute vertex positions in worldspace, or a relative position in modelspace and vertex positions in modelspace, right?

If gl.Light is being transformed by ModelViewMatrix when it's created, then I was on the right track, using Spring.GetUnitPiecePosition, since that returns the relative piece positions, but I probably need to multiply it by what- the unit-space matrix?
dizekat
Posts: 437
Joined: 07 Dec 2007, 12:10

Re: Simple Real-Time lighting (example code)

Post by dizekat »

1: "Try changing the positions of x,y,z and see for yourselves. It just uses the sun light, and refuses to use anything else."
first thing to consider, your DrawWorld is not *replacing* Spring's unit drawing. Its called *after* Spring's unit drawing(or even before?!), so if you fail to draw (which is probably what's happening considering that you dont set up any other light parameters besides position), of course you see what spring draws by itself.
2:
vec3 (gl_LightSource[].position - (gl_Vertex * gl_ModelViewMatrix).xyz)
use
gl_ModelViewMatrix * gl_Vertex
Matrix multiplication is generally non-commutative.
(also, again, either learn some stuff, or you gotta have to copy what you're told *exactly*, not even switching order)
BTW, should be gl_LightSource[].position.xyz methink.
User avatar
Argh
Posts: 10920
Joined: 21 Feb 2005, 03:38

Re: Simple Real-Time lighting (example code)

Post by Argh »

"Try changing the positions of x,y,z and see for yourselves. It just uses the sun light, and refuses to use anything else."
first thing to consider, your DrawWorld is not *replacing* Spring's unit drawing. Its called *after* Spring's unit drawing, so if you fail to draw, of course you see what spring draws by itself.
It draws, just not as expected ;) Try it, it's something you can stick into any mod real quick.

Substituting:
vec3 lightVector = gl_LightSource[1].position.xyz - gl_ModelViewMatrix * gl_Vertex;

For the way I wrote it... does compile, but exhibits the same behaviors- lightVector seems to be getting returned as a constant, and does not vary with the position of the light source. Period.

I mean, hell, at least with my earlier hack, which you've spent so much time saying is horrible and wrong, 90% of the time it works acceptably, and the 10% it doesn't isn't that obvious. This doesn't work, period.
User avatar
jK
Spring Developer
Posts: 2299
Joined: 28 Jun 2007, 07:30

Re: Simple Real-Time lighting (example code)

Post by jK »

begin to think ...
Argh wrote:gl.Light(0,GL.POSITION,x,y,z,1)
Argh wrote:vec3 lightVector = gl_LightSource[1].position.xyz - gl_ModelViewMatrix * gl_Vertex;
So what's wrong here?

PS: Don't kill the messenger.
Andrej
Posts: 176
Joined: 13 Aug 2006, 18:55

Re: Simple Real-Time lighting (example code)

Post by Andrej »

this thread made me want to try
and fail at making shaders too

so far i have
http://img152.imageshack.us/my.php?imag ... 340lk3.jpg
one quad with light circling above

can someone download this & do a quick check
if the shader code is correct?
http://www.darkstars.co.uk/downloads/vi ... tarzip.zip
Post Reply

Return to “Lua Scripts”