[MERGED] Grass Layer Lightning + PATCH

captnoord

27-06-2008 19:23:49

Hey guys.. we were using paged geometry for a while and I thought it was time to do something back.
We use paged geometry in combination with caelum and the fact is... it works great. There is only 1 problem the grass does not light with the ambient. So that frustrated me for a while. While I was studying for exams ( and needed a break ) I began messing with the grass layer stuff.
And finally came with this, I know its not perfect and I will spent more time on it to make it perfect. But now the grass is dark when its night.
night

Day

afternoon


DIFF: Patch file

Thanks for be able to use Paged geometry... :D

Jules Robichaud Gagnon

27-06-2008 21:40:53

Oh noes, broken links. :(

captnoord

28-06-2008 01:08:00

the links should work also the images should work....

JohnJ

28-06-2008 02:31:58

Thanks, I'm sure this is very useful for dynamically lit worlds :)

syedhs

28-06-2008 03:04:41

Hmm what is the difference with colour map (aka lightmap) already supported in PagedGeometry?

JohnJ

28-06-2008 03:51:56

I assume this dynamically scales the color of all the grass globally, without requiring you to update a colormap (which is not trivial to update in real-time since all grass batches would need to be regenerated).

captnoord

28-06-2008 13:54:07

yup

Jules Robichaud Gagnon

29-06-2008 18:34:33

By the time I checked the images it was a broken link. I am glad it got fixed on it's own. :)

Arc

25-07-2008 12:27:45

First of all, thank you for the patch. We were missing similar functionality. I notice that this patch has not made into the latest svn revision, for some reason. Here's, however, a bit more polished (and simplest possible diff) version of, essentially, the same thing (corrected 'lightning' to 'lighting', for instance).


Index: GrassLoader.h
===================================================================
--- GrassLoader.h (revision 2478)
+++ GrassLoader.h (working copy)
@@ -434,6 +434,10 @@
*/
void setAnimationEnabled(bool enabled);

+ /** \brief Enables/disables lighting on this layer
+ */
+ void setLightingEnabled(bool enabled);
+
/** \brief Sets how far grass should sway back and forth

\note Since this is measured in world units, you may have to adjust this depending on
@@ -501,7 +505,7 @@
MapFilter colorMapFilter;

//Grass shader properties
- bool animate, blend, shaderNeedsUpdate;
+ bool animate, blend, lighting, shaderNeedsUpdate;
float animMag, animSpeed, animFreq;

//Current frame of animation for this layer



Index: GrassLoader.cpp
===================================================================
--- GrassLoader.cpp (revision 2478)
+++ GrassLoader.cpp (working copy)
@@ -667,6 +667,7 @@
waveCount = 0.0f;
animate = false;
blend = false;
+ lighting = false;
shaderNeedsUpdate = true;

densityMap = NULL;
@@ -733,6 +734,11 @@
}
}

+void GrassLayer::setLightingEnabled(bool enabled)
+{
+ lighting = enabled;
+}
+
void GrassLayer::setDensityMap(const String &mapFile, MapChannel channel)
{
if (densityMap){
@@ -970,6 +976,8 @@
tmpName << "anim_";
if (blend)
tmpName << "blend_";
+ if (lighting)
+ tmpName << "lighting_";
tmpName << renderTechnique << "_";
tmpName << fadeTechnique << "_";
if (fadeTechnique == FADETECH_GROW || fadeTechnique == FADETECH_ALPHAGROW)
@@ -1005,6 +1013,11 @@
" out float4 oColor : COLOR, \n"
" out float2 oUV : TEXCOORD0, \n";

+ if (lighting) vertexProgSource +=
+ " uniform float4 objSpaceLight, \n"
+ " uniform float4 lightDiffuse, \n"
+ " uniform float4 lightAmbient, \n";
+
if (animate) vertexProgSource +=
" uniform float time, \n"
" uniform float frequency, \n"
@@ -1013,7 +1026,7 @@
if (fadeTechnique == FADETECH_GROW || fadeTechnique == FADETECH_ALPHAGROW) vertexProgSource +=
" uniform float grassHeight, \n";

- if (renderTechnique == GRASSTECH_SPRITE) vertexProgSource +=
+ if (renderTechnique == GRASSTECH_SPRITE || lighting) vertexProgSource +=
" float4 iNormal : NORMAL, \n";

vertexProgSource +=
@@ -1025,6 +1038,19 @@
" float4 position = iPosition; \n"
" float dist = distance(camPos.xz, position.xz); \n";

+ if (lighting)
+ {
+ vertexProgSource +=
+ " float3 light = normalize(objSpaceLight.xyz - (iPosition.xyz * objSpaceLight.w)); \n"
+ " float diffuseFactor = max(dot(float4(0,1,0,0), light), 0); \n"
+ " oColor = (lightAmbient + diffuseFactor * lightDiffuse) * iColor; \n";
+ }
+ else
+ {
+ vertexProgSource +=
+ " oColor.rgb = iColor.rgb; \n";
+ }
+
if (fadeTechnique == FADETECH_ALPHA || fadeTechnique == FADETECH_ALPHAGROW) vertexProgSource +=
//Fade out in the distance
" oColor.a = 2.0f - (2.0f * dist / fadeRange); \n";
@@ -1107,6 +1133,12 @@
params->setNamedAutoConstant("direction", GpuProgramParameters::ACT_CUSTOM, 4);
}

+ if (lighting){
+ params->setNamedAutoConstant("objSpaceLight", GpuProgramParameters::ACT_LIGHT_POSITION_OBJECT_SPACE);
+ params->setNamedAutoConstant("lightDiffuse", GpuProgramParameters::ACT_DERIVED_LIGHT_DIFFUSE_COLOUR);
+ params->setNamedAutoConstant("lightAmbient", GpuProgramParameters::ACT_DERIVED_AMBIENT_LIGHT_COLOUR);
+ }
+
if (fadeTechnique == FADETECH_GROW || fadeTechnique == FADETECH_ALPHAGROW){
params->setNamedAutoConstant("grassHeight", GpuProgramParameters::ACT_CUSTOM, 1);
params->setNamedConstant("grassHeight", maxHeight * 1.05f);




There is one difference to the previous patch, though. Instead of determining the light factor from normal, we used positive Y-axis, which results in more correct lighting when the sun is near zenith.


float diffuseFactor = max(dot(float4(0,1,0,0), light), 0);


I suspect, it might be justifiable to parametrize the vector against which the lighting is determined.

Keep up the good work! Regards,

-A

dudeabot

27-07-2008 01:24:30

can you post the diff file?

its not reconigzing when i copy and paste, thanks!

nargil

26-02-2009 13:48:32

It's strange.
Look at the screen: http://img16.imageshack.us/img16/6764/grasse.jpg
(1) One second (15:52:24) the grass is bright,
(2) next second (15:52:25) it turns sudenly dark.

The sun direction is:
(1) Vector3(-0.777273, -0.620406, 0.104609)
(2) Vector3(-0.77731, -0.62366, 0.104609)

So there is nothing wrong with caelum. It must be the shader

Edit 1: I'm not able to reproduce it with my own directional light instead of caelum, so propably the shader works fine
Edit 2: Batched geometry is also affected by this bug. I can't reproduce this with caelum and any other non PG based entity...

Edit 3:
Ogre::Vector3 dir = engine->getCaelum()->getSunDirection(engine->getCaelum()->getJulianDay());
std::cout << "dir: " << dir << std::endl;
std::cout << "ambient: " << engine->getSceneMgrRW()->getAmbientLight() << std::endl;
std::cout << "light: " <<engine->getCaelum()->getSunLightColour(engine->getCaelum()->getJulianDay(), dir) << std::endl;


gives this output :

Upper values are for 24 sec, lower for 25 sec
So everything seems fine with it...

I'm confused now !


PS How do I enable lighting for Impostors ? Is there also a shader to modify ?

nargil

07-03-2009 14:52:49

It was due to ogre passing the closest light to the shader. I wrote my own shader that supports multiple lights




float3 getLightDirection(float4 lightPosition, float4 position)
{
return lightPosition.xyz - (position.xyz * lightPosition.w);
}

void main_vp(
float4 iPosition : POSITION,
float4 iColor : COLOR,
float2 iUV : TEXCOORD0,
out float4 oPosition : POSITION,
out float4 oColor : COLOR,
out float2 oUV : TEXCOORD0,

uniform float time,
uniform float frequency,
uniform float4 direction,

uniform float4 objSpaceLight[8],
uniform float4 lightDiffuse[8],
uniform float4 lightAtt[8],
uniform float4 lightAmbient,

uniform float grassHeight,
float4 iNormal : NORMAL,

uniform float4x4 worldViewProj,
uniform float3 camPos,
uniform float fadeRange )

{
float4 position = iPosition;
float dist = distance(camPos.xz, position.xz);

float ldist0 = distance(position.xyz, objSpaceLight[0].xyz) * objSpaceLight[0].w;
float ldist1 = distance(position.xyz, objSpaceLight[1].xyz) * objSpaceLight[1].w;
float ldist2 = distance(position.xyz, objSpaceLight[2].xyz) * objSpaceLight[2].w;
float ldist3 = distance(position.xyz, objSpaceLight[3].xyz) * objSpaceLight[3].w;
float ldist4 = distance(position.xyz, objSpaceLight[4].xyz) * objSpaceLight[4].w;
float ldist5 = distance(position.xyz, objSpaceLight[5].xyz) * objSpaceLight[5].w;
float ldist6 = distance(position.xyz, objSpaceLight[6].xyz) * objSpaceLight[6].w;
float ldist7 = distance(position.xyz, objSpaceLight[7].xyz) * objSpaceLight[7].w;

float3 light0 = getLightDirection(objSpaceLight[0], iPosition);
float3 light1 = getLightDirection(objSpaceLight[1], iPosition);
float3 light2 = getLightDirection(objSpaceLight[2], iPosition);
float3 light3 = getLightDirection(objSpaceLight[3], iPosition);
float3 light4 = getLightDirection(objSpaceLight[4], iPosition);
float3 light5 = getLightDirection(objSpaceLight[5], iPosition);
float3 light6 = getLightDirection(objSpaceLight[6], iPosition);
float3 light7 = getLightDirection(objSpaceLight[7], iPosition);

float diffuseFactor0 = max(dot(float3(0,1,0), light0), 0);
float diffuseFactor1 = max(dot(float3(0,1,0), light1), 0);
float diffuseFactor2 = max(dot(float3(0,1,0), light2), 0);
float diffuseFactor3 = max(dot(float3(0,1,0), light3), 0);
float diffuseFactor4 = max(dot(float3(0,1,0), light4), 0);
float diffuseFactor5 = max(dot(float3(0,1,0), light5), 0);
float diffuseFactor6 = max(dot(float3(0,1,0), light6), 0);
float diffuseFactor7 = max(dot(float3(0,1,0), light7), 0);

oColor = iColor * (lightAmbient
+ diffuseFactor0 * lightDiffuse[0] * saturate(1 / ldist0 / lightAtt[0].z) * saturate(1 / pow(ldist0,2) / lightAtt[0].w)
+ diffuseFactor1 * lightDiffuse[1] * saturate(1 / ldist1 / lightAtt[1].z) * saturate(1 / pow(ldist1,2) / lightAtt[1].w)
+ diffuseFactor2 * lightDiffuse[2] * saturate(1 / ldist2 / lightAtt[2].z) * saturate(1 / pow(ldist2,2) / lightAtt[2].w)
+ diffuseFactor3 * lightDiffuse[3] * saturate(1 / ldist3 / lightAtt[3].z) * saturate(1 / pow(ldist3,2) / lightAtt[3].w)
+ diffuseFactor4 * lightDiffuse[4] * saturate(1 / ldist4 / lightAtt[4].z) * saturate(1 / pow(ldist4,2) / lightAtt[4].w)
+ diffuseFactor5 * lightDiffuse[5] * saturate(1 / ldist5 / lightAtt[5].z) * saturate(1 / pow(ldist5,2) / lightAtt[5].w)
+ diffuseFactor6 * lightDiffuse[6] * saturate(1 / ldist6 / lightAtt[6].z) * saturate(1 / pow(ldist6,2) / lightAtt[6].w)
+ diffuseFactor7 * lightDiffuse[7] * saturate(1 / ldist7 / lightAtt[7].z) * saturate(1 / pow(ldist7,2) / lightAtt[7].w)
);

oColor.a = 2.0f - (2.0f * dist / fadeRange);
float oldposx = position.x;
if (iUV.y == 0.0f)
{
//Wave grass in breeze
float offset = sin(time + oldposx * frequency);
position += direction * offset;
}

float offset = (2.0f * dist / fadeRange) - 1.0f;
position.y -= grassHeight * clamp(offset, 0, 1);
oPosition = mul(worldViewProj, position);
oUV = iUV;
}


Use it if you want. If you optimize it - please post the modified version ;)

tdev

29-06-2009 10:40:17

First of all, thank you for the patch. We were missing similar functionality. I notice that this patch has not made into the latest svn revision, for some reason. Here's, however, a bit more polished (and simplest possible diff) version of, essentially, the same thing (corrected 'lightning' to 'lighting', for instance).
-A

merged with SVN HEAD, thanks! :)