;vividgl-3d lite 
;
;(c)antony wells 2004.
;
;-[ fx skins ] -[core]



Function glfx.fx(shade=gl_smooth,depthtest=gl_depth_test,depthfunc=gl_less) ;INTERNAL FUNCTOIN
	out.fx=New fx
	out\shade=shade
	out\depthtest=depthtest
	out\depthfunc=depthfunc
	Return out
End Function

Type fx
	Field shade
	Field depthtest
	Field depthfunc
	Field fs.fxskin,sc
End Type

Type fxsys
	Field cc,c2
	Field vp,fp
End Type

Type shader
	Field sp,shaderoff
	Field pn$[255] ;255 is the hardware register limit, so no need to go beyond.
	Field pt[255]
	Field ut[255]
	Field po[255]
	Field tex[32],tc
	Field pd.pdat[255],file$
	Field pc,fx.fxskin
End Type
Type pdat
	Field x#,y#,z#,w#
End Type

Type fxskin
	Field sp.shader[20],sc 
	Field vp#[10],pp[10],parent.ent,typ
	Field light.ent[255],lc
	Field srfown.sdat[5000]
	Field vshad.shader,pshad.shader
End Type

Global fxs.fxsys

Function fxskin_VertexShaderState(fxskin,enable=0)
	in.fxskin=Object.fxskin(fxskin)
	in\vshad\shaderoff=1-enable
End Function
Function fxskin_pixelshaderState(fxskin,enable=0)
	in.fxskin=Object.fxskin(fxskin)
	in\pshad\shaderoff=1-enable
End Function



Function fxskin_texture(fxskin,texture,index=0)
	in.fxskin=Object.fxskin(fxskin)
	If in\sp[1]\tex[index]=0 in\sp[1]\tc=in\sp[1]\tc+1
	in\sp[1]\tex[index]=texture
End Function

Function fxskin_textures(fxskin)
	in.fxskin=Object.fxskin(fxskin)
	in\sp[1]\tc=0
End Function


Function glInitFxSys(forcevertexprofile=-1,forcefragmentprofile=-1)
	fxs=New fxsys
	fxs\cc =cgCreateContext()
	fxs\fp=cgGLGetLatestProfile(cg_gl_fragment)
	fxs\vp=cgGLGetLatestProfile(cg_gl_vertex)
	If forcevertexprofile<>-1 
		If cgGLIsProfileSupported(forcevertexprofile) fxs\vp=forcevertexprofile
	EndIf
	
	If forcefragmentprofile<>-1 
		If cgGLIsProfileSupported(forcefragmentprofile) fxs\fp=forcefragmentprofile
	EndIf
	
	If fxs\fp cgGLSetOptimalOptions(fxs\fp)
	If fxs\vp cgGLSetOptimalOptions(fxs\vp)
End Function


Function FxSkin_Create()
	out.fxskin =New fxskin
	Return Handle(out)
End Function


Const spviewmatrix=1 ;sends the view matrix etc to the par
Const spfloat4=2 ;send a 4part coord(x,y,z,w)
Const spfloat3=3 ;send a 3part coord(x,y,z)
Const spmodelviewproj=4
Const spmodelviewit=5
Const spmodelview=9
Const splightvector=6
Const spcameraposition=93
Const splightcolor=94,splightspecular=95
Const splightposition=92
Const spproject=30
Const spcameravector=7
Const sptexture=8,spprojectmatrix=20


Const sppercolor=1
Const spwhenon=2 
Const sppervert=3 
Const spnever=4
Function Entity_ShadersOn(entity)
	in.ent=Object.ent(entity)
	in\disableshaders=True
End Function

Function Entity_ShadersOff(entity)
	in.ent=Object.ent(entity)
	in\disableshaders=False
End Function

Function resetpars(in.shader) ;internal func
	For j=0 To in\pc-1
		in\po[pc]=cgGetNamedParameter(in\sp,in\pn[j])
		If in\po[j]=0 RuntimeError "could not re-initlize shader. interface not compatible"
	Next
End Function

Function Shader_InitPar( shader,par$,partype,updatetype)
	in.shader=Object.shader(shader)
	pc=in\pc
	in\pn[pc] =par
	in\po[pc] =cgGetNamedParameter(in\sp,par)
	If Not in\po[pc] Return
	in\pt[pc]=partype
	in\ut[pc]=updatetype
	Select partype
		Case spfloat3,spfloat4,sptexture
			in\pd[pc] =New pdat
	End Select
	in\pc=pc+1
	Return Handle(in\pd[pc])
End Function

Function Fx_ShaderTexture(shader,texture,index=-1)
	in.shader=Object.shader(shader)
	If index=-1 index=in\tc
	in\tex[in\tc]=texture
	in\tc=in\tc+1
End Function

Function Fx_PurgeShaderTextures(shader)
	ins.shader=Object.shader(shader)
	ins\tc=0
End Function

Function Shader_SetPar( shaderpar,v1#=0,v2#=0,v3#=0,v4#=0,v5#=0)
	in.pdat=Object.pdat(shaderpar)
	in\x=v1
	in\y=v2
	in\z=v3
	in\w=v4
End Function
Const glforceim=1
Global glfirstshader=0

Function skinprofile(in.fxskin) 
	If in\vshad<>Null
		If in\vshad\shaderoff=False cgGLEnableProfile fxs\vp
	EndIf
	If in\pshad<>Null
		If in\pshad\shaderoff=False cgGLEnableProfile fxs\fp
	EndIf
End Function

Function glshaderon2(in.shader) 
	If in=Null Return 
	If in\shaderoff Return 
	For j=0 To shadeonc-1
			If shaderon[j]=in Return ;already on.
	Next
	cgGLBindProgram in\sp
	shadersareon=True
	shaderon[shadeonc]=in
	shadeonc=shadeonc+1
	

	;if in\pc=0 end
For j=0 To in\pc-1
	Select in\ut[j]
	Case spwhenon

		Select in\pt[j]
		Case spprojectmat
			cgGLSetStateMatrixParameter(in\po[j], cg_gl_projection_matrix, cg_gl_matrix_identity);
		Case spmodelviewproj
			cgGLSetStateMatrixParameter(in\po[j], cg_gl_modelview_projection_matrix, cg_gl_matrix_identity);
		Case spmodelview
			cgGLSetStateMatrixParameter(in\po[j],cg_gl_modelview_matrix,cg_gl_matrix_identity);
		Case spfloat4
			cgGLSetParameter4f in\po[j],in\pd[j]\x,in\pd[j]\y,in\pd[j]\z,in\pd[j]\w
		Case spfloat3
	 		cgGLSetParameter3f in\po[j],in\pd[j]\x,in\pd[j]\y,in\pd[j]\z
		Case splightposition
			cgGLSetParameter4f in\po[j],esys\light[0]\x,esys\light[0]\y,esys\light[0]\z,0
		Case splightcolor
			cgGLSetParameter4f in\po[j],esys\light[0]\r,esys\light[0]\g,esys\light[0]\b,1
		Case splightspecular
			cgGLSetParameter4f in\po[j],esys\light[0]\sr,esys\light[0]\sg,esys\light[0]\sb,1
		Case splightvector
			cgGLSetParameter4f in\po[j],lvecx[0],lvecy[0],lvecz[0],1
		Case spcameraposition
			cgGLSetParameter4f in\po[j],dsys\cam\x,dsys\cam\y,dsys\cam\z,0
		Case spcameravector
			cgGLSetParameter4f in\po[j],cvecx,cvecy,cvecz,1
		Case spmodelviewit
			 cgGLSetStateMatrixParameter(in\po[j], cg_gl_modelview_matrix, cg_gl_matrix_inverse_transpose);
		Case spprojectmatrix
			glMatrixMode(gl_projection); 
			glPushMatrix(); 
			glGetFloatv(gl_projection_matrix, tempbank); 
			glLoadIdentity(); 
			;Entity_Translatef(0.5, 0.5, 0.5); 
			glScalef(0.5, 0.5, 0.5); 
			glMultMatrixf(tempbank); 
			cgGLSetStateMatrixParameter(in\po[j], cg_gl_projection_matrix, cg_gl_matrix_identity); 
			glPopMatrix(); 
			glMatrixMode(gl_modelview);
		Case sptexture
			cgGLEnableTextureParameter in\po[j]
			If in\tex[in\pd[j]\x]<>0
			;	cgglsettextureparameter in\po[j],in\tex[in\pd[j]\x]\rgba
			EndIf
		End Select
	Case sppervert,sppercolor
		spt[spc]=in\po[j]
		spc=spc+1
		If spc>5 RuntimeError "shit dog"
		force=True
	End Select
Next
	Return force

End Function

Function glresize2(width#,height#)
	glViewport(0, 0, w, h);
       glMatrixMode(gl_projection);    
    glLoadIdentity();               
    gluortho2d(-1, 1, -1, 1);       
    glMatrixMode(gl_modelview);     
    glLoadIdentity(); 
End Function
Global shaderon.shader[255]
Global shadeonc;
Global surfon.sdat[255]
Function glshaderon(in.shader,surf.sdat) 
	
	If in=Null Return
	If in\shaderoff Return
	If surf=Null RuntimeError "surface does not exist"
	shadersareon=True
	For j=0 To shadeonc-1
			If shaderon[j]=in And surfon[j]=surf Return ;already on.
	Next
	
	cgGLBindProgram in\sp
	cgGLEnableProfile fxs\vp
	cgGLEnableProfile fxs\fp
	;if in\pc=0 end
	shaderon[shadeonc]=in
	surfon[shadeonc]=surf
	shadeonc=shadeonc+1
	
	For j=0 To in\pc-1
	Select in\ut[j]
	Case spwhenon

		Select in\pt[j]
		Case spmodelviewproj
			cgGLSetStateMatrixParameter(in\po[j], cg_gl_modelview_projection_matrix, cg_gl_matrix_identity);
		Case spmodelview
			cgGLSetStateMatrixParameter(in\po[j],cg_gl_modelview_matrix,cg_gl_matrix_identity);
		Case spfloat4
			cgGLSetParameter4f in\po[j],in\pd[j]\x,in\pd[j]\y,in\pd[j]\z,in\pd[j]\w
		Case spfloat3
	 		cgGLSetParameter3f in\po[j],in\pd[j]\x,in\pd[j]\y,in\pd[j]\z
		Case splightvector
			cgGLSetParameter4f in\po[j],lvecx[0],lvecy[0],lvecz[0],1
		Case spcameravector
			cgGLSetParameter4f in\po[j],cvecx,cvecy,cvecz,1
		Case spmodelviewit
			 cgGLSetStateMatrixParameter(in\po[j], cg_gl_modelview_matrix, cg_gl_matrix_inverse_transpose);
		Case spprojectmatrix
			glMatrixMode(gl_projection); 
			glPushMatrix(); 
	 		glGetFloatv(gl_projection_matrix, tempbank); 
			glLoadIdentity(); 
			glScalef(0.5, 0.5, 0.5); 
			glMultMatrixf(tempbank); 
			cgGLSetStateMatrixParameter(in\po[j], cg_gl_projection_matrix, cg_gl_matrix_identity); 
			glPopMatrix(); 
			glMatrixMode(gl_modelview);
		Case sptexture
			;Legacy. Use texture binding in cg.
			;i.e, sample2D myTest : TEXUNIT0 etc.
		End Select
	Case sppervert,sppercolor
		spt[spc]=in\po[j]
		spc=spc+1
		force=True
	End Select
Next
	Return force
End Function

Function glshadersoff()
	cgGLDisableProfile fxs\vp
	cgGLDisableProfile fxs\fp
	While shadeonc>0
		shadeonc=shadeonc-1
		cgGLUnbindProgram shaderon[shadeonc]\sp
	Wend
	shadersareonnow=False
	glfirstshader=False
	shadersareon=False
	spc=0
End Function

Function Shader_loadpixelshader( fxskin,file$,failsilent=False)
	in.fxskin=Object.fxskin(fxskin)
	in\sp[in\sc] =New shader
	in\sp[in\sc]\fx=in
	in\sp[in\sc]\file=file
	in\sp[in\sc]\sp=cgCreateProgramFromFile(fxs\cc,cg_source,file,fxs\fp,0,0)
	ptt$=cgGetError()
	cgGLLoadProgram in\sp[in\sc]\sp
	If Not in\sp[in\sc]\sp 
		cp.shader=in\sp[in\sc]
		If failsilent Return
		RuntimeError "PixelShader Error"
	EndIf
	in\sc=in\sc+1
	Return Handle(in\sp[in\sc-1])
End Function

Function Shader_loadvertexshader(fxskin,file$,failsilent=True)
	in.fxskin=Object.fxskin(fxskin)
	in\sp[in\sc] =New shader
	in\sp[in\sc]\fx=in
	in\sp[in\sc]\sp=cgCreateProgramFromFile(fxs\cc,cg_source,file,fxs\vp,0,0)
	sip$=cgGetError()
	cgGLLoadProgram in\sp[in\sc]\sp
	If Not in\sp[in\sc]\sp 
		If failSilent Return
		RuntimeError "VertexShader Error"
	EndIf
	in\sc=in\sc+1
	Return Handle(in\sp[in\sc-1])
End Function

Global surfc,lrensrf.sdat,lockedfx.fxskin
Function fxskin_on(fxskin) 
		in.fxskin=Object.fxskin(fxskin)
		For j=0 To in\sc-1
			glshaderon2(in\sp[j])
		Next
		skinprofile(in)
		lockedfx=in
		shadersareon=True
End Function

Function fxskin_off()
	glshadersoff()
	lockedfx=Null
	shadersareon=False
End Function

Function FxSkin_VertexShader(FxSkin,Shader)
	in.fxskin=Object.fxSkin(fxskin)
	in\vshad=Object.shader(shader)
End Function

Function FxSkin_PixelShader(FxSkin,Shader)
	in.FxSkin=Object.fxSkin(FxSkin)
	in\pShad=Object.shader(shader)
End Function

