zoukankan      html  css  js  c++  java
  • celshading搭配硬件蒙皮

    之前使用celshading实现简单的模型身上的阴影.现在因为要加入ogre的硬件蒙皮,导致阴影消失了.只有直接在shader里改里,一张shader里包含了celshading和硬件蒙皮.感觉不是太好,但硬件蒙皮+normal map也是得这么做,还没找到方法.全程使用的shader似乎不得不写在一起了.

    把硬件蒙皮融合进自己的shader,一定要注意顶点程序中输出顶点的坐标,关注你自己的shader中position所在空间关系.笔者由于复制粘贴的低级错误排查了蛮久.

    提升效率不是太明显.在普通的显卡上有15%-20%左右的提升,在特别低端(办公用集成显卡g41之类的)上,只有7%左右提升.

    // Shadow caster vertex program.
    void casterVP(
        float4 position            : POSITION,
    
        out float4 outPosition    : POSITION,
        out float2 outDepth        : TEXCOORD0,
    
        uniform float4x4 worldViewProj,
        uniform float4 texelOffsets
        //uniform float4 depthRange
        )
    {
        outPosition = mul(worldViewProj, position);
    
        // fix pixel / texel alignment
        outPosition.xy += texelOffsets.zw * outPosition.w;
        // linear depth storage
        // offset / scale range output
    #if LINEAR_RANGE
        outDepth.x = (outPosition.z - depthRange.x) * depthRange.w;
    #else
        outDepth.x = outPosition.z;
    #endif
        outDepth.y = outPosition.w;
    }
    
    // Shadow caster fragment program for high-precision single-channel textures    
    void casterFP(
        float2 depth            : TEXCOORD0,
        out float4 result        : COLOR
        )
    {
    #if LINEAR_RANGE
        float finalDepth = depth.x;
    #else
        float finalDepth = depth.x / depth.y;
    #endif
        // just smear across all components 
        // therefore this one needs high individual channel precision
        result = float4(finalDepth, finalDepth, finalDepth, 1);
    }
    
    void receiverVP(
        float4 position        : POSITION,
        float3 normal        : NORMAL,
        float2 uv            : TEXCOORD0,
    
        out float4 outPosition    : POSITION,
        out float2 outUV        : TEXCOORD0,
        out float4 outShadowUV    : TEXCOORD1,
        out float outDiffuse    : TEXCOORD2,
        //out float outLightDir : TEXCOORD4,
    #if SPECULAR
        out float outSpecular    : TEXCOORD3,
        uniform float4 eyePosition,
        uniform float shininess,
    #endif
        uniform float4x4 world,
        //uniform float4x4 worldViewProj,
        uniform float4x4 texViewProj,
        //uniform float4 shadowDepthRange,
        //uniform float4 lightPositionObjectSpace,
        
        uniform float4 lightPosition,
        uniform float3x4   worldMatrix3x4Array[64],
        uniform float4x4 viewProjectionMatrix,
        //uniform float4x4 inverseWorldMatrix,
        float4 blendIdx : BLENDINDICES,
        float4 blendWgt : BLENDWEIGHT
        //uniform float4   lightDiffuseColour,
        //uniform float4   ambient,
        //uniform float4   diffuse,
        //uniform float4   emissive,
        )
    {
        //outPosition = mul(worldViewProj, position);
        outUV = uv;
        // calculate shadow map coords
        //outShadowUV = mul(texViewProj, position);
        
        // transform by indexed matrix
        float4 blendPos = float4(0,0,0,0);
        int i;
        for (i = 0; i < 3; ++i)
        {
            blendPos += float4(mul(worldMatrix3x4Array[blendIdx[i]], position).xyz, 1.0) * 
            blendWgt[i];
        }
        float4 worldPos = mul(world, blendPos);
        outShadowUV = mul(texViewProj, worldPos);
    #if LINEAR_RANGE
        // adjust by fixed depth bias, rescale into range
        outShadowUV.z = (outShadowUV.z - shadowDepthRange.x) * shadowDepthRange.w;
    #endif
        // view / projection
        outPosition = mul(viewProjectionMatrix, blendPos);
        
        float3 N = float3(0,0,0);
        for (i = 0; i < 3; ++i)
        {
            N += mul((float3x3)worldMatrix3x4Array[blendIdx[i]], normal) * 
            blendWgt[i];
        }
        //N = mul((float3x3)inverseWorldMatrix, N);
        N = normalize(N);
        float3 L =     normalize(
            lightPosition.xyz -  (blendPos.xyz * lightPosition.w));
        
    // #if DIRECTIONAL
        // // used in directional light source
        // float3 L = normalize(lightPositionObjectSpace.xyz);
    // #else
        // // use this line if used in point light source
        // float3 L = normalize(lightPositionObjectSpace.xyz - position.xyz);
    // #endif
        
        // Calculate diffuse component
        outDiffuse = max(dot(N, L) , 0);
        
    #if SPECULAR
        // Calculate specular component
        float3 E = normalize(eyePosition.xyz - position.xyz);
        float3 H = normalize(L + E);
        outSpecular = pow(max(dot(N, H), 0), shininess);
    #endif
    }
    
    void receiverFP(
        float4 position            : POSITION,
        float2 uv                : TEXCOORD0,
        float4 shadowUV            : TEXCOORD1,
        float diffuse            : TEXCOORD2,
    #if SPECULAR
        float specular            : TEXCOORD3,
    #endif
        //float4 lightColor       : TEXCOORD4,
        uniform sampler2D myTexture        : register(s0),
        uniform sampler2D shadowMap        : register(s1),
        uniform sampler1D diffuseRamp    : register(s2),
    #if SPECULAR
        uniform sampler1D specularRamp    : register(s3),
    #endif
        uniform float inverseShadowmapSize,
        uniform float fixedDepthBias,
        uniform float gradientClamp,
        uniform float gradientScaleBias,
        //uniform float shadowFuzzyWidth,
        uniform float darken,
    #if SPECULAR
        uniform float lighten,
    #endif
    
        out float4 result        : COLOR
        )
    {
        // point on shadowmap
    #if LINEAR_RANGE
        shadowUV.xy = shadowUV.xy / shadowUV.w;
    #else
        shadowUV = shadowUV / shadowUV.w;
    #endif
    
        float centerdepth = tex2D(shadowMap, shadowUV.xy).x;
        
        // gradient calculation
          float pixeloffset = inverseShadowmapSize;
        float4 depths = float4(
            tex2D(shadowMap, shadowUV.xy + float2(-pixeloffset, 0)).x,
            tex2D(shadowMap, shadowUV.xy + float2(+pixeloffset, 0)).x,
            tex2D(shadowMap, shadowUV.xy + float2(0, -pixeloffset)).x,
            tex2D(shadowMap, shadowUV.xy + float2(0, +pixeloffset)).x);
    
        float2 differences = abs( depths.yw - depths.xz );
        float gradient = min(gradientClamp, max(differences.x, differences.y));
        float gradientFactor = gradient * gradientScaleBias;
    
        // visibility function
        float depthAdjust = gradientFactor + (fixedDepthBias * centerdepth);
        float finalCenterDepth = centerdepth + depthAdjust;
    
        // shadowUV.z contains lightspace position of current object
    
        float shadow;
    #if FUZZY_TEST
        // fuzzy test - introduces some ghosting in result and doesn't appear to be needed?
        //shadow = saturate(1 + delta_z / (gradient * shadowFuzzyWidth));
        shadow = saturate(1 + (finalCenterDepth - shadowUV.z) * shadowFuzzyWidth * shadowUV.w);
    #else
        // hard test
    #if PCF
        // use depths from prev, calculate diff
        depths += depthAdjust.xxxx;
        shadow = (finalCenterDepth > shadowUV.z) ? 1.0f : 0.0f;
        shadow += (depths.x > shadowUV.z) ? 1.0f : 0.0f;
        shadow += (depths.y > shadowUV.z) ? 1.0f : 0.0f;
        shadow += (depths.z > shadowUV.z) ? 1.0f : 0.0f;
        shadow += (depths.w > shadowUV.z) ? 1.0f : 0.0f;
        
        shadow *= 0.2f;
    #else
        shadow = (finalCenterDepth > shadowUV.z) ? 1.0f : 0.0f;
    #endif
    
    #endif
        float4 vertexColour = tex2D(myTexture, uv);
        //result = float4(vertexColour.xyz * shadow, 1);
    
        diffuse = tex1D(diffuseRamp, diffuse).x;
        float darkness = (shadow > diffuse) ? diffuse : shadow;
    
        float final = (darkness - 1) * darken;
    #if SPECULAR
        // if there is already a shadow, no specular will be casted
        final += (shadow > 0.0f) ? tex1D(specularRamp, specular).x * lighten : 0;
    #endif
    
        // then darken the original texture.
        result = float4(vertexColour.xyz + float3(final), 1);
    }
    vertex_program CelShading/CasterVP cg
    {
    	source CelShadingShadow.cg
    	entry_point casterVP
    	profiles arbvp1 vs_2_0
    	
    	compile_arguments -DLINEAR_RANGE=0
    
    	default_params
    	{
    		param_named_auto worldViewProj worldviewproj_matrix
    		param_named_auto texelOffsets texel_offsets
    		//param_named_auto depthRange scene_depth_range
    	}
    }
    
    fragment_program CelShading/CasterFP cg
    {
    	source CelShadingShadow.cg
    	entry_point casterFP
    	profiles arbfp1 ps_2_0 fp20
    
    	compile_arguments -DLINEAR_RANGE=0
    	
    	default_params
    	{
    	}
    }
    
    vertex_program CelShading/ReceiverVP cg
    {
    	source CelShadingShadow.cg
    	entry_point receiverVP
    	profiles arbvp1 vs_2_0
    	includes_skeletal_animation true
    	
    	// set DDIRECTIONAL=1 if used with directional light
    	compile_arguments -DDIRECTIONAL=1 -DLINEAR_RANGE=0 -DSPECULAR=0
    
    	default_params
    	{
    		param_named_auto world world_matrix
    		param_named_auto worldViewProj worldviewproj_matrix
    		param_named_auto texViewProj texture_viewproj_matrix
    		param_named_auto lightPosition light_position 0
    		//param_named_auto shadowDepthRange shadow_scene_depth_range 0
    		//param_named_auto lightPositionObjectSpace light_position_object_space 0
    		
    		//param_named_auto inverseWorldMatrix inverse_world_matrix
    		param_named_auto worldMatrix3x4Array world_matrix_array_3x4
    		//param_named_auto viewProjectionMatrix viewproj_matrix
    		//param_named_auto lightDiffuseColour light_diffuse_colour 0
    		//param_named_auto ambient ambient_light_colour
    		//param_named_auto diffuse surface_diffuse_colour
    		//param_named_auto emissive surface_emissive_colour
    	}
    }
    
    fragment_program CelShading/ReceiverFP cg
    {
    	source CelShadingShadow.cg
    	entry_point receiverFP
    	profiles arbfp1 ps_2_0 fp20
    	
    	compile_arguments -DLINEAR_RANGE=0 -DSPECULAR=0 -DFUZZY_TEST=0 -DPCF=0
    	
    	default_params
    	{
    		param_named inverseShadowmapSize float 0.0009765625
    		param_named fixedDepthBias float 0.01
    		param_named gradientClamp float 0.0098
    		param_named gradientScaleBias float 1
    		//param_named shadowFuzzyWidth float 0.3
    		param_named darken float 0.15
    	}
    }
    

      

  • 相关阅读:
    负载均衡session会话保持方法
    PHP分布式中Redis实现Session
    Nginx内置变量
    Nginx配置文件解析
    Nginx重写
    Nginx与Apache比较
    CGI概念
    Linux笔记(十四)
    Linux笔记(十三)
    hdu 4039
  • 原文地址:https://www.cnblogs.com/flytrace/p/2771118.html
Copyright © 2011-2022 走看看