Display a models texture
I have asked a question over a the App Hub, but not had any responses so I thought I'd ask the gurus here.
Is it possible to get the model to 开发者_如何学Godisplay its texture rather than the greyscale that this project outputs?
The code can be found on this site.
EDIT
I have uploaded the source code here, because I still can't get this to work correctly. Can someone please help?
I just took a quick look at the shader code and as I had suspected the pixel shader does not use any sort of texture,
// Calculates the contribution for a single light source using phong lighting
float3 CalcLighting ( float3 vDiffuseAlbedo,
float3 vSpecularAlbedo,
float fSpecularPower,
float3 vLightColor,
float3 vNormal,
float3 vLightDir,
float3 vViewDir )
{
float3 R = normalize(reflect(-vLightDir, vNormal));
// Calculate the raw lighting terms
float fDiffuseReflectance = saturate(dot(vNormal, vLightDir));
float fSpecularReflectance = saturate(dot(R, vViewDir));
// Modulate the lighting terms based on the material colors, and the attenuation factor
float3 vSpecular = vSpecularAlbedo * vLightColor * pow(fSpecularReflectance, fSpecularPower);
float3 vDiffuse = vDiffuseAlbedo * vLightColor * fDiffuseReflectance;
// Lighting contribution is the sum of the diffuse and specular terms
return vDiffuse + vSpecular;
}
As you can see a texture is not being refrenced, the diffuse is being calculated as a combination of various other variables.
This was almost certainly done to reduce the complexity of the code, however adding support for textures should be fairly trivial. You should take a look at the pixel and vertex shaders at the bottom of this sample to see how textures can be used in shaders and integrate that with the CalcLighting() function.
You'll need to set the models texture yourself in code for the shader to see it. I cant remember the exact syntax but something like this:
effect.SetTexture("texture_name", texture);
Is what you're looking for, where "texture_name" is the name of the type texture you have declared in the shader file.
Another thing you'll need to consider is re-writing the parameters CalcLighting takes in, you will need to pass the texture coordinates from the vertex shader and you can probably remove vDiffuseAlbedo as that can be replaced by the colour of the texture.
Unfortunately I can't make this answer any more thorough without actually writing code (and I have no access to an XNA install currently), consider these pointers and try and find a tutorial for loading a textured model using shaders. Since you seem to be interested in using custom shaders avoid tutorials talking about BasicEffect as BasicEffect hides pretty much all relevant shader code from you and you won't learn anything.
It's hard for me to suggest tutorials you could learn from since there are so many tutorials online and each strikes someone elses fancy. So keeping in mind what i've said feel free to find a tutorial you're comfortable with which explains how to load and properly render a textured model, then using that knowledge apply it to this sample. It's really not as hard as it may seem at first!
Just did a quick'n'dirty modification to the sample code for you, it should work well enough to demonstrate texture mapping in shaders,
I added a texture variable to model.fx which I set through code so that it draws the texture instead of the white colour and I made sure the vertex shader passed the texture coordinates of the vertex to the pixel shader. keep in mind I deliberately broke the lighting calculation to simplify the purpouse of the texture sampler.
//=========================================================================
//
// DeferredShadowMaps
//
// by MJP (mpettineo@gmail.com)
// 12/14/08
//
//=========================================================================
//
// File: Model.fx
//
// Desc: Outputs the lighting contribution for a single directional
// light source. Also samples shadow occlusion from a texture.
//
//=========================================================================
float4x4 g_matWorld;
float4x4 g_matViewProj;
float4x4 g_matWorldIT;
float2 g_vRTDimensions;
float3 g_vDiffuseAlbedo = {0.5f, 0.5f, 0.5f};
float3 g_vSpecularAlbedo = {1.0f, 1.0f, 1.0f};
float g_fSpecularPower = 32.0f;
float3 g_vLightDirectionWS;
float3 g_vLightColor;
float3 g_vAmbientColor;
float3 g_vCameraPositionWS;
texture ShadowOcclusion;
sampler2D ShadowOcclusionSampler = sampler_state
{
Texture = <ShadowOcclusion>;
MinFilter = Point;
MagFilter = Point;
MipFilter = Point;
};
texture ModelTexture;
sampler2D ModelSampler = sampler_state
{
Texture = <ModelTexture>;
MinFilter = Linear;
MagFilter = Linear;
MipFilter = Linear;
};
void ModelVS( in float4 in_vPositionOS : POSITION,
in float3 in_vNormalOS : NORMAL,
in float2 in_vTexCoord : TEXCOORD0,
out float4 out_vPositionCS : POSITION,
out float3 out_vNormalWS : TEXCOORD0,
out float3 out_vPositionWS : TEXCOORD1,
out float4 out_vPositionCS2 : TEXCOORD2,
out float2 out_vTexCoord : TEXCOORD3 )
{
// Figure out the position of the vertex in world space, and clip space
out_vPositionWS = mul(in_vPositionOS, g_matWorld).xyz;
out_vPositionCS = mul(float4(out_vPositionWS, 1), g_matViewProj);
// Rotate the normal so it's in world space
out_vNormalWS = mul(in_vNormalOS, g_matWorldIT);
// Also store the clip-space position in a TEXCOORD, since we can't
// read from the POSITION register in the pixel shader.
out_vPositionCS2 = out_vPositionCS;
// Pass out the texture coordinates to the pixel shader
out_vTexCoord = in_vTexCoord;
}
// Calculates the contribution for a single light source using phong lighting
float3 CalcLighting ( float3 vDiffuseAlbedo,
float3 vSpecularAlbedo,
float fSpecularPower,
float3 vLightColor,
float3 vNormal,
float3 vLightDir,
float3 vViewDir )
{
float3 R = normalize(reflect(-vLightDir, vNormal));
// Calculate the raw lighting terms
float fDiffuseReflectance = saturate(dot(vNormal, vLightDir));
float fSpecularReflectance = saturate(dot(R, vViewDir));
// Modulate the lighting terms based on the material colors, and the attenuation factor
float3 vSpecular = vSpecularAlbedo * vLightColor * pow(fSpecularReflectance, fSpecularPower);
float3 vDiffuse = vDiffuseAlbedo * vLightColor * fDiffuseReflectance;
// Lighting contribution is the sum of the diffuse and specular terms
return vDiffuse + vSpecular;
}
// Gets the screen-space texel coord from clip-space position
float2 CalcSSTexCoord (float4 vPositionCS)
{
float2 vSSTexCoord = vPositionCS.xy / vPositionCS.w;
vSSTexCoord = vSSTexCoord * 0.5f + 0.5f;
vSSTexCoord.y = 1.0f - vSSTexCoord.y;
vSSTexCoord += 0.5f / g_vRTDimensions;
return vSSTexCoord;
}
float4 ModelPS( in float3 in_vNormalWS : TEXCOORD0,
in float3 in_vPositionWS : TEXCOORD1,
in float4 in_vPositionCS : TEXCOORD2,
in float2 in_vTexCoord : TEXCOORD3) : COLOR0
{
// Sample the shadow term based on screen position
float2 vScreenCoord = CalcSSTexCoord(in_vPositionCS);
float fShadowTerm = tex2D(ShadowOcclusionSampler, vScreenCoord).r;
// Normalize after interpolation
float3 vNormalWS = normalize(in_vNormalWS);
float3 vLightDirWS = normalize(-g_vLightDirectionWS);
float3 vViewDirWS = normalize(g_vCameraPositionWS - in_vPositionWS);
// Calculate the lighting term for the directional light
float3 vLightContribition = 0;
vLightContribition = fShadowTerm * tex2D(ModelSampler, in_vTexCoord);
// Add in ambient term
vLightContribition.xyz += g_vDiffuseAlbedo * g_vAmbientColor;
return float4(vLightContribition, 1.0f);
}
technique Model
{
pass Pass1
{
VertexShader = compile vs_2_0 ModelVS();
PixelShader = compile ps_2_0 ModelPS();
ZEnable = true;
ZWriteEnable = true;
CullMode = CCW;
FillMode = Solid;
AlphaBlendEnable = false;
AlphaTestEnable = false;
}
}
And using one of your samples in the 'DefferedShadowMaps.cs' source file in the 'DrawMainLightingPass' I modified some of the draw code to be as follows:
// Loads the texture here (note this is put here for the skae of simplicity, the texture should generally be retrieved from the model)
Texture texture = Content.Load<Texture>("Models/Beast_1");
// Begin the Effect
modelEffect.Begin();
modelEffect.CurrentTechnique.Passes[0].Begin();
// Draw the models
foreach (ModelInstance modelInstance in modelList)
{
modelEffect.Parameters["ModelTexture"].SetValue(texture);
modelInstance.Draw(GraphicsDevice, modelEffect);
}
Please note this is not the way you should handle model drawing and management but it is the most straightforward way I could demonstrate you to texture your model. This works (I ran it and it was fine), so feel free to modify it and make it suited for your own engine design :)
精彩评论