fog problem with OpenGL

i have a fog problem with Opengl: some 3D objects in the scene have fog effect but some don’t. (they all have correct normals, and lighting effect on them is correct).
so now i use DX9 as renderer. but DX9 has much less performance on my PC (40FPS with DX9 vs 100FPS with Opengl)

i have a small program written in ASM and render with OpenGL functions, the fog is correct in that program, which means my graphic card drivers is not wrong.

is there a way to solve the fog problem with Opengl in Panda3D?

You’ll need to provide some more details.
What language are you using ? Python or c++ ?
Can you provide some simple test code that won’t work for you ?

i am using python. this is my code to setup fog. it works well in Dx9, but wrong in Opengl.

self.fog0color=(0.66,0.75,0.85,1.0)
base.setBackgroundColor(self.fog0color)
self.fog0=Fog(“distancefog”)
self.fog0.setColor(self.fog0color)
self.fog0.setMode(Fog.MExponentialSquared)
self.fog0.setExpDensity(0.0002)
render.setFog(self.fog0)

i also have directional light and ambient light in my scene, they also work well in DX9.

there are only 1 flat ocean mesh and 1 geomipterrain in my scene.

i think the problem is graphic driver specific. the way Panda3D setups the fog is not suitable for my graphic driver.

can you tell me where i can find the internal code of Panda3D on the subject FOG ? maybe i would check how Panda3D setup the fog when the graphics API is Opengl, and modify them like the procedure i setup fog in ASM.

It’s possible that you are not getting fog effect on some nodes in your scene because you have called setShaderAuto() on them, which switches the fixed-function pipeline of the rendering for that node to a shader generated by the ShaderGenerator. As ShaderGenerator doesn’t support fog, you won’t see fog on that node. Now this might not be noticeable in DX9 rendering mode because the ShaderGenerator was written for OpenGL, so it’s possible that those nodes have fog applied on them because no shaders are generated and they are rendered with the fixed-function, even if you called setShaderAuto().
If this is the case, I’m afraid there is no easy workaround. You’ll have to edit the ShaderGenerator class and add fog support yourself, or not use the shaders provided by Panda at all on these nodes.

i didn’t use any function of shader.
my scene has an ocean made of a flat mesh(from egg file) and a geomipterrain(from png file) with material and texture.
they are setup in the most simple ways - the least possible calls.

the only settings about shader i can think of , is the config file, this is my config file:

#load-display pandagl
load-display pandadx9
#load-display pandadx8
framebuffer-hardware 1
framebuffer-software 0
display-lists 1
display-list-animation 1
force-parasite-buffer 0
prefer-parasite-buffer 1
prefer-single-buffer 0
shader-utilization none
support-render-texture 0
texture-anisotropic-degree 1

texture-minfilter linear
textures-square none

win-origin 0 0
win-size 1024 768
#aspect-ratio 1.333333333333333333333333333333333
pixel-zoom 1.0
fullscreen 0
undecorated 1
window-title Panda3D
cursor-hidden 1
background-color 0.25 0.5 0.75
sync-video 1
want-pstats 0
text-minfilter linear
text-anisotropic-degree 1
text-quality-level best
text-render-mode texture
text-scale-factor 1.0
text-small-caps 0
text-small-caps-scale 0.6
text-tab-width 5.0
#text-default-font
#clock-degrade-factor 1.0
#clock-mode limited
#clock-frame-rate 100.0

depth-bits 1
color-bits 1
alpha-bits 0
stencil-bits 0
multisamples 0

notify-level error
default-directnotify-level error

model-path $MAIN_DIR
model-path $THIS_PRC_DIR/…
model-path $THIS_PRC_DIR/…/models
#particle-path

want-directtools f
want-tk f

track-memory-usage 0
report-memory-usage 0

audio-library-name p3openal_audio
audio-volume 1.0
audio-doppler-factor 1.0
audio-drop-off-factor 1.0
audio-buffering-seconds 3.0
audio-cache-limit 8
audio-min-hw-channels 15
audio-output-rate 22050
audio-preload-threshold 1000000
fmod-number-of-sound-channels 32

use-movietexture 0
hardware-animated-vertices 0

#model-cache-dir $USER_APPDATA/Panda3D-1.7/cache
model-cache-textures 0
transform-cache 0

basic-shaders-only 1

support-rescale-normal 1
#rescale-normals none
premunge-data 0
preload-textures 0
max-texture-dimension 1024
max-texture-stages 3
simple-image-size 16 16
jpeg-quality 95
compress-chan-quality 95
compressed-textures 1
driver-compress-textures 1
driver-generate-mipmaps 0
gl-force-mipmaps 0
gl-force-no-error 1
gl-ignore-filters 0
gl-ignore-mipmaps 0
graphics-memory-limit -1

coordinate-system z-up
default-far 80000.0
default-near 0.8
default-fov 45.0
depth-offset-decals 0
retransform-sprites 0

default-lod-type pop
support-fade-lod 0
lod-fade-time 0.5
view-frustum-cull 1
vertex-data-compression-level 1
vertex-data-small-size 64
#vertex-save-file-directory
egg-mesh 0
egg-suppress-hidden 0
egg-coplanar-threshold 0.01
default_max_angular_dt 0.033333333333333333333333333
default_max_linear_dt 0.033333333333333333333333333
default_terminal_velocity 400.0

disable-sticky-keys 0

even-animation 0
restore-initial-pose 0

Mind posting your code? It’ll help everyone to solve your problem a lot faster.

i can’t upload attachment here, so 5 files are missing in this code:
ocean.egg ocean.bmp land1.png land1.jpg arial.ttf

from	pandac.PandaModules import loadPrcFileData
loadPrcFileData("", ''' show-frame-rate-meter 0 ''')
loadPrcFileData("", ''' sync-video 1 ''')
loadPrcFileData("", ''' clock-mode limited ''')
loadPrcFileData("", ''' clock-frame-rate 50.0 ''')
loadPrcFileData("", ''' cursor-hidden 1 ''')
loadPrcFileData("", ''' undecorated 1 ''')
loadPrcFileData("", ''' fullscreen 0 ''')
loadPrcFileData("", ''' win-origin 0 0 ''')
loadPrcFileData("", ''' win-size 1024 768 ''')
loadPrcFileData("", ''' aspect-ratio 1.333333333333333333333333333333333333333333333333 ''')
loadPrcFileData("", ''' coordinate-system z-up ''')
loadPrcFileData("", ''' text-minfilter linear ''')
loadPrcFileData("", ''' texture-minfilter linear ''')
loadPrcFileData("", ''' max-texture-dimension 1024 ''')
loadPrcFileData("", ''' max-texture-stages 3 ''')
loadPrcFileData("", ''' view-frustum-cull 1 ''')
loadPrcFileData("", ''' exclude-texture-scale land1.jpg ''')
loadPrcFileData("", ''' basic-shaders-only 1 ''')
loadPrcFileData("", ''' rescale-normals auto ''')
import	sys,os,random,math
from	math import pi,sin,cos,tan,sqrt
from	direct.showbase import Audio3DManager
from	direct.showbase.ShowBase import ShowBase
from	direct.showbase.DirectObject import DirectObject
from	direct.gui.OnscreenText import OnscreenText
from	panda3d.core import PerspectiveLens,TextureStage,Material
from	panda3d.core import AmbientLight,DirectionalLight,Fog,GeoMipTerrain
from	panda3d.core import PandaNode,NodePath,Camera,TextNode
from	panda3d.core import Point3,Vec3,Vec4,BitMask32
from	panda3d.core import CollisionTraverser,CollisionNode,CollisionHandlerQueue,CollisionRay
from	pandac.PandaModules import Filename
from	direct.task import Task

class Simulator(ShowBase):
	def __init__(self):
		ShowBase.__init__(self)
		self.interval=0.02
		self.aspect=1024.0/768.0
		self.fov=45.0
		self.nearclip=0.5
		self.farclip=5000.0
		base.camLens.setAspectRatio(self.aspect)
		base.camLens.setNearFar(self.nearclip,self.farclip)
		base.camLens.setFov(self.fov)

		self.fog0color=(0.66,0.75,0.85,1.0)
		base.setBackgroundColor(self.fog0color)
		self.fog0=Fog("distancefog")
		self.fog0.setColor(self.fog0color)
		self.fog0.setMode(Fog.MExponentialSquared)
		self.fog0.setExpDensity(0.0002)
		render.setFog(self.fog0)
		self.suncolor=Vec4(1.0,1.0,1.0,1.0)
		self.sun=DirectionalLight('sunlight')
		self.sun.setColor(self.suncolor)
		self.sun.setSpecularColor(self.suncolor)
		self.sun.setDirection(Vec3(0.1,0.9,-0.9))
		render.setLight(render.attachNewNode(self.sun))
		self.ambientlightcolor=Vec4(0.1,0.1,0.1,1.0)
		self.ambientlight=AmbientLight('ambientlight')
		self.ambientlight.setColor(self.ambientlightcolor)
		render.setLight(render.attachNewNode(self.ambientlight))

		self.showhud=0
		self.frametime1=self.frametime2=0.0
		self.hudtimer=0
		self.zoomtimer=9
		self.simmode=0
		self.eye2cg=1.0
		self.groundheight=0.0
		self.camminheight=0.25
		self.cammaxheight=50000.0
		self.camspeed=0.0
		self.camforwardtimer=0
		self.camsidetimer=0
		self.mapwidth=1000000.0
		self.borderwidth=60000.0
		self.startx0=500000.0
		self.starty0=500000.0
		self.startz0=1500.0
		self.cgcoordx=self.startx0
		self.cgcoordy=self.starty0
		self.cgcoordz=self.startz0
		self.startx=self.startx0
		self.starty=self.starty0
		self.startz=self.startz0
		self.camcoordx=self.startx
		self.camcoordy=self.starty
		self.camcoordz=self.startz
		self.camheading=self.campitch=self.camlean=0.0
		self.mousex=self.mousey=0
		self.campanrate=0.11
		self.campitchrate=0.1
		self.camshakeh=self.camshakep=self.camshaker=0.0
		self.camskrateh=self.camskratep=self.camskrater=0.0
		self.deg2rad=pi/180.0
		self.rad2deg=180.0/pi
		self.mousebtn=[0,0,0]
		self.keymap={"keyi":0,"keyk":0,"keyj":0,"keyl":0,"keyu":0,"keyo":0,"keyn":0,
			"ctrl0":0,"ctrl1":0,"ctrl2":0,"ctrl3":0,"up":0,"down":0,"left":0,"right":0}
		self.accept("i",self.setkey,["keyi",1])
		self.accept("i-up",self.setkey,["keyi",0])
		self.accept("k",self.setkey,["keyk",1])
		self.accept("k-up",self.setkey,["keyk",0])
		self.accept("j",self.setkey,["keyj",1])
		self.accept("j-up",self.setkey,["keyj",0])
		self.accept("l",self.setkey,["keyl",1])
		self.accept("l-up",self.setkey,["keyl",0])
		self.accept("u",self.setkey,["keyu",1])
		self.accept("u-up",self.setkey,["keyu",0])
		self.accept("o",self.setkey,["keyo",1])
		self.accept("o-up",self.setkey,["keyo",0])
		self.accept("n",self.setkey,["keyn",1])
		self.accept("n-up",self.setkey,["keyn",0])
		self.accept("arrow_up",self.setkey,["up",1])
		self.accept("arrow_up-up",self.setkey,["up",0])
		self.accept("arrow_down",self.setkey,["down",1])
		self.accept("arrow_down-up",self.setkey,["down",0])
		self.accept("arrow_left",self.setkey,["left",1])
		self.accept("arrow_left-up",self.setkey,["left",0])
		self.accept("arrow_right",self.setkey,["right",1])
		self.accept("arrow_right-up",self.setkey,["right",0])
		self.accept("control-0",self.setkey,["ctrl0",1])
		self.accept("control-1",self.setkey,["ctrl1",1])
		self.accept("control-2",self.setkey,["ctrl2",1])
		self.accept("control-3",self.setkey,["ctrl3",1])
		self.accept("control-h",self.setkey,["ctrlh",1])
		self.keymap["ctrlh"]=0
		base.disableMouse()
		base.win.movePointer(0,512,384)
		self.accept("mouse1",self.mousebutton,[0,1])
		self.accept("mouse1-up",self.mousebutton,[0,0])
		self.accept("mouse2",self.mousebutton,[1,1])
		self.accept("mouse2-up",self.mousebutton,[1,0])
		self.accept("mouse3",self.mousebutton,[2,1])
		self.accept("mouse3-up",self.mousebutton,[2,0])
		self.arial=loader.loadFont('model/arial.ttf')
		self.simmodetext=["MODE1","MODE2","MODE3","MODE4"]
		self.ocean=self.loader.loadModel("model/ocean")
		self.ocean.reparentTo(render)
		self.ocean.setScale(1,1,1)
		self.ocean.setPos(0,0,0)
		for oceanIDy in range(10):
			for oceanIDx in range(10):
				oceanrepeat = render.attachNewNode("oceanrepeater")
				oceanrepeat.setPos(oceanIDx*99999.9,oceanIDy*99999.9,0)
				self.ocean.instanceTo(oceanrepeat)
		self.land1=GeoMipTerrain("Land1")
		self.land1.setHeightfield("model/land1.png")
		self.land1.getRoot().reparentTo(render)
		self.land1scalex=self.land1scaley=50.0
		self.land1scalez=2560.0
		self.land1offx=self.land1offy=475000.0
		self.land1offz=-6.0
		self.land1.getRoot().setScale(self.land1scalex,self.land1scaley,self.land1scalez)
		self.land1.getRoot().setPos(self.land1offx,self.land1offy,self.land1offz)
		self.land1.setBlockSize(64)
		self.land1.setNearFar(10000.0,20000.0)
		self.land1.setFocalPoint(base.camera)
		self.land1.setAutoFlatten(GeoMipTerrain.AFMOff)
		self.land1skin=TextureStage('Land1skin')
		self.land1jpg=loader.loadTexture('model/land1.jpg')
		self.land1jpg.setMagfilter(self.land1jpg.FTLinear)
		self.land1jpg.setMinfilter(self.land1jpg.FTLinear)
		self.land1.getRoot().setTexture(self.land1skin,self.land1jpg)
		self.land1mat=Material()
		self.land1mat.setShininess(20.0)
		self.land1mat.setAmbient(Vec4(1,1,1,1))
		self.land1mat.setDiffuse(Vec4(1,1,1,1))
		self.land1mat.setEmission(Vec4(0,0,0,0))
		self.land1mat.setSpecular(Vec4(0.03,0.03,0.03,0.03))
		self.land1.getRoot().setMaterial(self.land1mat)
		self.land1.generate()

		taskMgr.add(self.mode1,"mode1-task")
		taskMgr.add(self.mode2,"mode2-task")
		taskMgr.add(self.mode3,"mode3-task")
		taskMgr.add(self.mode4,"mode4-task")

	def setkey(self,key,value):
		self.keymap[key]=value
	def mousebutton(self,id,value):
		self.mousebtn[id]=value
	def updatehud(self):
		self.frametime2=globalClock.getFrameTime()
		self.averframerate=10.0/(self.frametime2-self.frametime1)
		self.frametime1=self.frametime2
		self.frameratetext.setText(str(int(self.averframerate)))
		self.info1.setText(str(int(self.camheading)))
		self.info2.setText(str(int(self.campitch)))
		self.info3.setText(str(int(self.camlean)))
		self.info4.setText(str(float(int(self.camcoordx*10))/10))
		self.info5.setText(str(float(int(self.camcoordy*10))/10))
		self.info6.setText(str(float(int(self.camcoordz*10))/10))
		self.hudtimer=0
	def togglehud(self):
		if (self.showhud==1):self.hudoff()
		else:self.hudon()
		self.keymap["ctrlh"]=0
	def hudon(self):
		self.frameratetext=OnscreenText(text="0",
			style=2,font=self.arial,fg=(1,1,1,1),pos=(-1.30,0.96),scale=.05)
		self.simmodetitle=OnscreenText(text=self.simmodetext[self.simmode],
			style=1,font=self.arial,fg=(1,1,1,1),pos=(1.16,-0.97),scale=.03)
		self.title=OnscreenText(text="Simulator",style=2,font=self.arial,
			fg=(1,1,1,1),pos=(1.05,-0.93),scale=.09)
		self.infohpr=OnscreenText(text="H           P          R",
			style=1,font=self.arial,fg=(1,1,1,1),pos=(-1.16,-0.98),scale=.04)
		self.infoxyz=OnscreenText(text="X                     Y                    Z",
			style=1,font=self.arial,fg=(1,1,1,1),pos=(-0.50,-0.98),scale=.04)
		self.info1=OnscreenText(text="0",
			style=1,font=self.arial,fg=(1,1,1,0.7),pos=(-1.24,-0.98),scale=.04)
		self.info2=OnscreenText(text="0",
			style=1,font=self.arial,fg=(1,1,1,0.7),pos=(-1.10,-0.98),scale=.04)
		self.info3=OnscreenText(text="0",
			style=1,font=self.arial,fg=(1,1,1,0.7),pos=(-0.97,-0.98),scale=.04)
		self.info4=OnscreenText(text="0",
			style=1,font=self.arial,fg=(1,1,1,0.7),pos=(-0.63,-0.98),scale=.04)
		self.info5=OnscreenText(text="0",
			style=1,font=self.arial,fg=(1,1,1,0.7),pos=(-0.38,-0.98),scale=.04)
		self.info6=OnscreenText(text="0",
			style=1,font=self.arial,fg=(1,1,1,0.7),pos=(-0.15,-0.98),scale=.04)
		self.showhud=1
		self.hudtimer=0
	def hudoff(self):
		self.frameratetext.destroy()
		self.simmodetitle.destroy()
		self.title.destroy()
		self.infohpr.destroy()
		self.infoxyz.destroy()
		self.info1.destroy()
		self.info2.destroy()
		self.info3.destroy()
		self.info4.destroy()
		self.info5.destroy()
		self.info6.destroy()
		self.showhud=0
	def readmouse(self):
		getmousepos=base.win.getPointer(0)
		self.mousex=getmousepos.getX()
		self.mousey=getmousepos.getY()
		base.win.movePointer(0,512,384)
	def camleanreturn(self):
		if (self.camlean==0):return
		if (self.camlean<0.05) & (self.camlean>-0.05):self.camlean=0.0
		else:self.camlean*=0.92
	def getcamhpr1(self):
		self.camheading-=(self.mousex-512)*self.campanrate*self.fov*self.interval
		self.campitch-=(self.mousey-384)*self.campitchrate*self.fov*self.interval
		if (self.camheading<-180):self.camheading+=360
		if (self.camheading>180):self.camheading-=360
		if (self.campitch<-75):self.campitch=-75
		if (self.campitch>75):self.campitch=75
	def getcamhpr2(self):
		return
	def getgroundheight(self,groundx,groundy):
		return
	def camclamp(self):
		self.camcoordz=max(self.camcoordz,self.groundheight+self.camminheight)
		self.camcoordz=min(self.camcoordz,self.cammaxheight)
		self.camcoordx=min(self.camcoordx,self.mapwidth-self.borderwidth)
		self.camcoordx=max(self.camcoordx,self.borderwidth)
		self.camcoordy=min(self.camcoordy,self.mapwidth-self.borderwidth)
		self.camcoordy=max(self.camcoordy,self.borderwidth)
	def freecammove(self):
		forward=self.keymap["up"]-self.keymap["down"]
		side=self.keymap["left"]-self.keymap["right"]
		if (forward==0):self.camforwardtimer=int(self.camforwardtimer*0.95)
		elif (forward>0):self.camforwardtimer+=1
		else:self.camforwardtimer-=1
		if (side==0):self.camsidetimer=int(self.camsidetimer*0.95)
		elif (side>0):self.camsidetimer+=1
		else:self.camsidetimer-=1
		forwardspeed=self.camforwardtimer*25.0
		sidespeed=self.camsidetimer*25.0
		pitchcos=cos(self.campitch*self.deg2rad)
		headingsin=sin(self.camheading*self.deg2rad)
		headingcos=cos(self.camheading*self.deg2rad)
		self.camcoordx-=(forwardspeed*headingsin*pitchcos+sidespeed*headingcos)*self.interval
		self.camcoordy+=(forwardspeed*headingcos*pitchcos-sidespeed*headingsin)*self.interval
		self.camcoordz+=forwardspeed*sin(self.campitch*self.deg2rad)*self.interval
		if (self.mousebtn[0]==1):
			self.startx=self.camcoordx
			self.starty=self.camcoordy
			self.startz=self.camcoordz
		if (self.mousebtn[2]==1):
			self.camcoordx=self.startx0
			self.camcoordy=self.starty0
			self.camcoordz=self.startz0
	def globaltask1(self):
		base.win.closeIme()
		self.land1.update()
		self.readmouse()
	def globaltask2(self):
		base.camera.setHpr(self.camheading,self.campitch,self.camlean)
		base.camera.setPos(self.camcoordx,self.camcoordy,self.camcoordz)
		if (self.keymap["ctrlh"]==1):self.togglehud()
		if (self.showhud==1):
			self.hudtimer+=1
			if (self.hudtimer==10):self.updatehud()
	def camzoom1(self):
		if (self.mousebtn[1]==1):
			if (self.zoomtimer==0):self.fpszoom()
		elif (self.zoomtimer>0):self.zoomtimer-=1
	def fpszoom(self):
		if (self.fov<3.0):self.fov=45.0
		else:self.fov*=0.25
		self.nearclip=0.5*45.0/self.fov
		self.farclip=5000.0*sqrt(45.0/self.fov)
		base.camLens.setNearFar(self.nearclip,self.farclip)
		base.camLens.setFov(self.fov)
		self.zoomtimer=25
	def simmodeswitch(self,targetmode):
		self.simmode=targetmode
		self.keymap["ctrl0"]=0
		self.keymap["ctrl1"]=0
		self.keymap["ctrl2"]=0
		self.keymap["ctrl3"]=0
		if (self.showhud==1):self.simmodetitle.setText(self.simmodetext[targetmode])
	def mode4(self,task):
		if (self.simmode!=3):return Task.cont
		if (self.keymap["ctrl0"]==1):self.simmodeswitch(0)
		elif (self.keymap["ctrl1"]==1):self.simmodeswitch(1)
		elif (self.keymap["ctrl2"]==1):self.simmodeswitch(2)
		self.globaltask1()
		self.globaltask2()
		return Task.cont
	def mode3(self,task):
		if (self.simmode!=2):return Task.cont
		if (self.keymap["ctrl0"]==1):self.simmodeswitch(0)
		elif (self.keymap["ctrl1"]==1):self.simmodeswitch(1)
		elif (self.keymap["ctrl3"]==1):self.simmodeswitch(3)
		self.globaltask1()
		self.globaltask2()
		return Task.cont
	def mode2(self,task):
		if (self.simmode!=1):return Task.cont
		if (self.keymap["ctrl0"]==1):self.simmodeswitch(0)
		elif (self.keymap["ctrl2"]==1):self.simmodeswitch(2)
		elif (self.keymap["ctrl3"]==1):self.simmodeswitch(3)
		self.globaltask1()
		self.getcamhpr1()
		self.camcoordx=self.cgcoordx
		self.camcoordy=self.cgcoordy
		self.camcoordz=self.cgcoordz+self.eye2cg*cos(self.camlean)
		self.camzoom1()
		self.globaltask2()
		return Task.cont
	def mode1(self,task):
		if (self.simmode!=0):return Task.cont
		if (self.keymap["ctrl1"]==1):self.simmodeswitch(1)
		elif (self.keymap["ctrl2"]==1):self.simmodeswitch(2)
		elif (self.keymap["ctrl3"]==1):self.simmodeswitch(3)
		self.globaltask1()
		self.getcamhpr1()
		self.camleanreturn()
		self.freecammove()
		self.getgroundheight(self.camcoordx,self.camcoordy)
		self.camclamp()
		self.camzoom1()
		self.globaltask2()
		return Task.cont

app=Simulator()
run()

the ocean.egg file is simple though:


<CoordinateSystem> { Z-Up }

<Texture> oceanbmp {	ocean.bmp
	<Scalar> format { rgb }
	<Scalar> wrapu { repeat }
	<Scalar> wrapv { repeat }
	<Scalar> minfilter { linear }
	<Scalar> magfilter { linear }}

<Group> ocean { <Collide> { Plane Keep }
<VertexPool> oceanvertex {
<Vertex> 1 { 0.0 0.0 0.0
	<UV> { 0.0 0.0 }
	<Normal> { 0.0 0.0 1.0 }}

<Vertex> 2 { 100000.0 0.0 0.0
	<UV> { 100.0 0.0 }
	<Normal> { 0.0 0.0 1.0 }}

<Vertex> 3 { 100000.0 100000.0 0.0
	<UV> { 100.0 100.0 }
	<Normal> { 0.0 0.0 1.0 }}

<Vertex> 4 { 0.0 100000.0 0.0
	<UV> { 0.0 100.0 }
	<Normal> { 0.0 0.0 1.0 }}}

<Polygon> {
	<Normal> { 0.0 0.0 1.0 }
	<TRef> { oceanbmp }
	<VertexRef> { 1 2 3 4 <Ref> { oceanvertex }}}
}

in my code,
Ctrl+0,1,2,3 switch modes.
only MODE1 is functioning: arrowkeys move camera, mouse rotates camera and middle button zooms.
Ctrl+h toggles onscreentext.

Hmm, I don’t suppose you could post a simpler program that demonstrates your problem with fog? I tried running your code above, but it’s quite complex, and all I see is a thin stripe of ocean in the foreground against a blue screen. Keyboard buttons and mouse buttons don’t appear to be functional when I run it.

For the record, Panda enables fog for OpenGL mode in glGraphicsStateGuardian_src.cxx, in the apply_fog() method. But I don’t understand what you mean when you say you want to use ASM to do the same thing. Are you referring to assembly language, or something different? What does assembly language have to do with OpenGL?

When you say “some objects” don’t receive fog, what do you mean? The code you pasted above doesn’t seem to load any objects except for the ocean.

David

i testran the code before posting, it ran correctly.
the code has a free cam movement function for the purpose of testing.

possible explanation of wrong test result on your PC:

  1. some lines in the code have been altered because of word wrap when posted, such as the paragraphs:

self.keymap={…}
self.land1.getRoot().setScale(…)
def getcamhpr1()
def simmodeswitch()
def freecammove()

  1. the free cam movement mode is activated at the start of program, it is MODE1-task, corresponding switch key is Ctrl+0 . currently the camera can only be moved in this mode. modes of Ctrl+1,2,3 are still empty.

  2. in the code , a file /model/LAND1.PNG should be loaded, it is for the geomipterrain. as the file was not posted, you can’t see the terrain , but if you have any grayscale image to put into the sub folder, it can work.

  3. the screen color should be almost white, i used setBackgroundColor() to make it white:
    self.fog0color=(0.66,0.75,0.85,1.0)
    base.setBackgroundColor(self.fog0color)

to sum up, in my scene, there is a flat ocean with dimension of 1,000,000.0 x 1,000,000.0 units made by a sqare polygon repeaded 100 times. in the middle of the scene , there is a terrain of 50k x 50k units. the background color and fog color are both almost white.

too bad i can’t post a zip file containing necessary 3D models.


i mentioned about ASM. i meant, i wrote a program in ASM language, and i know the procedure of setting up fog with Opengl API functions , such as

invoke glFogi,GL_FOG_MODE,GL_LINEAR
invoke glFogfv,GL_FOG_COLOR,addr fogcolor
invoke glEnable,GL_FOG

i can rewrite the C language like i wrote the procedure in ASM language - if the procedure in Panda3D is different from my procedure. because my ASM program shows fog correctly on my PC.

But in what way does your program demonstrate fog not working? What part of it doesn’t have fog that should have fog?

And does fog work for you if you just create a simple model and parent it to render, with fog enabled on it? At what point does fog not work?

David

when i tested my program previously, the ocean didn’t receive fog correcly, the terrain received fog correctly with Opengl.
with DX9, the fog was correct on both the ocean and the terrain.

just now i tested again, i found the fog was related to the direction of camera.
at some heading, the fog is gone, when i pan the camera, the fog increase quickly and soon i can’t see the ocean at all (the fog being too dense). same thing to the pitch of camera.

It sounds like your driver is enabling vertex-based fog (as opposed to the more usual pixel-based fog), which some drivers do to save processing time.

One of the artifacts of vertex-based fog is that a very large polygon will tend to be fogged incorrectly, especially if you use a non-linear fog equation. The workaround is to add more intermediate vertices to your polygon.

Edit: there also might be a user-configurable preference setting for this in your driver settings. Worth taking a look to see if there’s an option to use pixel-based fog instead of vertex-based fog. (There’s no way in OpenGL to select one or the other from the application layer.)

David

i just found out the stuttering was caused by setting the clock-frame-rate .
when it’s limited to a lower number(50fps) than max achievable framerate(about 90fps), i have to enable sync-video to eliminate stuttering. but then the performance(40fps) would be lowered by large in DX mode, while in Opengl mode the performance is still high (output 50fps, just like the limited number).

now i set the clock-frame-rate at 100.0 and sync-video off. i get 90 fps in DX9. i am satisfied with this framerate. so i decide to use only DX9 now.

finally i know why my graphic card shows per-vertex-fog in Panda.
when Panda calls glHint(GL_FOG,param2), param2 is not GL_NICEST. if the param2 is GL_NICEST, my graphic card shows per-pixel-fog, or else, it shows per-vertex-fog.
currently i use ctypes to call glHint to correct that problem. i can use OpenGL now :smiley:
i hope Panda will fix that in the next version.

The fix here is to allow setting the fog quality similar to how we allow setting that of an AntialiasAttrib using set_mode_quality and that of a Texture using using set_quality_level. This is straightforward - I’ll put it on my todo list.