简体   繁体   English

使用法线贴图的OpenGL hieghtmap渲染

[英]OpenGL hieghtmap rendering with normal map

I'm trying to render heightmap with normal map, using OpenGL and GLSL. 我正在尝试使用OpenGL和GLSL使用法线贴图渲染高度图。 What I have so far: quadtree grid with height being updated in vertex shader based on heightmap. 到目前为止,我有:在基于高度图的顶点着色器中更新高度的四叉树网格。 Generated normal texture Example od simillar one: http://www.leadwerks.com/wiki/images/0/08/Terr16.JPG 生成的普通纹理示例1: http : //www.leadwerks.com/wiki/images/0/08/Terr16.JPG

Terrain don't have tangents or vertex normals. 地形没有切线或顶点法线。 I can't get my light system working without those attributes. 没有这些属性,我的照明系统将无法正常工作。 I'm guessing that I have to use TBN matrix to produce vectors correctly. 我猜想我必须使用TBN矩阵正确生成向量。 But how to do it without vertex normal or tangent? 但是,如何在没有顶点法线或切线的情况下进行呢? Is there any simpler way than complicated reproducing of everything? 有比复杂复制所有内容更简单的方法吗? Is it really leak of normal transformation? 真的是正常转型的泄密吗? Or my whole way of light calculation is wrong? 还是我的整个光计算方式是错误的? Code fragments: 代码片段:

VS: 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: 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

Right now terrain is getting brighter/darker based on camera left/right rotation. 目前,根据相机向左/向右旋转,地形变得更亮/更暗。 So it's far from correct. 因此,这远非正确。

I've done this by sampling the height map on the neighboring vertices and calculating the normals with the result. 我通过在相邻顶点上采样高度图并计算结果的法线来做到这一点。 So for vertex (x,y), I sample the height map at that point. 因此,对于顶点(x,y),我在该点采样了高度图。 Then I also sample it at (x+1,y) and (x, y+1) and take the cross product of the resulting vectors. 然后,我还在(x + 1,y)和(x,y + 1)对其进行采样,并取所得向量的叉积。 So my vertex shader looks something like this: 所以我的顶点着色器看起来像这样:

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);
}

This assumes that the vertices are uniformly spaced in the x and y directions by vertexDelta.xy . 这假定顶点在x和y方向上vertexDelta.xy均匀间隔。 It also assumes you've set up the texture coordinates of texture units 3, 4, and 5. Texture unit 3 contains the actual texture coordinates of the height map. 它还假定您已经设置了纹理单元3、4和5的纹理坐标。纹理单元3包含高度图的实际纹理坐标。 Texture unit 4 is the same thing but moved over by the distance between the vertices in the x direction. 纹理单元4是相同的东西,但是在x方向上移动了顶点之间的距离。 Texture unit 5 is the same as texture unit 3, but with the coordinates moved by the y distance between vertices. 纹理单元5与纹理单元3相同,但坐标移动了顶点之间的y距离。 (You could calculate the distance in the vertex shader, but it becomes a dependent look-up which is slower.) (您可以在顶点着色器中计算距离,但它会成为依赖的查找,速度较慢。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM