fxGrassReplicator v.1.01 (and v1.11)
by Bendik Stang · 12/03/2002 (8:25 am) · 36 comments
Download Code File
Using this object you can provide total coverage of your maps or target areas that need grass.
It provides you with the ability to create hundreds of thousands of grass items over a controlled area. You can also control whether items are placed on terrain, interiors, statics or water. You can also control the terrain slope limit so that you don't get foliage stuck on steep angles of terrain. The grass elements will however follow the terrain, but very steep angles might cause ugly artifacts.
You can setup random sizes of grass elements plus have the ability to fix the aspect ratio where you don't want your textures distorted but still have different sizes within the scene.
A neat feature is the ability to setup random swaying to simulate wind effects. There is also a lighting feature that changes the luminance of the foliage over time to simulate lighting changes in the scene.
On the performance side of things you can set the distance at which grass appears. If you don't want the grass just appearing/disappearing then there is the ability to control that too so items gradually fade in/out of view.
Melv have also added a very efficient culling algorithm that literally removes the processing of objects that are not within the view.
You can use grayscale textures and then apply vertex colors to color your grass. Top and bottom colors can be adjusted to any variation you like. NOTE: If you use a multi colored texture, then be sure to toggle this option off.
Each grass element does a double collision test to perfectly follow the curves of the terrain.
Optimization suggestion:
You can effectively cover a huge area by making two fxGrassObjects; One where you make the grass elements display only close to the camera, and then the other less dense GrassObject can take over where the first fades out. The second grass object can be larger and taller and serve as a LOD.
In this version of fxGrassReplicator there is no LOD.
A 4Mb DivX4.2 Preview video is available here. Thanks to the Fraps Movie Maker!
Using this object you can provide total coverage of your maps or target areas that need grass.
It provides you with the ability to create hundreds of thousands of grass items over a controlled area. You can also control whether items are placed on terrain, interiors, statics or water. You can also control the terrain slope limit so that you don't get foliage stuck on steep angles of terrain. The grass elements will however follow the terrain, but very steep angles might cause ugly artifacts.
You can setup random sizes of grass elements plus have the ability to fix the aspect ratio where you don't want your textures distorted but still have different sizes within the scene.
A neat feature is the ability to setup random swaying to simulate wind effects. There is also a lighting feature that changes the luminance of the foliage over time to simulate lighting changes in the scene.
On the performance side of things you can set the distance at which grass appears. If you don't want the grass just appearing/disappearing then there is the ability to control that too so items gradually fade in/out of view.
Melv have also added a very efficient culling algorithm that literally removes the processing of objects that are not within the view.
You can use grayscale textures and then apply vertex colors to color your grass. Top and bottom colors can be adjusted to any variation you like. NOTE: If you use a multi colored texture, then be sure to toggle this option off.
Each grass element does a double collision test to perfectly follow the curves of the terrain.
Optimization suggestion:
You can effectively cover a huge area by making two fxGrassObjects; One where you make the grass elements display only close to the camera, and then the other less dense GrassObject can take over where the first fades out. The second grass object can be larger and taller and serve as a LOD.
In this version of fxGrassReplicator there is no LOD.
A 4Mb DivX4.2 Preview video is available here. Thanks to the Fraps Movie Maker!
About the author
#2
edit: I like the coloring option you got in there too. Makes it very easy to tweak the look to fit the terrain style.
12/03/2002 (10:21 am)
Bendik, This works great. It looks like a good option to use along with the fxFoliage and fxShape things Melv added.edit: I like the coloring option you got in there too. Makes it very easy to tweak the look to fit the terrain style.
#3
12/03/2002 (6:53 pm)
hhm .. I got it to work a few times - I keep getting culling resolution errors - no matter what I enter :/
#4
12/03/2002 (8:27 pm)
woohoo lets get those bugs ironed out and stabilise this necessary and vast improvement for anyones game.
#5
-Not sure if it works on the previous ones. If anyone tests it with 1.1.1 pleas let us know how it goes.
Sabrecyd, thanks!
I'd love to see some snapshots from you guys when you have gotten it well implemented in your games.
Trevor, read the DrinkMe. The culling rezolution must be of a factor 2, and it has to be less than the size of your area.
So if you make the area 10x10, then use a cull rez of 8.
Tim, please do. Report bugs here. I will fix them as fast as I can.
Some have emailed me and said that the grass is invisible. Remember to add the texture file into your fps folder eg. fps/data/plant/grass.png
Then put the path and file name in the fxGrassReplicator item. If the path is good, the grass will show, else it will be white/colored faces.
-Bendik
12/04/2002 (1:11 am)
Paul, I have only tried this on v.1.1.2-Not sure if it works on the previous ones. If anyone tests it with 1.1.1 pleas let us know how it goes.
Sabrecyd, thanks!
I'd love to see some snapshots from you guys when you have gotten it well implemented in your games.
Trevor, read the DrinkMe. The culling rezolution must be of a factor 2, and it has to be less than the size of your area.
So if you make the area 10x10, then use a cull rez of 8.
Tim, please do. Report bugs here. I will fix them as fast as I can.
Some have emailed me and said that the grass is invisible. Remember to add the texture file into your fps folder eg. fps/data/plant/grass.png
Then put the path and file name in the fxGrassReplicator item. If the path is good, the grass will show, else it will be white/colored faces.
-Bendik
#6
I wonder if some people that are having a problem are just using the default settings for the grassreplicator? I only ask because I noticed the OuterRadius(X and Y) for the grass is set at 50 and the culling is set at 64. The culling needs to be smaller then the OuterRadius. If it's bigger the grass png images don't appear and a culling error will show up. Hope that helps some people.
Will do on the screenshots when I have something :)
edit: It does mention that though in the drinkme like you mentioned.
12/04/2002 (4:16 am)
Bendik,I wonder if some people that are having a problem are just using the default settings for the grassreplicator? I only ask because I noticed the OuterRadius(X and Y) for the grass is set at 50 and the culling is set at 64. The culling needs to be smaller then the OuterRadius. If it's bigger the grass png images don't appear and a culling error will show up. Hope that helps some people.
Will do on the screenshots when I have something :)
edit: It does mention that though in the drinkme like you mentioned.
#7
-Bendik
It is fixed and uploaded in the download file.
12/04/2002 (4:36 am)
Oh, bad initial values....better fix that then. :)-Bendik
It is fixed and uploaded in the download file.
#8
12/04/2002 (7:28 pm)
Outstanding Bendik, loved the video too!
#9
Do you think theres a way to link the terrains backface culling into your fxgrass? I noticed with melvs fxreplicators there visible from "inside" the terrain. Would this not be an effective way to occlude large quantities of terrain occluded fxgrass? It seems that the visibility checks for the terrains backface poly's is already occuring so why not use that to occlude? Or is there already a system for occlusion implemented?
12/04/2002 (9:33 pm)
GREAT WORK BENDIK, I cant wait to use this but im on 1.1.2 Im really dissapointed when i try to use code from old resources, or really new ones and it dosnt work. I think 1.2 will solve alot of these intermediatte build problems. Maybe everyone should be forced to use HEAD...Do you think theres a way to link the terrains backface culling into your fxgrass? I noticed with melvs fxreplicators there visible from "inside" the terrain. Would this not be an effective way to occlude large quantities of terrain occluded fxgrass? It seems that the visibility checks for the terrains backface poly's is already occuring so why not use that to occlude? Or is there already a system for occlusion implemented?
#10
Very good question Tim. I have not even thought about it. I will look into it.
*makes a note on the bottom of a very long list.*
:)
-Bendik
12/05/2002 (1:46 am)
hmm..Very good question Tim. I have not even thought about it. I will look into it.
*makes a note on the bottom of a very long list.*
:)
-Bendik
#12
12/07/2002 (5:53 am)
Any chance you could post one of your script settings used in the movie? The movie looks awesome, while the included sample in the DL looks somewhat goofy. Whenever I try changing the settings to match what you've done, something goes wrong and the grass no longer shows.
#13
#include "ARPG/environment/atgeDayNight.h"
And multiply glColor variables:
// Set Colour.
glColor4f( mFieldData.mPlaceAreaColour.red * tgeDNCurrentColor.x,
mFieldData.mPlaceAreaColour.green * tgeDNCurrentColor.y,
mFieldData.mPlaceAreaColour.blue * tgeDNCurrentColor.z,
AREA_ANIMATION_ARC * (Angle-mCreationAreaAngle));
Here's my screenshot:
http://pingu.ii.uj.edu.pl/~ono/sgTree4.jpg
Bendik: How make grass to be visible only on specific ground texture ??? Just wanna have foliage on grass texture, but not on sand. Now it's everywhere inside specified radious.
Good luck,
12/07/2002 (6:05 am)
If you find it usefull.. I've played with Bendik's grass to fit Day/Night engine by Joshua... at fxGrassReplicator.cc just include:#include "ARPG/environment/atgeDayNight.h"
And multiply glColor variables:
// Set Colour.
glColor4f( mFieldData.mPlaceAreaColour.red * tgeDNCurrentColor.x,
mFieldData.mPlaceAreaColour.green * tgeDNCurrentColor.y,
mFieldData.mPlaceAreaColour.blue * tgeDNCurrentColor.z,
AREA_ANIMATION_ARC * (Angle-mCreationAreaAngle));
Here's my screenshot:
http://pingu.ii.uj.edu.pl/~ono/sgTree4.jpg
Bendik: How make grass to be visible only on specific ground texture ??? Just wanna have foliage on grass texture, but not on sand. Now it's everywhere inside specified radious.
Good luck,
#14
You need to apply the lighting to the billboards.
What I did was add the following changes to fxGrassReplicator.cc
add as last #include
In method void fxGrassReplicator::renderObject(SceneState* state, SceneRenderImage*) make the following changes.
Only the code in bold is new(this is taken from fxFolliageReplicator which Joshua Ritter patched), use the other code(non-bold) as a reference. This is at the top of the method.
further down at the end of the method...
This seams to work for me. The billboards are lit correctly with the time of day.
I noticed that the vertex coloring seems to not longer work. I don't really know that much about OpenGL I'm guessing that lighting up a gl quad negates any calls to glColor*()
So now I'm using a colored grass texture and every thing is looking good.
Also I took a guess at which way to have the normals pointing, if anyone really knows what's going on here feel free to comment. :-)
12/07/2002 (12:13 pm)
Adam that doesn't seem correct to me. I think that's the color of the placement area your changing.You need to apply the lighting to the billboards.
What I did was add the following changes to fxGrassReplicator.cc
add as last #include
#include "ARPG/environment/atgeDayNight.h"
In method void fxGrassReplicator::renderObject(SceneState* state, SceneRenderImage*) make the following changes.
Only the code in bold is new(this is taken from fxFolliageReplicator which Joshua Ritter patched), use the other code(non-bold) as a reference. This is at the top of the method.
// Calculate Elapsed Time and take new Timestamp.
S32 Time = Platform::getVirtualMilliseconds();
F32 ElapsedTime = (Time - mLastRenderTime) * 0.001f;
mLastRenderTime = Time;
[b]
//TGEDN
glEnable (GL_LIGHTING);
GLfloat matProp[] = {1.0f,1.0f,1.0f,1.0f};
GLfloat zeroColor[] = {0,0,0,0};
glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE,matProp);
glMaterialfv(GL_FRONT_AND_BACK,GL_EMISSION,zeroColor);
glMaterialfv(GL_FRONT_AND_BACK,GL_SPECULAR,zeroColor);
LightManager * lightManager = gClientSceneGraph->getLightManager();
lightManager->setVectorLightsEnabled(false);
lightManager->setAmbientColor(ColorF(tgeDNCurrentColor.x,tgeDNCurrentColor.y,tgeDNCurrentColor.z));
MatrixF origProj;
MatrixF origModelView;
SphereF FoliageSphere;
glGetFloatv(GL_MODELVIEW_MATRIX,origModelView) ;
glGetFloatv(GL_PROJECTION_MATRIX,origProj) ;
//ENDTGEDN
[/b]
// Setup out the Projection Matrix/Viewport.
RectI viewport;
glMatrixMode(GL_PROJECTION);
glPushMatrix();
dglGetViewport(&viewport);
state->setupBaseProjection();further down at the end of the method...
// set an abitrar angle to the face
float tmpSplitFactor =0;
if (mFieldData.mIsRandom){
glRotatef(pGrassItem->rAngle, 0,0,1);
tmpSplitFactor = Height/2.0;
}
else {
glRotatef(mFieldData.mRotateAngle, 0,0,1);
tmpSplitFactor = Height/4.0;
}
[b]
//TGEDN
matProp[0]=Luminance;
matProp[1]=Luminance;
matProp[2]=Luminance;
matProp[3]=ItemAlpha;
glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE,matProp);
//whee install lights.. watch framerate die... add a pref
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadMatrixf(origProj);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadMatrixf(origModelView);
FoliageSphere.center=pGrassItem->Transform.getPosition();
FoliageSphere.radius=Width *1.2f;
lightManager->installGLLights(FoliageSphere);
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
//TGEDNEND
[/b]
// Draw Billboard.
glBegin(GL_QUADS);
[b]
glNormal3f(0.0f,0.0f,1.0f);
// Set Blend Function.
//glColor4f(tmpColorTop[0],tmpColorTop[1],tmpColorTop[2], ItemAlpha);
[/b]
// Draw Top part of billboard.
glTexCoord2f (LeftTexPos,0);
glVertex3f (SwayOffsetX,SwayOffsetY-tmpSplitFactor,Height);
glTexCoord2f (RightTexPos,0);
glVertex3f (2*Width+SwayOffsetX,SwayOffsetY-tmpSplitFactor,Height + pGrassItem->Direction[2]);
// Set Ground Blend.
glColor4f(tmpColorBtm[0],tmpColorBtm[1],tmpColorBtm[2], ItemAlpha);
// Draw bottom part of billboard.
glTexCoord2f (RightTexPos,1);
glVertex3f (2*Width,0,+ pGrassItem->Direction[2]);
glTexCoord2f (LeftTexPos,1);
glVertex3f (0,0,0);
glEnd();
glBegin(GL_QUADS);
[b]
glNormal3f(0.0f,0.0f,-1.0f);
// Set Blend Function.
//glColor4f(tmpColorTop[0],tmpColorTop[1],tmpColorTop[2], ItemAlpha);
[/b]
// Draw Top part of billboard.
glTexCoord2f (RightTexPos,0);
glVertex3f (SwayOffsetX,SwayOffsetY+tmpSplitFactor,Height);
glTexCoord2f (LeftTexPos,0);
glVertex3f (2*Width+SwayOffsetX,SwayOffsetY+tmpSplitFactor,Height + pGrassItem->Direction[2]);
// Set Ground Blend.
glColor4f(tmpColorBtm[0],tmpColorBtm[1],tmpColorBtm[2], ItemAlpha);
// Draw bottom part of billboard.
glTexCoord2f (LeftTexPos,1);
glVertex3f (2*Width,0,+ pGrassItem->Direction[2]);
glTexCoord2f (RightTexPos,1);
glVertex3f (0,0,0);
glEnd();
[b]
//TGEDN
lightManager->uninstallGLLights();
[/b]This seams to work for me. The billboards are lit correctly with the time of day.
I noticed that the vertex coloring seems to not longer work. I don't really know that much about OpenGL I'm guessing that lighting up a gl quad negates any calls to glColor*()
So now I'm using a colored grass texture and every thing is looking good.
Also I took a guess at which way to have the normals pointing, if anyone really knows what's going on here feel free to comment. :-)
#15
I will see if I can make it work with the vertex colors, and include the normals the way they should be.
EDITED: After having thought about this, I don't see the need to include materaials an normals. This will slow down the rendering a little, and with the light function it is not really needed. (IMO)
All you need is to access the day/night light values, and make them affect the MinLuminance & MaxLuminance values. If you want to include the color values, then instead apply the lightvalues to the vertex colors.
This will save the enableing of GL_LIGHT, the addition of materials and normals.
But, I have not seen the effects of the grass with material and nomals, could you post a preview so we can see if it is worth the extra rendering cost?
Erik: Always remember to get the cullsize below the maximum radius. I will get the setting for the grass and post it here as well.
Here it is:
Using the terrain texture to place grass would be awsome! It is the goal with this code, but I have not time to make it yet. If anyone have worked with the terrain textures, they might want to have a go?
:)
Bendik
12/09/2002 (3:02 am)
Paul: That is a great addititon!I will see if I can make it work with the vertex colors, and include the normals the way they should be.
EDITED: After having thought about this, I don't see the need to include materaials an normals. This will slow down the rendering a little, and with the light function it is not really needed. (IMO)
All you need is to access the day/night light values, and make them affect the MinLuminance & MaxLuminance values. If you want to include the color values, then instead apply the lightvalues to the vertex colors.
This will save the enableing of GL_LIGHT, the addition of materials and normals.
But, I have not seen the effects of the grass with material and nomals, could you post a preview so we can see if it is worth the extra rendering cost?
Erik: Always remember to get the cullsize below the maximum radius. I will get the setting for the grass and post it here as well.
Here it is:
new fxGrassReplicator(grass) {
position = "207.299 -743.595 295.197";
rotation = "1 0 0 0";
scale = "1 1 1";
UseDebugInfo = "0";
DebugBoxHeight = "1";
HideGrass = "0";
ShowPlacementArea = "0";
PlacementAreaHeight = "15";
PlacementColour = "0.400000 0.000000 0.800000 1.000000";
Seed = "1376312589";
GrassFile = "~/data/plants/grass10b";
GrassCount = "10000";
GrassRetries = "10";
InnerRadiusX = "0";
InnerRadiusY = "0";
OuterRadiusX = "100";
OuterRadiusY = "100";
MinWidth = "4";
MaxWidth = "4";
MinHeight = "1.1";
MaxHeight = "1.5";
FixAspectRatio = "0";
FixSizeToMax = "0";
OffsetZ = "0";
RandomFlip = "0";
UseCulling = "1";
CullResolution = "32";
ViewDistance = "70";
ViewClosest = "1";
FadeInRegion = "40";
FadeOutRegion = "1";
AlphaCutoff = "0.5";
GroundAlpha = "0.9";
SwayOn = "1";
SwaySync = "1";
SwayMagSide = "0.1";
SwayMagFront = "0.6";
MinSwayTime = "10";
MaxSwayTime = "20";
LightOn = "1";
LightSync = "0";
MinLuminance = "0.6";
MaxLuminance = "1";
lightTime = "5";
AllowOnTerrain = "1";
AllowOnInteriors = "0";
AllowOnStatics = "0";
AllowOnWater = "0";
AllowWaterSurface = "0";
AllowedTerrainSlope = "40";
FoilageColourTop = "0.200000 0.700000 0.000000 1.000000";
FoilageColourBtm = "0.100000 0.500000 0.000000 1.000000";
UseColour = "1";
IsRandomRot = "1";
IsSquareArea = "1";
RotationAngle = "90";
};Using the terrain texture to place grass would be awsome! It is the goal with this code, but I have not time to make it yet. If anyone have worked with the terrain textures, they might want to have a go?
:)
Bendik
#16
Maybe I've changed to many glColor calls ;)
All I've done was mix static green (or other one set by user) grass foliage vertex color with current color of DN engine...
And for me it worked okay :)
Of course you cannot avoid lighting when you want play with some torches and lights at night because static vertex coloring makes grass (my fixed one) all time black.
So getting your point: Your fix enables lighting on Grass Replicator and makes DN trough material properties.. the same I'm doing with my custom tree objects.
Anyway you can still use uncoloured texture mixing it with current grass color by changing:
matProp[] = {f,f,f,1.0f};
That should cause uncoloured texture be mixed with current material color.
Bendik:
I'll try to dig out how to check the what's texture on specified terrain position.. so then we could decide if we render grass or not there.
Thanks for reply and regards,
12/09/2002 (6:03 am)
Paul: Maybe I've changed to many glColor calls ;)
All I've done was mix static green (or other one set by user) grass foliage vertex color with current color of DN engine...
And for me it worked okay :)
Of course you cannot avoid lighting when you want play with some torches and lights at night because static vertex coloring makes grass (my fixed one) all time black.
So getting your point: Your fix enables lighting on Grass Replicator and makes DN trough material properties.. the same I'm doing with my custom tree objects.
Anyway you can still use uncoloured texture mixing it with current grass color by changing:
matProp[] = {
That should cause uncoloured texture be mixed with current material color.
Bendik:
I'll try to dig out how to check the what's texture on specified terrain position.. so then we could decide if we render grass or not there.
Thanks for reply and regards,
#17
www.garagegames.com/index.php?sec=mg&mod=resource&page=view&qid=3615
The resource includes instructions on how to modify fxGrassReplicator to work with twSurfaceReference.
Just a matter waiting for the resource to be approved...
12/09/2002 (11:45 am)
I've posted a resource for twSurfaceReference, an object to do the terrain texture work here:www.garagegames.com/index.php?sec=mg&mod=resource&page=view&qid=3615
The resource includes instructions on how to modify fxGrassReplicator to work with twSurfaceReference.
Just a matter waiting for the resource to be approved...
#18
Perhaps the normals are totally wrong. I need to think though it but I don't have the time right now.
How do I display my FPS?
Also how do I take a screen shot?
12/09/2002 (12:03 pm)
Well I have it working with both lighting and materials. There is such as large contrast between the front and back of the billboards that it looks kinda stupid. :)Perhaps the normals are totally wrong. I need to think though it but I don't have the time right now.
How do I display my FPS?
Also how do I take a screen shot?
#19
Thanks to Ken we can now draw the grass on the ground!
There is a minor bug with the squared area placement, so if you get into trouble disable the 'isSquareArea' flag.
fxGrass_v1.11.zip
12/09/2002 (1:49 pm)
New version where the twSurfaceReference have been integrated!Thanks to Ken we can now draw the grass on the ground!
There is a minor bug with the squared area placement, so if you get into trouble disable the 'isSquareArea' flag.
fxGrass_v1.11.zip
#20
12/09/2002 (2:49 pm)
Bendik, this is a change I made in my version to your code to do the square area vs circular area placement :.
.
.
Angle2 = RandomGen.randF(0, M_2PI);
[b]
HypX = RandomGen.randF(mFieldData.mInnerRadiusX, mFieldData.mOuterRadiusX<<1);
HypY = RandomGen.randF(mFieldData.mInnerRadiusY, mFieldData.mOuterRadiusY<<1);
Angle = RandomGen.randF(0, M_2PI);
if (mFieldData.mIsSquare)
{
GrassPosition.x += (HypX-mFieldData.mOuterRadiusX);
GrassPosition.y += (HypY-mFieldData.mOuterRadiusY);
}
else
{
GrassPosition.x += (HypX/2) * mCos(Angle);
GrassPosition.y += (HypY/2) * mSin(Angle);
}
[/b]
if (mFieldData.mIsRandom)
.
.
. 
Torque Owner Paul Sprague