teko
7th Oct 2006, 2:48 PM
I've done some researches about the Mirror Material Shader (0xFF123570) and tried to understand it. I followed up the MirrorReflectionMaterial which is responsible for the reflection on mirrors.
The shader code in the MirrorReflectionMaterial is written in Assembler language. Assembler is a really primitive code language but not so difficult to understand when you know what it does. ;)
Below in SetSpecifiedZOnMirrorRTT(zValue) there is some shader code written in HLSL (High Level Shading Language) but I'm not 100% sure. It looks just like this. :P
This is how a vertexshader in Assembler works.
http://img165.imageshack.us/img165/848/vertexprocessingeu6.gif
The adress-registers (vertexattributes and constant-registers) are where the data is taken from. The computations are saved in the temporary registers where they can be used later. The output register is the final data.
Then some informations about the assembler-opperands which are used in the MirrorReflectionMaterial.
def : define
m4x4 : multiplication with a vector and a matrix
mov : move data
mul : scalar multiplication of all components of two vectors
mad : multiplication and addition in one
rcp : divide
Ok, let's have a look at the first vertex program in the MirrorReflectionMaterial.
(Bold notes added by me)
# vertex program
shaderProgram -target vertexProgram -method assemble
bindConstants 0 -bindingID geomToClipFromParentView -constantCount 4 # set the matrices from the parent (i.e. the main view) so that the stencil is written to the right place
shaderSource
; vertext shader version 1.1
vs_1_1
; write position of world-/objectcoordinates (?) in the register v0
dcl_position v0
; color output for debugging (write values for xyzw in the constantregister c5)
def c5, 1,0,0,1
; project vertex to clip coords (multiply vertexattribute v0 with constantregister c0 and put the result in the temporarely register r0)
m4x4 r0, v0, c0
; flip the x coordinate so the stencil is marked in the right place (stencil = mask (mask = the reflection is only rendered on the mirrorplane))
mov oPos.x, -r0 ; kind of flipping the x axis and move the data to the outputregister for position (final)
mov oPos.yzw, r0 ; move the data of position yzw to the outputregister for position (final)
endShaderSource
end
Note please the X axis flipping. I'm gonna test if it's possible to flipp the Z axis so there isn't needed a transform bone to display the reflection correctly. This should help for reflective ponds. ;)
Let's have a look at the second shader program what's going on there. :)
(Bold notes added by me)
shaderProgram -target vertexProgram -method assemble
bindConstants 0 -bindingID geomToClip -constantCount 4
bindConstants 4 -bindingID clipToViewTarget -constantCount 4
shaderSource
vs_1_1
dcl_position v0
#data for xyzw is written into constantregisters c8/c9/c10
def c8, -0.5, -0.5, 1, 1
def c9, 0.5, 0.5, 0, 0
def c10, 0.25, 0.25, 0, 0
# project vertex to clip coords (multiply v0 with c0 and move data into r0)
m4x4 r0, v0, c0
# move data from r0 in outputregister position (final)
mov oPos, r0
# I guess the part below resizes the textures but I'm not sure!
# multiply 0.5 * w so homogenous divide will make it 0.5 again (multiply c9 (data above) with w from r0 and move data into r2)
mul r2, c9, r0.w
# scale projected xy by .5 and re-center so it's in 0-w range (multiplication and addition in one - no idea how. saved in r4)
mad r4, r0, c8, r2
# Try to get an exact texel to pixel mapping by shifting texture coordinates
# slightly.
# A texture coordinate of 0 must map to 1/2*(texture dimension) and a
# coordinate of 1 must map to (1 - 1/2*(texture dimension)).
# Note: This does not seem to eliminate the wobble on the mirror
# reflection entirely.
rcp r3.x, c4.x ;# 2/width (not sure were c4 does come frome, maybe from above bindConstants 4 and not sure how rcp works)
rcp r3.y, c5.y ;# 2/height (c5 is known from the upper shader source)
mov r3.zw, c9.zw ;# r3 = (2/width, 2/height, 0, 0) (the values for z,w = 0,0 are saved in zw of r3)
mul r3, r3, c10 ;# r3 = (1/2*width, 1/2*height, 0, 0) (multiply r3 with c10 from above and save it again in r3)
mad r6, r0, r3, r4 ;# multiplication and addition in one (how?) saved in r6
mov oT0, r6.xyww ;# move w into z so we can divide by z in the texture stage; some cards don't handle division by w correctly
endShaderSource
end
I actually don't know what this second shader program really does but I guess it resizes the textures to don't slow down the game too much. There's a third shader program but it's more or less the same so I don't want pay much attention to it. ;)
I have the following problem. I can't make a shader to be standalone - to be a totally new shader. The thing is, I want to have a transparent mirror material without affecting all mirrors. :blink:
http://img308.imageshack.us/img308/7860/muranotransparentmirrorsmaix6.jpg
The shader code in the MirrorReflectionMaterial is written in Assembler language. Assembler is a really primitive code language but not so difficult to understand when you know what it does. ;)
Below in SetSpecifiedZOnMirrorRTT(zValue) there is some shader code written in HLSL (High Level Shading Language) but I'm not 100% sure. It looks just like this. :P
This is how a vertexshader in Assembler works.
http://img165.imageshack.us/img165/848/vertexprocessingeu6.gif
The adress-registers (vertexattributes and constant-registers) are where the data is taken from. The computations are saved in the temporary registers where they can be used later. The output register is the final data.
Then some informations about the assembler-opperands which are used in the MirrorReflectionMaterial.
def : define
m4x4 : multiplication with a vector and a matrix
mov : move data
mul : scalar multiplication of all components of two vectors
mad : multiplication and addition in one
rcp : divide
Ok, let's have a look at the first vertex program in the MirrorReflectionMaterial.
(Bold notes added by me)
# vertex program
shaderProgram -target vertexProgram -method assemble
bindConstants 0 -bindingID geomToClipFromParentView -constantCount 4 # set the matrices from the parent (i.e. the main view) so that the stencil is written to the right place
shaderSource
; vertext shader version 1.1
vs_1_1
; write position of world-/objectcoordinates (?) in the register v0
dcl_position v0
; color output for debugging (write values for xyzw in the constantregister c5)
def c5, 1,0,0,1
; project vertex to clip coords (multiply vertexattribute v0 with constantregister c0 and put the result in the temporarely register r0)
m4x4 r0, v0, c0
; flip the x coordinate so the stencil is marked in the right place (stencil = mask (mask = the reflection is only rendered on the mirrorplane))
mov oPos.x, -r0 ; kind of flipping the x axis and move the data to the outputregister for position (final)
mov oPos.yzw, r0 ; move the data of position yzw to the outputregister for position (final)
endShaderSource
end
Note please the X axis flipping. I'm gonna test if it's possible to flipp the Z axis so there isn't needed a transform bone to display the reflection correctly. This should help for reflective ponds. ;)
Let's have a look at the second shader program what's going on there. :)
(Bold notes added by me)
shaderProgram -target vertexProgram -method assemble
bindConstants 0 -bindingID geomToClip -constantCount 4
bindConstants 4 -bindingID clipToViewTarget -constantCount 4
shaderSource
vs_1_1
dcl_position v0
#data for xyzw is written into constantregisters c8/c9/c10
def c8, -0.5, -0.5, 1, 1
def c9, 0.5, 0.5, 0, 0
def c10, 0.25, 0.25, 0, 0
# project vertex to clip coords (multiply v0 with c0 and move data into r0)
m4x4 r0, v0, c0
# move data from r0 in outputregister position (final)
mov oPos, r0
# I guess the part below resizes the textures but I'm not sure!
# multiply 0.5 * w so homogenous divide will make it 0.5 again (multiply c9 (data above) with w from r0 and move data into r2)
mul r2, c9, r0.w
# scale projected xy by .5 and re-center so it's in 0-w range (multiplication and addition in one - no idea how. saved in r4)
mad r4, r0, c8, r2
# Try to get an exact texel to pixel mapping by shifting texture coordinates
# slightly.
# A texture coordinate of 0 must map to 1/2*(texture dimension) and a
# coordinate of 1 must map to (1 - 1/2*(texture dimension)).
# Note: This does not seem to eliminate the wobble on the mirror
# reflection entirely.
rcp r3.x, c4.x ;# 2/width (not sure were c4 does come frome, maybe from above bindConstants 4 and not sure how rcp works)
rcp r3.y, c5.y ;# 2/height (c5 is known from the upper shader source)
mov r3.zw, c9.zw ;# r3 = (2/width, 2/height, 0, 0) (the values for z,w = 0,0 are saved in zw of r3)
mul r3, r3, c10 ;# r3 = (1/2*width, 1/2*height, 0, 0) (multiply r3 with c10 from above and save it again in r3)
mad r6, r0, r3, r4 ;# multiplication and addition in one (how?) saved in r6
mov oT0, r6.xyww ;# move w into z so we can divide by z in the texture stage; some cards don't handle division by w correctly
endShaderSource
end
I actually don't know what this second shader program really does but I guess it resizes the textures to don't slow down the game too much. There's a third shader program but it's more or less the same so I don't want pay much attention to it. ;)
I have the following problem. I can't make a shader to be standalone - to be a totally new shader. The thing is, I want to have a transparent mirror material without affecting all mirrors. :blink:
http://img308.imageshack.us/img308/7860/muranotransparentmirrorsmaix6.jpg