我正在处理为DirectX编写的游戏中的数据,而我正在使用OpenGL。 我已经设法找出99%的关于纹理翻译的所有内容,它们在地形上看起来是正确的。
这是我遇到的问题.. 我知道将法线混合在一起并不能很好地发挥作用。我读过有一种可行的方法,但我从未能得到满意的结果。 这是我正在做的基础知识。
每个地图部分有4个纹理。其中三个具有匹配的法线贴图。其中一个是颜色基础,从未翻译过。它在翻译后混合在一起。我跟踪这个纹理,并将值发送到用作遮罩的着色器,以避免翻译颜色纹理或使用其不存在的法线贴图。我已经确认通过渲染不同的纹理,法线贴图和颜色贴图来进行遮罩。
纹理的顺序不一样。也就是说,虽然纹理可能是相同的,但它们是乱序的。第一个纹理可能是岩石,第二个草在一个区域,但其相邻的邻居可能会将这两个相反。我考虑过对它们进行排序,但并非所有部分都包含相同的纹理。
所以...我做的是掩盖纹理和法线贴图,并在法线贴图上单独进行数学运算并求它们。我不认为地图的顺序很重要,但显然我错了?也许转换后的纹理需要翻译法线?我正在改变法线贴图而不是法线本身。
这是我屏蔽和计算NdotL的代码:
MixLevel = texture2D(mixtexture, mix_coords.xy).rgba;
//Which ever is the blend color can't be translated.
t1 = mix(texture2D(layer_1, color_uv), t1, mask_2.r);
t2 = mix(texture2D(layer_2, color_uv), t2, mask_2.g);
t3 = mix(texture2D(layer_3, color_uv), t3, mask_2.b);
t4 = mix(texture2D(layer_4, color_uv), t4, mask_2.a);
//Now we mix our textures
vec4 base;
base = t4 * MixLevel.a ;
base += t3 * MixLevel.b ;
base += t2 * MixLevel.g ;
base += t1 * MixLevel.r ;
//Get our normal maps.
n1.rgb = normalize(2.0 * n1.rgb - 1.0);
n2.rgb = normalize(2.0 * n2.rgb - 1.0);
n3.rgb = normalize(2.0 * n3.rgb - 1.0);
n4.rgb = normalize(2.0 * n4.rgb - 1.0);
//-------------------------------------------------------------
//There is no good way to add normals together and not destroy them.
//We have to do the math on each one THAN add them together.
vec3 N = normalize(n);
vec3 L = normalize(lightDirection);
PN4 = normalize(TBN * n4.rgb)* mask_2.a;
PN3 = normalize(TBN * n3.rgb)* mask_2.b;
PN2 = normalize(TBN * n2.rgb)* mask_2.g;
PN1 = normalize(TBN * n1.rgb)* mask_2.r;
float NdotL = 0.0;
NdotL = NdotL + (max(dot(PN4, L), 0.0) * MixLevel.a );
NdotL = NdotL + (max(dot(PN3, L), 0.0) * MixLevel.b );
NdotL = NdotL + (max(dot(PN2, L), 0.0) * MixLevel.g );
NdotL = NdotL + (max(dot(PN1, L), 0.0) * MixLevel.r );
更新: 根据要求,我附上了一些代码: 这是片段着色器中执行纹理变换的部分:
//calcualte texcoords for mix texture.
float scale = 256.0/272.0;
vec2 mc;
mc = color_uv;
mc *= scale;
mc += .030303030;// = 8/264
mix_coords = mc.xy;
// layer 4 ---------------------------------------------
vec2 tv4;
tv4 = vec2(dot(-layer3U, Vertex), dot(layer3V, Vertex));
t4 = texture2D(layer_4, -tv4 + .5);
n4 = texture2D(n_layer_4, -tv4 + .5);
// layer 3 ---------------------------------------------
vec2 tv3;
tv3 = vec2(dot(-layer2U, Vertex), dot(layer2V, Vertex));
t3 = texture2D(layer_3, -tv3 + .5);
n3 = texture2D(n_layer_3, -tv3 + .5);
// layer 2 ---------------------------------------------
vec2 tv2;
tv2 = vec2(dot(-layer1U, Vertex), dot(layer1V, Vertex));
t2 = texture2D(layer_2, -tv2 + .5);
n2 = texture2D(n_layer_2, -tv2 + .5);
// layer 1 ---------------------------------------------
vec2 tv1;
tv1 = vec2(dot(-layer0U, Vertex), dot(layer0V, Vertex));
t1 = texture2D(layer_1, -tv1 + .5);
n1 = texture2D(n_layer_1, -tv1 + .5);
//------------------------------------------------------------------
Vertex是模型空间中的gl_Vertex。 Layer0U和Layer0V是vec4,来自游戏数据。 这是在顶点着色器中创建mask_2的方式。
// Create the mask. Used to cancel transform of color/paint texture;
mask_2 = vec4(1.0 ,1.0 ,1.0 ,1.0);
switch (main_texture){
case 1: mask_2.r = 0.0; break;
case 2: mask_2.g = 0.0; break;
case 3: mask_2.b = 0.0; break;
case 4: mask_2.a = 0.0; break;
}
这是一张显示照明问题的图片:
更新:我想我知道什么是错的...当法线贴图被转换(实际上是它的UV)时,这会使法线指向错误的方向。 我需要帮助将在变换后的UV处读取的实际法线转换回原始状态,我无法移除UV转换......这只是为该纹理像素位置读取了错误的法线。这都错了。 我必须使用的是2个执行uv变换和顶点的vec4。如果我可以使用这些来构建3x3矩阵,我可以将法线乘以它并使其面向正确的方向?我不擅长高等数学,需要帮助。 (据我所知,这种方法甚至不起作用) 这是一个镜面反射的图像..你可以看到法线方向是如何导致光照问题的。