游戏开发论坛

 找回密码
 立即注册
搜索
查看: 8094|回复: 11

基于GPU的4层纹理地形渲染

[复制链接]

9

主题

28

帖子

49

积分

注册会员

Rank: 2

积分
49
发表于 2008-12-5 14:09:00 | 显示全部楼层 |阅读模式
这个是在做基于GPU的LOD技术学习中写的一个程序,当时对<GPU精粹2>介绍的一种LOD技术反复研究,发现很难实现,于是写了这个测试程序.
该示例使用fault formation算法生成地形数据,之后进行平滑处理,最后把高度数据转存成bmp文件,程序在首次执行时检查有没有之前生成的高度数据文件,没有就使用fault formation算法生成高度图.
主函数读入4张纹理,在shader中对pos的y值做判断,计算出每个高度对应的一个纹理系数.
shader.fx如下:
float4 complex(float3 x)
{
        float4 p = float4(1.0f,1.0f,1.0f,0.3f);
        float4 low = float4(0.0f,63.0f,126.0f,189.0f);
        float4 high = float4(62.0f,125.0f,188.0f,251.0f);
        float4 uphigh = float4(124.0f,187.0f,250.0f,313.0f);
       
        x *=33.33f;
        x.y = (x.y+70)*4;
        float2 uv = float2((x.x+64)/128,(128-x.z)/128)*4.0f;
       
       
        /*p.w = floor( x.y/192.0f );
        p.z = clamp(floor((x.y-p.w*255)/128),0,1);
        p.y = clamp(floor((x.y-p.w*255-p.z*255)/64),0,1);
        p.x = clamp(floor(x.y-p.w*255-p.z*255-p.y*255),0,1);*/
       
        for( int i =0; i<4; i++ )
        {
                if(x.y<high)
                        p = (x.y-low)/62.0f;
                else if(x.y == high)
                        p = 1.0f;
                else if(x.y>high)
                        p = 1.0f-(x.y-high)/62.0f;
                               
                if(x.y<low)
                        p = 0.0f;
                else if(x.y>uphigh)
                        p = 0.0f;
                               
                if(x.y<low[1])
                        p[0] = 1.0f;
                               
        }
       

        return p.x*tex2D(lowestSampler,uv)+p.y*tex2D(lowSampler,uv)                                 +p.z*tex2D(highSampler,uv)+p.w*tex2D(highestSampler,uv);
}

该段代码之前并未使用for 循环和 if语句,使用一种顺序语句代替if语句的,它的结果只生成0\1两种结果,但我改用现在这种形式,发现效率也没什么改变,为了可读性,使用分支语句看来也无妨了

itlmy@163.com
sf_200812514842.jpg

59

主题

984

帖子

1200

积分

金牌会员

Rank: 6Rank: 6

积分
1200
发表于 2008-12-6 20:29:00 | 显示全部楼层

Re:基于GPU的4层纹理地形渲染

你这个代码效率也太低了点....

8

主题

390

帖子

390

积分

中级会员

Rank: 3Rank: 3

积分
390
发表于 2008-12-8 09:00:00 | 显示全部楼层

Re:基于GPU的4层纹理地形渲染


//VTX2LAYERUV and VTX2BLENDUV are defined in app

//TERRAIN_TEX_NUM is defined in app, TERRAIN_TEX_NUM belong to [2,5];
sampler2D TerrainTextures[TERRAIN_TEX_NUM];

float4x4 WorldViewProj;

void MainVS(
        in float4 InPosition : POSITION,
        out float2 outLayerUV : TEXCOORD0,
        out float2 outBlendUV : TEXCOORD1,
        out float4 OutPosition : POSITION
        )
{
        OutPosition = mul(WorldViewProj,InPosition);
        outLayerUV = InPosition.xz*VTX2LAYERUV;
        outBlendUV = InPosition.xz*VTX2BLENDUV;
}






void MainPS(
        in float2 LayerTexUV: TEXCOORD0,
        in float2 BlendUV : TEXCOORD1,
        out float4 OutColor : COLOR0
        )
{
                float4 blend = tex2D(TerrainTextures[0], BlendUV);
        //
#if TERRAIN_TEX_NUM>1
                float4 color0 = tex2D(TerrainTextures[1], LayerTexUV);
#endif //TERRAIN_TEX_NUM>1
       
#if TERRAIN_TEX_NUM>2
                float4 color2 = tex2D(TerrainTextures[2], LayerTexUV);
                float4 color1 = color2*blend.b + color0*(1.0-blend.b);
                color0=color1;
#endif //

#if TERRAIN_TEX_NUM>3
                color2 = tex2D(TerrainTextures[3] , LayerTexUV);
                color0 = color2*blend.g+color1*(1.0-blend.g);       
#endif//
       
#if TERRAIN_TEX_NUM>4
        color2 = tex2D(TerrainTextures[4], LayerTexUV);
        color1 = color2*blend.r+color0*(1.0-blend.r);
        color0=color1;
#endif//
               
  float4 final_color = color0*blend.a;//a should be shadow value
  OutColor=float4(final_color.rgb,1.0);
}


--可以参考我们现在项目的,几个做的比较好的,1:vertex数据非常小,超大视野可见度,仍然保证几何数据带宽不造成瓶颈;2:灵活支持1-4层detail纹理,加1层混合纹理,(其中一个通道做shadow);3全部代码预处理,运行时无分支跳转;

9

主题

28

帖子

49

积分

注册会员

Rank: 2

积分
49
 楼主| 发表于 2008-12-8 11:23:00 | 显示全部楼层

Re:基于GPU的4层纹理地形渲染

ReallyBigBug:
你们的代码需要两个纹理坐标,BlendUV 坐标是美工添加的吧,我们这边没有美工,呵呵,谢谢你的代码。
我帖的这个shader效率并不低多少,可能看上去不太高校,但测试并不像想象的那么糟,几乎与之前的顺序语句没什么区别,而且模拟城市5也用了很多循环分支语句在shader里,呵呵,只是个人想法

8

主题

390

帖子

390

积分

中级会员

Rank: 3Rank: 3

积分
390
发表于 2008-12-8 11:33:00 | 显示全部楼层

Re:基于GPU的4层纹理地形渲染

看我的vertex格式,VB中存储的就是一个x,y,z,数据非常小,纹理坐标和地形坐标的x,y重用的。in的就是一个float3;


void MainVS(
in float4 InPosition : POSITION,
out float2 outLayerUV : TEXCOORD0,
out float2 outBlendUV : TEXCOORD1,
out float4 OutPosition : POSITION
)

---不过,学习,自己玩玩,怎么搞都可以,如果做项目就谨慎一点,哈哈

9

主题

28

帖子

49

积分

注册会员

Rank: 2

积分
49
 楼主| 发表于 2008-12-8 11:43:00 | 显示全部楼层

Re:基于GPU的4层纹理地形渲染

噢,我明白了,你们的代码是每层纹理都在对应顶点坐标为 (x,z)的位置取贴图颜色值,逐层混合的,可是不明白为什么混合系数float4 blend = tex2D(TerrainTextures[0], BlendUV);要取第一层纹理的颜色值呢?

59

主题

984

帖子

1200

积分

金牌会员

Rank: 6Rank: 6

积分
1200
发表于 2008-12-8 15:22:00 | 显示全部楼层

Re:基于GPU的4层纹理地形渲染

itlmy:
不太清楚你在什么平台上做测试,不过对于Geforece 8系列以下的显卡来说
使用循环明显要比手动把循环展开慢
动态分支就更慢了,对于不支持动态分支的硬件,分支的两端都会执行,即使是完全支持sm3.0的硬件,分支指令也比其他指令慢。再者,嵌套的动态分支会极大的破坏流水线的并行性,比单层分支还要慢。
最后不要忘了你是在做浮点运算,浮点数总是有误差的,无论是写shader还是普通程序,都应该避免类似(x.y == high) 这样的表达式,很有可能永远也不会出现相等的情况。

对于地形纹理来说,通常都用一张格外的纹理来记录其他每层纹理的权重,实现和修改起来都非常简单

8

主题

390

帖子

390

积分

中级会员

Rank: 3Rank: 3

积分
390
发表于 2008-12-8 17:25:00 | 显示全部楼层

Re:基于GPU的4层纹理地形渲染

第一张纹理存储4个系数,每个0-255(在应用程序角度看),分别是ARGB,A控制静态阴影深度,R控制第一层纹理和第二层直接的混合系数,G控制第三层纹理和之前2层混合后的结果之间的混合系统,B就是控制第四层纹理和前面结果的混合系数;都是参考wow来的,呵呵。

然后,这张混合纹理是纹理坐标Clamp的,一块地形一张,大小128差不多够了;而一到四层的detail纹理是wrap的,平铺在地表上;

14

主题

345

帖子

376

积分

中级会员

Rank: 3Rank: 3

积分
376
QQ
发表于 2008-12-9 09:46:00 | 显示全部楼层

Re:基于GPU的4层纹理地形渲染

PS有点复杂, 老显卡估计撑不住

9

主题

28

帖子

49

积分

注册会员

Rank: 2

积分
49
 楼主| 发表于 2008-12-11 18:57:00 | 显示全部楼层

Re:基于GPU的4层纹理地形渲染

多谢ReallyBigBug与clayman两位,你们的建议对我很有启发,谢谢
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

作品发布|文章投稿|广告合作|关于本站|游戏开发论坛 ( 闽ICP备17032699号-3 )

GMT+8, 2026-1-20 15:35

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表