我尝试使用OpenGL和GLSL使用法线贴图渲染高度图。 到目前为止我所拥有的: 基于高度图在顶点着色器中更新高度的四叉树网格。 生成正常纹理 示例od simillar one: http://www.leadwerks.com/wiki/images/0/08/Terr16.JPG
地形没有切线或顶点法线。没有这些属性,我无法让我的灯光系统工作。我猜测我必须使用TBN矩阵才能正确生成向量。但是如何在没有顶点法线或切线的情况下做到这一点?有没有比复杂的一切更简单的方法? 这真的是正常转型的泄漏吗?或者我的整个光计算方式都错了? 代码片段:
VS
vec4 pos=vertex_position;//grid position (only x,z)
pos.y=((texture(heightmap_tex,uv_coords).x)*scale_height);
pos.w=1.0;//to be safe
vec4 P=viewMatrix*pos;
vec3 L=mat3(MVmatrix)*vec3(worldLightPos)-P.xyz;
Out.lightDir=L;
vec3 V=-P.xyz;
Out.eyeDir=V;
Out.texCOORD=uv_coords;
gl_Position = MVPmatrix * pos;
FS
vec3 V=normalize(In.eyeDir);
vec3 L=normalize(In.lightDir);
vec2 norm_texture=texture(texturenormal,In.TexCoord).xy*2.0-vec2(1.0);
vec3 N=normalize(vec3(norm_texture,sqrt(1.0-dot(norm_texture.xy, norm_texture.xy))*2.0-vec3(1.0)));//unpacking from 2 channel
vec3 R=reflect(-L,N);//phong
vec3 specular=pow(max(dot(R,V),0.0),shininess)*specularColor;//phong
vec3 diffuse=max(dot(N,L),0.1)*vec3(texColor);//phong
现在,根据相机左/右旋转,地形变得更亮/更暗。所以它远非正确。
答案 0 :(得分:0)
我通过对相邻顶点上的高度图进行采样并使用结果计算法线来完成此操作。所以对于顶点(x,y),我在那个点采样高度图。然后我也在(x + 1,y)和(x,y + 1)处对其进行采样,并取得所得矢量的叉积。所以我的顶点着色器看起来像这样:
vec3 calculateNormal (float y0, float y1, float y2)
{
vec3 p1 = gl_Vertex.xyz;
vec3 p2 = gl_Vertex.xyz;
vec3 p3 = gl_Vertex.xyz;
p2.x += vertexDelta.x;
p3.z += vertexDelta.y;
p1.y = y0;
p2.y = y1;
p3.y = y2;
return normalize(gl_NormalMatrix * cross(p3 - p1, p2 - p1));
}
void main ()
{
vec4 heightSample = texture2DRect(heightMap, gl_MultiTexCoord3.xy);
vec4 heightSampleX = texture2DRect(heightMap, gl_MultiTexCoord4.xy);
vec4 heightSampleY = texture2DRect(heightMap, gl_MultiTexCoord5.xy);
...
normal = calculateNormal (heightSample, heightSampleX, heightSampleY);
}
这假定顶点在x和y方向上均匀间隔vertexDelta.xy
。它还假设您已设置纹理单元3,4和5的纹理坐标。纹理单元3包含高度图的实际纹理坐标。纹理单元4是相同的,但是在x方向上的顶点之间的距离移动。纹理单元5与纹理单元3相同,但坐标移动了顶点之间的y距离。 (您可以计算顶点着色器中的距离,但它会变为相关的查找速度较慢。)