我的照明有问题。当光线越过顶点或线条时,光线会变得奇怪。 (这应该是圆的。)我一直在尝试各种各样的事情,但我无法找到原因。
我创建了一个天幕并正常化它的位置
double deltaLatitude = XM_PI / segments;
double deltaLongitude = XM_PI * 2.0 / segments;
int index = 0;
D3DXCOLOR bottomColor = D3DXCOLOR(0.529f, 0.807f, 0.821f, 1.0f);
D3DXCOLOR topColor = D3DXCOLOR(0.179f, 0.557f, 1.0f, 1.0f);
for (int i = 1; i < segments; i++)
{
double r0 = sin(i * deltaLatitude);
double y0 = cos(i * deltaLatitude);
for (int j = 0; j < segments; j++)
{
double x0 = r0 * sin(j * deltaLongitude);
double z0 = r0 * cos(j * deltaLongitude);
D3DXVECTOR3 v = D3DXVECTOR3(x0, y0, z0);//create normal based on possition (-1 <> 1)
D3DXVec3Normalize(&v, &v);//normalize
vertPos.push_back(Vertex(x0, y0, z0, lerp(bottomColor, topColor, y0), v));
}
}
vertPos.push_back(Vertex(0, 1, 0, lerp(bottomColor, topColor, 1), D3DXVECTOR3(0.0f, 1.0f, 0.0f)));
vertPos.push_back(Vertex(0, -1, 0, lerp(bottomColor, topColor, -1), D3DXVECTOR3(0.0f, -1.0f, 0.0f)));
for (int i = 0; i < segments - 2; i++)
{
for (int j = 0; j < segments; j++)
{
indices.push_back(segments * i + j);
indices.push_back(segments * i + (j + 1) % segments);
indices.push_back(segments * (i + 1) + (j + 1) % segments);
indices.push_back(segments * i + j);
indices.push_back(segments * (i + 1) + (j + 1) % segments);
indices.push_back(segments * (i + 1) + j);
}
}
// create the faces of the top of the dome
for (int i = 0; i < segments; i++)
{
indices.push_back(segments * (segments - 1));
indices.push_back((i + 1) % segments);
indices.push_back(i);
}
// create the faces of the bottom of the dome
for (int i = 0; i < segments; i++)
{
indices.push_back(segments * (segments - 1) + 1);
indices.push_back(segments * (segments - 2) + i);
indices.push_back(segments * (segments - 2) + (i + 1) % segments);
}
顶点着色器:
VS_OUTPUT VS(float4 inPos : POSITION, float2 inTexCoord : TEXCOORD, float4 inColor : COLOR, float3 normal : NORMAL)
{
VS_OUTPUT output;
output.Pos = mul(inPos, WVP);
output.worldPos = mul(inPos, World);
output.normal = mul(normal, World);
output.Color = inColor;
return output;
}
这是像素着色器:
float4 PS(VS_OUTPUT input) : SV_TARGET
{
input.normal = normalize(input.normal);
float4 diffuse = input.Color;
float skyColor = light.spos.a;
float4 sunColor = float4(500.0f, 100.0f, 100.0f, 1.0f);
float3 finalColor = float3(0.0f, 0.0f, 0.0f);
float3 finalAmbient = diffuse * skyColor;
float sunRange = 1000.0f;
float3 lightToPixelVec = light.spos - input.worldPos;
float d = length(lightToPixelVec);
if( d > sunRange ){
return float4(finalAmbient, diffuse.a);
}
//Turn lightToPixelVec into a unit length vector describing
//the pixels direction from the lights position
lightToPixelVec /= d;
//Calculate how much light the pixel gets by the angle
//in which the light strikes the pixels surface
float howMuchLight = dot(lightToPixelVec, input.normal);
//If light is striking the front side of the pixel
if( howMuchLight > 0.0f )
{
//Add light to the finalColor of the pixel
finalColor += howMuchLight * finalAmbient * sunColor;
//Calculate Light's Falloff factor
finalColor /= 10.0f + (0.01 * d) + (0.01 * (d*d));
}
finalColor = saturate(finalColor + finalAmbient);
return float4(finalColor, diffuse.a);
}
答案 0 :(得分:1)
你不需要考虑面部来获得顶点的法线。它只是一个半球,对,所以法线只是从球体中心(我猜测的原点)到顶点的向量,但是你应该将它标准化为长度为1.所以正常顶点只是它的坐标标准化。
答案 1 :(得分:0)
传统的OpenGL固定功能管道照明仅在顶点进行计算,并在两者之间进行插值。根据网格的拓扑结构,您可能会出现由OpenGL在顶点之间插值的方式导致的光栅化拓扑不连续性。
解决方案:使用每个片段照明,在片段着色器中实现。
BTW:你为什么要首先将照明应用于天幕?