Rendermonkey 软件实现模型描边效果

对选中物品的高亮描边效果,利用rendermonkey软件实现模拟,主要部分即是:获取法线放大后的模型,单色填充,并渲染到target; 然后对该target进行模糊处理。具体重要的几个步骤如下:

1.右键新建一个Directx effect,选择一个model

Rendermonkey 软件实现模型描边效果_第1张图片

2.双击 Steam Mapping,在编辑框中初始化需要传递的变量,这些信息会被导入到Vertex Shader 的输入寄存器

Rendermonkey 软件实现模型描边效果_第2张图片

3.编写法线放大程序

shader书写阶段分为Vertex-shader Stage, Geometry-shader Stage,Pix-shader Stage:
Vertex-Shader Stage 处理 input传进来的顶点,比如皮肤处理,坐标转换,形状变化,以及逐个顶点光照等。每个vertex shader 都要最少有一个输入和一个输出。
Geometry-Shader Stage: 不同于Vertex Shader仅对单个顶点处理,Geometry shader 输入全部的顶点
Pixel-shader Stage: 可以逐像素照亮和后期处理,结合常量,纹理数据,等数据生成输出。输出为颜色,深度信息等,但是不可输出模板信息
首先需要定义一个 float4X4 view_proj_matix, 作为后面变换需要。然后定义一个变量,作为法线放大参数;

struct VS_OUTPUT 结构,用于传递到 pixel shader的信息。
可得到如下的vertex shader 程序

float4x4 view_proj_matrix;
float   flBiggerFactor;

struct VS_OUTPUT 
{
   float4 Position : POSITION0;
};

VS_OUTPUT vs_main(float3 Position:POSITION0, float3 normal:NORMAL0)
{
   VS_OUTPUT Out = (VS_OUTPUT) 0;  
   // turn bigger
   float3 pos = Position + normal * flBiggerFactor;
   //transform matrix
   Out.Position = mul(float4(pos, 1), view_proj_matrix);

   return Out ; 
}

4.因为需要把法线放大部分渲染到纹理,在工程中需要添加renderable texture,如下所示

Rendermonkey 软件实现模型描边效果_第3张图片

5.写模糊pass

vertex shader 部分,同理用mul运算作下 position 的变换,很简单。

VS_OUTPUT vs_main(float4 Pos: POSITION)
{
   VS_OUTPUT Out;

   // this is half a pixel with and height because
   // the screen-aligned quad has a width and height of 2
   float2 halfPixelSize = 0.5 * float2( viewport_inv_width, viewport_inv_height);

   // Clean up inaccuracies
   Out.Pos = float4(Pos.xy, 0, 1);

   Out.texCoord = float2(0.5f, 0.5f) + float2(0.5f, -0.5f) * Pos.xy;

   return Out;
}

接下来,用高斯模糊box,对刚才渲染纹理进行模糊

const float4 samples[9] = {
-3.0, -3.0, 0, 1.0/16.0,
-3.0, 3.0, 0, 1.0/16.0,
3.0, -3.0, 0, 1.0/16.0,
3.0, 3.0, 0, 1.0/16.0,
-3.0, 0.0, 0, 2.0/16.0,
3.0, 0.0, 0, 2.0/16.0,   
0.0, -3.0, 0, 2.0/16.0,
0.0, 2.0, 0, 2.0/16.0,
0.0, 0.0, 0, 4.0/16.0
};
float4 ps_main(float2 texcoord: TEXCOORD0) : COLOR
{
   //return float4(1,0,1,1);
   float4 col = float4(0,0,0,0);
   //Sample and output the averaged colors
    for(int i=0;i<9;i++)
     col += samples[i].w * tex2D(sceneTex,texcoord+
        float2(samples[i].x * viewport_inv_width,samples[i].y * viewport_inv_height));
    return col;

   //return tex2D(Texture0Map,texcoord);
}

该部分要注意几个 render的设置如下, Blur Pass 中吧 前一个target colormap 作为输入,输出到 toonmap,blurPass——1 就把toonmap 再做模糊
Rendermonkey 软件实现模型描边效果_第4张图片

6.最后一个贴图pass

vertex shader 主要做工作是计算位置,纹理,法线等,和第一个pass一样,需要设置摄像机。

struct VS_OUTPUT 
{
   float4 Position : POSITION0;
   float2 Texcoord:TEXCOORD0;
   float3 normal:TEXCOORD1;
   float2 Texcoord1:TEXCOORD2;

};

VS_OUTPUT vs_main(VS_INPUT Input,float2 Texcoord:TEXCOORD0,float3 normal:NORMAL0)
{
   VS_OUTPUT Out = (VS_OUTPUT)0;
   //tiny little model  give it some size and center it better
   Out.Position = mul(Input.Position, view_proj_matrix);

   Out.Texcoord = Texcoord;
   Out.normal = normal;

   float3 PosW = mul(Input.Position, view_matrix);
   float3 normalV = mul(normal, (float3x3)view_matrix);

   float diffuse = max(0,dot(-lightDir,normalV));
   Out.Texcoord1.x = diffuse;
   Out.Texcoord1.y = 0.0f;   
   //Output.Position = mul( Input.Position, matViewProjection );

   return( Out );


}

最后截个效果图

Rendermonkey 软件实现模型描边效果_第5张图片

另外提一下,在C++中调用pass 的过程,设置shader文件中参数,设置渲染状态,设置纹理,之后就是设置technique,beginpass,drawRangeIndexPrimitive,endpass了,代码大致如下所示

        postEffect->setFloat("rimback_biggerFactor", rimback_biggerFactor);
            postEffect->setVector4("edgeColor", (Vector4*)(&Stagescenerender->highLights(colorID).color));  

            //postEffect->setupAutoParameters(renderable);

            //set texture
            if(appear.material[eMaterial_0].numTextureUnit)
                appear.material[eMaterial_0].setTextureUnit(pRenderSys,0);
            else
                pRenderSys->setTexture(0, 0);

            pRenderSys->setTexture(1, (ITexture*)pRenderSys->getRenderTargetTexture(blurRTT1));

            uint iPass;
            postEffect->setTechnique("FinalBlend");
            postEffect->begin(&iPass);
            postEffect->beginPass(0);
            pRenderSys->drawRangeIndexedPrimitive(PT_TRIANGLES, geo.indexBuffer->getType(),geo.indexStart,geo.indexCount,geo.vertexStart,geo.vertexEnd);
            postEffect->endPass();
            postEffect->end();
            appear.geometry.resetStream(pRenderSys);

project download:
https://github.com/codeAPmind/normal-bigger
Refference:
《shaders for game programs and artists》

你可能感兴趣的:(Algorithms,Game,develop,HLSL,描边)