Code archives/3D Graphics - Mesh/Procedural Grass Pattern for texture
This code has been declared by its author to be Public Domain code.
Download source code
| |||||
This code produices a large floor of grass using meshes. The original idea comes from this youtube tutorial (this is just a way to get a similar result in code) https://www.youtube.com/watch?v=cqn_jryEXLw | |||||
Const LEAF_MAX_RES% = 24 Function RandomLeaf(NIter%=-1, LeafW#=0.2, LeafVarX#=0.10, LeafVarY#=0.25, Parent=0) Local mesh = CreateMesh(Parent) EntityFX mesh, 1+2+8+32 Local surf = CreateSurface(mesh) If (NIter<4) Then NIter = Rand(4,LEAF_MAX_RES-1) If (NIter>=LEAF_MAX_RES) Then NIter = LEAF_MAX_RES-1 Local lx#[LEAF_MAX_RES] Local ly#[LEAF_MAX_RES] Local lw#[LEAF_MAX_RES] Local x# = 0 Local y# = 0 Local w# = 1 Local i% = 0 Local xSens# = -1+2*Rand(0,1) Local RndXAng# = Rand(170,320) For i = 0 To NIter lx[i] = x*xSens ly[i] = y Local ang0 = Rand(-90,-80) lw[i] = LeafW * Cos(ang0+(90-ang0)*i/NIter)+LeafW*Rnd(-0.1,0.1) Local y0# = Float(1+i)/NIter Local y1# = Float(2+i)/NIter y = y + LeafVarY*Rnd(y0,y1) x = x + LeafVarX*Cos(i*RndXAng / NIter) Next Local v0% Local NV% = 9 Local AO# = LeafW*1.2 Local AOy# = -AO For i = 0 To NIter Local DI# = lw[i]*0.001 v0 = AddVertex ( surf, lx[i]-lw[i]-AO,-0.001,ly[i]+AOy ) : VertexColor surf, v0+0, 0,0,0, 0.0 AddVertex ( surf, lx[i]-lw[i]+DI,-0.001,ly[i]+AOy ) : VertexColor surf, v0+1, 0,0,0, 0.3 AddVertex ( surf, lx[i]+lw[i]-DI,-0.001,ly[i]+AOy ) : VertexColor surf, v0+2, 0,0,0, 0.3 AddVertex ( surf, lx[i]+lw[i]+AO,-0.001,ly[i]+AOy ) : VertexColor surf, v0+3, 0,0,0, 0.0 If i>0 AddTriangle surf, v0-4, v0+1, v0-3 AddTriangle surf, v0-4, v0 , v0+1 AddTriangle surf, v0-3, v0+2, v0-2 AddTriangle surf, v0-3, v0+1, v0+2 AddTriangle surf, v0-2, v0+3, v0-1 AddTriangle surf, v0-2, v0+2, v0+3 EndIf If i=0 AOy = 0 ElseIf i=NIter-1 AOy = AO EndIf Next Local vS% = CountVertices(surf) Local v_% AOy# = -AO For i = 0 To NIter v_ = AddVertex ( surf, lx[i]-lw[i]*1.2,0,ly[i]+AOy ) AddVertex ( surf, lx[i]-lw[i] ,0,ly[i] ) AddVertex ( surf, lx[i]-lw[i]*.6 ,0,ly[i] ) If i>NIter/6 And i <NIter*7/8 AddVertex ( surf, lx[i]-lw[i]*Rnd(.2,0.4) ,0,ly[i] ) AddVertex ( surf, lx[i] ,0,ly[i] ) AddVertex ( surf, lx[i]+lw[i]*Rnd(.2,0.4) ,0,ly[i] ) Else AddVertex ( surf, lx[i] ,0,ly[i] ) AddVertex ( surf, lx[i] ,0,ly[i] ) AddVertex ( surf, lx[i] ,0,ly[i] ) EndIf AddVertex ( surf, lx[i]+lw[i]*.6 ,0,ly[i] ) AddVertex ( surf, lx[i]+lw[i] ,0,ly[i] ) AddVertex ( surf, lx[i]+lw[i]*1.2,0,ly[i]+AOy ) If i=0 AOy = 0 ElseIf i=NIter-1 AOy = AO EndIf If i>0 For j = 0 To NV-2 v0 = v_+j AddTriangle surf, v0-NV,v0+1,v0-NV+1 AddTriangle surf, v0-NV,v0,v0+1 Next EndIf Next Local r0 = 255, g0=225, b0=060 Local r1 = 055, g1=160, b1=010 Local r2 = 040, g2=110, b2=005 Local c0# = 0.2 Local c1# = 1 - c0 For i = 0 To NIter Local c# = c0+c1*ly[i]/ly[NIter] Local rl = c*(r1+(r0-r1)*c) Local gl = c*(g1+(g0-g1)*c) Local bl = c*(b1+(b0-b1)*c) Local rm = c*(r1+(r0-r1)*c*0.7) Local gm = c*(g1+(g0-g1)*c*0.7) Local bm = c*(b1+(b0-b1)*c*0.7) Local rn = c*(r1+(r0-r1)*c*0.95) Local gn = c*(g1+(g0-g1)*c*0.95) Local bn = c*(b1+(b0-b1)*c*0.95) VertexColor surf, vS+i*NV+0, rl,gl,bl, 0.0 VertexColor surf, vS+i*NV+1, rl,gl,bl VertexColor surf, vS+i*NV+2, rm,gm,bm VertexColor surf, vS+i*NV+3, rn,gn,bn VertexColor surf, vS+i*NV+4, c*r2,c*g2,c*b2 VertexColor surf, vS+i*NV+5, rn,gn,bn VertexColor surf, vS+i*NV+6, rm,gm,bm VertexColor surf, vS+i*NV+7, rl,gl,bl VertexColor surf, vS+i*NV+8, rl,gl,bl, 0.0 Next Return mesh End Function Graphics3D 1024,768,0,2 Local cam = CreateCamera() CameraProjMode cam, 2 CameraZoom cam, 0.075 CameraClsColor cam, 255,000,255 Local Leaf_Model_Pivot = CreatePivot() HideEntity Leaf_Model_Pivot Local Leaf_Brush_Pivot = CreatePivot() HideEntity Leaf_Brush_Pivot Local Leaf_Copies_Pivot = CreatePivot() Const NLeaves% = 8 Local Leaves[NLeaves+1] For i = 0 To NLeaves Leaves[i] = RandomLeaf(6+i*2, 0.3, 0.1, 0.3, Leaf_Model_Pivot) Next Local LeavesBrush[10] For i = 0 To 6 LeavesBrush[i] = CreatePivot(Leaf_Brush_Pivot) Local l_NLeaves% = Rand(8,12) For j = 0 To l_NLeaves Local f = CopyEntity(Leaves[Rand(0, NLeaves)], LeavesBrush[i]) ScaleEntity f, Rnd(.9,1.1), Rnd(.9,1.1), Rnd(.9,1.1) PositionEntity f, Rnd(-0.1,0.1)*Float(j)/l_NLeaves, -0.01*Float(j+1)/l_NLeaves,Rnd(-0.1,0.1) + j*0.15 RotateEntity f, 0,Rand(-60,60),0 Next Next For a = - 16 To 16 Step 4 For b = - 16 To 16 Step 4 Local l_BrushPiv = CreatePivot(Leaf_Copies_Pivot) PositionEntity l_BrushPiv, a+Rnd(-1,1), -.1+Float(0.3)*Sqr(a*a+b*b)/(16*16+16*16), b+Rnd(-1,1) RotateEntity l_BrushPiv, 0,Rand(360),0 For i = 0 To 12 Local l_FBrush = CopyEntity(LeavesBrush[Rand(0,6)], l_BrushPiv) RotateEntity l_FBrush, 0,(i*360)/13,0 MoveEntity l_FBrush, 0,0,Rnd(0.0,1.5) ScaleEntity l_FBrush, Rnd(.9,1.1), Rnd(.9,1.1), Rnd(.9,1.1) Next Next Next PositionEntity cam, 0,16,0 RotateEntity cam, 90,0,0 RenderWorld Flip True FreeEntity Leaf_Model_Pivot FreeEntity Leaf_Copies_Pivot FreeEntity Leaf_Brush_Pivot WaitKey() End |
Comments
| ||
It would look really better with hilights on the leaves, but ... you know ... I'm lazzy :) I think a simple texture on the leaves could do the trick without too much effort. |
| ||
Looks great! |
| ||
That's pretty neat. ;) |
| ||
Really nice. |
| ||
Mighty purdy. Amazing what some people can do with procedural gfx. |
| ||
Glad you like it. Procedural is my god, I beleive in procedural ;) Mighty purdy. I had to google it to know it means :) (never heard this expression before) |
| ||
nice ! |
| ||
Mighty purdy It's hillbilly/red neck talk. XD |
| ||
@Bobysait>>can you explain why you need vertex alpha to make this kind of leaf ? (i see how to create the same result without any alpha...) |
| ||
(I'll answer with the Paul Taylor' style) My name is Bobysait, I used to be a graphist but now I build everything with procedural stuff. One of the thing I've never understood is the generation of procedural stuff using only mesh and surfaces when it's easier to create models with a dedicated software. WTF Procedural ?! There are many ways to get the job done with 3dsmax or blender or [...] and a texture, so ... "Why is it better to use the procedural way using vertex alpha Jean-Pierre ?" I'M GLAD YOU FUC**NG ASK ! I use vertex alpha for 3 reasons. Number One : It's used to blend the edges so it makes a kind of low-cost anti-aliasing Number 2 ! At the same time it generates some ambient occlusion on the leaves behind. And Number 3 ? I just didn't want to use a texture to do it, so i use Vertex color+alpha. That's it :) |
| ||
there was a shorter answer : "because i want to" or "i like to use vertexalpha, that's my thing." ;) to blend the edges so it makes a kind of low-cost anti-aliasing it generates some ambient occlusion on the leaves behind ok! |
| ||
It's really nice and technically very interestung, but... the Triscount is 3.644.476. So you can only use it as a texture and not in 3D with the original meshes, unfortunately. |
| ||
Well, the demo is only for example, but it's absolutely not made to be used as a mesh It's just a starting point for something else. (see the video of the tutorial posted above, it shows how the guy do it with photoshop, I only rebuilt the shapes so we can do the same with procedural stuff) The theory behind : - Create random patterns and copyrect each of them to a separate texture - Apply each texture to a quad (with equal width and height) offset each texture (PositionTexture) to fit the viewport (it will wrap the borders) - Finally copyrect the viewport to a texture So you end with a seamless texture. That's how it's supposed to be used :) |
Code Archives Forum