Bonjour !
Sur mon petit Castor3D, je fignole l'implémentation du rendu via Direct3D 9.
Je finalise les shaders et pour cela j'ai traduit en HLSL le shader de Relief mapping que j'ai en GLSL, et qui ne fonctionne pas trop mal.
Cependant je remarque quelque chose qui me chiffonne : sur Direct3D le rendu de la lumière spéculaire est pixellisé contrairement à OpenGl où il est bien lisse.
Je vous mets 2 copies d'écrans afin que vous voyiez où je veux en venir (il faut regarder les reflets spéculaires en rouge/rose)
Rendu OpenGL :
Rendu Direct3D 9 :
Savez-vous d'où ça peut provenir ? (je ne suis pas très calé en Direct3D, j'ai peut être oublié quelque chose à faire, notamment au niveau de la création des textures)
Je vous mets les codes des shaders GLSL et HLSL qui ont servi pour ces rendus :
GLSL
HLSL :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227 //VERTEX SHADER #version 140 in vec3 tangent; in vec4 vertex; in vec3 normal; in vec2 texture; uniform mat4 ProjectionModelViewMatrix; uniform mat4 ModelViewMatrix; uniform mat3 NormalMatrix; uniform vec4 in_LightsPosition[8]; uniform vec4 in_LightsSpecular[8]; uniform vec4 in_LightsDiffuse[8]; uniform vec4 in_LightsAmbient[8]; uniform vec4 in_AmbientLight; uniform vec4 in_MatAmbient; uniform vec4 in_MatDiffuse; uniform vec4 in_MatSpecular; uniform float in_MatShininess; out vec2 ex_TexCoord; out vec3 ex_EyeSpaceVert; out vec3 ex_EyeSpaceTangent; out vec3 ex_EyeSpaceBinormal; out vec3 ex_EyeSpaceNormal; out vec3 ex_EyeSpaceLight; out vec4 ex_AmbientLight; out vec4 ex_MatAmbient; out vec4 ex_MatDiffuse; out vec4 ex_MatSpecular; out float ex_MatShininess; out vec4 ex_LightSpecular; out vec4 ex_LightDiffuse; out vec4 ex_LightAmbient; float length( vec3 p_vector) { return sqrt( p_vector.x * p_vector.x + p_vector.y * p_vector.y + p_vector.z * p_vector.z); } void main() { vec3 binormal = cross( tangent, normal); ex_EyeSpaceTangent = NormalMatrix * tangent; ex_EyeSpaceBinormal = NormalMatrix * binormal; ex_EyeSpaceNormal = NormalMatrix * normal; ex_AmbientLight = in_AmbientLight; ex_MatAmbient = in_MatAmbient; ex_MatDiffuse = in_MatDiffuse; ex_MatSpecular = in_MatSpecular; ex_MatShininess = in_MatShininess; ex_TexCoord = texture.xy; ex_LightSpecular = vec4( 0.0); ex_LightDiffuse = vec4( 0.0); ex_LightAmbient = vec4( 0.0); ex_EyeSpaceVert = (ModelViewMatrix * vertex).xyz; ex_EyeSpaceLight = (ModelViewMatrix * in_LightsPosition[0]).xyz; ex_LightSpecular += in_LightsSpecular[0] * in_MatSpecular; ex_LightDiffuse += in_LightsDiffuse[0] * in_MatDiffuse; ex_LightAmbient += in_LightsAmbient[0] * in_MatAmbient; gl_Position = ProjectionModelViewMatrix * vertex; } //FRAGMENT SHADER #version 140 uniform float Depth; uniform float Tile; uniform int LinearSearchSteps; uniform int BinarySearchSteps; in vec2 ex_TexCoord; in vec3 ex_EyeSpaceVert; in vec3 ex_EyeSpaceTangent; in vec3 ex_EyeSpaceBinormal; in vec3 ex_EyeSpaceNormal; in vec3 ex_EyeSpaceLight; uniform sampler2D DiffuseMap; uniform sampler2D NormalMap; in vec4 ex_AmbientLight; in vec4 ex_MatAmbient; in vec4 ex_MatDiffuse; in vec4 ex_MatSpecular; in float ex_MatShininess; in vec4 ex_LightSpecular; in vec4 ex_LightDiffuse; in vec4 ex_LightAmbient; out vec4 out_FragColor; float RayIntersectRM( in vec2 dp, in vec2 ds); void main() { vec4 l_vAmbient = ex_AmbientLight * ex_MatAmbient; vec4 l_vSpecular = vec4( 0.0); vec4 l_vDiffuse = vec4( 0.0); float l_fShine = ex_MatShininess; l_vAmbient += ex_LightAmbient; l_vSpecular += ex_LightSpecular; l_vDiffuse += ex_LightDiffuse; vec4 l_vTextureRelief; vec4 l_vTextureColour; vec3 l_vTmp1; vec3 l_vTmp2; vec3 l_eyeSpaceVertex; vec3 l_vLightDirection; vec2 l_vUV; float l_fDot; float d; vec2 dp, ds; // ray intersect in view direction l_vTmp2 = ex_EyeSpaceVert; l_eyeSpaceVertex = normalize( l_vTmp2); l_fDot = dot( ex_EyeSpaceNormal, -l_eyeSpaceVertex); l_vTmp1 = normalize( vec3( dot( l_eyeSpaceVertex, ex_EyeSpaceTangent), dot( l_eyeSpaceVertex, ex_EyeSpaceBinormal), l_fDot)); l_vTmp1 *= Depth / l_fDot; dp = ex_TexCoord * Tile; ds = l_vTmp1.xy; d = RayIntersectRM( dp, ds); // get rm and color texture points l_vUV = dp + ds * d; l_vTextureRelief = texture2D( NormalMap, l_vUV); l_vTextureColour = texture2D( DiffuseMap, l_vUV); // expand normal from normal map in local polygon space l_vTextureRelief.xy = l_vTextureRelief.xy * 2.0 - 1.0; l_vTextureRelief.z = sqrt( 1.0 - dot( l_vTextureRelief.xy, l_vTextureRelief.xy)); l_vTextureRelief.xyz = normalize( l_vTextureRelief.x * ex_EyeSpaceTangent + l_vTextureRelief.y * ex_EyeSpaceBinormal + l_vTextureRelief.z * ex_EyeSpaceNormal); // compute light direction l_vTmp2 += l_eyeSpaceVertex * d * l_fDot; l_vLightDirection = normalize( l_vTmp2 - ex_EyeSpaceLight.xyz); // ray intersect in light direction dp += ds * d; l_fDot = dot( ex_EyeSpaceNormal, -l_vLightDirection); l_vTmp1 = normalize( vec3( dot( l_vLightDirection, ex_EyeSpaceTangent), dot( l_vLightDirection, ex_EyeSpaceBinormal), l_fDot)); l_vTmp1 *= Depth / l_fDot; ds = l_vTmp1.xy; dp -= ds * d; float dl = RayIntersectRM( dp, l_vTmp1.xy); float l_fShadow = 1.0; vec3 l_vSpecularShadow = l_vSpecular.xyz; if (dl < d - 0.05) // if pixel in shadow { l_fShadow = dot( l_vAmbient.xyz, vec3( 1.0)) * 0.333333; l_vSpecularShadow = vec3( 0.0); } // compute diffuse and specular terms float l_fAttenuation = max( 0.0, dot( -l_vLightDirection, ex_EyeSpaceNormal)); float l_fDiffuseTerm = l_fShadow * max( 0.0, dot( -l_vLightDirection, l_vTextureRelief.xyz)); float l_fSpecularTerm = max( 0.0, dot( normalize( -l_vLightDirection - l_eyeSpaceVertex), l_vTextureRelief.xyz)); // compute final color vec4 l_vFinalColour; l_vFinalColour.xyz = l_vAmbient.xyz * l_vTextureColour.xyz + l_fAttenuation * (l_vTextureColour.xyz * l_vDiffuse.xyz * l_fDiffuseTerm + l_vSpecularShadow * pow( l_fSpecularTerm, l_fShine)); l_vFinalColour.w = 1.0; out_FragColor = vec4( l_vFinalColour.rgb, 1.0); } float RayIntersectRM( in vec2 p_vDP, in vec2 p_vDS) { float l_fDepthStep = 1.0 / float( LinearSearchSteps); // current size of search window float l_fSize = l_fDepthStep; // current depth position float l_fDepth = 0.0; // best match found (starts with last position 1.0) float l_fDepthReturn = 1.0; vec4 l_vTexColour; // search front to back for first point inside object for (int i = 0 ; i < LinearSearchSteps - 1 ; i++) { l_fDepth += l_fSize; l_vTexColour = texture2D( NormalMap, p_vDP + p_vDS * l_fDepth); if (l_fDepthReturn > 0.996) // if no depth found yet { if (l_fDepth >= l_vTexColour.w) { l_fDepthReturn = l_fDepth; // store best depth } } } l_fDepth = l_fDepthReturn; // recurse around first point (l_fDepth) for closest match for (int i = 0 ; i < BinarySearchSteps ; i++) { l_fSize *= 0.5; l_vTexColour = texture2D( NormalMap, p_vDP + p_vDS * l_fDepth); if (l_fDepth >= l_vTexColour.w) { l_fDepthReturn = l_fDepth; l_fDepth -= 2.0 * l_fSize; } l_fDepth += l_fSize; } return l_fDepthReturn; }
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188 float4x4 ProjectionModelViewMatrix; float4x4 ProjectionMatrix; float4x4 ModelViewMatrix; float3x3 NormalMatrix; float4 in_LightsPosition[8]; float4 in_LightsSpecular[8]; float4 in_LightsDiffuse[8]; float4 in_LightsAmbient[8]; float4 in_AmbientLight; float4 in_MatAmbient; float4 in_MatDiffuse; float4 in_MatSpecular; float in_MatShininess; float Depth; float Tile; int LinearSearchSteps; int BinarySearchSteps; sampler2D DiffuseMap; sampler2D NormalMap; struct VtxInput { float3 tangent : TANGENT; float4 vertex : POSITION0; float3 normal : NORMAL0; float2 Texture : TEXCOORD0; }; struct VtxOutput { float4 Position : POSITION0; float3 vertex : POSITION1; float3 tangent : NORMAL0; float3 binormal : NORMAL1; float3 normal : NORMAL2; float2 Texture : TEXCOORD0; }; float RayIntersectRM( in float2 dp, in float2 ds); float length( float3 p_vector) { return sqrt( p_vector.x * p_vector.x + p_vector.y * p_vector.y + p_vector.z * p_vector.z); } VtxOutput mainVx( in VtxInput p_input) { VtxOutput l_output; float3 binormal = cross( p_input.tangent, p_input.normal); float3x3 l_normalMatrix = (float3x3)NormalMatrix; l_output.tangent = mul( p_input.tangent, l_normalMatrix); l_output.binormal = mul( binormal, l_normalMatrix); l_output.normal = mul( p_input.normal, l_normalMatrix); l_output.vertex = mul( p_input.vertex, ModelViewMatrix).xyz; l_output.Texture = p_input.Texture; l_output.Position = mul( p_input.vertex, ProjectionModelViewMatrix); return l_output; } float4 mainPx( in VtxOutput p_input) : COLOR0 { float4 l_vAmbient = in_LightsAmbient[0] * in_MatAmbient; float3 l_vLight = mul( in_LightsPosition[0], ModelViewMatrix).xyz; float4 l_vSpecular = float4( 0, 0, 0, 0); float4 l_vDiffuse = float4( 0, 0, 0, 0); float l_fShine = in_MatShininess; l_vAmbient += in_MatAmbient * in_LightsAmbient[0]; l_vSpecular += in_MatSpecular * in_LightsSpecular[0]; l_vDiffuse += in_MatDiffuse * in_LightsDiffuse[0]; float4 l_vTextureRelief; float4 l_vTextureColour; float3 l_vTmp1; float3 l_vTmp2; float3 l_eyeSpaceVertex; float3 l_vLightDirection; float2 l_vUV; float l_fDot; float d; float2 dp, ds; // ray intersect in view direction l_vTmp2 = p_input.vertex; l_eyeSpaceVertex = normalize( l_vTmp2); l_fDot = dot( p_input.normal, -l_eyeSpaceVertex); l_vTmp1 = normalize( float3( dot( l_eyeSpaceVertex, p_input.tangent), dot( l_eyeSpaceVertex, p_input.binormal), l_fDot)); l_vTmp1 *= Depth / l_fDot; dp = p_input.Texture * Tile; ds = l_vTmp1.xy; d = RayIntersectRM( dp, ds); // get rm and color texture points l_vUV = dp + ds * d; l_vTextureRelief = tex2D( NormalMap, l_vUV); l_vTextureColour = tex2D( DiffuseMap, l_vUV); // expand normal from normal map in local polygon space l_vTextureRelief.xy = l_vTextureRelief.xy * 2.0 - 1.0; l_vTextureRelief.z = sqrt( 1.0 - dot( l_vTextureRelief.xy, l_vTextureRelief.xy)); l_vTextureRelief.rgb = normalize( l_vTextureRelief.x * p_input.tangent + l_vTextureRelief.y * p_input.binormal + l_vTextureRelief.z * p_input.normal); // compute light direction l_vTmp2 += l_eyeSpaceVertex * d * l_fDot; l_vLightDirection = normalize( l_vTmp2 - l_vLight.xyz); // ray intersect in light direction dp += ds * d; l_fDot = dot( p_input.normal, -l_vLightDirection); l_vTmp1 = normalize( float3( dot( l_vLightDirection, p_input.tangent), dot( l_vLightDirection, p_input.normal), l_fDot)); l_vTmp1 *= Depth / l_fDot; ds = l_vTmp1.xy; dp -= ds * d; float dl = RayIntersectRM( dp, l_vTmp1.xy); float l_fShadow = 1.0; float3 l_vSpecularShadow = l_vSpecular.rgb; if (dl < d - 0.05) // if pixel in shadow { l_fShadow = dot( l_vAmbient.rgb, float3( 1, 1, 1)) * 0.333333; l_vSpecularShadow = float3( 0, 0, 0); } // compute diffuse and specular terms float l_fAttenuation = max( 0.0, dot( -l_vLightDirection, p_input.normal)); float l_fDiffuseTerm = l_fShadow * max( 0.0, dot( -l_vLightDirection, l_vTextureRelief.rgb)); float l_fSpecularTerm = max( 0.0, dot( normalize( -l_vLightDirection - l_eyeSpaceVertex), l_vTextureRelief.rgb)); // compute final color float4 l_vFinalColour; l_vFinalColour.rgb = l_vAmbient.rgb * l_vTextureColour.rgb + l_fAttenuation * (l_vTextureColour.rgb * l_vDiffuse.rgb * l_fDiffuseTerm + l_vSpecularShadow * pow( l_fSpecularTerm, l_fShine)); l_vFinalColour.a = 1; return l_vFinalColour; } float RayIntersectRM( in float2 p_vDP, in float2 p_vDS) { float l_fDepthStep = 1.0 / float( LinearSearchSteps); // current size of search window float l_fSize = l_fDepthStep; // current depth position float l_fDepth = 0.0; // best match found (starts with last position 1.0) float l_fDepthReturn = 1.0; float4 l_vTexColour; int i; // search front to back for first point inside object for (i = 0 ; i < LinearSearchSteps - 1 ; i++) { l_fDepth += l_fSize; l_vTexColour = tex2Dlod( NormalMap, float4( p_vDP + p_vDS * l_fDepth, 0, 0)); if (l_fDepthReturn > 0.996) // if no depth found yet { if (l_fDepth >= l_vTexColour.w) { l_fDepthReturn = l_fDepth; // store best depth } } } l_fDepth = l_fDepthReturn; // recurse around first point (l_fDepth) for closest match for (i = 0 ; i < BinarySearchSteps ; i++) { l_fSize *= 0.5; l_vTexColour = tex2Dlod( NormalMap, float4( p_vDP + p_vDS * l_fDepth, 0, 0)); if (l_fDepth >= l_vTexColour.w) { l_fDepthReturn = l_fDepth; l_fDepth -= 2.0 * l_fSize; } l_fDepth += l_fSize; } return l_fDepthReturn; }
Partager