The Shader example...

BlitzMax Modules Forums/MiniB3D/The Shader example...

It does not appear to be working correctly. Has anyone else noticed this? The light in the scene does not appear to be affecting the model at all...

Except if you click, then it's affecting the model. I believe if you would want to have an effect on shader rendering then it should be transmitted to the shader program (and the shader program would have to be programmed to compute lights from passed data). That seems normal to me.

I know ;)

Replace with original Shader.bmx
SuperStrict

Framework BRL.FileSystem
Import BRL.StandardIO
Import BRL.LinkedList
Import BRL.JPGLoader
Import BRL.PNGLoader
Import BRL.BMPLoader
Import BRL.System

Import klepto.minib3d


Local width:Int = 800 , height:Int = 600
Global W:Byte = False


Graphics3D 1024 , 768 , 32 , 2

THardwareInfo.DisplayInfo(True)
AmbientLight(125,125,125)


Local cam:TCamera=CreateCamera()
PositionEntity cam,0,10,-50
CameraRange(cam,.1,200000)

Local light:TLight = CreateLight(0)
PositionEntity Light , 0 , 10 , - 50

Local LDummy:TMesh = CreateSphere(16,Light)


light.LightColor(255, 255, 255)

Local ent:TMesh = LoadAnimMesh("imp.b3d")
ScaleEntity(ent , 2 , 2 , 2)



Local Tex:TBrush = LoadBrush("imp_d.png") 'Creating a new Brush for the imp
Tex.BrushShininess(20.0)

' Loading the correct textures
Local Decal:TTexture = LoadTexture("imp_d.png") ; Decal.TextureBlend(2)
Local Normalmap:TTexture = LoadTexture("imp_dot3.png") ; Normalmap.TextureBlend(4)

'Applying the Textures to the shader slots
BrushShaderTexture(Tex,Decal , 0)
BrushShaderTexture(Tex , Normalmap , 1)

InitShader(Tex)' Initiating the shader for the Brush
AddShaderObject(Tex,"bump.vert" , "bump.frag") ' Loading the shader

'Setting the shader attributes
Tex.ProgramAttriBegin()
Tex.SetUI1("colorMap" , 0) 
Tex.SetUI1("normalMap" , 1)
Tex.SetAF3("vTangent" , 1.0 , 0.0 , 0.0)
Tex.SetUF1("invRadius",0.001)
Tex.ProgramAttriEnd()


' Paint the entity with the brush
PaintEntity(ent , Tex)

'Activate the shader
ActivateShader(ent , True)




' used by camera code
Local mxs#=0
Local mys#=0
Local move#=2.5
MouseXSpeed() ' flush
MouseYSpeed() ' flush

' used by fps code
Local old_ms:Int=MilliSecs()
Local renders:Int
Local fps:Int = 10
Local anim_time:Float = 0

Local angle:Float = 0
Local bias:Float = 1.0
Local speed:Float = 0.05

While Not KeyDown(KEY_ESCAPE)		

	If KeyHit(KEY_ENTER) Then DebugStop
	
	If KeyHit(Key_W) Then 
		Wireframe(Not W)
		W = Not W
	EndIf


	'' control camera
	
	' mouse look
	
	mxs#=mxs#+(MouseXSpeed()/5.0)
	mys#=mys#+(MouseYSpeed()/5.0)

	RotateEntity cam , mys# , - mxs# , 0
	
	MoveMouse width/2,height/2
	MouseXSpeed() ' flush
	MouseYSpeed() ' flush

	' move camera forwards/backwards/left/right with cursor keys
	
	If KeyDown(KEY_UP)=True Then MoveEntity cam,0,0,move# ' move camera forward
	If KeyDown(KEY_DOWN)=True Then MoveEntity cam,0,0,-move# ' move camera back

	If KeyDown(KEY_LEFT)=True Then MoveEntity cam,-move#,0,0 ' move camera left
	If KeyDown(KEY_RIGHT) = True Then MoveEntity cam , move# , 0 , 0 ' move camera right
	
	If KeyDown(KEY_A) Then bias:+ .1
	If KeyDown(KEY_Y) Then bias:- .1

	
	If MouseDown(1) Then 
		ActivateShader(ent , False)
	Else
		ActivateShader(ent , True)
	End If
	
	
	angle:-1.0
	Local LightX:Float = Cos(angle) * Float((145.0/FPS)*20)
	Local LightY:Float = - Sin(angle) * Float( (145.0 / FPS) * 20)
	

	Local LightZ:Float = Sin(angle) * Float( (150.0 / FPS) * 20)

	EntityShininess(ent,bias)

	PositionEntity(Light, LightX, LightY, LightZ)	
	
	SetAnimTime(ent,anim_time#)
	anim_time:+0.1

		
	Tex.ProgramAttriBegin()
			Tex.SetUF3("lightpos",EntityX(Light),EntityY(Light),EntityZ(Light)) 
	Tex.ProgramAttriEnd()


	If Rand(10) > 5 Then
		speed:+ 0.01
	Else
		speed:- 0.01
	EndIf
	
	If speed < 0.3 Then speed = .3
	If speed > 1 Then speed = 1.0
	'If KeyDown(KEY_SPACE) Then 
	'TurnEntity(ent , 0 , 0.3 , 0)
	'turnentity(ent2 , -speed , speed , 0)
	
	UpdateWorld
	RenderWorld
	renders=renders+1

	' calculate fps
	If MilliSecs()-old_ms>=1000
		old_ms=MilliSecs()
		fps=renders
		renders=0
	EndIf
	
	
	Text 0,20,"FPS: "+String(fps) +" Speed :" + speed
	Text 0 , 40 , "Light : " + EntityX(light) + " : " + EntityY(Light) + " : " + EntityZ(Light) 
	Text 0 , 60 , "Adjust Entity shinniness by A/Y : " + bias 
	Text 0,80,"Hold Down Left Mouse Button deactivate Shader"
	Local Is:String = ""
	If THardwareInfo.ShaderSupport Then 
		is = "Shader 2.0 GLSL Supported"
	Else
		is = "Shader 2.0 GLSL not Supported"
	EndIf
	
	Text 0,100,is
	Flip 

Wend


and this with bump.vert.
uniform vec3 lightpos;
varying vec3 lightVec; 
varying vec3 eyeVec;
varying vec2 texCoord;
attribute vec3 vTangent; 
					 

void main(void)
{
	gl_Position = ftransform();
	texCoord = gl_MultiTexCoord0.xy;
	
	vec3 n = normalize(gl_NormalMatrix * gl_Normal);
	vec3 t = normalize(gl_NormalMatrix * vTangent);
	vec3 b = cross(n, t);
	
	vec3 vVertex = vec3(gl_ModelViewMatrix * gl_Vertex);
	vec3 tmpVec = lightpos - vVertex;

	lightVec.x = dot(tmpVec, t);
	lightVec.y = dot(tmpVec, b);
	lightVec.z = dot(tmpVec, n);

	tmpVec = -vVertex;
	eyeVec.x = dot(tmpVec, t);
	eyeVec.y = dot(tmpVec, b);
	eyeVec.z = dot(tmpVec, n);
}


Hmm, better, but still not correct. It seems to work close up, but not as I pull the camera further away. :(

Aaaaargh! I don't understand why the light has an effect on the shader, but when I hold the mouse button down so the shader is turned off, the moving light no longer affects the object.

I decided to experiment. I commented out the lines that set the angle and update the light position based on that, and instead parented the light to a pivot point in the middle which is continuously turning. Now that I've made these changes, it is the shader that is unaffected and the object that is so when shaders are turned off.

What the...?

Okay, I have learned that simply passing the entity x, y, and z values is resulting in the wrong position for the light. Using gl_LightSource[0].position does work, but I'd like to understand what the difference is. The built in light source position value is a vec4 instead of a vec3, for instance.

Does anyone know how this stuff works or where I can find a good GLSL tutorial? The ones I've found so far have been lacking...

I'm not exactly a shaders person, but I wrote a little article linking together a whole bunch of other resources here.

(Scroll down for the more useful external resources).

Thanks, but all I can find are specs. Does anyone know WHY gl_LightSource[0].position is a vec4? Aside from x, y, and z, what is there?

I know that passing x, y, and z in order doesn't work for MiniB3D because the axes are not the same, but I don't know how to transform the values properly. The shader example that was supplied by Klepto is not working correctly and I'd like to know if anyone has already solved this problem. ???

In OpenGL and DX anything is a Vec4
For the reason that all matrices are 4x4 matrices.

the forth is w and normally 1 unless you use the position to save quaternions in there instead of vectors.

as you seem to lack the 3d programming basics, understanding them before trying to do shader (higher end math) might be a usefull idea.

@Dreamora - Actually, that is an assumption on your part. I have written 3dsMax .fx shaders and work professionally in the game biz as a technical artist. Knowing what the FOURTH value contains is not a 3d programming basic. :P