我已经对App Hub提出了一个问题,但没有任何回复,所以我想我会问这里的大师。
是否可以让模型显示其纹理而不是此项目输出的灰度?
可在此site上找到代码。
修改
我上传了源代码here,因为我仍然无法使其正常工作。有人可以帮忙吗?
答案 0 :(得分:4)
我只是快速浏览了着色器代码,因为我怀疑像素着色器不使用任何纹理,
// 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;
}
正如您所看到的,纹理未被修复,漫反射被计算为各种其他变量的组合。
这几乎肯定是为了降低代码的复杂性,但是添加对纹理的支持应该是相当微不足道的。您应该查看this sample底部的像素和顶点着色器,以了解如何在着色器中使用纹理并将其与CalcLighting()函数集成。
您需要在代码中自己设置模型纹理,以便着色器查看它。我无法记住确切的语法,但是这样的话:
effect.SetTexture("texture_name", texture);
您正在寻找什么,其中“texture_name”是您在着色器文件中声明的类型纹理的名称。
你需要考虑的另一件事是重写CalcLighting接受的参数,你需要从顶点着色器传递纹理坐标,你可以可能删除vDiffuseAlbedo,因为它可以是取而代之的是纹理的颜色。
不幸的是,如果没有实际编写代码(我目前无法访问XNA安装),我无法更彻底地回答这个问题,请考虑这些指针并尝试找到使用着色器加载纹理模型的教程。由于您似乎对使用自定义着色器感兴趣,因此避免使用关于BasicEffect的教程,因为BasicEffect几乎隐藏了所有相关着色器代码,您将不会学到任何东西。
我很难建议你可以学习的教程,因为有很多在线教程,每个教程都有人喜欢。所以请记住我所说的随意找到一个你熟悉的教程,解释如何加载和正确渲染纹理模型,然后使用该知识将其应用于此示例。它真的不像最初看起来那么难!
刚刚对您的示例代码进行了快速修改,它应该可以很好地演示着色器中的纹理映射,
我在model.fx中添加了一个纹理变量,我通过代码设置它,以便绘制纹理而不是白色,并确保顶点着色器将顶点的纹理坐标传递给像素着色器。请记住,我故意打破了光照计算,以简化纹理采样器的属性。
//=========================================================================
//
// 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;
}
}
使用'DrawMainLightingPass'中'DefferedShadowMaps.cs'源文件中的一个样本我修改了一些绘图代码如下:
// 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);
}
请注意,这不是您应该处理模型绘制和管理的方式,但它是我可以演示您纹理模型的最直接方式。这是有效的(我运行它很好),所以随意修改它,使其适合您自己的引擎设计:)