Jump to content

Josh

Staff
  • Posts

    23,307
  • Joined

  • Last visited

Posts posted by Josh

  1. The reason these entities are linked to a model is because a model has a script, and can be moved around and deleted again. This allows you to make lights, particle emitters, or anything else in script, and the editor doesn't have to have everything hard-coded.

     

    If you want to get rid of the model component in your own game loading routine, you can just modify the script to remove the model when your game loads the scene. Something like this:

     

    if MyGameIsRunning==1 then

    object.light:SetParent(nil,1)

    object.light=nil

    object.model:Free()

    end

  2. Add a call to GCCollect() in your main loop.

     

    I don't recommend using the auto GC mode because it is possible for it to cause crashes. The problem is object Delete() methods might be called at any time, and in the case of OpenGL or Newton objects, it might cause the program to delete these things during a sensitive routine when they are being used. It might do something like delete an OpenGL buffer while another buffer is being set, and it is possible this might cause a crash in some situations.

     

    In the future I will add the deleted objects to a queue to be deleted during the UpdateWorld() routine, so they will be more safe in auto GC mode, instead of deleting them in the Object Delete() method.

  3. The reason I ask for a demo of your problem is because I suspect you either have some very unoptimal physics shapes or you are using a high value for the update iterations for the controller. Or there may be some other problem. It doesn't make sense for someone else to try to guess and recreate your program. It's much more efficient to see what you are doing and then see if there are any problems.

  4. I think for nighttime scenes a somewhat desaturated dark blue is good for ambient light, and a white slightly blue light is good for moonlight, with the intensity set pretty low.

     

    Unless you want it to be dark for a reason, don't make it too dark. Rely on the blue tint and keep it bright enough to see. You'll notice this technique used in movies a lot.

  5. Well, I don't think you are giving away any valuable secrets in this thread. I just moved it because it seemed like an editor question. There should still be some discussion in the general forum because then the existing users will still go there and it doesn't become silent. And it also gives people a glimpse at how the community interacts, and how people go about making a game.

     

    Now if an unknown user starts asking programming questions in the general forum, that's when I become suspicious, but those cases are pretty obvious.

  6. You actually can get antialiasing right now, and not the edge antialias shader. Just render to a double-size buffer, then draw this onto a buffer half that size, with the smooth texture filter set. This will produce about the same results as 2x MSAA. I don't recommend using this technique for anything you release, because the bandwidth usage would be ridiculous, but its okay for testing.

  7. To edit the terrain heightmap on the GPU, I create a small buffer and copy part of the heightmap to this. Then I enable the terrain editor shader and draw this small buffer back onto the same spot on the heightmap buffer:

    Strict
    
    Import leadwerks.ENGINE
    Import "terrain.bmx"
    Import "Globals.bmx"
    
    Global oldTerrainToolPosition:TVec3=Vec3(-1000)
    
    Global terrainfilter:TShader[10]
    
    Global terrainchanged:Int
    
    Global editterrainaabb:TAABB
    
    TTerrain.highresheightmap=1
    
    Function UpdateTerrain(terrain:TTerrain)
    Local x:Int,z:Int,size:Int
    If terrainchanged
    	'terrain.generatecolormap()
    	If terrainchanged=2
    		terrain.getheightmap()
    		If TerrainSectorAABBUpdate
    			size=Int(Sqr(TerrainSectorAABBUpdate.length)+0.5)
    			For x=0 To size-1
    				For z=0 To size-1
    					If TerrainSectorAABBUpdate[x,z]
    						terrain.sector[x,z].UpdateAABB()
    						TerrainSectorAABBUpdate[x,z]=0
    					EndIf
    				Next
    			Next
    		EndIf
    		If editterrainaabb
    			ForEachEntityInAABBDo(editterrainaabb,callback,terrain,ENTITY_MODEL)
    			terrain.quadtree.root.ForEachLeafInAABBDo(editterrainaabb,func,Null)
    			terrain.quadtree.root.UpdateAABB()
    		EndIf
    	EndIf
    	editterrainaabb=Null
    	terrainchanged=False
    EndIf
    
    Function func(leaf:TQuadTreeLeaf,o:Object)
    	leaf.UpdateInstanceHeights(terrain)
    EndFunction
    
    Function Callback:Int(entity:TEntity,extra:Object)
    	If Int(entity.GetKey("aligntoground"))
    		entity.AlignToTerrain(TTerrain(extra))
    	EndIf
    	Return 1
    EndFunction
    
    EndFunction
    
    Global TerrainSectorAABBUpdate:Byte[,]
    
    
    Function AddVegetationInstance(terrain:TTerrain,x:Float,z:Float,layer:Int,density:Float,randrotation:Int,randscale:Float,aligntonormal:Int,tilt:Float)
    Local pitch#,yaw#,dist#
    Local dir:TVec3
    Local roll:Float=0.0
    Local mat:TMat4
    Local scale:Float
    Local alignmat:TMat4
    
    If terrain.quadtree.layers[layer]=Null Return
    If terrain.quadtree.layers[layer].model=Null Return
    If randrotation
    	mat=TMat4.FromYawPitchRoll(Rnd(0.0,360.0),Rnd(-tilt,tilt),Rnd(-tilt,tilt))
    Else
    	'SeedRnd (mat.ix+mat.iy+mat.iz+mat.jx+mat.jy+mat.jz+mat.kx+mat.ky+mat.kz+mat.tx+mat.ty+mat.tz)*1000.0
    	mat=TMat4.FromYawPitchRoll(0.0,Rnd(-tilt,tilt),Rnd(-tilt,tilt))
    EndIf
    'SeedRnd (mat.ix+mat.iy+mat.iz+mat.jx+mat.jy+mat.jz+mat.kx+mat.ky+mat.kz+mat.tx+mat.ty+mat.tz)*1000.0
    scale=Rnd(1.0-randscale,1.0+randscale)				
    mat.ix:*scale
    mat.iy:*scale
    mat.iz:*scale
    mat.jx:*scale
    mat.jy:*scale
    mat.jz:*scale
    mat.kx:*scale
    mat.ky:*scale
    mat.kz:*scale
    mat.tx=x'x+x0*density+Rnd(-density*0.5,density*0.5)
    mat.tz=z'z+z0*density+Rnd(-density*0.5,density*0.5)
    mat.ty=terrain.GetElevation(mat.tx,mat.tz)
    If aligntonormal	
    	dir=terrain.CalcNormal(x,z)
    	dist#=Sqr(dir.x#*dir.x#+dir.z#*dir.z#)
    	pitch#=ATan2(-dir.y#,dist#)
    	yaw#=ATan2(-dir.x#,dir.z#)
    	If randrotation
    		'SeedRnd (mat.ix+mat.iy+mat.iz+mat.jx+mat.jy+mat.jz+mat.kx+mat.ky+mat.kz+mat.tx+mat.ty+mat.tz)*1000.0
    		roll=Rnd(0.0,360.0)
    	EndIf
    	alignmat=TMat4.FromYawPitchRoll(yaw,pitch,roll)
    	alignmat.tx=mat.tx
    	alignmat.ty=mat.ty
    	alignmat.tz=mat.tz
    	mat.ix=-alignmat.ix*scale
    	mat.iy=-alignmat.iy*scale
    	mat.iz=-alignmat.iz*scale
    	mat.jx=alignmat.kx*scale
    	mat.jy=alignmat.ky*scale
    	mat.jz=alignmat.kz*scale
    	mat.kx=alignmat.jx*scale
    	mat.ky=alignmat.jy*scale
    	mat.kz=alignmat.jz*scale
    	If randrotation
    		'SeedRnd (mat.ix+mat.iy+mat.iz+mat.jx+mat.jy+mat.jz+mat.kx+mat.ky+mat.kz+mat.tx+mat.ty+mat.tz)*1000.0
    		mat=mat.times(TMat4.FromYawPitchRoll(0.0,Rnd(-tilt,tilt),Rnd(-tilt,tilt)))
    	EndIf
    EndIf
    terrain.quadtree.addinstance(mat,layer,density)
    EndFunction
    
    
    Global toolimage:TTexture
    
    Function EditTerrain(terrain:TTerrain,x:Float,z:Float,outerradius:Float,innerradius:Float,editmode:Int=0,strength:Float=1.0,channel:Int=0,flattenheight:Float,toolfloor#=0.0,toolceiling#=1.0)
    
    Global toolimagebuffer:TBuffer
    Global channelmask:Float[4]
    
    Local x0:Float,z0:Float,x1:Float,z1:Float
    Local w:Int,h:Int
    Local tw:Int,th:Int
    Local cx:Float,cy:Float
    Local terrainsize:Float
    Local buffer:TBuffer
    Local format:Int
    Local terrbuffer:TBuffer
    Local texture:TTexture
    Local constraints:Float[2]
    Local i:Int
    Local scale:Float
    Local ix:Float=x
    Local iz:Float=z
    
    scenechanged=1
    
    If editmode=4
    	Local gx0:Int,gy0:Int
    	Local gx1:Int,gy1:Int
    
    	x=Round(x/terrain.scale.x+0.5)+terrain.resolution/2-1
    	z=Round(z/terrain.scale.z+0.5)+terrain.resolution/2-1	
    
    	gx0=x-outerradius
    	gx1=x+outerradius
    	gy0=z-outerradius
    	gy1=z+outerradius
    
    	gx0=Max(0,gx0)
    	gx0=Min(gx0,terrain.resolution-1)
    	gy0=Max(0,gy0)
    	gy0=Min(gy0,terrain.resolution-1)
    	gx1=Max(0,gx1)
    	gx1=Min(gx1,terrain.resolution-1)
    	gy1=Max(0,gy1)
    	gy1=Min(gy1,terrain.resolution-1)
    
    	w=(gx1-gx0)/2
    	For x0=gx0 To gx1
    		For z0=gy0 To gy1
    			If strength>0
    				terrain.SetTileVisibility(x0,z0,0,0)
    			Else
    				terrain.SetTileVisibility(x0,z0,1,0)
    			EndIf
    		Next
    	Next
    	terrain.UpdateVisibilityTexture(gx0,gy0,gx1-gx0+1,gy1-gy0+1)
    	Return
    EndIf
    
    If editmode=5
    
    	If Not CurrentVegetationLayer Return
    
    	'If Not terrain.quadtree.layers[TerrainVegetationLayer] Return
    	'If Not terrain.quadtree.layers[TerrainVegetationLayer].model Return
    	'If SelectedGadgetItem(Gadget_VegetationList)=-1 Return
    	If strength>0.0
    
    		'Add instances
    		Local tilt:Float=CurrentVegetationLayer.randomtilt'VegetationTilt[TerrainVegetationLayer]
    		Local density:Float=CurrentVegetationLayer.density'VegetationDensity[TerrainVegetationLayer]'Float(GadgetText(Gadget_VegetationDensity))
    		For x0=-outerradius/density To outerradius/density
    			For z0=-outerradius/density To outerradius/density
    				If Sqr(x0*density*x0*density+z0*density*z0*density)>outerradius Continue
    				'SeedRnd x+x0*density+z+z0*density
    				cx=x+x0*density+Rnd(-density*0.5,density*0.5)
    				cy=z+z0*density+Rnd(-density*0.5,density*0.5)		
    				AddVegetationInstance(terrain,cx,cy,CurrentVegetationLayer.index,CurrentVegetationLayer.density,CurrentVegetationLayer.randomrotation,CurrentVegetationLayer.randomscale,CurrentVegetationLayer.aligntoterrain,CurrentVegetationLayer.randomtilt)
    			Next
    			GCCollect()
    		Next
    
    	Else
    
    		'Remove instances
    		Local aabb:TAABB=New TAABB
    		aabb.x0=x-outerradius
    		aabb.x1=x+outerradius
    		aabb.y0=-infinity
    		aabb.y1=infinity
    		aabb.z0=z-outerradius
    		aabb.z1=z+outerradius
    		aabb.update()
    		terrain.quadtree.root.ForEachLeafInAABBDo(aabb,func,vec3(x,outerradius,z))
    
    		Function func(leaf:TQuadTreeLeaf,o:Object)
    			Local n:Int
    			Local dx:Float,dz:Float
    			Local t:TVec3
    			Local count:Int
    
    			t=TVec3(o)
    			count=leaf.instance_count[CurrentVegetationLayer.index]
    			n=0
    			If count
    				Repeat
    					dx=Abs(leaf.instances[CurrentVegetationLayer.index][n*16+12]-t.x)
    					dz=Abs(leaf.instances[CurrentVegetationLayer.index][n*16+14]-t.z)
    					If Sqr(dx*dx+dz*dz)<t.y
    						leaf.DeleteInstance(n,CurrentVegetationLayer.index)
    						n:-1
    						count:-1
    					EndIf
    					If n>=count-1 Exit
    					If count<1 Exit
    					n:+1
    				Forever
    			EndIf
    		EndFunction
    
    	EndIf
    	Return
    EndIf
    
    If editmode=1
    	terrainchanged=1
    Else
    	terrainchanged=2
    EndIf
    
    If Not TerrainSectorAABBUpdate Or TerrainSectorAABBUpdate.length<>terrain.sectors*terrain.sectors
    	TerrainSectorAABBUpdate=New Byte[terrain.sectors,terrain.sectors]
    EndIf
    
    If editmode<>1
    	terrbuffer=terrain.heightbuffer
    	texture=terrain.heightmap
    Else
    	terrbuffer=terrain.alphabuffer
    	texture=terrain.alphatexture
    EndIf
    
    x0=Floor((0.5+(x-outerradius+0.5*terrain.scale.x)/(Float(terrain.resolution)*terrain.meterspertile))*(terrain.resolution-1))
    x1=Ceil((0.5+(x+outerradius+0.5*terrain.scale.x)/(Float(terrain.resolution)*terrain.meterspertile))*(terrain.resolution-1))
    z0=Floor((0.5+(z-outerradius+0.5*terrain.scale.x)/(Float(terrain.resolution)*terrain.meterspertile))*(terrain.resolution-1))
    z1=Ceil((0.5+(z+outerradius+0.5*terrain.scale.x)/(Float(terrain.resolution)*terrain.meterspertile))*(terrain.resolution-1))
    
    'Figure out which sectors are affected and need their AABBs updated (skip for paint edit mode)
    If editmode<>1 And editmode<>4 And editmode<>5
    	Local sx0:Int,sx1:Int,sz0:Int,sz1:Int
    	sx0=Floor(x0/Float(terrain.sectorresolution))
    	sx1=Ceil(x1/Float(terrain.sectorresolution))-1
    	sz0=Floor(z0/Float(terrain.sectorresolution))
    	sz1=Ceil(z1/Float(terrain.sectorresolution))-1
    	If sx0<0 sx0=0
    	If sz0<0 sz0=0
    	If sx1>terrain.sectors-1 sx1=terrain.sectors-1
    	If sz1>terrain.sectors-1 sz1=terrain.sectors-1
    	For x=sx0 To sx1
    		For z=sz0 To sz1
    			TerrainSectorAABBUpdate[x,z]=1
    		Next
    	Next
    EndIf
    
    'Create small image
    If editmode=1
    	format=TEXTURE_RGBA8
    Else
    	If GetGraphicsVendor()=VENDOR_NVIDIA
    		If GetShaderModel()=4
    			format=TEXTURE_FLOAT32
    		Else
    			format=TEXTURE_FLOAT
    			Print 1
    		EndIf
    	Else
    		format=TEXTURE_FLOAT32
    	EndIf
    EndIf
    w=x1-x0+1+1+1
    h=z1-z0+1+1+1
    tw=Pow2(w,1)
    th=Pow2(h,1)
    If tw<2 tw=2
    If th<2 th=2	
    'If tw<64 tw=64
    'If th<64 th=64	
    If toolimage
    	If toolimage.width()<>tw Or toolimage.height()<>th
    		toolimage=Null
    	EndIf
    EndIf
    If toolimage
    	If TextureFormat(toolimage)<>format toolimage=Null
    EndIf
    If Not toolimage
    	toolimage=CreateTexture(tw,th,format)
    	'If TextureFormat(toolimage)<>format Notify 1
    	toolimagebuffer=CreateBuffer(tw,th,BUFFER_COLOR)
    	toolimage.setfilter(TEXFILTER_PIXEL)
    	toolimage.bind()
    	SetColorBuffer(toolimagebuffer,toolimage)		
    EndIf
    
    If editmode=1
    	Select channel
    		Case 0
    			If strength>0.0
    				channelmask[0]=-1.0
    				channelmask[1]=-1.0
    				channelmask[2]=-1.0
    				channelmask[3]=-1.0
    			Else
    				channelmask[0]=0.0
    				channelmask[1]=0.0
    				channelmask[2]=0.0
    				channelmask[3]=0.0
    			EndIf
    		Case 1
    			If strength>0.0
    				channelmask[0]=1.0
    				channelmask[1]=-1.0
    				channelmask[2]=-1.0
    				channelmask[3]=-1.0
    			Else
    				channelmask[0]=1.0
    				channelmask[1]=0.0
    				channelmask[2]=0.0
    				channelmask[3]=0.0
    			EndIf
    		Case 2
    			If strength>0.0
    				channelmask[0]=0.0
    				channelmask[1]=1.0
    				channelmask[2]=-1.0
    				channelmask[3]=-1.0
    			Else
    				channelmask[0]=0.0
    				channelmask[1]=1.0
    				channelmask[2]=0.0
    				channelmask[3]=0.0
    			EndIf
    		Case 3
    			If strength>0.0
    				channelmask[0]=0.0
    				channelmask[1]=0.0
    				channelmask[2]=1.0
    				channelmask[3]=-1.0
    			Else
    				channelmask[0]=0.0
    				channelmask[1]=0.0
    				channelmask[2]=1.0
    				channelmask[3]=0.0
    			EndIf
    		Case 4
    			If strength>0.0
    				channelmask[0]=0.0
    				channelmask[1]=0.0
    				channelmask[2]=0.0
    				channelmask[3]=1.0
    			Else
    				channelmask[0]=0.0
    				channelmask[1]=0.0
    				channelmask[2]=0.0
    				channelmask[3]=1.0
    			EndIf
    	EndSelect
    Else
    	channelmask[0]=1.0
    	channelmask[1]=1.0
    	channelmask[2]=1.0
    	channelmask[3]=1.0
    
    	If Not editterrainaabb
    		editterrainaabb=New TAABB
    		editterrainaabb.x0=-infinity
    		editterrainaabb.y0=-infinity
    		editterrainaabb.z0=-infinity
    		editterrainaabb.x1=infinity
    		editterrainaabb.y1=infinity
    		editterrainaabb.z1=infinity
    	EndIf
    	editterrainaabb.x0=Min(editterrainaabb.x0,x-outerradius)
    	editterrainaabb.z0=Min(editterrainaabb.z0,z-outerradius)
    	editterrainaabb.x1=Max(editterrainaabb.x1,x+outerradius)
    	editterrainaabb.z1=Max(editterrainaabb.z1,z+outerradius)		
    EndIf
    
    'Disable heightmap linear filter
    glActiveTextureARB GL_TEXTURE15
    glTexParameteri GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST
    glTexParameteri GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST
    glActiveTextureARB GL_TEXTURE0
    
    'Draw heightmap onto small image
    SetBuffer(toolimagebuffer)
    SetShader Null
    'Global Texture_Contour:TTexture
    'If Not Texture_Contour Texture_Contour=LoadTexture("abstract::crysisocean_DISP.dds")
    'BindTexture Texture_Contour,1
    SetColor vec4(1)
    FlipImage(texture,-x0+1.0,-z0+1.0)
    SetColor vec4(1)
    SetBuffer(BackBuffer())
    
    terrainsize=(Float(terrain.resolution)*Terrain.meterspertile)
    ix:-terrain.scale.x*0.5
    iz:-1
    cx=((ix/terrain.scale.x+0.5*Float(terrain.resolution))/Float(terrain.resolution))+0.5/Float(terrain.resolution)
    cy=((iz/terrain.scale.z+0.5*Float(terrain.resolution))/Float(terrain.resolution))+0.5/Float(terrain.resolution)
    
    'Load terrain edit shader
    If Not terrainfilter[editmode]
    	terrainfilter[editmode]=LoadShader("abstract::generic.vert","abstract::terraintool.frag","#define TOOLMODE "+editmode+"~n")
    EndIf
    
    'Set shader uniforms
    toolceiling=Min(1.0,toolceiling)
    toolfloor=Max(0.0,toolfloor)
    constraints[0]=toolfloor'0'Float(SliderValue(Gadget_TerrainToolFloor)-1)/29.0
    constraints[1]=toolceiling'1'Float(SliderValue(Gadget_TerrainToolCeiling)-1)/29.0
    If strength>0.0 constraints[0]=0.0
    If strength<0.0 constraints[1]=1.0
    If editmode>1
    	constraints[0]=0.0
    	constraints[1]=1.0	
    EndIf
    SetShaderVec2 terrainfilter[editmode],"toolposition",[cx,cy]
    SetShaderVec2 terrainfilter[editmode],"toolradius",[outerradius/terrain.size,innerradius/terrain.size]
    SetShaderFloat terrainfilter[editmode],"toolstrength",strength
    SetShaderFloat terrainfilter[editmode],"flattenheight",flattenheight
    SetShaderVec2 terrainfilter[editmode],"heightmapsize",[Float(terrain.resolution),Float(terrain.resolution)]
    SetShaderVec2 terrainfilter[editmode],"imagesize",[Float(tw),Float(th)]
    SetShaderVec4 terrainfilter[editmode],"channelmask",channelmask
    SetShaderVec2 terrainfilter[editmode],"constraints",constraints
    
    'Draw the small image onto the heightmap
    buffer=GetBuffer()
    SetBuffer(terrbuffer)
    SetShader terrainfilter[editmode]
    glCheckError()
    flipImage(toolimage,x0-1,z0-1)
    glCheckError()
    SetBuffer buffer
    SetShader(Null)
    
    'Update the normals of the edited area
    If editmode<>1
    	terrain.UpdateNormals(x0-1,z0-1,w,h)
    EndIf
    
    'Restore heightmap linear filter
    glActiveTextureARB GL_TEXTURE15
    glTexParameteri GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR
    glTexParameteri GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR
    glActiveTextureARB GL_TEXTURE0
    
    terrain.generatecolormap()
    EndFunction
    
    
    Function FlipImage(image:TTexture,x,y)
    image.bind(0)
    glcolor4f 1,1,1,1
    glEnable image.target()
    gldisable GL_CULL_FACE
    DrawRect x,BufferHeight(GetBuffer())-y,image.width(),-image.height()
    glDisable image.target()
    
    Function DrawRect(x,y,width,height)
    	glBegin GL_QUADS
    	glTexCoord2f 0.0,0.0
    	glVertex2i x,y
    	glTexCoord2f 0.0,1.0
    	glVertex2i x,y+height
    	glTexCoord2f 1.0,1.0
    	glVertex2i x+width,y+height
    	glTexCoord2f 1.0,0.0
    	glVertex2i x+width,y
    	glEnd
    EndFunction	
    
    EndFunction

  8. I think it looks good. They're using a forward renderer in that shot, which can be good in an outdoors scene with one directional light. However, it doesn't allow for shadow-casting point or spot lights.

     

    With MSAA the edges of trees and small objects will look a lot smoother, pretty close to that image. MSAA will be added when the engine is updated to use OpenGL 3.

  9. - Make LWE deployable to lower end specs (and I don't mean 300bucks mini laptops, but for example I can run L4D2 on a GeForce go 7600, but I can't run leadwerks at decent framerates).

    Yes you can. Turn off shadows.

     

    Left 4 dead uses a combination of static lightmaps and single projected shadows, with vertex colors for lighting of dynamic objects. This is the approach I used to use before version 2.0 came out. I will never again implement a bsp-based engine like this.

     

    One consequence of a uniform lighting model like STALKER and Crysis use is that on low-end cards the older engines may actually look better than the newer one with settings lowered. The same was true when HL2 came out; the fixed-function renderer was so simple it looked worse than Quake 3.

×
×
  • Create New...